[FFmpeg-devel] [PATCH] Adds support parsing the QuickTime Metadata Keys.

Derek Buitenhuis derek.buitenhuis at gmail.com
Thu Oct 22 20:43:54 CEST 2015


On 10/20/2015 7:29 PM, Tinglin Liu wrote:
> The Apple dev specification:
> https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
> ---
>  libavformat/isom.h |  3 +++
>  libavformat/mov.c  | 77 +++++++++++++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 74 insertions(+), 6 deletions(-)

Is there a test file around we can add to FATE?

> @@ -177,6 +177,9 @@ 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
> +    char **meta_keys;
> +    unsigned meta_keys_count;

How exactly is it intended for these gets to be accessed? MOVContext is an internal
structure only. Perhaps this should be exported via side-data?

> @@ -368,6 +369,11 @@ retry:
>                      av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
>                  }
>                  return ret;
> +            } else if (!key && c->found_hdlr_mdta && c->meta_keys) {

Is it ever possible for c->meta_keys to not be allocated here? (Patch doesn't
provide me enough context liens to determine that.)

> +                uint32_t index = AV_RB32(&atom.type);
> +                if (index < c->meta_keys_count && c->meta_keys[index]) {

If we have already allocated c->meta_keys_count * sizeof(*c->meta_keys) entries,
the latter check is redundant.

> +                    key = c->meta_keys[index];
> +                }

Perhaps some sort of warning if the index is out-of-range?

> +    // Allocates enough space if data_type is a float32 number, otherwise
>      // worst-case requirement for output string in case of utf8 coded input
> -    str_size_alloc = (raw ? str_size : str_size * 2) + 1;
> +    num = (data_type == 23) ? 1 : 0;

Redundant ternary operator.

> +    str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
>      str = av_mallocz(str_size_alloc);
>      if (!str)
>          return AVERROR(ENOMEM);
> @@ -405,6 +413,10 @@ retry:
>      else {
>          if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
>              mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
> +        } else if (data_type == 23 && str_size >= 4) {  // BE float32

Where does 4 come from?

> +            union av_intfloat32 val;
> +            val.i = avio_rb32(pb);

I'm not entirely sure of the portability of this code. Would this not fail on
any system without IEEE floats?

> +            snprintf(str, str_size_alloc, "%f", val.f);

Return value should be checked when using %f, in case of insane input.

> @@ -614,6 +621,15 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>      av_log(c->fc, AV_LOG_TRACE, "ctype= %.4s (0x%08x)\n", (char*)&ctype, ctype);
>      av_log(c->fc, AV_LOG_TRACE, "stype= %.4s\n", (char*)&type);
>  
> +    if (c->fc->nb_streams < 1) {  // meta before first trak
> +        if (type == MKTAG('m','d','t','a')) {
> +            c->found_hdlr_mdta = 1;
> +        }
> +        return 0;
> +    }
> +
> +    st = c->fc->streams[c->fc->nb_streams-1];

Any reason this was moved lower?

> +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))
> +        return 0;

This shouldn't really return success.

Also, probably could do with a warning.

> +    av_freep(&c->meta_keys);

Why are we freeing this here? It should not be set at all, or it should not be
overwritten silently, no?

> +    c->meta_keys_count = count + 1;

Some may complain we are wasting 1 entry's worth of memory ;)... not that I particularily
care, but it may end up with some funny bugs later on if others assume a 0-origin.

> +    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 (type != MKTAG('m','d','t','a') || key_size < 8)
> +            return 0;

Logging? Also, is it reasonable to return success here as you do?

The rest is just simple stuff like inconsistent use of braces and post/pre-increment,
and not worth noting.

- Derek


More information about the ffmpeg-devel mailing list