[FFmpeg-devel] AVWriter again (was: v2 1/2] avformat/url: check double dot is not to parent directory)

Nicolas George george at nsup.org
Tue Jul 28 00:34:13 EEST 2020


Steven Liu (12020-07-27):
> Because language barries. maybe I cannot deep understand, maybe need
> more code examples.
> But look interesting, maybe more easy for use.

All right, here is a practical albeit fictional example.

Let us say we want av_metadata_to_user_string() that turns an
AVDictionary into a string for users, and show_metadata_in_dialog() to
print the metadata of all the streams in a file in a GUI dialog.

av_metadata_to_user_string() using naïve av_malloc():

char *av_metadata_to_user_string(AVDictionary *meta)
{
    size_t size = 1, len;
    AVDictionaryEntry *entry;
    char *str, *cur;

    entry = NULL;
    while ((entry = av_dict_get(meta, "", entry, AV_DICT_IGNORE_SUFFIX))) {
        len = strlen(entry->key);
        if (len > SIZE_MAX - size)
            return NULL;
        size += len;
        len = strlen(entry->value);
        if (len > SIZE_MAX - size)
            return NULL;
        size += len;
        if (3 > SIZE_MAX - size)
            return NULL;
        size += 3;
    }
    str = av_malloc(size);
    if (!str)
        return AVERROR(ENOMEM);
    cur = str;
    entry = NULL;
    while ((entry = av_dict_get(meta, "", entry, AV_DICT_IGNORE_SUFFIX))) {
        cur += av_strlcatf(cur, "%s: %s\n", entry->key, entry->value, str + size - cur);
    }
    av_assert0(cur == str + size - 1);
    return str;
}

av_metadata_to_user_string() using AVBPrint:

void av_metadata_to_user_string(AVWriter wr, AVDictionary *meta)
{
    AVDictionaryEntry *entry;

    while ((entry = av_dict_get(meta, "", entry, AV_DICT_IGNORE_SUFFIX))) {
        av_writer_printf(wr, entry->key, entry->value, str + size - cur);
    }
}

show_metadata_in_dialog(), without AVBPrint, but relying on Gtk+'s
features (I want to show AVWriter is good, it would be dishonest not to
use all the tools to make the other side look good):

void show_metadata_in_dialog(AVFormatContext *ctx, GtkLabel *label)
{
    GString *str = g_string_new();
    unsigned i;

    for (i = 0; i < ctx->nb_streams; i++) {
        char *meta = av_metadata_to_user_string(ctx->streams->metadata);
        if (!meta)
            fatal_error("out of memory");
        g_string_printf("Stream #%d:\n%s\n", i, meta);
        av_free(meta);
    }
    gtk_label_set_text(label, str->str);
    g_string_free(str);
}

show_metadata_in_dialog() using AVBPrint:

void show_metadata_in_dialog(AVFormatContext *ctx, GtkLabel *label)
{
    AVWriter = av_dynbuf_writer();
    unsigned i;

    for (i = 0; i < ctx->nb_streams; i++) {
        av_writer_printf(wr, "Stream #%d:\n", i);
        av_metadata_to_user_string(wr, ctx->streams->metadata);
        g_string_print(wr, "\n");
    }
    if (av_dynbuf_writer_get_error(wr))
        fatal_error("out of memory");
    gtk_label_set_text(label, av_dynbuf_writer_get_data(wr, NULL));
    av_dynbuf_writer_reset(wr);
}

Now, imagine if a lot of FFmpeg functions did use the same AVWriter, and
therefore worked well together.

Also, not visible in the code: unless the metadata is big, the AVWriter
version will keep all in the stack.

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20200727/de3adba9/attachment.sig>


More information about the ffmpeg-devel mailing list