diff --git a/libavformat/matroska.c b/libavformat/matroska.c index d2d07a8eca..652e4d0b03 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -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}, diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index ff2a6c29dc..69a8c7f06e 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -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); diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 9d9c223dbb..521f6b5c1a 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -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) {