summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/mov.c109
1 files changed, 87 insertions, 22 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 6d2262a2c3..f70ec6169a 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1079,42 +1079,66 @@ static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}
+static int mov_realloc_extradata(AVCodecContext *codec, MOVAtom atom)
+{
+ int err = 0;
+ uint64_t size = (uint64_t)codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
+ if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
+ return AVERROR_INVALIDDATA;
+ if ((err = av_reallocp(&codec->extradata, size)) < 0) {
+ codec->extradata_size = 0;
+ return err;
+ }
+ codec->extradata_size = size - FF_INPUT_BUFFER_PADDING_SIZE;
+ return 0;
+}
+
+/* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
+static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
+ AVCodecContext *codec, uint8_t *buf)
+{
+ int64_t result = atom.size;
+ int err;
+
+ AV_WB32(buf , atom.size + 8);
+ AV_WL32(buf + 4, atom.type);
+ err = avio_read(pb, buf + 8, atom.size);
+ if (err < 0) {
+ codec->extradata_size -= atom.size;
+ return err;
+ } else if (err < atom.size) {
+ av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
+ codec->extradata_size -= atom.size - err;
+ result = err;
+ }
+ memset(buf + 8 + err, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ return result;
+}
+
/* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */
static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
enum AVCodecID codec_id)
{
AVStream *st;
- uint64_t size;
- uint8_t *buf;
+ uint64_t original_size;
int err;
if (c->fc->nb_streams < 1) // will happen with jp2 files
return 0;
- st= c->fc->streams[c->fc->nb_streams-1];
+ st = c->fc->streams[c->fc->nb_streams-1];
if (st->codec->codec_id != codec_id)
return 0; /* unexpected codec_id - don't mess with extradata */
- size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
- if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
- return AVERROR_INVALIDDATA;
- if ((err = av_reallocp(&st->codec->extradata, size)) < 0) {
- st->codec->extradata_size = 0;
+ original_size = st->codec->extradata_size;
+ err = mov_realloc_extradata(st->codec, atom);
+ if (err)
return err;
- }
- buf = st->codec->extradata + st->codec->extradata_size;
- st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE;
- AV_WB32( buf , atom.size + 8);
- AV_WL32( buf + 4, atom.type);
- err = avio_read(pb, buf + 8, atom.size);
- if (err < 0) {
+
+ err = mov_read_atom_into_extradata(c, pb, atom, st->codec, st->codec->extradata + original_size);
+ if (err < 0)
return err;
- } else if (err < atom.size) {
- av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
- st->codec->extradata_size -= atom.size - err;
- }
- memset(buf + 8 + err, 0, FF_INPUT_BUFFER_PADDING_SIZE);
- return 0;
+ return 0; // Note: this is the original behavior to ignore truncation.
}
/* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
@@ -1178,6 +1202,47 @@ static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return mov_read_avid(c, pb, atom);
}
+static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ int ret = 0;
+ int length = 0;
+ uint64_t original_size;
+ if (c->fc->nb_streams >= 1) {
+ AVCodecContext *codec = c->fc->streams[c->fc->nb_streams-1]->codec;
+ if (atom.size == 16) {
+ original_size = codec->extradata_size;
+ ret = mov_realloc_extradata(codec, atom);
+ if (!ret) {
+ length = mov_read_atom_into_extradata(c, pb, atom, codec, codec->extradata + original_size);
+ if (length == atom.size) {
+ const uint8_t range_value = codec->extradata[original_size + 19];
+ switch (range_value) {
+ case 1:
+ codec->color_range = AVCOL_RANGE_MPEG;
+ break;
+ case 2:
+ codec->color_range = AVCOL_RANGE_JPEG;
+ break;
+ default:
+ av_log(c, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
+ break;
+ }
+ av_dlog(c, "color_range: %"PRIu8"\n", codec->color_range);
+ } else {
+ /* For some reason the whole atom was not added to the extradata */
+ av_log(c, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
+ }
+ } else {
+ av_log(c, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
+ }
+ } else {
+ av_log(c, AV_LOG_WARNING, "aclr not decoded - unexpected size %ld\n", atom.size);
+ }
+ }
+
+ return ret;
+}
+
static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
@@ -3390,7 +3455,7 @@ static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
}
static const MOVParseTableEntry mov_default_parse_table[] = {
-{ MKTAG('A','C','L','R'), mov_read_avid },
+{ MKTAG('A','C','L','R'), mov_read_aclr },
{ MKTAG('A','P','R','G'), mov_read_avid },
{ MKTAG('A','A','L','P'), mov_read_avid },
{ MKTAG('A','R','E','S'), mov_read_ares },