From 1bbfa060cf0af7b02e6bd9c94d6386bd04b3cd07 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sat, 11 Aug 2012 20:28:05 -0500 Subject: [PATCH] Fixed a huge regression with PTS, that caused all sorts of issues with encoded videos, especially webm. --- include/FFmpegWriter.h | 1 + src/FFmpegWriter.cpp | 36 +++++++++++++++++++++++++----------- src/Main.cpp | 25 +++++++++++++++---------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 107cc2b2..ad57474d 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -21,6 +21,7 @@ extern "C" { #include #include #include + #include } #include #include diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 41486728..0448119b 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -196,7 +196,7 @@ void FFmpegWriter::SetOption(Stream_Type stream, string name, string value) // Was option found? if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" || - name == "level" || name == "profile")) + name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate")) { // Check for specific named options if (name == "g") @@ -204,29 +204,41 @@ void FFmpegWriter::SetOption(Stream_Type stream, string name, string value) convert >> c->gop_size; else if (name == "qmin") - // minimum quantizer + // Minimum quantizer convert >> c->qmin; else if (name == "qmax") - // maximum quantizer + // Maximum quantizer convert >> c->qmax; else if (name == "max_b_frames") - // maximum number of B-frames between non-B-frames + // Maximum number of B-frames between non-B-frames convert >> c->max_b_frames; else if (name == "mb_decision") - // macroblock decision mode + // Macroblock decision mode convert >> c->mb_decision; else if (name == "level") - // set codec level + // Set codec level convert >> c->level; else if (name == "profile") - // set codec profile + // Set codec profile convert >> c->profile; + else if (name == "slices") + // Indicates number of picture subdivisions + convert >> c->slices; + + else if (name == "rc_min_rate") + // Minimum bitrate + convert >> c->rc_min_rate; + + else if (name == "rc_max_rate") + // Maximum bitrate + convert >> c->rc_max_rate; + else // Set AVOption av_set_string3 (c->priv_data, name.c_str(), value.c_str(), 0, NULL); @@ -471,8 +483,8 @@ AVStream* FFmpegWriter::add_video_stream() of which frame timestamps are represented. for fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. */ - c->time_base.den = info.video_timebase.den; c->time_base.num = info.video_timebase.num; + c->time_base.den = info.video_timebase.den; c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */ c->pix_fmt = PIX_FMT_YUV420P; if (c->codec_id == CODEC_ID_MPEG2VIDEO) { @@ -658,7 +670,8 @@ void FFmpegWriter::write_audio_packet(Frame* frame) pkt.size = avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, (short *) samples); if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts = c->coded_frame->pts; + // Set the correct rescaled timestamp + pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = audio_st->index; pkt.data = audio_outbuf; @@ -784,8 +797,9 @@ void FFmpegWriter::write_video_packet(Frame* frame) AVPacket pkt; av_init_packet(&pkt); - if (c->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts= c->coded_frame->pts; + if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) + // Set the correct rescaled timestamp + pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base); if(c->coded_frame->key_frame) pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index= video_st->index; diff --git a/src/Main.cpp b/src/Main.cpp index 89c75570..2ef6318a 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -34,22 +34,27 @@ int main() w.DisplayInfo(); // Set options - w.SetVideoOptions(true, "libvpx", Fraction(24, 1), 640, 360, Fraction(1,1), false, false, 384000); w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000); + w.SetVideoOptions(true, "libvpx", Fraction(25, 1), 640, 360, Fraction(1,1), false, false, 2000000); // Prepare Streams w.PrepareStreams(); // Set Options - //w.SetOption(VIDEO_STREAM, "quality", "good"); - w.SetOption(VIDEO_STREAM, "g", "120"); - w.SetOption(VIDEO_STREAM, "qmin", "10"); - w.SetOption(VIDEO_STREAM, "qmax", "42"); - w.SetOption(VIDEO_STREAM, "profile", "0"); - w.SetOption(VIDEO_STREAM, "level", "216"); - w.SetOption(VIDEO_STREAM, "rc_lookahead", "16"); - //w.SetOption(VIDEO_STREAM, "max_b_frames", "2"); - //w.SetOption(VIDEO_STREAM, "mb_decision", "2"); + w.SetOption(VIDEO_STREAM, "quality", "good"); +// w.SetOption(VIDEO_STREAM, "g", "120"); +// w.SetOption(VIDEO_STREAM, "qmin", "11"); +// w.SetOption(VIDEO_STREAM, "qmax", "51"); +// w.SetOption(VIDEO_STREAM, "profile", "0"); +// w.SetOption(VIDEO_STREAM, "speed", "0"); +// w.SetOption(VIDEO_STREAM, "level", "216"); +// w.SetOption(VIDEO_STREAM, "rc_lookahead", "16"); +// w.SetOption(VIDEO_STREAM, "rc_min_rate", "100000"); +// w.SetOption(VIDEO_STREAM, "rc_max_rate", "24000000"); +// w.SetOption(VIDEO_STREAM, "slices", "4"); +// w.SetOption(VIDEO_STREAM, "arnr_max_frames", "7"); +// w.SetOption(VIDEO_STREAM, "arnr_strength", "5"); +// w.SetOption(VIDEO_STREAM, "arnr_type", "3"); // Write header w.WriteHeader();