Skip to content

Commit

Permalink
avconv: replace -vsync cfr code with the fps filter.
Browse files Browse the repository at this point in the history
Invented timestamps for the h264 tests return to something resembling
sanity.

In the idroq-video-encode test when converting 25 fps -> 30 fps the
fifth frame gets duplicated instead of the sixth.
  • Loading branch information
elenril committed May 18, 2012
1 parent 755cd41 commit 74b961d
Show file tree
Hide file tree
Showing 48 changed files with 3,355 additions and 3,391 deletions.
150 changes: 57 additions & 93 deletions avconv.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,8 @@ static int configure_video_filters(FilterGraph *fg, AVFilterContext **in_filter,
sample_aspect_ratio = ist->st->codec->sample_aspect_ratio;

snprintf(args, 255, "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
ist->st->codec->height, ist->st->codec->pix_fmt,
ist->st->time_base.num, ist->st->time_base.den,
sample_aspect_ratio.num, sample_aspect_ratio.den);

ret = avfilter_graph_create_filter(&fg->inputs[0]->filter,
Expand Down Expand Up @@ -780,6 +781,20 @@ static int configure_video_filters(FilterGraph *fg, AVFilterContext **in_filter,
*in_filter = filter;
}

if (ost->frame_rate.num) {
snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num,
ost->frame_rate.den);
ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("fps"),
"fps", args, NULL, fg->graph);
if (ret < 0)
return ret;

ret = avfilter_link(filter, 0, *out_filter, 0);
if (ret < 0)
return ret;
*out_filter = filter;
}

