matroska: implement support for ALAC
authorMoritz Bunkus <moritz@bunkus.org>
Fri, 14 Sep 2012 20:26:14 +0000 (22:26 +0200)
committerLuca Barbato <lu_zero@gentoo.org>
Wed, 19 Sep 2012 18:34:14 +0000 (20:34 +0200)
Support Matroska native formatting.

On demuxing reconstruct the 36-bytes QuickTime atom that the ALAC
decoder expects by prepending the "atom size", "tag" and
"tag version" fields missing from the Matroska's CodecPrivate
element.

On muxing remove the initial 12 bytes

Sample files are available:
http://www.bunkus.org/videotools/mkvtoolnix/samples/alac/alac-in-matroska.mka
and the CoreAudio file it was created from with today's mkvmerge:
http://www.bunkus.org/videotools/mkvtoolnix/samples/alac/alac-in-matroska-source.caf

Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
libavformat/matroska.c
libavformat/matroskadec.c
libavformat/matroskaenc.c

index d2d07a8eca6b3db41da0f00b07a15298e0a7d294..652e4d0b033045578bdcc44af0e5ec0bae45fd9b 100644 (file)
@@ -24,6 +24,7 @@
 const CodecTags ff_mkv_codec_tags[]={
     {"A_AAC"            , AV_CODEC_ID_AAC},
     {"A_AC3"            , AV_CODEC_ID_AC3},
+    {"A_ALAC"           , AV_CODEC_ID_ALAC},
     {"A_DTS"            , AV_CODEC_ID_DTS},
     {"A_EAC3"           , AV_CODEC_ID_EAC3},
     {"A_FLAC"           , AV_CODEC_ID_FLAC},
index ff2a6c29dc2738268fec79113ee3635b6e788c1f..69a8c7f06e5ba06588a521710195bb127da6d76e 100644 (file)
@@ -1528,6 +1528,19 @@ static int matroska_read_header(AVFormatContext *s)
                 extradata_size = 5;
             } else
                 extradata_size = 2;
+        } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size) {
+            /* Only ALAC's magic cookie is stored in Matroska's track headers.
+               Create the "atom size", "tag", and "tag version" fields the
+               decoder expects manually. */
+            extradata_size = 12 + track->codec_priv.size;
+            extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+            if (extradata == NULL)
+                return AVERROR(ENOMEM);
+            AV_WB32(extradata, extradata_size);
+            memcpy(&extradata[4], "alac", 4);
+            AV_WB32(&extradata[8], 0);
+            memcpy(&extradata[12], track->codec_priv.data,
+                                   track->codec_priv.size);
         } else if (codec_id == AV_CODEC_ID_TTA) {
             extradata_size = 30;
             extradata = av_mallocz(extradata_size);
index 9d9c223dbbd8cf43ceb8060c5e72c492ae5bdc12..521f6b5c1a100098b2c7adbfbb545512ae4cbead 100644 (file)
@@ -475,6 +475,16 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
             ret = ff_flac_write_header(dyn_cp, codec, 1);
         else if (codec->codec_id == AV_CODEC_ID_H264)
             ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size);
+        else if (codec->codec_id == AV_CODEC_ID_ALAC) {
+            if (codec->extradata_size < 36) {
+                av_log(s, AV_LOG_ERROR,
+                       "Invalid extradata found, ALAC expects a 36-byte "
+                       "QuickTime atom.");
+                ret = AVERROR_INVALIDDATA;
+            } else
+                avio_write(dyn_cp, codec->extradata + 12,
+                                   codec->extradata_size - 12);
+        }
         else if (codec->extradata_size)
             avio_write(dyn_cp, codec->extradata, codec->extradata_size);
     } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {