diff --git a/libavformat/matroska.c b/libavformat/matroska.c index fccacc7f68..64d0a459b4 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -73,6 +73,7 @@ const CodecTags ff_mkv_codec_tags[]={ {"V_MPEG4/ISO/SP" , AV_CODEC_ID_MPEG4}, {"V_MPEG4/ISO/AVC" , AV_CODEC_ID_H264}, {"V_MPEG4/MS/V3" , AV_CODEC_ID_MSMPEG4V3}, + {"V_PRORES" , AV_CODEC_ID_PRORES}, {"V_REAL/RV10" , AV_CODEC_ID_RV10}, {"V_REAL/RV20" , AV_CODEC_ID_RV20}, {"V_REAL/RV30" , AV_CODEC_ID_RV30}, diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 5dd8dd52fc..bc0f72863b 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -37,6 +37,7 @@ #include "isom.h" #include "rm.h" #include "matroska.h" +#include "libavcodec/bytestream.h" #include "libavcodec/mpeg4audio.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" @@ -1615,7 +1616,7 @@ static int matroska_read_header(AVFormatContext *s) 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); + extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (extradata == NULL) return AVERROR(ENOMEM); AV_WB32(extradata, extradata_size); @@ -2117,6 +2118,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, MatroskaTrackEncoding *encodings = track->encodings.elem; uint32_t pkt_size = lace_size[n]; uint8_t *pkt_data = data; + int offset = 0; if (encodings && encodings->scope & 1) { res = matroska_decode_buffer(&pkt_data, &pkt_size, track); @@ -2124,15 +2126,24 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, break; } + if (st->codec->codec_id == AV_CODEC_ID_PRORES) + offset = 8; + pkt = av_mallocz(sizeof(AVPacket)); /* XXX: prevent data copy... */ - if (av_new_packet(pkt, pkt_size) < 0) { + if (av_new_packet(pkt, pkt_size + offset) < 0) { av_free(pkt); res = AVERROR(ENOMEM); break; } - memcpy(pkt->data, pkt_data, pkt_size); + if (st->codec->codec_id == AV_CODEC_ID_PRORES) { + uint8_t *buf = pkt->data; + bytestream_put_be32(&buf, pkt_size); + bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f')); + } + + memcpy(pkt->data + offset, pkt_data, pkt_size); if (pkt_data != data) av_free(pkt_data); diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index f7438f28f4..4fd30b86fb 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -475,8 +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 && (12 < codec->extradata_size)) - ret = ff_isom_write_avcc(dyn_cp, codec->extradata + 12, codec->extradata_size - 12); + 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) { @@ -1061,7 +1069,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, MatroskaMuxContext *mkv = s->priv_data; AVCodecContext *codec = s->streams[pkt->stream_index]->codec; uint8_t *data = NULL; - int size = pkt->size; + int offset = 0, size = pkt->size; int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " @@ -1072,12 +1080,20 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, ff_avc_parse_nal_units_buf(pkt->data, &data, &size); else data = pkt->data; + + if (codec->codec_id == AV_CODEC_ID_PRORES) { + /* Matroska specification requires to remove the first QuickTime atom + */ + size -= 8; + offset = 8; + } + put_ebml_id(pb, blockid); put_ebml_num(pb, size+4, 0); avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 avio_wb16(pb, ts - mkv->cluster_pts); avio_w8(pb, flags); - avio_write(pb, data, size); + avio_write(pb, data + offset, size); if (data != pkt->data) av_free(data); }