if ((pix_fmts = choose_pix_fmts(ost))) {
if ((ret = avfilter_graph_create_filter(&filter,
avfilter_get_by_name("format"),
Expand Down Expand Up @@ -1382,13 +1397,6 @@ static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec,
}
}

static double
get_sync_ipts(const OutputStream *ost, int64_t pts)
{
OutputFile *of = output_files[ost->file_index];
return (double)(pts - of->start_time) / AV_TIME_BASE;
}

static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
{
AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
Expand Down Expand Up @@ -1600,67 +1608,39 @@ static void do_video_out(AVFormatContext *s,
AVFrame *in_picture,
int *frame_size, float quality)
{
int nb_frames, i, ret, format_video_sync;
AVCodecContext *enc;
double sync_ipts, delta;

enc = ost->st->codec;

sync_ipts = get_sync_ipts(ost, in_picture->pts) / av_q2d(enc->time_base);
delta = sync_ipts - ost->sync_opts;

/* by default, we output a single frame */
nb_frames = 1;
int ret, format_video_sync;
AVPacket pkt;
AVCodecContext *enc = ost->st->codec;

*frame_size = 0;

format_video_sync = video_sync_method;
if (format_video_sync == VSYNC_AUTO)
format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH :
(s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR;

switch (format_video_sync) {
case VSYNC_CFR:
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
if (delta < -1.1)
nb_frames = 0;
else if (delta > 1.1)
nb_frames = lrintf(delta);
break;
case VSYNC_VFR:
if (delta <= -0.6)
nb_frames = 0;
else if (delta > 0.6)
ost->sync_opts = lrint(sync_ipts);
break;
case VSYNC_PASSTHROUGH:
ost->sync_opts = lrint(sync_ipts);
break;
default:
av_assert0(0);
}

nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
if (nb_frames == 0) {
if (format_video_sync != VSYNC_PASSTHROUGH &&
ost->frame_number &&
in_picture->pts != AV_NOPTS_VALUE &&
in_picture->pts < ost->sync_opts) {
nb_frames_drop++;
av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n");
return;
} else if (nb_frames > 1) {
nb_frames_dup += nb_frames - 1;
av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
}

if (in_picture->pts == AV_NOPTS_VALUE)
in_picture->pts = ost->sync_opts;
ost->sync_opts = in_picture->pts;


if (!ost->frame_number)
ost->first_pts = ost->sync_opts;
ost->first_pts = in_picture->pts;

/* duplicates frame if needed */
for (i = 0; i < nb_frames; i++) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;

if (!check_recording_time(ost))
if (!check_recording_time(ost) ||
ost->frame_number >= ost->max_frames)
return;

if (s->oformat->flags & AVFMT_RAWPICTURE &&
Expand All @@ -1672,7 +1652,7 @@ static void do_video_out(AVFormatContext *s,
enc->coded_frame->top_field_first = in_picture->top_field_first;
pkt.data = (uint8_t *)in_picture;
pkt.size = sizeof(AVPicture);
pkt.pts = av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);
pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;

write_frame(s, &pkt, ost);
Expand All @@ -1696,7 +1676,6 @@ static void do_video_out(AVFormatContext *s,
big_picture.quality = quality;
if (!enc->me_threshold)
big_picture.pict_type = 0;
big_picture.pts = ost->sync_opts;
if (ost->forced_kf_index < ost->forced_kf_count &&
big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
big_picture.pict_type = AV_PICTURE_TYPE_I;
Expand Down Expand Up @@ -1731,7 +1710,6 @@ static void do_video_out(AVFormatContext *s,
* flush, we need to limit them here, before they go into encoder.
*/
ost->frame_number++;
}
}

static double psnr(double d)
Expand Down Expand Up @@ -1809,11 +1787,7 @@ static int poll_filters(void)
break;

avfilter_copy_buf_props(filtered_frame, picref);
if (ost->enc->type == AVMEDIA_TYPE_VIDEO)
filtered_frame->pts = av_rescale_q(picref->pts,
ost->filter->filter->inputs[0]->time_base,
AV_TIME_BASE_Q);
else if (picref->pts != AV_NOPTS_VALUE)
if (picref->pts != AV_NOPTS_VALUE)
filtered_frame->pts = av_rescale_q(picref->pts,
ost->filter->filter->inputs[0]->time_base,
ost->st->codec->time_base) -
Expand Down Expand Up @@ -2288,7 +2262,7 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
return ret;
}

static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts)
static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVFrame *decoded_frame;
void *buffer_to_free = NULL;
Expand All @@ -2300,9 +2274,6 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
else
avcodec_get_frame_defaults(ist->decoded_frame);
decoded_frame = ist->decoded_frame;
pkt->pts = *pkt_pts;
pkt->dts = ist->last_dts;
*pkt_pts = AV_NOPTS_VALUE;

ret = avcodec_decode_video2(ist->st->codec,
decoded_frame, got_output, pkt);
Expand Down Expand Up @@ -2406,7 +2377,6 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
{
int i;
int got_output;
int64_t pkt_pts = AV_NOPTS_VALUE;
AVPacket avpkt;

if (ist->next_dts == AV_NOPTS_VALUE)
Expand All @@ -2424,8 +2394,6 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)

if (pkt->dts != AV_NOPTS_VALUE)
ist->next_dts = ist->last_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
if (pkt->pts != AV_NOPTS_VALUE)
pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);

// while we have more to decode or while the decoder did output something on EOF
while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
Expand All @@ -2445,7 +2413,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
ret = transcode_audio (ist, &avpkt, &got_output);
break;
case AVMEDIA_TYPE_VIDEO:
ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts);
ret = transcode_video (ist, &avpkt, &got_output);
if (avpkt.duration)
ist->next_dts += av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
else if (ist->st->r_frame_rate.num)
Expand Down Expand Up @@ -2733,6 +2701,27 @@ static int transcode_init(void)
ist->decoding_needed = 1;
ost->encoding_needed = 1;

/*
* We want CFR output if and only if one of those is true:
* 1) user specified output framerate with -r
* 2) user specified -vsync cfr
* 3) output format is CFR and the user didn't force vsync to
* something else than CFR
*
* in such a case, set ost->frame_rate
*/
if (codec->codec_type == AVMEDIA_TYPE_VIDEO &&
!ost->frame_rate.num && ist &&
(video_sync_method == VSYNC_CFR ||
(video_sync_method == VSYNC_AUTO &&
!(oc->oformat->flags & (AVFMT_NOTIMESTAMPS | AVFMT_VARIABLE_FPS))))) {
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25, 1};
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
ost->frame_rate = ost->enc->supported_framerates[idx];
}
}

if (!ost->filter &&
(codec->codec_type == AVMEDIA_TYPE_VIDEO ||
codec->codec_type == AVMEDIA_TYPE_AUDIO)) {
Expand All @@ -2753,32 +2742,7 @@ static int transcode_init(void)
codec->time_base = (AVRational){ 1, codec->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
/*
* We want CFR output if and only if one of those is true:
* 1) user specified output framerate with -r
* 2) user specified -vsync cfr
* 3) output format is CFR and the user didn't force vsync to
* something else than CFR
*
* in such a case, set ost->frame_rate
*/
if (!ost->frame_rate.num && ist &&
(video_sync_method == VSYNC_CFR ||
(video_sync_method == VSYNC_AUTO &&
!(oc->oformat->flags & (AVFMT_NOTIMESTAMPS | AVFMT_VARIABLE_FPS))))) {
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25, 1};
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
ost->frame_rate = ost->enc->supported_framerates[idx];
}
}
if (ost->frame_rate.num) {
codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
video_sync_method = VSYNC_CFR;
} else if (ist)
codec->time_base = ist->st->time_base;
else
codec->time_base = ost->filter->filter->inputs[0]->time_base;
codec->time_base = ost->filter->filter->inputs[0]->time_base;

codec->width = ost->filter->filter->inputs[0]->w;
codec->height = ost->filter->filter->inputs[0]->h;
Expand Down
60 changes: 30 additions & 30 deletions tests/ref/fate/h264-conformance-cabac_mot_fld0_full
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
#tb 0: 1/25
0, 2, 2, 1, 518400, 0xbf168f4e
0, 4, 4, 1, 518400, 0xeda5e54f
0, 6, 6, 1, 518400, 0xef496d43
0, 8, 8, 1, 518400, 0x6b68dad5
0, 10, 10, 1, 518400, 0x9a40a7de
0, 12, 12, 1, 518400, 0x0c21c018
0, 14, 14, 1, 518400, 0x4ac5a846
0, 16, 16, 1, 518400, 0x3a1aa817
0, 18, 18, 1, 518400, 0xcc4eb434
0, 20, 20, 1, 518400, 0x4368a3c2
0, 22, 22, 1, 518400, 0xb923682f
0, 24, 24, 1, 518400, 0xd95460a8
0, 26, 26, 1, 518400, 0x8e8518aa
0, 28, 28, 1, 518400, 0x292a1a80
0, 30, 30, 1, 518400, 0xbada388e
0, 32, 32, 1, 518400, 0xa67f63c9
0, 34, 34, 1, 518400, 0x9fc77e21
0, 36, 36, 1, 518400, 0xe99dc2ac
0, 38, 38, 1, 518400, 0x17d7d080
0, 40, 40, 1, 518400, 0x41760c0b
0, 42, 42, 1, 518400, 0x3c70f34d
0, 44, 44, 1, 518400, 0x0d640285
0, 46, 46, 1, 518400, 0x448893e8
0, 48, 48, 1, 518400, 0x08194490
0, 50, 50, 1, 518400, 0xcf227031
0, 52, 52, 1, 518400, 0x8d94587d
0, 54, 54, 1, 518400, 0x696fca01
0, 56, 56, 1, 518400, 0xe0ab234b
0, 58, 58, 1, 518400, 0x0620153b
0, 59, 59, 1, 518400, 0xb78c146c
0, 0, 0, 1, 518400, 0xbf168f4e
0, 1, 1, 1, 518400, 0xeda5e54f
0, 2, 2, 1, 518400, 0xef496d43
0, 3, 3, 1, 518400, 0x6b68dad5
0, 4, 4, 1, 518400, 0x9a40a7de
0, 5, 5, 1, 518400, 0x0c21c018
0, 6, 6, 1, 518400, 0x4ac5a846
0, 7, 7, 1, 518400, 0x3a1aa817
0, 8, 8, 1, 518400, 0xcc4eb434
0, 9, 9, 1, 518400, 0x4368a3c2
0, 10, 10, 1, 518400, 0xb923682f
0, 11, 11, 1, 518400, 0xd95460a8
0, 12, 12, 1, 518400, 0x8e8518aa
0, 13, 13, 1, 518400, 0x292a1a80
0, 14, 14, 1, 518400, 0xbada388e
0, 15, 15, 1, 518400, 0xa67f63c9
0, 16, 16, 1, 518400, 0x9fc77e21
0, 17, 17, 1, 518400, 0xe99dc2ac
0, 18, 18, 1, 518400, 0x17d7d080
0, 19, 19, 1, 518400, 0x41760c0b
0, 20, 20, 1, 518400, 0x3c70f34d
0, 21, 21, 1, 518400, 0x0d640285
0, 22, 22, 1, 518400, 0x448893e8
0, 23, 23, 1, 518400, 0x08194490
0, 24, 24, 1, 518400, 0xcf227031
0, 25, 25, 1, 518400, 0x8d94587d
0, 26, 26, 1, 518400, 0x696fca01
0, 27, 27, 1, 518400, 0xe0ab234b
0, 28, 28, 1, 518400, 0x0620153b
0, 29, 29, 1, 518400, 0xb78c146c
60 changes: 30 additions & 30 deletions tests/ref/fate/h264-conformance-cabac_mot_picaff0_full
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
#tb 0: 1/25
0, 1, 1, 1, 518400, 0xd8b58a23
0, 3, 3, 1, 518400, 0xe53b4aba
0, 4, 4, 1, 518400, 0x6cbca47a
0, 5, 5, 1, 518400, 0xceb51253
0, 6, 6, 1, 518400, 0x60cb3cdd
0, 8, 8, 1, 518400, 0x7b633553
0, 10, 10, 1, 518400, 0x10c012c9
0, 12, 12, 1, 518400, 0xa340ee20
0, 13, 13, 1, 518400, 0x574c22c2
0, 14, 14, 1, 518400, 0xbcdb1bf7
0, 15, 15, 1, 518400, 0x57811e9a
0, 17, 17, 1, 518400, 0xdd4af748
0, 19, 19, 1, 518400, 0xb931a637
0, 21, 21, 1, 518400, 0xcef6ce95
0, 22, 22, 1, 518400, 0xd28c7085
0, 23, 23, 1, 518400, 0xae9daf53
0, 24, 24, 1, 518400, 0xca29d819
0, 26, 26, 1, 518400, 0x3c4bd7eb
0, 28, 28, 1, 518400, 0x912ee227
0, 30, 30, 1, 518400, 0xb67d0e27
0, 31, 31, 1, 518400, 0x8cf7309d
0, 32, 32, 1, 518400, 0x358ad344
0, 33, 33, 1, 518400, 0x4462c642
0, 35, 35, 1, 518400, 0x3bb43428
0, 37, 37, 1, 518400, 0x12d6f8ca
0, 39, 39, 1, 518400, 0x003f13aa
0, 40, 40, 1, 518400, 0x6cd8c432
0, 41, 41, 1, 518400, 0xee5ff01b
0, 43, 43, 1, 518400, 0xba0616ee
0, 44, 44, 1, 518400, 0x37fa7891
0, 0, 0, 1, 518400, 0xd8b58a23
0, 1, 1, 1, 518400, 0xe53b4aba
0, 2, 2, 1, 518400, 0x6cbca47a
0, 3, 3, 1, 518400, 0xceb51253
0, 4, 4, 1, 518400, 0x60cb3cdd
0, 5, 5, 1, 518400, 0x7b633553
0, 6, 6, 1, 518400, 0x10c012c9
0, 7, 7, 1, 518400, 0xa340ee20
0, 8, 8, 1, 518400, 0x574c22c2
0, 9, 9, 1, 518400, 0xbcdb1bf7
0, 10, 10, 1, 518400, 0x57811e9a
0, 11, 11, 1, 518400, 0xdd4af748
0, 12, 12, 1, 518400, 0xb931a637
0, 13, 13, 1, 518400, 0xcef6ce95
0, 14, 14, 1, 518400, 0xd28c7085
0, 15, 15, 1, 518400, 0xae9daf53
0, 16, 16, 1, 518400, 0xca29d819
0, 17, 17, 1, 518400, 0x3c4bd7eb
0, 18, 18, 1, 518400, 0x912ee227
0, 19, 19, 1, 518400, 0xb67d0e27
0, 20, 20, 1, 518400, 0x8cf7309d
0, 21, 21, 1, 518400, 0x358ad344
0, 22, 22, 1, 518400, 0x4462c642
0, 23, 23, 1, 518400, 0x3bb43428
0, 24, 24, 1, 518400, 0x12d6f8ca
0, 25, 25, 1, 518400, 0x003f13aa
0, 26, 26, 1, 518400, 0x6cd8c432
0, 27, 27, 1, 518400, 0xee5ff01b
0, 28, 28, 1, 518400, 0xba0616ee
0, 29, 29, 1, 518400, 0x37fa7891
Loading

0 comments on commit 74b961d

Please sign in to comment.