diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b0ec18a49c..f38ad2bdb7 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -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 */ diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 149094a5b4..4d1d3f35e2 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -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; diff --git a/libavformat/utils.c b/libavformat/utils.c index 0b036f48a0..1804167e2d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -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); }