[FFmpeg-devel] [PATCH] Store Major brand, Minor version and compatible brands of a mov file using the metadata API

Baptiste Coudurier baptiste.coudurier
Thu Sep 17 19:53:10 CEST 2009


Hi,

On 09/10/2009 12:55 AM, haim alon wrote:
> Hi,
>
> On Wed, Sep 9, 2009 at 8:47 PM, Baptiste Coudurier<
> baptiste.coudurier at gmail.com>  wrote:
>
>> Hi,
>>
>>
>> On 09/09/2009 06:28 AM, haim alon wrote:
>>
>>> Hi,
>>>
>>> On Wed, Sep 9, 2009 at 3:22 PM, Reimar D?ffinger
>>> <Reimar.Doeffinger at gmx.de>wrote:
>>>
>>>   On Wed, Sep 09, 2009 at 02:00:47PM +0300, haim alon wrote:
>>>>
>>>>> No, at least av_strlcpy reads at most "size-1" bytes, 4 in this case.
>>>>>> The problem is with the return value of it:
>>>>>> return len + strlen(src) - 1;
>>>>>> So my suggestion to replace strncpy with av_strlcpy actually completely
>>>>>> broke things, (av_)strlcpy can only be used for correctly 0-terminated
>>>>>> strings, and I fear that this is used wrongly in some places in
>>>>>> FFmpeg, e.g. rtmppkt.c looks suspicious.
>>>>>>
>>>>>>
>>>>>>   Why there is a problem with the return value?
>>>>> In this case, it copies 4 characters from the source uint32_t and then
>>>>>
>>>> add
>>>>
>>>>> NULL terminator.
>>>>>
>>>> And then it will call strlen on the input value to calculate the return
>>>> value and overread until it either hits a 0 by chance or crashes.
>>>>
>>>>   By the way, I've tried using AV_WB32 instead but it swapped the
>>>>>
>>>> characters.
>>>>
>>>>> Maybe AV_WL32 should be used.
>>>>>
>>>> Since get_le32 was used, yes it should be AV_WL32.
>>>> But the log message will still print it in the wrong order on big-endian
>>>> systems.
>>>> IMO the whole casting mess should be removed and type would better be
>>>> uint8_t type[5] ={0};
>>>> get_buffer(pb, type, 4);
>>>>
>>>>
>>>>   Looks to me like a good solution.
>>>
>>>
>>>   +        // check that char is legal - not NULL
>>>>> +        if (next_comp_brand_ptr[0]&&   next_comp_brand_ptr[1]&&
>>>>>
>>>> next_comp_brand_ptr[2]&&   next_comp_brand_ptr[3]) {
>>>>
>>>> Not sure if this should be checked more tightly, e.g. for ASCII, or for
>>>> printable or...
>>>>
>>>>
>>> I think isprint() is better than just compare to NULL.
>>>
>>
>> IMHO get rid of the cruft and export everything even if it's not printable.
>>
>> "Each brand is a printable four-character code, registered with ISO, that
>> identifies a precise specification."
>>
>> It should not happen, if it happens, well, file is broken and we will add
>> cruft to handle this later.
>>
>
> OK, but the NULL check is important to enable proper dispatching by the
> client application.
>
> Attached.
>
> Thanks,
> Haim.
>
>
> ------------------------------------------------------------------------
>
> Index: libavformat/mov.c
> ===================================================================
> --- libavformat/mov.c	(revision 19796)
> +++ libavformat/mov.c	(working copy)
> @@ -485,15 +485,50 @@
> [...]
>
> +
> +    num_comp_brand = (atom.size - 8) / 4;
> +    comp_brands_str = av_malloc(num_comp_brand*4 + 1); /* 4 characters for each brand + null terminator */
> +    curr_comp_brand_ptr = comp_brands_str;
> +    orig_num_comp_brand = num_comp_brand;
> +    for (i = 0; i<  orig_num_comp_brand; i++) { /*compatible brands*/
> +        next_comp_brand = get_le32(pb);
> +        next_comp_brand_ptr = (char*)&next_comp_brand;
> +        // check that char is legal - not NULL
> +        if (next_comp_brand_ptr[0]&&  next_comp_brand_ptr[1]&&  next_comp_brand_ptr[2]&&  next_comp_brand_ptr[3]) {
> +            memcpy(curr_comp_brand_ptr,&next_comp_brand, 4);
> +            curr_comp_brand_ptr += 4;
> +        } else {
> +            av_log(c->fc, AV_LOG_WARNING, "compatible brand name contains illegal character - skipped.\n");
> +            num_comp_brand -= 1; /* reduce counter since brand is skipped */
> +        }
> +    }
> +    *curr_comp_brand_ptr = '\0';
> +    av_metadata_set(&c->fc->metadata, "compatible_brands", comp_brands_str);
> +    av_freep(&comp_brands_str);
> +    snprintf(num_comp_brand_str, sizeof(num_comp_brand_str), "%d", num_comp_brand);
> +    av_metadata_set(&c->fc->metadata, "compatible_brands_num", num_comp_brand_str);
>       return 0;
>   }

Please remove the special treatment of compatible brands.
It should be one get_buffer only, and compatible_brands_num is useless: 
it will be strlen(compatible_brands)/4.

Besides, as an overall comment, too much code is needed to export 
metadata, but that's not your fault.
Especially these array declarations, snprintf, av_metadata_set for ints 
really annoy me, this should be simplified by adding av_metadata_set_int 
or something.

-- 
Baptiste COUDURIER
Key fingerprint                 8D77134D20CC9220201FC5DB0AC9325C5C1ABAAA
FFmpeg maintainer                                  http://www.ffmpeg.org



More information about the ffmpeg-devel mailing list