Use context variable repeat_pict for frame duration computation and
authorIvan Schreter <schreter@gmx.net>
Sat, 21 Feb 2009 20:11:47 +0000 (20:11 +0000)
committerCarl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at>
Sat, 21 Feb 2009 20:11:47 +0000 (20:11 +0000)
document this new use.

Patch by Ivan Schreter, schreter gmx net

Originally committed as revision 17492 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/avcodec.h
libavcodec/h264_parser.c
libavformat/utils.c

index b0ec18a..f38ad2b 100644 (file)
@@ -3005,6 +3005,18 @@ typedef struct AVCodecParserContext {
     int64_t next_frame_offset; /* offset of the next frame */
     /* video info */
     int pict_type; /* XXX: Put it back in AVCodecContext. */
+    /**
+     * This field is used for proper frame duration computation in lavf.
+     * It signals, how much longer the frame duration of the current frame
+     * is compared to normal frame duration.
+     *
+     * frame_duration = (2 + repeat_pict) / (2*fps)
+     *
+     * It is used by codecs like H.264 to display telecined material.
+     *
+     * @note This field can also be set to -1 for half-frame duration in case
+     *       of field pictures.
+     */
     int repeat_pict; /* XXX: Put it back in AVCodecContext. */
     int64_t pts;     /* pts of the current frame */
     int64_t dts;     /* dts of the current frame */
index 149094a..4d1d3f3 100644 (file)
@@ -192,6 +192,35 @@ 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 = -1;
+                        break;
+                    case SEI_PIC_STRUCT_FRAME:
+                    case SEI_PIC_STRUCT_TOP_BOTTOM:
+                    case SEI_PIC_STRUCT_BOTTOM_TOP:
+                        s->repeat_pict = 0;
+                        break;
+                    case SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
+                    case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
+                        s->repeat_pict = 1;
+                        break;
+                    case SEI_PIC_STRUCT_FRAME_DOUBLING:
+                        s->repeat_pict = 2;
+                        break;
+                    case SEI_PIC_STRUCT_FRAME_TRIPLING:
+                        s->repeat_pict = 4;
+                        break;
+                    default:
+                        s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 0 : -1;
+                        break;
+                }
+            } else {
+                s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 0 : -1;
+            }
+
             return 0; /* no need to evaluate the rest */
         }
         buf += consumed;
index 0b036f4..1804167 100644 (file)
@@ -680,6 +680,8 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st,
             *pnum = st->codec->time_base.num;
             *pden = st->codec->time_base.den;
             if (pc && pc->repeat_pict) {
+                // NOTE: repeat_pict can be also -1 for half-frame durations,
+                // e.g., in H.264 interlaced field picture stream
                 *pden *= 2;
                 *pnum = (*pnum) * (2 + pc->repeat_pict);
             }