* commit '117d8c6d1f1c187ffc6098d9618457e00534e013': matroska: implement support for ProRes matroska: implement support for ALAC Conflicts: libavformat/matroskaenc.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.0
@@ -73,6 +73,7 @@ const CodecTags ff_mkv_codec_tags[]={ | |||||
{"V_MPEG4/ISO/SP" , AV_CODEC_ID_MPEG4}, | {"V_MPEG4/ISO/SP" , AV_CODEC_ID_MPEG4}, | ||||
{"V_MPEG4/ISO/AVC" , AV_CODEC_ID_H264}, | {"V_MPEG4/ISO/AVC" , AV_CODEC_ID_H264}, | ||||
{"V_MPEG4/MS/V3" , AV_CODEC_ID_MSMPEG4V3}, | {"V_MPEG4/MS/V3" , AV_CODEC_ID_MSMPEG4V3}, | ||||
{"V_PRORES" , AV_CODEC_ID_PRORES}, | |||||
{"V_REAL/RV10" , AV_CODEC_ID_RV10}, | {"V_REAL/RV10" , AV_CODEC_ID_RV10}, | ||||
{"V_REAL/RV20" , AV_CODEC_ID_RV20}, | {"V_REAL/RV20" , AV_CODEC_ID_RV20}, | ||||
{"V_REAL/RV30" , AV_CODEC_ID_RV30}, | {"V_REAL/RV30" , AV_CODEC_ID_RV30}, | ||||
@@ -37,6 +37,7 @@ | |||||
#include "isom.h" | #include "isom.h" | ||||
#include "rm.h" | #include "rm.h" | ||||
#include "matroska.h" | #include "matroska.h" | ||||
#include "libavcodec/bytestream.h" | |||||
#include "libavcodec/mpeg4audio.h" | #include "libavcodec/mpeg4audio.h" | ||||
#include "libavutil/intfloat.h" | #include "libavutil/intfloat.h" | ||||
#include "libavutil/intreadwrite.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 | Create the "atom size", "tag", and "tag version" fields the | ||||
decoder expects manually. */ | decoder expects manually. */ | ||||
extradata_size = 12 + track->codec_priv.size; | 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) | if (extradata == NULL) | ||||
return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
AV_WB32(extradata, extradata_size); | AV_WB32(extradata, extradata_size); | ||||
@@ -2117,6 +2118,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, | |||||
MatroskaTrackEncoding *encodings = track->encodings.elem; | MatroskaTrackEncoding *encodings = track->encodings.elem; | ||||
uint32_t pkt_size = lace_size[n]; | uint32_t pkt_size = lace_size[n]; | ||||
uint8_t *pkt_data = data; | uint8_t *pkt_data = data; | ||||
int offset = 0; | |||||
if (encodings && encodings->scope & 1) { | if (encodings && encodings->scope & 1) { | ||||
res = matroska_decode_buffer(&pkt_data, &pkt_size, track); | res = matroska_decode_buffer(&pkt_data, &pkt_size, track); | ||||
@@ -2124,15 +2126,24 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, | |||||
break; | break; | ||||
} | } | ||||
if (st->codec->codec_id == AV_CODEC_ID_PRORES) | |||||
offset = 8; | |||||
pkt = av_mallocz(sizeof(AVPacket)); | pkt = av_mallocz(sizeof(AVPacket)); | ||||
/* XXX: prevent data copy... */ | /* XXX: prevent data copy... */ | ||||
if (av_new_packet(pkt, pkt_size) < 0) { | |||||
if (av_new_packet(pkt, pkt_size + offset) < 0) { | |||||
av_free(pkt); | av_free(pkt); | ||||
res = AVERROR(ENOMEM); | res = AVERROR(ENOMEM); | ||||
break; | 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) | if (pkt_data != data) | ||||
av_free(pkt_data); | av_free(pkt_data); | ||||
@@ -475,8 +475,16 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo | |||||
ret = ff_flac_write_header(dyn_cp, codec, 1); | ret = ff_flac_write_header(dyn_cp, codec, 1); | ||||
else if (codec->codec_id == AV_CODEC_ID_H264) | else if (codec->codec_id == AV_CODEC_ID_H264) | ||||
ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size); | 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) | else if (codec->extradata_size) | ||||
avio_write(dyn_cp, codec->extradata, codec->extradata_size); | avio_write(dyn_cp, codec->extradata, codec->extradata_size); | ||||
} else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { | } 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; | MatroskaMuxContext *mkv = s->priv_data; | ||||
AVCodecContext *codec = s->streams[pkt->stream_index]->codec; | AVCodecContext *codec = s->streams[pkt->stream_index]->codec; | ||||
uint8_t *data = NULL; | 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; | 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, " | 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); | ff_avc_parse_nal_units_buf(pkt->data, &data, &size); | ||||
else | else | ||||
data = pkt->data; | 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_id(pb, blockid); | ||||
put_ebml_num(pb, size+4, 0); | put_ebml_num(pb, size+4, 0); | ||||
avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 | avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 | ||||
avio_wb16(pb, ts - mkv->cluster_pts); | avio_wb16(pb, ts - mkv->cluster_pts); | ||||
avio_w8(pb, flags); | avio_w8(pb, flags); | ||||
avio_write(pb, data, size); | |||||
avio_write(pb, data + offset, size); | |||||
if (data != pkt->data) | if (data != pkt->data) | ||||
av_free(data); | av_free(data); | ||||
} | } | ||||