]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/movenc.c
ARM: dca: disable optimised decode_blockcodes() for old gcc
[ffmpeg] / libavformat / movenc.c
index 5f4eea49fc8c3a9a9ab61b700097301cd444dd0f..d1076c34c49b638ba9c5edf9a42c04a90039cba9 100644 (file)
 #include "libavcodec/put_bits.h"
 #include "internal.h"
 #include "libavutil/avstring.h"
+#include "libavutil/intfloat.h"
+#include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/dict.h"
+#include "rtpenc.h"
+#include "mov_chan.h"
 
 #undef NDEBUG
 #include <assert.h>
 
 static const AVOption options[] = {
-    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), FF_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
-    { "rtphint", "Add RTP hint tracks", 0, FF_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
     { NULL },
 };
 
-static const AVClass mov_muxer_class = {
-    .class_name = "MOV/3GP/MP4/3G2 muxer",
-    .item_name  = av_default_item_name,
-    .option     = options,
-    .version    = LIBAVUTIL_VERSION_INT,
+#define MOV_CLASS(flavor)\
+static const AVClass flavor ## _muxer_class = {\
+    .class_name = #flavor " muxer",\
+    .item_name  = av_default_item_name,\
+    .option     = options,\
+    .version    = LIBAVUTIL_VERSION_INT,\
 };
 
 //FIXME support 64 bit variant with wide placeholders
@@ -204,7 +210,7 @@ static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
     avio_wb32(pb, 11);
     ffio_wfourcc(pb, "dac3");
 
-    init_get_bits(&gbc, track->vosData+4, track->vosLen-4);
+    init_get_bits(&gbc, track->vosData+4, (track->vosLen-4) * 8);
     fscod      = get_bits(&gbc, 2);
     frmsizecod = get_bits(&gbc, 6);
     bsid       = get_bits(&gbc, 5);
@@ -237,7 +243,7 @@ static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track)
 
 /**
  * This function writes extradata "as is".
- * Extradata must be formated like a valid atom (with size and tag)
+ * Extradata must be formatted like a valid atom (with size and tag).
  */
 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
 {
@@ -333,6 +339,31 @@ static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
     return updateSize(pb, pos);
 }
 
+static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track)
+{
+    uint32_t layout_tag, bitmap;
+    int64_t pos = avio_tell(pb);
+
+    layout_tag = ff_mov_get_channel_layout_tag(track->enc->codec_id,
+                                               track->enc->channel_layout,
+                                               &bitmap);
+    if (!layout_tag) {
+        av_log(track->enc, AV_LOG_WARNING, "not writing 'chan' tag due to "
+               "lack of channel information\n");
+        return 0;
+    }
+
+    avio_wb32(pb, 0);           // Size
+    ffio_wfourcc(pb, "chan");   // Type
+    avio_w8(pb, 0);             // Version
+    avio_wb24(pb, 0);           // Flags
+    avio_wb32(pb, layout_tag);  // mChannelLayoutTag
+    avio_wb32(pb, bitmap);      // mChannelBitmap
+    avio_wb32(pb, 0);           // mNumberChannelDescriptions
+
+    return updateSize(pb, pos);
+}
+
 static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
@@ -355,6 +386,7 @@ static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
     } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
         mov_write_amr_tag(pb, track);
     } else if (track->enc->codec_id == CODEC_ID_AC3) {
+        mov_write_chan_tag(pb, track);
         mov_write_ac3_tag(pb, track);
     } else if (track->enc->codec_id == CODEC_ID_ALAC) {
         mov_write_extradata_tag(pb, track);
@@ -413,15 +445,9 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
     uint32_t tag = track->tag;
 
     if (track->mode == MODE_MOV) {
-        if (track->timescale > UINT16_MAX) {
-            if (mov_get_lpcm_flags(track->enc->codec_id))
-                tag = AV_RL32("lpcm");
-            version = 2;
-        } else if (track->audio_vbr || mov_pcm_le_gt16(track->enc->codec_id) ||
-                   track->enc->codec_id == CODEC_ID_ADPCM_MS ||
-                   track->enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
-            version = 1;
-        }
+        if (mov_get_lpcm_flags(track->enc->codec_id))
+            tag = AV_RL32("lpcm");
+        version = 2;
     }
 
     avio_wb32(pb, 0); /* size */
@@ -442,40 +468,24 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track)
         avio_wb16(pb, 0);
         avio_wb32(pb, 0x00010000);
         avio_wb32(pb, 72);
