|
|
|
@ -4676,6 +4676,31 @@ static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st) |
|
|
|
|
{ |
|
|
|
|
MOVStreamContext *sc = st->priv_data; |
|
|
|
|
char buf[AV_TIMECODE_STR_SIZE]; |
|
|
|
|
int64_t cur_pos = avio_tell(sc->pb); |
|
|
|
|
int hh, mm, ss, ff, drop; |
|
|
|
|
|
|
|
|
|
if (!st->nb_index_entries) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
avio_seek(sc->pb, st->index_entries->pos, SEEK_SET); |
|
|
|
|
avio_skip(s->pb, 13); |
|
|
|
|
hh = avio_r8(s->pb); |
|
|
|
|
mm = avio_r8(s->pb); |
|
|
|
|
ss = avio_r8(s->pb); |
|
|
|
|
drop = avio_r8(s->pb); |
|
|
|
|
ff = avio_r8(s->pb); |
|
|
|
|
snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d", |
|
|
|
|
hh, mm, ss, drop ? ';' : ':', ff); |
|
|
|
|
av_dict_set(&st->metadata, "timecode", buf, 0); |
|
|
|
|
|
|
|
|
|
avio_seek(sc->pb, cur_pos, SEEK_SET); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mov_read_timecode_track(AVFormatContext *s, AVStream *st) |
|
|
|
|
{ |
|
|
|
|
MOVStreamContext *sc = st->priv_data; |
|
|
|
@ -4954,8 +4979,11 @@ static int mov_read_header(AVFormatContext *s) |
|
|
|
|
if (mov->chapter_track > 0 && !mov->ignore_chapters) |
|
|
|
|
mov_read_chapters(s); |
|
|
|
|
for (i = 0; i < s->nb_streams; i++) |
|
|
|
|
if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) |
|
|
|
|
if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) { |
|
|
|
|
mov_read_timecode_track(s, s->streams[i]); |
|
|
|
|
} else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) { |
|
|
|
|
mov_read_rtmd_track(s, s->streams[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* copy timecode metadata from tmcd tracks to the related video streams */ |
|
|
|
|