Fixed a huge regression with PTS, that caused all sorts of issues with encoded videos, especially webm.

This commit is contained in:
Jonathan Thomas
2012-08-11 20:28:05 -05:00
parent 7eeb8f7c80
commit 1bbfa060cf
3 changed files with 41 additions and 21 deletions

View File

@@ -21,6 +21,7 @@ extern "C" {
#include <libavcodec/opt.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/mathematics.h>
}
#include <cmath>
#include <ctime>

View File

@@ -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;

View File

@@ -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();