-        avio_wb64(pb, av_dbl2int(track->timescale));
+        avio_wb64(pb, av_double2int(track->timescale));
         avio_wb32(pb, track->enc->channels);
         avio_wb32(pb, 0x7F000000);
         avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
         avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
         avio_wb32(pb, track->sampleSize);
-        avio_wb32(pb, track->enc->frame_size);
+        avio_wb32(pb, track->audio_vbr ? track->enc->frame_size : 1);
     } else {
-        if (track->mode == MODE_MOV) {
-            avio_wb16(pb, track->enc->channels);
-            if (track->enc->codec_id == CODEC_ID_PCM_U8 ||
-                track->enc->codec_id == CODEC_ID_PCM_S8)
-                avio_wb16(pb, 8); /* bits per sample */
-            else
-                avio_wb16(pb, 16);
-            avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
-        } else { /* reserved for mp4/3gp */
-            avio_wb16(pb, 2);
-            avio_wb16(pb, 16);
-            avio_wb16(pb, 0);
-        }
+        /* reserved for mp4/3gp */
+        avio_wb16(pb, 2);
+        avio_wb16(pb, 16);
+        avio_wb16(pb, 0);
 
         avio_wb16(pb, 0); /* packet size (= 0) */
         avio_wb16(pb, track->timescale); /* Time scale */
         avio_wb16(pb, 0); /* Reserved */
     }
 
-    if(version == 1) { /* SoundDescription V1 extended info */
-        avio_wb32(pb, track->enc->frame_size); /* Samples per packet */
-        avio_wb32(pb, track->sampleSize / track->enc->channels); /* Bytes per packet */
-        avio_wb32(pb, track->sampleSize); /* Bytes per frame */
-        avio_wb32(pb, 2); /* Bytes per sample */
-    }
-
     if(track->mode == MODE_MOV &&
        (track->enc->codec_id == CODEC_ID_AAC ||
         track->enc->codec_id == CODEC_ID_AC3 ||
@@ -707,7 +717,7 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
             if (!tag) { // if no mac fcc found, try with Microsoft tags
                 tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id);
                 if (tag)
-                    av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, "
+                    av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
                            "the file may be unplayable!\n");
             }
         } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -716,7 +726,7 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
                 int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id);
                 if (ms_tag) {
                     tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
-                    av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, "
+                    av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
                            "the file may be unplayable!\n");
                 }
             }
@@ -1212,7 +1222,8 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
 
     avio_wb32(pb, 0); /* reserved */
     avio_wb32(pb, 0); /* reserved */
-    avio_wb32(pb, 0x0); /* reserved (Layer & Alternate group) */
+    avio_wb16(pb, 0); /* layer */
+    avio_wb16(pb, st ? st->codec->codec_type : 0); /* alternate group) */
     /* Volume, only for audio */
     if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
         avio_wb16(pb, 0x0100);
@@ -1275,7 +1286,7 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
     avio_wb32(pb, track->enc->height << 16);
 
     return updateSize(pb, pos);
-};
+}
 
 // This box seems important for the psp playback ... without it the movie seems to hang
 static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)
@@ -1354,12 +1365,12 @@ static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov)
     return 0x34;
 }
 
-static int mov_write_udta_sdp(AVIOContext *pb, AVCodecContext *ctx, int index)
+static int mov_write_udta_sdp(AVIOContext *pb, AVFormatContext *ctx, int index)
 {
     char buf[1000] = "";
     int len;
 
-    ff_sdp_write_media(buf, sizeof(buf), ctx, NULL, NULL, 0, 0);
+    ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0]->codec, NULL, NULL, 0, 0, ctx);
     av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", index);
     len = strlen(buf);
 
