From 46a7e3ec14941fb363a95c37ec10083a2730e9e8 Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Mon, 9 Mar 2009 00:14:55 +0000 Subject: write timecode track in gxf Originally committed as revision 17890 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/gxfenc.c | 91 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 26 deletions(-) (limited to 'libavformat/gxfenc.c') diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 142342239f..710b1dfa6f 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -58,6 +58,7 @@ typedef struct GXFContext { uint16_t umf_media_size; int sample_rate; int flags; + GXFStreamContext timecode_track; } GXFContext; typedef struct GXF_Lines { @@ -198,7 +199,6 @@ static int gxf_write_mpeg_auxiliary(ByteIOContext *pb, AVStream *st) static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *sc) { - /* FIXME implement that */ put_byte(pb, 0); /* fields */ put_byte(pb, 0); /* seconds */ put_byte(pb, 0); /* minutes */ @@ -208,14 +208,15 @@ static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *sc) return 8; } -static int gxf_write_track_description(ByteIOContext *pb, AVStream *st) +static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, int index) { - GXFStreamContext *sc = st->priv_data; + ByteIOContext *pb = s->pb; int64_t pos; + int mpeg = sc->track_type == 4 || sc->track_type == 9; /* track description section */ put_byte(pb, sc->media_type + 0x80); - put_byte(pb, st->index + 0xC0); + put_byte(pb, index + 0xC0); pos = url_ftell(pb); put_be16(pb, 0); /* size */ @@ -227,11 +228,11 @@ static int gxf_write_track_description(ByteIOContext *pb, AVStream *st) put_be16(pb, sc->media_info); put_byte(pb, 0); - if (st->codec->codec_id != CODEC_ID_MPEG2VIDEO) { + if (!mpeg) { /* auxiliary information */ put_byte(pb, TRACK_AUX); put_byte(pb, 8); - if (st->codec->codec_id == CODEC_ID_NONE) + if (sc->track_type == 3) gxf_write_timecode_auxiliary(pb, sc); else put_le64(pb, 0); @@ -242,8 +243,8 @@ static int gxf_write_track_description(ByteIOContext *pb, AVStream *st) put_byte(pb, 4); put_be32(pb, 0); - if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) - gxf_write_mpeg_auxiliary(pb, st); + if (mpeg) + gxf_write_mpeg_auxiliary(pb, s->streams[index]); /* frame rate */ put_byte(pb, TRACK_FPS); @@ -313,6 +314,7 @@ static int gxf_write_material_data_section(AVFormatContext *s) static int gxf_write_track_description_section(AVFormatContext *s) { + GXFContext *gxf = s->priv_data; ByteIOContext *pb = s->pb; int64_t pos; int i; @@ -320,7 +322,10 @@ static int gxf_write_track_description_section(AVFormatContext *s) pos = url_ftell(pb); put_be16(pb, 0); /* size */ for (i = 0; i < s->nb_streams; ++i) - gxf_write_track_description(pb, s->streams[i]); + gxf_write_track_description(s, s->streams[i]->priv_data, i); + + gxf_write_track_description(s, &gxf->timecode_track, s->nb_streams); + return updateSize(pb, pos); } @@ -385,7 +390,7 @@ static int gxf_write_umf_material_description(AVFormatContext *s) put_le16(pb, 0); /* reserved */ put_le16(pb, 0); /* reserved */ put_le16(pb, gxf->audio_tracks); - put_le16(pb, 0); /* timecode track count */ + put_le16(pb, 1); /* timecode track count */ put_le16(pb, 0); /* reserved */ put_le16(pb, gxf->mpeg_tracks); return 48; @@ -398,10 +403,10 @@ static int gxf_write_umf_payload(AVFormatContext *s) put_le32(pb, gxf->umf_length); /* total length of the umf data */ put_le32(pb, 3); /* version */ - put_le32(pb, s->nb_streams); + put_le32(pb, s->nb_streams+1); put_le32(pb, gxf->umf_track_offset); /* umf track section offset */ put_le32(pb, gxf->umf_track_size); - put_le32(pb, s->nb_streams); + put_le32(pb, s->nb_streams+1); put_le32(pb, gxf->umf_media_offset); put_le32(pb, gxf->umf_media_size); put_le32(pb, gxf->umf_length); /* user data offset */ @@ -424,6 +429,10 @@ static int gxf_write_umf_track_description(AVFormatContext *s) put_le16(pb, sc->media_info); put_le16(pb, 1); } + + put_le16(pb, gxf->timecode_track.media_info); + put_le16(pb, 1); + return url_ftell(pb) - pos; } @@ -452,15 +461,14 @@ static int gxf_write_umf_media_mpeg(ByteIOContext *pb, AVStream *st) static int gxf_write_umf_media_timecode(ByteIOContext *pb, GXFStreamContext *sc) { - /* FIXME implement */ - put_be32(pb, 0); /* drop frame flag */ - put_be32(pb, 0); /* reserved */ - put_be32(pb, 0); /* reserved */ - put_be32(pb, 0); /* reserved */ - put_be32(pb, 0); /* reserved */ - put_be32(pb, 0); /* reserved */ - put_be32(pb, 0); /* reserved */ - put_be32(pb, 0); /* reserved */ + put_le32(pb, 1); /* non drop frame */ + put_le32(pb, 0); /* reserved */ + put_le32(pb, 0); /* reserved */ + put_le32(pb, 0); /* reserved */ + put_le32(pb, 0); /* reserved */ + put_le32(pb, 0); /* reserved */ + put_le32(pb, 0); /* reserved */ + put_le32(pb, 0); /* reserved */ return 32; } @@ -505,13 +513,17 @@ static int gxf_write_umf_media_description(AVFormatContext *s) pos = url_ftell(pb); gxf->umf_media_offset = pos - gxf->umf_start_offset; - for (i = 0; i < s->nb_streams; ++i) { - AVStream *st = s->streams[i]; - GXFStreamContext *sc = st->priv_data; + for (i = 0; i <= s->nb_streams; ++i) { + GXFStreamContext *sc; char buffer[88]; int64_t startpos, curpos; int path_size = strlen(ES_NAME_PATTERN); + if (i == s->nb_streams) + sc = &gxf->timecode_track; + else + sc = s->streams[i]->priv_data; + memset(buffer, 0, 88); startpos = url_ftell(pb); put_le16(pb, 0); /* length */ @@ -530,6 +542,11 @@ static int gxf_write_umf_media_description(AVFormatContext *s) put_le32(pb, sc->sample_rate); put_le32(pb, sc->sample_size); put_le32(pb, 0); /* reserved */ + + if (sc == &gxf->timecode_track) + gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */ + else { + AVStream *st = s->streams[i]; switch (st->codec->codec_id) { case CODEC_ID_MPEG2VIDEO: gxf_write_umf_media_mpeg(pb, st); @@ -540,9 +557,9 @@ static int gxf_write_umf_media_description(AVFormatContext *s) case CODEC_ID_DVVIDEO: gxf_write_umf_media_dv(pb, sc); break; - default: - gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */ } + } + curpos = url_ftell(pb); url_fseek(pb, startpos, SEEK_SET); put_le16(pb, curpos - startpos); @@ -574,10 +591,26 @@ static int gxf_write_umf_packet(AVFormatContext *s) static const int GXF_samples_per_frame[] = { 32768, 0 }; +static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc) +{ + if (!vsc) + return; + + sc->media_type = vsc->sample_rate == 60 ? 7 : 8; + sc->sample_rate = vsc->sample_rate; + sc->media_info = ('T'<<8) | '0'; + sc->track_type = 3; + sc->frame_rate_index = vsc->frame_rate_index; + sc->lines_index = vsc->lines_index; + sc->sample_size = 16; + sc->fields = vsc->fields; +} + static int gxf_write_header(AVFormatContext *s) { ByteIOContext *pb = s->pb; GXFContext *gxf = s->priv_data; + GXFStreamContext *vsc = NULL; uint8_t tracks[255] = {0}; int i, media_info = 0; @@ -631,6 +664,9 @@ static int gxf_write_header(AVFormatContext *s) sc->lines_index = -1; sc->sample_size = st->codec->bit_rate; sc->fields = 2; /* interlaced */ + + vsc = sc; + switch (st->codec->codec_id) { case CODEC_ID_MJPEG: sc->track_type = 1; @@ -673,6 +709,9 @@ static int gxf_write_header(AVFormatContext *s) if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0) return -1; + gxf_init_timecode_track(&gxf->timecode_track, vsc); + gxf->flags |= 0x200000; // time code track is non-drop frame + gxf_write_map_packet(s); //gxf_write_flt_packet(s); gxf_write_umf_packet(s); -- cgit v1.2.3