[FFmpeg-cvslog] avformat/mov: Add simple ACLR atom reading to set the color range of the incomming track for codec 's like DNxHD that utilise AVID's proprietary atom.
Kevin Wheatley
git at videolan.org
Thu Feb 19 15:43:41 CET 2015
ffmpeg | branch: master | Kevin Wheatley <kevin.j.wheatley at gmail.com> | Thu Feb 19 11:08:14 2015 +0000| [fb3fb1d0d4bb21edcb1f9d932987eceeabe7f675] | committer: Michael Niedermayer
avformat/mov: Add simple ACLR atom reading to set the color range of the incomming track for codec's like DNxHD that utilise AVID's proprietary atom.
On input ACLR will be used to set colour range no matter which codec
it is associated with.
No change for when it will be output.
Rework mov_read_extradata function to allow detection of truncated
atom reads by callers.
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=fb3fb1d0d4bb21edcb1f9d932987eceeabe7f675
---
libavformat/mov.c | 109 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 87 insertions(+), 22 deletions(-)
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 6d2262a..f70ec61 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 },
More information about the ffmpeg-cvslog
mailing list