Re: [libav-devel] [PATCH] make parsers' repeat_pict consistent with decoders

2011-08-26 Thread John Stebbins
Hi,

On 08/26/2011 12:55 PM, Vladimir Pantelic wrote:
> On 08/26/2011 05:43 PM, John Stebbins wrote:
>> Hi,
>>
>> On 08/26/2011 05:48 AM, Vladimir Pantelic wrote:
> 
>>> int ticks = st->st->codec->ticks_per_frame + (ist->st->parser ? 
>>> ist->st->parser->repeat_pict : 0);
>>>
>>
>> Well, after all that, I did some more code reading and spelunking of mailing 
>> list archives and discovered
>> the reason that the code is the way it is.  The decoders define repeat_pict 
>> == 0 to mean one frame time because
>> a decoder always returns frames.  The parser defines repeat_pict == 0 to 
>> mean one field time because
>> the parser can return after parsing only a field.  So when the parser sees a 
>> frame, it must add 1
>> to repeat pict so that the caller can distinguish field from frame.  I think 
>> this is rather obtuse, but
>> it is what it is.  Is anybody in favor of adding a field to 
>> AVCodecParserContext to explicitly flag field
>> vs. frame?  This option was discussed and rejected in the original mailing 
>> list discussion.
>> This was all discussed in the context of this thread back in feb 2009.
>>
>> http://thread.gmane.org/gmane.comp.video.ffmpeg.devel/84007/focus=84344
>>
> 
> then maybe at least add some comment lines, otherwise somebody else
> will "discover" that again in 2013...
> 

I'll throw together a patch that improves the comments in avcodec.h for now.

Longer term, I'm investigating what it would take to do this right so it works
correctly with h.264 VFR video.  The code currently makes assumptions all
over the place that ticks per field == 1 (when there can be fields) and that
ticks_per_frame == ticks per field + 1. It should instead assume that
ticks_per_frame can be anything and that ticks per field == ticks_per_frame / 2.

I can do this using the current definitions of repeat_pict, or I can add
a flag that explicitly signals when the parser is outputting a field.
I prefer that latter since it removes the obfuscation and provides
additional information that might actually be useful.  But I would
like some opinions before I continue with that.

Changing those incorrect assumptions means code that does this:
duration = time_base
if (repeat_pict)
duration *= (1 + repeat_pict)

must become (if we keep the current definitions of repeat_pict)
duration = (1 + repeat_pict) * time_base * ticks_per_frame / 
((ticks_per_frame > 1) + 1)

or if we used a field flag to designate fields vs frames:
duration = (1 + !field + repeat_pict) * time_base * ticks_per_frame / 
((ticks_per_frame > 1) + 1)

This satisfies the case where there are fields and ticks_per_frame > 1.  
repeat_pict specifies the
number of additional field times.

And it satisfies the case where there are not fields and ticks_per_frame == 1.  
repeat_pict specifies
the number of additional frame times.



signature.asc
Description: OpenPGP digital signature
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [PATCH] make parsers' repeat_pict consistent with decoders

2011-08-26 Thread Vladimir Pantelic

On 08/26/2011 05:43 PM, John Stebbins wrote:

Hi,

On 08/26/2011 05:48 AM, Vladimir Pantelic wrote:



int ticks = st->st->codec->ticks_per_frame + (ist->st->parser ? 
ist->st->parser->repeat_pict : 0);



Well, after all that, I did some more code reading and spelunking of mailing 
list archives and discovered
the reason that the code is the way it is.  The decoders define repeat_pict == 
0 to mean one frame time because
a decoder always returns frames.  The parser defines repeat_pict == 0 to mean 
one field time because
the parser can return after parsing only a field.  So when the parser sees a 
frame, it must add 1
to repeat pict so that the caller can distinguish field from frame.  I think 
this is rather obtuse, but
it is what it is.  Is anybody in favor of adding a field to 
AVCodecParserContext to explicitly flag field
vs. frame?  This option was discussed and rejected in the original mailing list 
discussion.
This was all discussed in the context of this thread back in feb 2009.

http://thread.gmane.org/gmane.comp.video.ffmpeg.devel/84007/focus=84344