@@ -1387,7 +1398,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
     if (track->mode == MODE_PSP)
         mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
     if (track->tag == MKTAG('r','t','p',' '))
-        mov_write_udta_sdp(pb, track->rtp_ctx->streams[0]->codec, track->trackID);
+        mov_write_udta_sdp(pb, track->rtp_ctx, track->trackID);
     if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) {
         double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
         if (0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio)
@@ -1991,6 +2002,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     AVCodecContext *enc = trk->enc;
     unsigned int samplesInChunk = 0;
     int size= pkt->size;
+    uint8_t *reformatted_data = NULL;
 
     if (!s->pb->seekable) return 0; /* Can't handle that */
     if (!size) return 0; /* Discard 0 sized packets */
@@ -1998,7 +2010,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (enc->codec_id == CODEC_ID_AMR_NB) {
         /* We must find out how many AMR blocks there are in one packet */
         static uint16_t packed_size[16] =
-            {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
+            {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
         int len = 0;
 
         while (len < size && samplesInChunk < 100) {
@@ -2009,9 +2021,6 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
             return -1;
         }
-    } else if (enc->codec_id == CODEC_ID_ADPCM_MS ||
-               enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
-        samplesInChunk = enc->frame_size;
     } else if (trk->sampleSize)
         samplesInChunk = size/trk->sampleSize;
     else
@@ -2027,7 +2036,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
         /* from x264 or from bytestream h264 */
         /* nal reformating needed */
-        size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
+        if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
+            ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
+                                       &size);
+            avio_write(pb, reformatted_data, size);
+        } else {
+            size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
+        }
     } else {
         avio_write(pb, pkt->data, size);
     }
@@ -2082,7 +2097,9 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     avio_flush(pb);
 
     if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
-        ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry);
+        ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
+                                 reformatted_data, size);
+    av_free(reformatted_data);
     return 0;
 }
 
@@ -2098,7 +2115,7 @@ static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
     track->mode = mov->mode;
     track->tag = MKTAG('t','e','x','t');
     track->timescale = MOV_TIMESCALE;
-    track->enc = avcodec_alloc_context();
+    track->enc = avcodec_alloc_context3(NULL);
     track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
 
     for (i = 0; i < s->nb_chapters; i++) {
@@ -2125,6 +2142,7 @@ static int mov_write_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     MOVMuxContext *mov = s->priv_data;
+    AVDictionaryEntry *t;
     int i, hint_track = 0;
 
     if (!s->pb->seekable) {
@@ -2217,21 +2235,21 @@ static int mov_write_header(AVFormatContext *s)
                        "or choose different container.\n");
         }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
             track->timescale = st->codec->sample_rate;
