#include <limits.h>
#include <stdint.h>
-//#define MOV_EXPORT_ALL_METADATA
-
#include "libavutil/attributes.h"
#include "libavutil/channel_layout.h"
#include "libavutil/display.h"
static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
-#ifdef MOV_EXPORT_ALL_METADATA
char tmp_key[5];
-#endif
- char key2[16], language[4] = {0};
+ char key2[32], language[4] = {0};
char *str = NULL;
const char *key = NULL;
uint16_t langcode = 0;
int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
switch (atom.type) {
- case MKTAG(0xa9,'n','a','m'): key = "title"; break;
- case MKTAG(0xa9,'a','u','t'):
- case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
- case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
case MKTAG( 'c','p','i','l'): key = "compilation";
parse = mov_metadata_int8_no_padding; break;
- case MKTAG( 'c','p','r','t'):
- case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
- case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
- case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
- case MKTAG(0xa9,'c','m','t'):
- case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
- case MKTAG(0xa9,'a','l','b'): key = "album"; break;
- case MKTAG(0xa9,'d','a','y'): key = "date"; break;
- case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
- case MKTAG( 'g','n','r','e'): key = "genre";
- parse = mov_metadata_gnre; break;
- case MKTAG(0xa9,'t','o','o'):
- case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
- case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
- case MKTAG(0xa9,'m','a','k'): key = "make"; break;
- case MKTAG(0xa9,'m','o','d'): key = "model"; break;
- case MKTAG(0xa9,'x','y','z'): key = "location"; break;
- case MKTAG( 'd','e','s','c'): key = "description";break;
- case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
- case MKTAG( 't','v','s','h'): key = "show"; break;
- case MKTAG( 't','v','e','n'): key = "episode_id";break;
- case MKTAG( 't','v','n','n'): key = "network"; break;
- case MKTAG( 't','r','k','n'): key = "track";
- parse = mov_metadata_track_or_disc_number; break;
+ case MKTAG( 'c','p','r','t'): key = "copyright"; break;
+ case MKTAG( 'd','e','s','c'): key = "description"; break;
case MKTAG( 'd','i','s','k'): key = "disc";
parse = mov_metadata_track_or_disc_number; break;
- case MKTAG( 't','v','e','s'): key = "episode_sort";
- parse = mov_metadata_int8_bypass_padding; break;
- case MKTAG( 't','v','s','n'): key = "season_number";
- parse = mov_metadata_int8_bypass_padding; break;
- case MKTAG( 's','t','i','k'): key = "media_type";
- parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'g','n','r','e'): key = "genre";
+ parse = mov_metadata_gnre; break;
case MKTAG( 'h','d','v','d'): key = "hd_video";
parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
+ case MKTAG( 'l','o','c','i'):
+ return mov_metadata_loci(c, pb, atom.size);
case MKTAG( 'p','g','a','p'): key = "gapless_playback";
parse = mov_metadata_int8_no_padding; break;
case MKTAG( '@','P','R','M'):
return mov_metadata_raw(c, pb, atom.size, "premiere_version");
case MKTAG( '@','P','R','Q'):
return mov_metadata_raw(c, pb, atom.size, "quicktime_version");
- case MKTAG( 'l','o','c','i'):
- return mov_metadata_loci(c, pb, atom.size);
+ case MKTAG( 's','t','i','k'): key = "media_type";
+ parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 't','r','k','n'): key = "track";
+ parse = mov_metadata_track_or_disc_number; break;
+ case MKTAG( 't','v','e','n'): key = "episode_id"; break;
+ case MKTAG( 't','v','e','s'): key = "episode_sort";
+ parse = mov_metadata_int8_bypass_padding; break;
+ case MKTAG( 't','v','n','n'): key = "network"; break;
+ case MKTAG( 't','v','s','h'): key = "show"; break;
+ case MKTAG( 't','v','s','n'): key = "season_number";
+ parse = mov_metadata_int8_bypass_padding; break;
case MKTAG( 'X','M','P','_'):
return mov_metadata_raw(c, pb, atom.size, "xmp");
+ case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
+ case MKTAG(0xa9,'a','l','b'): key = "album"; break;
+ case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
+ case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
+ case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
+ case MKTAG(0xa9,'d','a','y'): key = "date"; break;
+ case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
+ case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
+ case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
+ case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
+ case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
+ case MKTAG(0xa9,'m','a','k'): key = "make"; break;
+ case MKTAG(0xa9,'m','o','d'): key = "model"; break;
+ case MKTAG(0xa9,'n','a','m'): key = "title"; break;
+ case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
+ case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
+ case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
+ case MKTAG(0xa9,'x','y','z'): key = "location"; break;
}
if (c->itunes_metadata && atom.size > 8) {
} else
str_size = atom.size;
-#ifdef MOV_EXPORT_ALL_METADATA
- if (!key) {
+ if (c->export_all && !key) {
snprintf(tmp_key, 5, "%.4s", (char*)&atom.type);
key = tmp_key;
}
-#endif
if (!key)
return 0;
key, str, (char*)&atom.type, str_size_alloc, atom.size);
av_freep(&str);
-
return 0;
}
if (!entries)
return 0;
- if (entries >= UINT_MAX/sizeof(int64_t))
- return AVERROR_INVALIDDATA;
- sc->chunk_offsets = av_malloc(entries * sizeof(int64_t));
+ if (sc->chunk_offsets)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
+ av_free(sc->chunk_offsets);
+ sc->chunk_count = 0;
+ sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
if (!sc->chunk_offsets)
return AVERROR(ENOMEM);
sc->chunk_count = entries;
if (!entries)
return 0;
- if (entries >= UINT_MAX / sizeof(*sc->stsc_data))
- return AVERROR_INVALIDDATA;
- sc->stsc_data = av_malloc(entries * sizeof(*sc->stsc_data));
+ if (sc->stsc_data)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
+ av_free(sc->stsc_data);
+ sc->stsc_count = 0;
+ sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
if (!sc->stsc_data)
return AVERROR(ENOMEM);
avio_rb32(pb); // version + flags
entries = avio_rb32(pb);
- if (entries >= UINT_MAX / sizeof(*sc->stps_data))
- return AVERROR_INVALIDDATA;
- sc->stps_data = av_malloc(entries * sizeof(*sc->stps_data));
+ if (sc->stps_data)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
+ av_free(sc->stps_data);
+ sc->stps_count = 0;
+ sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
if (!sc->stps_data)
return AVERROR(ENOMEM);
st->need_parsing = AVSTREAM_PARSE_HEADERS;
return 0;
}
- if (entries >= UINT_MAX / sizeof(int))
- return AVERROR_INVALIDDATA;
- sc->keyframes = av_malloc(entries * sizeof(int));
+ if (sc->keyframes)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
+ av_free(sc->keyframes);
+ sc->keyframe_count = 0;
+ sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
if (!sc->keyframes)
return AVERROR(ENOMEM);
if (!entries)
return 0;
- if (entries >= UINT_MAX / sizeof(int) || entries >= (UINT_MAX - 4) / field_size)
+ if (entries >= (UINT_MAX - 4) / field_size)
return AVERROR_INVALIDDATA;
- sc->sample_sizes = av_malloc(entries * sizeof(int));
+ if (sc->sample_sizes)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
+ av_free(sc->sample_sizes);
+ sc->sample_count = 0;
+ sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
if (!sc->sample_sizes)
return AVERROR(ENOMEM);
av_dlog(c->fc, "track[%i].stts.entries = %i\n",
c->fc->nb_streams-1, entries);
- if (entries >= UINT_MAX / sizeof(*sc->stts_data))
- return -1;
-
+ if (sc->stts_data)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
av_free(sc->stts_data);
- sc->stts_data = av_malloc(entries * sizeof(*sc->stts_data));
+ sc->stts_count = 0;
+ sc->stts_data = av_malloc_array(entries, sizeof(*sc->stts_data));
if (!sc->stts_data)
return AVERROR(ENOMEM);
entries = avio_rb32(pb);
if (!entries)
return 0;
- if (entries >= UINT_MAX / sizeof(*sc->rap_group))
- return AVERROR_INVALIDDATA;
- sc->rap_group = av_malloc(entries * sizeof(*sc->rap_group));
+ if (sc->rap_group)
+ av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n");
+ av_free(sc->rap_group);
+ sc->rap_group_count = 0;
+ sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group));
if (!sc->rap_group)
return AVERROR(ENOMEM);
return 0;
}
-static const AVOption options[] = {
+#define OFFSET(x) offsetof(MOVContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption mov_options[] = {
{"use_absolute_path",
"allow using absolute path when opening alias, this is a possible security issue",
offsetof(MOVContext, use_absolute_path), FF_OPT_TYPE_INT, {.i64 = 0},
AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM, "use_mfra_for" },
{"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM, "use_mfra_for" },
- {NULL}
+ { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS },
+ { NULL },
};
static const AVClass mov_class = {
.class_name = "mov,mp4,m4a,3gp,3g2,mj2",
.item_name = av_default_item_name,
- .option = options,
+ .option = mov_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_mov_demuxer = {
.name = "mov,mp4,m4a,3gp,3g2,mj2",
.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
+ .priv_class = &mov_class,
.priv_data_size = sizeof(MOVContext),
.extensions = "mov,mp4,m4a,3gp,3g2,mj2",
.read_probe = mov_probe,
.read_packet = mov_read_packet,
.read_close = mov_read_close,
.read_seek = mov_read_seek,
- .priv_class = &mov_class,
.flags = AVFMT_NO_BYTE_SEEK,
};