From 8fb2eb889d576fb3b298e68f07f7d6094e3372cf Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 00:24:06 -0800 Subject: [PATCH 01/14] Handle delayed frames at the end of the movie. --- Source/Core/VideoCommon/AVIDump.cpp | 64 ++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index d50f5b4b8d..95d7c686db 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -224,6 +224,25 @@ static int SendFrameAndReceivePacket(AVCodecContext* avctx, AVPacket* pkt, AVFra #endif } +static void WritePacket(AVPacket& pkt) +{ + // Write the compressed frame in the media file. + if (pkt.pts != (s64)AV_NOPTS_VALUE) + { + pkt.pts = av_rescale_q(pkt.pts, s_codec_context->time_base, s_stream->time_base); + } + if (pkt.dts != (s64)AV_NOPTS_VALUE) + { + pkt.dts = av_rescale_q(pkt.dts, s_codec_context->time_base, s_stream->time_base); + } +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 60, 100) + if (s_codec_context->coded_frame->key_frame) + pkt.flags |= AV_PKT_FLAG_KEY; +#endif + pkt.stream_index = s_stream->index; + av_interleaved_write_frame(s_format_context, &pkt); +} + void AVIDump::AddFrame(const u8* data, int width, int height, int stride, const Frame& state) { // Assume that the timing is valid, if the savestate id of the new frame @@ -284,34 +303,39 @@ void AVIDump::AddFrame(const u8* data, int width, int height, int stride, const s_last_pts = pts_in_ticks; error = SendFrameAndReceivePacket(s_codec_context, &pkt, s_scaled_frame, &got_packet); } - while (!error && got_packet) + if (!error && got_packet) { - // Write the compressed frame in the media file. - if (pkt.pts != (s64)AV_NOPTS_VALUE) - { - pkt.pts = av_rescale_q(pkt.pts, s_codec_context->time_base, s_stream->time_base); - } - if (pkt.dts != (s64)AV_NOPTS_VALUE) - { - pkt.dts = av_rescale_q(pkt.dts, s_codec_context->time_base, s_stream->time_base); - } -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 60, 100) - if (s_codec_context->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; -#endif - pkt.stream_index = s_stream->index; - av_interleaved_write_frame(s_format_context, &pkt); - - // Handle delayed frames. - PreparePacket(&pkt); - error = ReceivePacket(s_codec_context, &pkt, &got_packet); + WritePacket(pkt); } if (error) ERROR_LOG(VIDEO, "Error while encoding video: %d", error); } +static void HandleDelayedPackets() +{ + AVPacket pkt; + + while (true) + { + PreparePacket(&pkt); + int got_packet; + int error = ReceivePacket(s_codec_context, &pkt, &got_packet); + if (error) + { + ERROR_LOG(VIDEO, "Error while stopping video: %d", error); + break; + } + + if (!got_packet) + break; + + WritePacket(pkt); + } +} + void AVIDump::Stop() { + HandleDelayedPackets(); av_write_trailer(s_format_context); CloseVideoFile(); s_file_index = 0; From 1723645c994730c8c2ec86aaa4a757698df8eb05 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 01:43:31 -0800 Subject: [PATCH 02/14] guess format before allocating context --- Source/Core/VideoCommon/AVIDump.cpp | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 95d7c686db..bcd594a0c0 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -98,21 +98,22 @@ bool AVIDump::CreateVideoFile() { AVCodec* codec = nullptr; - s_format_context = avformat_alloc_context(); - std::stringstream s_file_index_str; - s_file_index_str << s_file_index; - snprintf(s_format_context->filename, sizeof(s_format_context->filename), "%s", - (File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + s_file_index_str.str() + ".avi") - .c_str()); - File::CreateFullPath(s_format_context->filename); + const char s_format[] = "avi"; + + std::stringstream file_ss; + file_ss << File::GetUserPath(D_DUMPFRAMES_IDX) + << "framedump" << s_file_index + << "." << s_format; + std::string filename = file_ss.str(); + File::CreateFullPath(filename); // Ask to delete file - if (File::Exists(s_format_context->filename)) + if (File::Exists(filename)) { if (SConfig::GetInstance().m_DumpFramesSilent || - AskYesNoT("Delete the existing file '%s'?", s_format_context->filename)) + AskYesNoT("Delete the existing file '%s'?", filename.c_str())) { - File::Delete(s_format_context->filename); + File::Delete(filename); } else { @@ -121,13 +122,13 @@ bool AVIDump::CreateVideoFile() } } - if (!(s_format_context->oformat = av_guess_format("avi", nullptr, nullptr))) - { - return false; - } + AVOutputFormat* output_format = av_guess_format(s_format, filename.c_str(), nullptr); + if (!output_format) return false; + avformat_alloc_output_context2(&s_format_context, output_format, nullptr, filename.c_str()); AVCodecID codec_id = - g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : s_format_context->oformat->video_codec; + g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : output_format->video_codec; + if (!(codec = avcodec_find_encoder(codec_id)) || !(s_codec_context = avcodec_alloc_context3(codec))) { From 86a838237631bb0a6a8e35d81f3ebb825014558e Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 02:43:49 -0800 Subject: [PATCH 03/14] Arbitrary dump formats. --- Source/Core/VideoCommon/AVIDump.cpp | 10 +++++++--- Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index bcd594a0c0..4c08550449 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -98,7 +98,7 @@ bool AVIDump::CreateVideoFile() { AVCodec* codec = nullptr; - const char s_format[] = "avi"; + const std::string& s_format = g_Config.sDumpFormat; std::stringstream file_ss; file_ss << File::GetUserPath(D_DUMPFRAMES_IDX) @@ -122,8 +122,12 @@ bool AVIDump::CreateVideoFile() } } - AVOutputFormat* output_format = av_guess_format(s_format, filename.c_str(), nullptr); - if (!output_format) return false; + AVOutputFormat* output_format = av_guess_format(s_format.c_str(), filename.c_str(), nullptr); + if (!output_format) + { + WARN_LOG(VIDEO, "Invalid format %s", s_format.c_str()); + return false; + } avformat_alloc_output_context2(&s_format_context, output_format, nullptr, filename.c_str()); AVCodecID codec_id = diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 96f35a0640..359c2f64f0 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -75,6 +75,7 @@ void VideoConfig::Load(const std::string& ini_file) settings->Get("DumpFramesAsImages", &bDumpFramesAsImages, false); settings->Get("FreeLook", &bFreeLook, false); settings->Get("UseFFV1", &bUseFFV1, false); + settings->Get("DumpFormat", &sDumpFormat, "avi"); settings->Get("BitrateKbps", &iBitrateKbps, 2500); settings->Get("InternalResolutionFrameDumps", &bInternalResolutionFrameDumps, false); settings->Get("EnablePixelLighting", &bEnablePixelLighting, false); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index ce80525a86..6ee5cd9e2e 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -102,6 +102,7 @@ struct VideoConfig final bool bDumpEFBTarget; bool bDumpFramesAsImages; bool bUseFFV1; + std::string sDumpFormat; bool bInternalResolutionFrameDumps; bool bFreeLook; bool bBorderlessFullscreen; From d4686aa1a7c312458a752b817804f398103b932d Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 09:19:33 -0800 Subject: [PATCH 04/14] More warnings for AVIDump. --- Source/Core/VideoCommon/AVIDump.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 4c08550449..a2781be3f8 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -136,6 +136,7 @@ bool AVIDump::CreateVideoFile() if (!(codec = avcodec_find_encoder(codec_id)) || !(s_codec_context = avcodec_alloc_context3(codec))) { + WARN_LOG(VIDEO, "Could not find encoder or allocate codec context."); return false; } @@ -153,6 +154,7 @@ bool AVIDump::CreateVideoFile() if (avcodec_open2(s_codec_context, codec, nullptr) < 0) { + WARN_LOG(VIDEO, "Could not open codec."); return false; } @@ -174,6 +176,7 @@ bool AVIDump::CreateVideoFile() if (!(s_stream = avformat_new_stream(s_format_context, codec)) || !AVStreamCopyContext(s_stream, s_codec_context)) { + WARN_LOG(VIDEO, "Could not create stream."); return false; } From a1a9e488a556ffa4763336711e7726eb7eb92f15 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 10:06:46 -0800 Subject: [PATCH 05/14] XVID FourCC for MPEG-4 codecs. --- Source/Core/VideoCommon/AVIDump.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index a2781be3f8..ef9ccaeed4 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -140,9 +140,10 @@ bool AVIDump::CreateVideoFile() return false; } - if (!g_Config.bUseFFV1) - s_codec_context->codec_tag = - MKTAG('X', 'V', 'I', 'D'); // Force XVID FourCC for better compatibility + // Force XVID FourCC for better compatibility + if (codec->id == AV_CODEC_ID_MPEG4) + s_codec_context->codec_tag = MKTAG('X', 'V', 'I', 'D'); + s_codec_context->codec_type = AVMEDIA_TYPE_VIDEO; s_codec_context->bit_rate = g_Config.iBitrateKbps * 1000; s_codec_context->width = s_width; From 21e66e60e33e2f2535b1521463f5f89955d5cd42 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 11:04:22 -0800 Subject: [PATCH 06/14] Configable dump codec. --- Source/Core/VideoCommon/AVIDump.cpp | 8 ++++---- Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index ef9ccaeed4..ccf355c712 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -96,8 +96,6 @@ bool AVIDump::Start(int w, int h) bool AVIDump::CreateVideoFile() { - AVCodec* codec = nullptr; - const std::string& s_format = g_Config.sDumpFormat; std::stringstream file_ss; @@ -130,8 +128,10 @@ bool AVIDump::CreateVideoFile() } avformat_alloc_output_context2(&s_format_context, output_format, nullptr, filename.c_str()); - AVCodecID codec_id = - g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : output_format->video_codec; + const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(g_Config.sDumpCodec.c_str()); + AVCodecID codec_id = codec_desc ? codec_desc->id : output_format->video_codec; + + const AVCodec* codec = nullptr; if (!(codec = avcodec_find_encoder(codec_id)) || !(s_codec_context = avcodec_alloc_context3(codec))) diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 359c2f64f0..fd8c6ea939 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -76,6 +76,7 @@ void VideoConfig::Load(const std::string& ini_file) settings->Get("FreeLook", &bFreeLook, false); settings->Get("UseFFV1", &bUseFFV1, false); settings->Get("DumpFormat", &sDumpFormat, "avi"); + settings->Get("DumpCodec", &sDumpCodec, ""); settings->Get("BitrateKbps", &iBitrateKbps, 2500); settings->Get("InternalResolutionFrameDumps", &bInternalResolutionFrameDumps, false); settings->Get("EnablePixelLighting", &bEnablePixelLighting, false); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 6ee5cd9e2e..ed8b7827cc 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -102,6 +102,7 @@ struct VideoConfig final bool bDumpEFBTarget; bool bDumpFramesAsImages; bool bUseFFV1; + std::string sDumpCodec; std::string sDumpFormat; bool bInternalResolutionFrameDumps; bool bFreeLook; From f82e3de763b3198b76935a42b8aa0ca1a5b17973 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 11:37:36 -0800 Subject: [PATCH 07/14] Dump to arbitrary URLs. --- Source/Core/VideoCommon/AVIDump.cpp | 42 ++++++++++++++----------- Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 1 + 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index ccf355c712..2ee3747bb6 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -58,6 +58,7 @@ static void InitAVCodec() if (first_run) { av_register_all(); + avformat_network_init(); first_run = false; } } @@ -98,35 +99,40 @@ bool AVIDump::CreateVideoFile() { const std::string& s_format = g_Config.sDumpFormat; - std::stringstream file_ss; - file_ss << File::GetUserPath(D_DUMPFRAMES_IDX) - << "framedump" << s_file_index - << "." << s_format; - std::string filename = file_ss.str(); - File::CreateFullPath(filename); + std::string s_dump_path = g_Config.sDumpPath; - // Ask to delete file - if (File::Exists(filename)) + if (s_dump_path.empty()) { - if (SConfig::GetInstance().m_DumpFramesSilent || - AskYesNoT("Delete the existing file '%s'?", filename.c_str())) + std::stringstream file_ss; + file_ss << File::GetUserPath(D_DUMPFRAMES_IDX) + << "framedump" << s_file_index + << "." << s_format; + s_dump_path = file_ss.str(); + File::CreateFullPath(s_dump_path); + + // Ask to delete file + if (File::Exists(s_dump_path)) { - File::Delete(filename); - } - else - { - // Stop and cancel dumping the video - return false; + if (SConfig::GetInstance().m_DumpFramesSilent || + AskYesNoT("Delete the existing file '%s'?", s_dump_path.c_str())) + { + File::Delete(s_dump_path); + } + else + { + // Stop and cancel dumping the video + return false; + } } } - AVOutputFormat* output_format = av_guess_format(s_format.c_str(), filename.c_str(), nullptr); + AVOutputFormat* output_format = av_guess_format(s_format.c_str(), s_dump_path.c_str(), nullptr); if (!output_format) { WARN_LOG(VIDEO, "Invalid format %s", s_format.c_str()); return false; } - avformat_alloc_output_context2(&s_format_context, output_format, nullptr, filename.c_str()); + avformat_alloc_output_context2(&s_format_context, output_format, nullptr, s_dump_path.c_str()); const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(g_Config.sDumpCodec.c_str()); AVCodecID codec_id = codec_desc ? codec_desc->id : output_format->video_codec; diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index fd8c6ea939..7e5f04f1db 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -77,6 +77,7 @@ void VideoConfig::Load(const std::string& ini_file) settings->Get("UseFFV1", &bUseFFV1, false); settings->Get("DumpFormat", &sDumpFormat, "avi"); settings->Get("DumpCodec", &sDumpCodec, ""); + settings->Get("DumpPath", &sDumpPath, ""); settings->Get("BitrateKbps", &iBitrateKbps, 2500); settings->Get("InternalResolutionFrameDumps", &bInternalResolutionFrameDumps, false); settings->Get("EnablePixelLighting", &bEnablePixelLighting, false); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index ed8b7827cc..dfab8bbcc3 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -104,6 +104,7 @@ struct VideoConfig final bool bUseFFV1; std::string sDumpCodec; std::string sDumpFormat; + std::string sDumpPath; bool bInternalResolutionFrameDumps; bool bFreeLook; bool bBorderlessFullscreen; From 6b1910a078ee80a0e544565d77af0c7c9d3134c0 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 11:49:37 -0800 Subject: [PATCH 08/14] Appease global header warning. --- Source/Core/VideoCommon/AVIDump.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 2ee3747bb6..10f9df6efc 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -159,6 +159,9 @@ bool AVIDump::CreateVideoFile() s_codec_context->gop_size = 12; s_codec_context->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA : AV_PIX_FMT_YUV420P; + if (output_format->flags & AVFMT_GLOBALHEADER) + s_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER; + if (avcodec_open2(s_codec_context, codec, nullptr) < 0) { WARN_LOG(VIDEO, "Could not open codec."); From a3af5b09d36e02a9e9c608bf02b5243db0a21d4a Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Tue, 21 Feb 2017 14:24:15 -0800 Subject: [PATCH 09/14] error logs --- Source/Core/VideoCommon/AVIDump.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 10f9df6efc..911f7951ad 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -129,10 +129,15 @@ bool AVIDump::CreateVideoFile() AVOutputFormat* output_format = av_guess_format(s_format.c_str(), s_dump_path.c_str(), nullptr); if (!output_format) { - WARN_LOG(VIDEO, "Invalid format %s", s_format.c_str()); + ERROR_LOG(VIDEO, "Invalid format %s", s_format.c_str()); + return false; + } + + if(avformat_alloc_output_context2(&s_format_context, output_format, nullptr, s_dump_path.c_str()) < 0) + { + ERROR_LOG(VIDEO, "Could not allocate output context"); return false; } - avformat_alloc_output_context2(&s_format_context, output_format, nullptr, s_dump_path.c_str()); const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(g_Config.sDumpCodec.c_str()); AVCodecID codec_id = codec_desc ? codec_desc->id : output_format->video_codec; @@ -142,7 +147,7 @@ bool AVIDump::CreateVideoFile() if (!(codec = avcodec_find_encoder(codec_id)) || !(s_codec_context = avcodec_alloc_context3(codec))) { - WARN_LOG(VIDEO, "Could not find encoder or allocate codec context."); + ERROR_LOG(VIDEO, "Could not find encoder or allocate codec context"); return false; } @@ -164,7 +169,7 @@ bool AVIDump::CreateVideoFile() if (avcodec_open2(s_codec_context, codec, nullptr) < 0) { - WARN_LOG(VIDEO, "Could not open codec."); + ERROR_LOG(VIDEO, "Could not open codec"); return false; } @@ -186,7 +191,7 @@ bool AVIDump::CreateVideoFile() if (!(s_stream = avformat_new_stream(s_format_context, codec)) || !AVStreamCopyContext(s_stream, s_codec_context)) { - WARN_LOG(VIDEO, "Could not create stream."); + ERROR_LOG(VIDEO, "Could not create stream"); return false; } @@ -194,7 +199,7 @@ bool AVIDump::CreateVideoFile() if (avio_open(&s_format_context->pb, s_format_context->filename, AVIO_FLAG_WRITE) < 0 || avformat_write_header(s_format_context, nullptr)) { - WARN_LOG(VIDEO, "Could not open %s", s_format_context->filename); + ERROR_LOG(VIDEO, "Could not open %s", s_format_context->filename); return false; } From 8c2438750958adbed7e99453077e27d359073096 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Sat, 25 Feb 2017 01:01:21 -0800 Subject: [PATCH 10/14] Use ffv1 if user requests it. --- Source/Core/VideoCommon/AVIDump.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 911f7951ad..3d7459d054 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -139,7 +139,8 @@ bool AVIDump::CreateVideoFile() return false; } - const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(g_Config.sDumpCodec.c_str()); + const std::string& codec_name = g_Config.bUseFFV1 ? "ffv1" : g_Config.sDumpCodec; + const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(codec_name.c_str()); AVCodecID codec_id = codec_desc ? codec_desc->id : output_format->video_codec; const AVCodec* codec = nullptr; From 9155af5103cb3f060376d7b6bdfa1e6cdcde6242 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Sat, 25 Feb 2017 01:02:20 -0800 Subject: [PATCH 11/14] GetDumpPath function. --- Source/Core/VideoCommon/AVIDump.cpp | 52 ++++++++++++++++------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 3d7459d054..d5616c4324 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -95,36 +95,40 @@ bool AVIDump::Start(int w, int h) return success; } +static std::string GetDumpPath(const std::string& format) +{ + if (!g_Config.sDumpPath.empty()) + return g_Config.sDumpPath; + + std::string s_dump_path = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + + std::to_string(s_file_index) + "." + format; + + // Ask to delete file + if (File::Exists(s_dump_path)) + { + if (SConfig::GetInstance().m_DumpFramesSilent || + AskYesNoT("Delete the existing file '%s'?", s_dump_path.c_str())) + { + File::Delete(s_dump_path); + } + else + { + // Stop and cancel dumping the video + return ""; + } + } + + return s_dump_path; +} + bool AVIDump::CreateVideoFile() { const std::string& s_format = g_Config.sDumpFormat; - std::string s_dump_path = g_Config.sDumpPath; + std::string s_dump_path = GetDumpPath(s_format); if (s_dump_path.empty()) - { - std::stringstream file_ss; - file_ss << File::GetUserPath(D_DUMPFRAMES_IDX) - << "framedump" << s_file_index - << "." << s_format; - s_dump_path = file_ss.str(); - File::CreateFullPath(s_dump_path); - - // Ask to delete file - if (File::Exists(s_dump_path)) - { - if (SConfig::GetInstance().m_DumpFramesSilent || - AskYesNoT("Delete the existing file '%s'?", s_dump_path.c_str())) - { - File::Delete(s_dump_path); - } - else - { - // Stop and cancel dumping the video - return false; - } - } - } + return false; AVOutputFormat* output_format = av_guess_format(s_format.c_str(), s_dump_path.c_str(), nullptr); if (!output_format) From fbff74c1ebe4999894800d9ab8e99a02e55e57f5 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Sat, 25 Feb 2017 01:28:51 -0800 Subject: [PATCH 12/14] Warn on invalid video codec. --- Source/Core/VideoCommon/AVIDump.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index d5616c4324..9cd3155edb 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -144,8 +144,17 @@ bool AVIDump::CreateVideoFile() } const std::string& codec_name = g_Config.bUseFFV1 ? "ffv1" : g_Config.sDumpCodec; - const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(codec_name.c_str()); - AVCodecID codec_id = codec_desc ? codec_desc->id : output_format->video_codec; + + AVCodecID codec_id = output_format->video_codec; + + if (!codec_name.empty()) + { + const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(codec_name.c_str()); + if (codec_desc) + codec_id = codec_desc->id; + else + WARN_LOG(VIDEO, "Invalid codec %s", codec_name.c_str()); + } const AVCodec* codec = nullptr; From 71c0e30655e3ed86905704dedb2b7fb5e62a1dbe Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Sun, 5 Mar 2017 17:29:46 -0800 Subject: [PATCH 13/14] Appease linter. --- Source/Core/VideoCommon/AVIDump.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoCommon/AVIDump.cpp b/Source/Core/VideoCommon/AVIDump.cpp index 9cd3155edb..dc4e806f6a 100644 --- a/Source/Core/VideoCommon/AVIDump.cpp +++ b/Source/Core/VideoCommon/AVIDump.cpp @@ -101,7 +101,7 @@ static std::string GetDumpPath(const std::string& format) return g_Config.sDumpPath; std::string s_dump_path = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + - std::to_string(s_file_index) + "." + format; + std::to_string(s_file_index) + "." + format; // Ask to delete file if (File::Exists(s_dump_path)) @@ -136,8 +136,9 @@ bool AVIDump::CreateVideoFile() ERROR_LOG(VIDEO, "Invalid format %s", s_format.c_str()); return false; } - - if(avformat_alloc_output_context2(&s_format_context, output_format, nullptr, s_dump_path.c_str()) < 0) + + if (avformat_alloc_output_context2(&s_format_context, output_format, nullptr, + s_dump_path.c_str()) < 0) { ERROR_LOG(VIDEO, "Could not allocate output context"); return false; @@ -362,10 +363,10 @@ static void HandleDelayedPackets() ERROR_LOG(VIDEO, "Error while stopping video: %d", error); break; } - + if (!got_packet) break; - + WritePacket(pkt); } } From 096f58b172804acacd79a199458ef373a04ee2e1 Mon Sep 17 00:00:00 2001 From: Vlad Firoiu Date: Wed, 8 Mar 2017 01:38:40 -0800 Subject: [PATCH 14/14] Save new framedump options. --- Source/Core/VideoCommon/VideoConfig.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 7e5f04f1db..1f3d3d10ea 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -298,6 +298,9 @@ void VideoConfig::Save(const std::string& ini_file) settings->Set("DumpFramesAsImages", bDumpFramesAsImages); settings->Set("FreeLook", bFreeLook); settings->Set("UseFFV1", bUseFFV1); + settings->Set("DumpFormat", sDumpFormat); + settings->Set("DumpCodec", sDumpCodec); + settings->Set("DumpPath", sDumpPath); settings->Set("BitrateKbps", iBitrateKbps); settings->Set("InternalResolutionFrameDumps", bInternalResolutionFrameDumps); settings->Set("EnablePixelLighting", bEnablePixelLighting);