[FFmpeg-devel] Suggestion for a centralized language-tag facility in libavformat

Michael Niedermayer michaelni
Mon Apr 20 04:26:07 CEST 2009


On Mon, Apr 20, 2009 at 12:07:47AM +0200, cyril comparon wrote:
> Here is the new implementation and its use in the asf demuxer and muxer.
> The algorithm has become fairly more complicated than originally :)
> but it works perfectly.

[...]
> +static int langTable_compare(const void *lhs, const void *rhs)
> +{
> +    return strcmp(((const LangEntry *)lhs)->str, ((const LangEntry *)rhs)->str);
> +}
> +

> +const char *av_convertLangTo(const char *lang, enum AV_LangCodespace targetCodespace)
> +{
> +    int i;
> +    LangEntry searchedEntry;
> +    const LangEntry *entry = NULL;
> +    const int NB_CODESPACES = sizeof(langTableCounts)/sizeof(*langTableCounts);

> +    assert(targetCodespace >= 0 && targetCodespace < NB_CODESPACES);

I would prefer if this would be a hard check instead of a assert()


> +
> +    av_strlcpy(searchedEntry.str, lang, 4);

this and searchedEntry are redundant


> +    for (i=0; i<NB_CODESPACES; i++) {
> +        void *res = bsearch(&searchedEntry,
> +                            langTable + langTableOffsets[i],
> +                            langTableCounts[i],
> +                            sizeof(LangEntry),
> +                            langTable_compare);
> +        if (res) {
> +            entry = res;
> +            break;
> +        }

the temporary variable res is redundant as well


[...]
> Index: libavformat/asfdec.c
> ===================================================================
> --- libavformat/asfdec.c	(revision 18630)
> +++ libavformat/asfdec.c	(working copy)
> @@ -25,6 +25,7 @@
>  #include "riff.h"
>  #include "asf.h"
>  #include "asfcrypt.h"
> +#include "avlanguage.h"
>  
>  void ff_mms_set_stream_selection(URLContext *h, AVFormatContext *format);
>  
> @@ -76,6 +77,7 @@
>      else PRINT_IF_GUID(g, ff_asf_ext_stream_audio_stream);
>      else PRINT_IF_GUID(g, ff_asf_metadata_header);
>      else PRINT_IF_GUID(g, stream_bitrate_guid);
> +    else PRINT_IF_GUID(g, ff_asf_language_guid);
>      else
>          dprintf(NULL, "(GUID: unknown) ");
>      for(i=0;i<16;i++)

> @@ -403,6 +405,16 @@
>  //                av_log(s, AV_LOG_ERROR, "flags: 0x%x stream id %d, bitrate %d\n", flags, stream_id, bitrate);
>                  asf->stream_bitrates[stream_id]= bitrate;
>              }
> +        } else if (!guidcmp(&g, &ff_asf_language_guid)) {
> +            int stream_count = get_le16(pb);
> +            int j;
> +            for(j = 0; j < stream_count; j++) {
> +                char lang[1024];
> +                uint8_t lang_len;
> +                lang_len = get_byte(pb);
> +                get_str16_nolen(pb, lang_len, lang, sizeof(lang));
> +                asf->stream_languages[j] = av_strdup(lang);
> +            }
>          } else if (!guidcmp(&g, &ff_asf_extended_content_header)) {
>              int desc_count, i;
>  

exploitable


> @@ -455,7 +467,7 @@
>              get_le32(pb); // max-object-size
>              get_le32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
>              stream_num = get_le16(pb); // stream-num
> -            get_le16(pb); // stream-language-id-index
> +            asf->streams[stream_num].stream_language_index = get_le16(pb); // stream-language-id-index
>              get_le64(pb); // avg frametime in 100ns units
>              stream_ct = get_le16(pb); //stream-name-count
>              payload_ext_ct = get_le16(pb); //payload-extension-system-count

> @@ -534,7 +546,16 @@
>                  av_reduce(&st->sample_aspect_ratio.num,
>                            &st->sample_aspect_ratio.den,
>                            dar[i].num, dar[i].den, INT_MAX);
> -//av_log(s, AV_LOG_ERROR, "dar %d:%d sar=%d:%d\n", dar[i].num, dar[i].den, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);

unrelated


> +
> +            // copy and convert language codes to the frontend
> +            uint16_t stream_language_index = asf->streams[i].stream_language_index;

mixing of declaration and statement breaks gcc 2.95


> +            const char *rfc1766 = asf->stream_languages[stream_language_index];

the array isnt as large as the index may be


[...]
>  #include <assert.h>
> @@ -364,6 +365,32 @@
>          end_header(pb, hpos);
>      }
>  
> +    /* language list */
> +    hpos = put_header(pb, &ff_asf_language_guid);
> +    {
> +        unsigned int streamsWithSupportedLang = 0;
> +        for(n=0;n<s->nb_streams;n++) {
> +            AVMetadataTag *lang_tag = av_metadata_get(s->streams[n]->metadata, "language", NULL, 0);
> +            if (lang_tag) {
> +                const char *language = av_convertLangTo(lang_tag->value, AV_LANG_ISO639_1);
> +                if (language)
> +                    streamsWithSupportedLang++;
> +            }
> +        }
> +        put_le16(pb, streamsWithSupportedLang);
> +    }
> +    for(n=0;n<s->nb_streams;n++) {
> +        AVMetadataTag *lang_tag = av_metadata_get(s->streams[n]->metadata, "language", NULL, 0);
> +        if (lang_tag) {
> +            const char *language = av_convertLangTo(lang_tag->value, AV_LANG_ISO639_1);
> +            if (language) {
> +                put_byte(pb, 2*(1+strlen(language)));
> +                put_str16_nolen(pb, language);
> +            }
> +        }
> +    }
> +    end_header(pb, hpos);

that looks like it randomly stores languages so that they no longer can be
matched to the streams

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090420/e5fd4fea/attachment.pgp>



More information about the ffmpeg-devel mailing list