then maybe at least add some comment lines, otherwise somebody else
will "discover" that again in 2013...

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [PATCH] make parsers' repeat_pict consistent with decoders

2011-08-26 Thread John Stebbins
Hi,

On 08/26/2011 05:48 AM, Vladimir Pantelic wrote:
> John Stebbins wrote:
>> On 08/25/2011 07:45 PM, John Stebbins wrote:
>>>  As we discussed on IRC this morning, this makes the value of repeat_pict 
>>> returned
>>>  by the parsers the same as the value returned by the decoders.
>>>
>>>  The parser was returning a value for repeat_pict that was the
>>>  actual number of repeats + 1.
>>>
>>>  Passes fate with the exception of 1 pre-existing failure 
>>> (fate-h264-conformance-mr3_tandberg_b).
>>
>> Heh, fate passed, but some samples I have that use pulldown didn't play
>> smoothly with avplay.  One line fix in compute_frame_duration.
>>
>>
> 
> @@ -1589,7 +1589,7 @@ static int output_packet(InputStream *ist, int 
> ist_index,
>  }
>  ist->next_pts = ist->pts = 
> guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts);
>  if (ist->st->codec->time_base.num != 0) {
> -int ticks= ist->st->parser ? 
> ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
> +int ticks= ist->st->parser ? 
> ist->st->parser->repeat_pict+ist->st->codec->ticks_per_frame :
> +   ist->st->codec->ticks_per_frame;
> 
> int ticks = st->st->codec->ticks_per_frame + (ist->st->parser ? 
> ist->st->parser->repeat_pict : 0);
> 

Well, after all that, I did some more code reading and spelunking of mailing 
list archives and discovered
the reason that the code is the way it is.  The decoders define repeat_pict == 
0 to mean one frame time because
a decoder always returns frames.  The parser defines repeat_pict == 0 to mean 
one field time because
the parser can return after parsing only a field.  So when the parser sees a 
frame, it must add 1
to repeat pict so that the caller can distinguish field from frame.  I think 
this is rather obtuse, but
it is what it is.  Is anybody in favor of adding a field to 
AVCodecParserContext to explicitly flag field
vs. frame?  This option was discussed and rejected in the original mailing list 
discussion.
This was all discussed in the context of this thread back in feb 2009.

http://thread.gmane.org/gmane.comp.video.ffmpeg.devel/84007/focus=84344

On a related note, the timebase for h.264 isn't limited to framerate and 
framerate/2.
When the vui fixed_frame_rate flag is not set (VFR content), timebase can be 
anything that
evenly divides the framerate.  Thus ticks_per_frame should be framerate / 
timebase.
And timebase shouldn't really be multiplied by 2 unconditionally.  FYI, 
handbrake
generates such files by default.



signature.asc
Description: OpenPGP digital signature
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [PATCH] make parsers' repeat_pict consistent with decoders

2011-08-26 Thread Vladimir Pantelic

John Stebbins wrote:

On 08/25/2011 07:45 PM, John Stebbins wrote:

 As we discussed on IRC this morning, this makes the value of repeat_pict 
returned
 by the parsers the same as the value returned by the decoders.

 The parser was returning a value for repeat_pict that was the
 actual number of repeats + 1.

 Passes fate with the exception of 1 pre-existing failure 
(fate-h264-conformance-mr3_tandberg_b).


Heh, fate passed, but some samples I have that use pulldown didn't play
smoothly with avplay.  One line fix in compute_frame_duration.




@@ -1589,7 +1589,7 @@ static int output_packet(InputStream *ist, int ist_index,
 }
 ist->next_pts = ist->pts = 
guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts);
 if (ist->st->codec->time_base.num != 0) {
-int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : 
ist->st->codec->ticks_per_frame;
+int ticks= ist->st->parser ? 
ist->st->parser->repeat_pict+ist->st->codec->ticks_per_frame :
+   ist->st->codec->ticks_per_frame;

int ticks = st->st->codec->ticks_per_frame + (ist->st->parser ? 
ist->st->parser->repeat_pict : 0);

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [PATCH] make parsers' repeat_pict consistent with decoders

2011-08-25 Thread John Stebbins
On 08/25/2011 07:45 PM, John Stebbins wrote:
> As we discussed on IRC this morning, this makes the value of repeat_pict 
> returned
> by the parsers the same as the value returned by the decoders.
> 
> The parser was returning a value for repeat_pict that was the
> actual number of repeats + 1.
> 
> Passes fate with the exception of 1 pre-existing failure 
> (fate-h264-conformance-mr3_tandberg_b).

Heh, fate passed, but some samples I have that use pulldown didn't play
smoothly with avplay.  One line fix in compute_frame_duration.

From dd49f30e1fdf33c06f530da102a3e968c1a1bb7c Mon Sep 17 00:00:00 2001
From: John Stebbins 
Date: Thu, 25 Aug 2011 22:26:14 -0700
Subject: [PATCH] make parsers' repeat_pict consistent with decoders

The parser was returning a value for repeat_pict that was the
actual number of repeats + 1.
---
 avconv.c  |4 ++--
 libavcodec/h264_parser.c  |   25 ++---
 libavcodec/mpegvideo_parser.c |9 +
 libavcodec/vc1_parser.c   |   19 ---
 libavformat/utils.c   |4 ++--
 5 files changed, 27 insertions(+), 34 deletions(-)

diff --git a/avconv.c b/avconv.c
index 57721f8..62951fa 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1589,7 +1589,7 @@ static int output_packet(InputStream *ist, int ist_index,
 }
 ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts);
 if (ist->st->codec->time_base.num != 0) {
-int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
+int ticks= ist->st->parser ? ist->st->parser->repeat_pict+ist->st->codec->ticks_per_frame : ist->st->codec->ticks_per_frame;
 ist->next_pts += ((int64_t)AV_TIME_BASE *
   ist->st->codec->time_base.num * ticks) /
 ist->st->codec->time_base.den;
@@ -1620,7 +1620,7 @@ static int output_packet(InputStream *ist, int ist_index,
 break;
 case AVMEDIA_TYPE_VIDEO:
 if (ist->st->codec->time_base.num != 0) {
-int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
+int ticks= ist->st->parser ? ist->st->parser->repeat_pict+ist->st->codec->ticks_per_frame : ist->st->codec->ticks_per_frame;
 ist->next_pts += ((int64_t)AV_TIME_BASE *
   ist->st->codec->time_base.num * ticks) /
 ist->st->codec->time_base.den;
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 5610269..050d30f 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -119,6 +119,7 @@ static inline int parse_nal_units(AVCodecParserContext *s,
 /* set some sane default values */
 s->pict_type = AV_PICTURE_TYPE_I;
 s->key_frame = 0;
+s->repeat_pict = 0;
 
 h->s.avctx= avctx;
 h->sei_recovery_frame_cnt = -1;
@@ -202,31 +203,25 @@ static inline int parse_nal_units(AVCodecParserContext *s,
 
 if(h->sps.pic_struct_present_flag) {
 switch (h->sei_pic_struct) {
-case SEI_PIC_STRUCT_TOP_FIELD:
-case SEI_PIC_STRUCT_BOTTOM_FIELD:
-s->repeat_pict = 0;
-break;
-case SEI_PIC_STRUCT_FRAME:
-case SEI_PIC_STRUCT_TOP_BOTTOM:
-case SEI_PIC_STRUCT_BOTTOM_TOP:
-s->repeat_pict = 1;
-break;
 case SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
 case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
-s->repeat_pict = 2;
+s->repeat_pict = 1;
 break;
 case SEI_PIC_STRUCT_FRAME_DOUBLING:
-s->repeat_pict = 3;
+s->repeat_pict = 2;
 break;
 case SEI_PIC_STRUCT_FRAME_TRIPLING:
-s->repeat_pict = 5;
+s->repeat_pict = 3;
 break;
+case SEI_PIC_STRUCT_TOP_FIELD:
+case SEI_PIC_STRUCT_BOTTOM_FIELD:
+case SEI_PIC_STRUCT_FRAME:
+case SEI_PIC_STRUCT_TOP_BOTTOM:
+case SEI_PIC_STRUCT_BOTTOM_TOP:
 default:
-s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 1 : 0;
+s->repeat_pict = 0;
 break;
 }
-} else {
-s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 1 : 0;
 }
 
 return 0; /* no need to evaluate the rest */
diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_pars