-            if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
-                av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
-                goto error;
-            }else if(st->codec->codec_id == CODEC_ID_ADPCM_MS ||
-                     st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV){
+            /* set sampleSize for PCM and ADPCM */
+            if (av_get_bits_per_sample(st->codec->codec_id)) {
                 if (!st->codec->block_align) {
-                    av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
+                    av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set\n", i);
                     goto error;
                 }
                 track->sampleSize = st->codec->block_align;
-            }else if(st->codec->frame_size > 1){ /* assume compressed audio */
+            }
+            /* set audio_vbr for compressed audio */
+            if (av_get_bits_per_sample(st->codec->codec_id) < 8) {
+                if (!st->codec->frame_size) {
+                    av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
+                    goto error;
+                }
                 track->audio_vbr = 1;
-            }else{
-                st->codec->frame_size = 1;
-                track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
             }
             if (track->mode != MODE_MOV) {
                 if (track->timescale > UINT16_MAX) {
@@ -2251,11 +2269,19 @@ static int mov_write_header(AVFormatContext *s)
         if (!track->height)
             track->height = st->codec->height;
 
-        av_set_pts_info(st, 64, 1, track->timescale);
+        avpriv_set_pts_info(st, 64, 1, track->timescale);
     }
 
     mov_write_mdat_tag(pb, mov);
-    mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
+
+#if FF_API_TIMESTAMP
+    if (s->timestamp)
+        mov->time = s->timestamp;
+    else
+#endif
+    if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
+        mov->time = ff_iso8601_to_unix_time(t->value);
+    mov->time += 0x7C25B080; //1970 based -> 1904 based
 
     if (mov->chapter_track)
         mov_create_chapter_track(s, mov->chapter_track);
@@ -2324,104 +2350,118 @@ static int mov_write_trailer(AVFormatContext *s)
 }
 
 #if CONFIG_MOV_MUXER
+MOV_CLASS(mov)
 AVOutputFormat ff_mov_muxer = {
-    "mov",
-    NULL_IF_CONFIG_SMALL("MOV format"),
-    NULL,
-    "mov",
-    sizeof(MOVMuxContext),
-    CODEC_ID_AAC,
-    CODEC_ID_MPEG4,
-    mov_write_header,
-    ff_mov_write_packet,
-    mov_write_trailer,
+    .name              = "mov",
+    .long_name         = NULL_IF_CONFIG_SMALL("MOV format"),
+    .extensions        = "mov",
+    .priv_data_size    = sizeof(MOVMuxContext),
+    .audio_codec       = CODEC_ID_AAC,
+#if CONFIG_LIBX264_ENCODER
+    .video_codec       = CODEC_ID_H264,
+#else
+    .video_codec       = CODEC_ID_MPEG4,
+#endif
+    .write_header      = mov_write_header,
+    .write_packet      = ff_mov_write_packet,
+    .write_trailer     = mov_write_trailer,
     .flags = AVFMT_GLOBALHEADER,
     .codec_tag = (const AVCodecTag* const []){codec_movvideo_tags, codec_movaudio_tags, 0},
     .priv_class = &mov_muxer_class,
 };
 #endif
 #if CONFIG_TGP_MUXER
+MOV_CLASS(tgp)
 AVOutputFormat ff_tgp_muxer = {
-    "3gp",
-    NULL_IF_CONFIG_SMALL("3GP format"),
-    NULL,
-    "3gp",
-    sizeof(MOVMuxContext),
-    CODEC_ID_AMR_NB,
-    CODEC_ID_H263,
-    mov_write_header,
-    ff_mov_write_packet,
-    mov_write_trailer,
+    .name              = "3gp",
+    .long_name         = NULL_IF_CONFIG_SMALL("3GP format"),
+    .extensions        = "3gp",
+    .priv_data_size    = sizeof(MOVMuxContext),
+    .audio_codec       = CODEC_ID_AMR_NB,
+    .video_codec       = CODEC_ID_H263,
+    .write_header      = mov_write_header,
+    .write_packet      = ff_mov_write_packet,
+    .write_trailer     = mov_write_trailer,
     .flags = AVFMT_GLOBALHEADER,
     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
-    .priv_class = &mov_muxer_class,
+    .priv_class = &tgp_muxer_class,
 };
 #endif
 #if CONFIG_MP4_MUXER
+MOV_CLASS(mp4)
 AVOutputFormat ff_mp4_muxer = {
-    "mp4",
-    NULL_IF_CONFIG_SMALL("MP4 format"),
-    "application/mp4",
-    "mp4",
-    sizeof(MOVMuxContext),
-    CODEC_ID_AAC,
-    CODEC_ID_MPEG4,
-    mov_write_header,
-    ff_mov_write_packet,
-    mov_write_trailer,
+    .name              = "mp4",
+    .long_name         = NULL_IF_CONFIG_SMALL("MP4 format"),
+    .mime_type         = "application/mp4",
+    .extensions        = "mp4",
+    .priv_data_size    = sizeof(MOVMuxContext),
+    .audio_codec       = CODEC_ID_AAC,
+#if CONFIG_LIBX264_ENCODER
+    .video_codec       = CODEC_ID_H264,
+#else
+    .video_codec       = CODEC_ID_MPEG4,
+#endif
+    .write_header      = mov_write_header,
+    .write_packet      = ff_mov_write_packet,
+    .write_trailer     = mov_write_trailer,
     .flags = AVFMT_GLOBALHEADER,
     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
-    .priv_class = &mov_muxer_class,
+    .priv_class = &mp4_muxer_class,
 };
 #endif
 #if CONFIG_PSP_MUXER
+MOV_CLASS(psp)
 AVOutputFormat ff_psp_muxer = {
-    "psp",
-    NULL_IF_CONFIG_SMALL("PSP MP4 format"),
-    NULL,
-    "mp4,psp",
-    sizeof(MOVMuxContext),
-    CODEC_ID_AAC,
-    CODEC_ID_MPEG4,
-    mov_write_header,
-    ff_mov_write_packet,
-    mov_write_trailer,
+    .name              = "psp",
+    .long_name         = NULL_IF_CONFIG_SMALL("PSP MP4 format"),
+    .extensions        = "mp4,psp",
+    .priv_data_size    = sizeof(MOVMuxContext),
+    .audio_codec       = CODEC_ID_AAC,
+#if CONFIG_LIBX264_ENCODER
+    .video_codec       = CODEC_ID_H264,
+#else
+    .video_codec       = CODEC_ID_MPEG4,
+#endif
+    .write_header      = mov_write_header,
+    .write_packet      = ff_mov_write_packet,
+    .write_trailer     = mov_write_trailer,
     .flags = AVFMT_GLOBALHEADER,
     .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0},
-    .priv_class = &mov_muxer_class,
+    .priv_class = &psp_muxer_class,
 };
 #endif
 #if CONFIG_TG2_MUXER
