matroska: implement support for ALAC

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>
This commit is contained in:
Moritz Bunkus 2012-09-14 22:26:14 +02:00 committed by Luca Barbato
parent 870e75524a
commit 8071dca3d5
3 changed files with 24 additions and 0 deletions

View 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},

View 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);

View 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) {