summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/isom.h1
-rw-r--r--libavformat/mov.c16
2 files changed, 15 insertions, 2 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 5caf42b15d..99408a42d1 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -214,6 +214,7 @@ typedef struct MOVStreamContext {
int has_palette;
int64_t data_size;
uint32_t tmcd_flags; ///< tmcd track flags
+ uint8_t tmcd_nb_frames; ///< tmcd number of frames per tick / second
int64_t track_end; ///< used for dts generation in fragmented movie files
int start_pad; ///< amount of samples to skip due to enc-dec delay
unsigned int rap_group_count;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 6c847de164..4db4ded101 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2364,6 +2364,7 @@ static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
tmcd_ctx->tmcd_flags = val;
st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
+ tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
if (size > 30) {
uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
uint32_t format = AV_RB32(st->codecpar->extradata + 22);
@@ -7848,7 +7849,7 @@ finish:
}
static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
- uint32_t value, int flags)
+ int64_t value, int flags)
{
AVTimecode tc;
char buf[AV_TIMECODE_STR_SIZE];
@@ -7893,11 +7894,16 @@ static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
FFStream *const sti = ffstream(st);
int flags = 0;
int64_t cur_pos = avio_tell(sc->pb);
- uint32_t value;
+ int64_t value;
+ AVRational tc_rate = st->avg_frame_rate;
+ int rounded_tc_rate;
if (!sti->nb_index_entries)
return -1;
+ if (!tc_rate.num || !tc_rate.den || !sc->tmcd_nb_frames)
+ return -1;
+
avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
value = avio_rb32(s->pb);
@@ -7910,6 +7916,12 @@ static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
* No sample with tmcd track can be found with a QT timecode at the moment,
* despite what the tmcd track "suggests" (Counter flag set to 0 means QT
* format). */
+
+ /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
+ * we multiply the frame number with the quotient. */
+ rounded_tc_rate = (tc_rate.num + tc_rate.den / 2) / tc_rate.den;
+ value = av_rescale(value, rounded_tc_rate, sc->tmcd_nb_frames);
+
parse_timecode_in_framenum_format(s, st, value, flags);
avio_seek(sc->pb, cur_pos, SEEK_SET);