+MOV_CLASS(tg2)
 AVOutputFormat ff_tg2_muxer = {
-    "3g2",
-    NULL_IF_CONFIG_SMALL("3GP2 format"),
-    NULL,
-    "3g2",
-    sizeof(MOVMuxContext),
-    CODEC_ID_AMR_NB,
-    CODEC_ID_H263,
-    mov_write_header,
-    ff_mov_write_packet,
-    mov_write_trailer,
+    .name              = "3g2",
+    .long_name         = NULL_IF_CONFIG_SMALL("3GP2 format"),
+    .extensions        = "3g2",
+    .priv_data_size    = sizeof(MOVMuxContext),
+    .audio_codec       = CODEC_ID_AMR_NB,
+    .video_codec       = CODEC_ID_H263,
+    .write_header      = mov_write_header,
+    .write_packet      = ff_mov_write_packet,
+    .write_trailer     = mov_write_trailer,
     .flags = AVFMT_GLOBALHEADER,
     .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0},
-    .priv_class = &mov_muxer_class,
+    .priv_class = &tg2_muxer_class,
 };
 #endif
 #if CONFIG_IPOD_MUXER
+MOV_CLASS(ipod)
 AVOutputFormat ff_ipod_muxer = {
-    "ipod",
-    NULL_IF_CONFIG_SMALL("iPod H.264 MP4 format"),
-    "application/mp4",
-    "m4v,m4a",
-    sizeof(MOVMuxContext),
-    CODEC_ID_AAC,
-    CODEC_ID_H264,
-    mov_write_header,
-    ff_mov_write_packet,
-    mov_write_trailer,
+    .name              = "ipod",
+    .long_name         = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 format"),
+    .mime_type         = "application/mp4",
+    .extensions        = "m4v,m4a",
+    .priv_data_size    = sizeof(MOVMuxContext),
+    .audio_codec       = CODEC_ID_AAC,
+    .video_codec       = CODEC_ID_H264,
+    .write_header      = mov_write_header,
+    .write_packet      = ff_mov_write_packet,
+    .write_trailer     = mov_write_trailer,
     .flags = AVFMT_GLOBALHEADER,
     .codec_tag = (const AVCodecTag* const []){codec_ipod_tags, 0},
-    .priv_class = &mov_muxer_class,
+    .priv_class = &ipod_muxer_class,
 };
 #endif