summaryrefslogtreecommitdiff
authorJian Wang <jian.wang@amlogic.com>2016-02-18 08:14:28 (GMT)
committer Jian Wang <jian.wang@amlogic.com>2016-02-18 08:18:41 (GMT)
commiteb147d85d5d8abafd056514379fcf0e55c56dfbf (patch)
treed019c165f8b2e4265d7161676b3edb74ca5b4dc1
parent6aacd39b56b681bcb53b180caeebf5faa653f72a (diff)
downloadffmpeg-eb147d85d5d8abafd056514379fcf0e55c56dfbf.zip
ffmpeg-eb147d85d5d8abafd056514379fcf0e55c56dfbf.tar.gz
ffmpeg-eb147d85d5d8abafd056514379fcf0e55c56dfbf.tar.bz2
PD#118065: cts: add mov support parsing QuickTime Metadata Keys
merge it from newer ffmpeg version commit 9ea812692c38c58a343cec5f66e8949655906edc Author: Tinglin Liu <tinglin@google.com> Date: Thu Oct 22 15:04:46 2015 -0700 mov: Add support parsing QuickTime Metadata Keys. Change-Id: I96c03fc4c6d7525db84f5767d1325e44c3f686d7
Diffstat
-rw-r--r--libavformat/isom.h4
-rw-r--r--libavformat/mov.c96
2 files changed, 95 insertions, 5 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 828e500..73ae25a 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -151,6 +151,10 @@ typedef struct MOVContext {
int64_t duration; ///< duration of the longest track
int found_moov; ///< 'moov' atom has been found
int found_mdat; ///< 'mdat' atom has been found
+ int found_hdlr_mdta; ///< 'hdlr' atom with type 'mdta' has been found
+ int trak_index; ///< Index of the current 'trak'
+ char **meta_keys;
+ unsigned meta_keys_count;
DVDemuxContext *dv_demux;
AVFormatContext *dv_fctx;
int isom; ///< 1 if file is ISO Media (mp4/3gp)
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 7d026df..ff0d0be 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -551,6 +551,16 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
return ret;
}
+ } else if (!key && c->found_hdlr_mdta && c->meta_keys) {
+ uint32_t index = AV_RB32(&atom.type);
+ if (index < c->meta_keys_count) {
+ key = c->meta_keys[index];
+ } else {
+ av_log(c->fc, AV_LOG_WARNING,
+ "The index of 'data' is out of range: %d >= %d.\n",
+ index, c->meta_keys_count);
+ }
+
}
} else return 0;
} else if (atom.size > 4 && key && !c->itunes_metadata) {
@@ -587,6 +597,17 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
mov_read_mac_string(c, pb, str_size, str, sizeof(str));
} else if (data_type == 13 || data_type == 14){
mov_extract_cover_pic(c->fc, pb, data_type, cover_size, str);
+ } else if (data_type == 23 && str_size >= 4) { // BE float32
+ // Allocates enough space if data_type is a float32 number
+ int str_size_alloc = 512 + 1;
+ float val = av_int2float(avio_rb32(pb));
+ if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
+ av_log(c->fc, AV_LOG_ERROR,
+ "Failed to store the float32 number (%f) in string.\n", val);
+ av_free(str);
+ return AVERROR_INVALIDDATA;
+ }
+
} else {
avio_read(pb, str, str_size);
str[str_size] = 0;
@@ -759,11 +780,6 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int title_size;
char *title_str;
- if (c->fc->nb_streams < 1) // meta before first trak
- return 0;
-
- st = c->fc->streams[c->fc->nb_streams-1];
-
avio_r8(pb); /* version */
avio_rb24(pb); /* flags */
@@ -774,6 +790,15 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_dlog(c->fc, "ctype= %.4s (0x%08x)\n", (char*)&ctype, ctype);
av_dlog(c->fc, "stype= %.4s\n", (char*)&type);
+ if (c->trak_index < 0) { // meta not inside a trak
+ if (type == MKTAG('m','d','t','a')) {
+ c->found_hdlr_mdta = 1;
+ }
+ return 0;
+ }
+
+ st = c->fc->streams[c->fc->nb_streams-1];
+
if (type == MKTAG('v','i','d','e'))
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
else if (type == MKTAG('s','o','u','n'))
@@ -2538,10 +2563,13 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
st->priv_data = sc;
st->codec->codec_type = AVMEDIA_TYPE_DATA;
sc->ffindex = st->index;
+ c->trak_index = st->index;
if ((ret = mov_read_default(c, pb, atom)) < 0)
return ret;
+ c->trak_index = -1;
+
/* sanity checks */
if (sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
(!sc->sample_size && !sc->sample_count))) {
@@ -2630,6 +2658,48 @@ static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return ret;
}
+static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ uint32_t count;
+ uint32_t i;
+
+ if (atom.size < 8)
+ return 0;
+
+ avio_skip(pb, 4);
+ count = avio_rb32(pb);
+ if (count > UINT_MAX / sizeof(*c->meta_keys)) {
+ av_log(c->fc, AV_LOG_ERROR,
+ "The 'keys' atom with the invalid key count: %d\n", count);
+ return AVERROR_INVALIDDATA;
+ }
+
+ c->meta_keys_count = count + 1;
+ c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
+ if (!c->meta_keys)
+ return AVERROR(ENOMEM);
+
+ for (i = 1; i <= count; ++i) {
+ uint32_t key_size = avio_rb32(pb);
+ uint32_t type = avio_rl32(pb);
+ if (key_size < 8) {
+ av_log(c->fc, AV_LOG_ERROR,
+ "The key# %d in meta has invalid size: %d\n", i, key_size);
+ return AVERROR_INVALIDDATA;
+ }
+ key_size -= 8;
+ if (type != MKTAG('m','d','t','a')) {
+ avio_skip(pb, key_size);
+ }
+ c->meta_keys[i] = av_mallocz(key_size + 1);
+ if (!c->meta_keys[i])
+ return AVERROR(ENOMEM);
+ avio_read(pb, c->meta_keys[i], key_size);
+ }
+
+ return 0;
+}
+
static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
while (atom.size > 8) {
@@ -3279,6 +3349,14 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
atom.type == MKTAG('i','l','s','t')))
parse = mov_read_udta_string;
+ // Supports parsing the QuickTime Metadata Keys.
+ // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
+ if (!parse && c->found_hdlr_mdta &&
+ atom.type == MKTAG('m','e','t','a') &&
+ a.type == MKTAG('k','e','y','s')) {
+ parse = mov_read_keys;
+ }
+
if (!parse) { /* skip leaf atoms data */
avio_skip(pb, a.size);
} else {
@@ -3541,6 +3619,13 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&mov->dv_demux);
}
+ if (mov->meta_keys) {
+ for (i = 1; i < mov->meta_keys_count; i++) {
+ av_freep(&mov->meta_keys[i]);
+ }
+ av_freep(&mov->meta_keys);
+ }
+
av_freep(&mov->trex_data);
av_freep(&mov->bitrates);
@@ -3589,6 +3674,7 @@ static int mov_read_header(AVFormatContext *s)
MOVAtom atom = { AV_RL32("root") };
mov->fc = s;
+ mov->trak_index = -1;
/* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
if (pb->seekable)
atom.size = avio_size(pb);