From: Ramiro Polla <ramiro.polla@gmail.com> To: ffmpeg-devel@ffmpeg.org Subject: Re: [FFmpeg-devel] [FFmpeg-cvslog] fftools/resources: Add resource manager files with build-time compression Date: Fri, 30 May 2025 13:23:40 +0200 Message-ID: <CALweWgAMMxGXrRmXMtLFtusSyRWZb+1RvrPH3R-wAv0tpDVgZg@mail.gmail.com> (raw) In-Reply-To: <20250515211142.3D1624128D7@natalya.videolan.org> On Thu, May 15, 2025 at 11:11 PM softworkz <git@videolan.org> wrote: > > ffmpeg | branch: master | softworkz <softworkz@hotmail.com> | Thu May 15 23:07:54 2025 +0200| [517a8055655798970d94a4c5ea912511362520ea] | committer: softworkz > > fftools/resources: Add resource manager files with build-time compression > > Compression requires zlib to be available, otherwise resources will > be included uncompressed - in either case via BIN2C. > > It can also be disabled via > > ./configure --disable-resource-compression > > Size figures: > > graph.css 7752 > graph.css.min 6655 (css is always minified) > graph.html 2153 > > No Compression > > graph.css.c 40026 > graph.css.o 9344 (6688) > graph.html.c 13016 > graph.html.o 4848 (2186) > > With Compression > > graph.css.c 10206 > graph.css.o 4368 (1718) > graph.html.c 5725 > graph.html.o 3632 (971) > > Numbers in brackets: .rodata size from 'size -Ax -d *.o' > > Signed-off-by: softworkz <softworkz@hotmail.com> > > > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=517a8055655798970d94a4c5ea912511362520ea > --- > > configure | 5 + > ffbuild/common.mak | 43 +++++- > fftools/Makefile | 3 +- > fftools/resources/.gitignore | 4 + > fftools/resources/Makefile | 13 ++ > fftools/resources/graph.css | 353 +++++++++++++++++++++++++++++++++++++++++++ > fftools/resources/graph.html | 86 +++++++++++ > fftools/resources/resman.c | 231 ++++++++++++++++++++++++++++ > fftools/resources/resman.h | 50 ++++++ > 9 files changed, 785 insertions(+), 3 deletions(-) [...] > diff --git a/fftools/resources/resman.c b/fftools/resources/resman.c > new file mode 100644 > index 0000000000..a9e21626fa > --- /dev/null > +++ b/fftools/resources/resman.c > @@ -0,0 +1,231 @@ > +/* > + * Copyright (c) 2025 - softworkz > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +/** > + * @file > + * output writers for filtergraph details > + */ > + > +#include "config.h" > + > +#include <string.h> > + > +#if CONFIG_RESOURCE_COMPRESSION > +#include <zlib.h> > +#endif > + > +#include "resman.h" > +#include "fftools/ffmpeg_filter.h" > +#include "libavutil/avassert.h" > +#include "libavutil/pixdesc.h" > +#include "libavutil/dict.h" > +#include "libavutil/common.h" > + > +extern const unsigned char ff_graph_html_data[]; > +extern const unsigned int ff_graph_html_len; > + > +extern const unsigned char ff_graph_css_data[]; > +extern const unsigned ff_graph_css_len; > + > +static const FFResourceDefinition resource_definitions[] = { > + [FF_RESOURCE_GRAPH_CSS] = { FF_RESOURCE_GRAPH_CSS, "graph.css", &ff_graph_css_data[0], &ff_graph_css_len }, > + [FF_RESOURCE_GRAPH_HTML] = { FF_RESOURCE_GRAPH_HTML, "graph.html", &ff_graph_html_data[0], &ff_graph_html_len }, > +}; > + > + > +static const AVClass resman_class = { > + .class_name = "ResourceManager", > +}; > + > +typedef struct ResourceManagerContext { > + const AVClass *class; > + AVDictionary *resource_dic; > +} ResourceManagerContext; > + > +static AVMutex mutex = AV_MUTEX_INITIALIZER; > + > +ResourceManagerContext *resman_ctx = NULL; static > +#if CONFIG_RESOURCE_COMPRESSION > + > +static int decompress_gzip(ResourceManagerContext *ctx, uint8_t *in, unsigned in_len, char **out, size_t *out_len) > +{ > + z_stream strm; > + unsigned chunk = 65534; > + int ret; > + uint8_t *buf; > + > + *out = NULL; > + memset(&strm, 0, sizeof(strm)); > + > + // Allocate output buffer with extra byte for null termination > + buf = (uint8_t *)av_mallocz(chunk + 1); Unnecessary cast. > + if (!buf) { > + av_log(ctx, AV_LOG_ERROR, "Failed to allocate decompression buffer\n"); > + return AVERROR(ENOMEM); > + } > + > + // 15 + 16 tells zlib to detect GZIP or zlib automatically > + ret = inflateInit2(&strm, 15 + 16); > + if (ret != Z_OK) { > + av_log(ctx, AV_LOG_ERROR, "Error during zlib initialization: %s\n", strm.msg); > + av_free(buf); > + return AVERROR(ENOSYS); > + } > + > + strm.avail_in = in_len; > + strm.next_in = in; > + strm.avail_out = chunk; > + strm.next_out = buf; > + > + ret = inflate(&strm, Z_FINISH); > + if (ret != Z_OK && ret != Z_STREAM_END) { > + av_log(ctx, AV_LOG_ERROR, "Inflate failed: %d, %s\n", ret, strm.msg); > + inflateEnd(&strm); > + av_free(buf); > + return (ret == Z_STREAM_END) ? Z_OK : ((ret == Z_OK) ? Z_BUF_ERROR : ret); > + } > + > + if (strm.avail_out == 0) { > + // TODO: Error or loop decoding? ^^ > + av_log(ctx, AV_LOG_WARNING, "Decompression buffer may be too small\n"); > + } > + > + *out_len = chunk - strm.avail_out; > + buf[*out_len] = 0; // Ensure null termination > + > + inflateEnd(&strm); > + *out = (char *)buf; > + return Z_OK; > +} > +#endif > + > +static ResourceManagerContext *get_resman_context(void) > +{ > + ResourceManagerContext *res = resman_ctx; > + > + ff_mutex_lock(&mutex); > + > + if (res) > + goto end; > + > + res = av_mallocz(sizeof(ResourceManagerContext)); > + if (!res) { > + av_log(NULL, AV_LOG_ERROR, "Failed to allocate resource manager context\n"); > + goto end; > + } > + > + res->class = &resman_class; > + resman_ctx = res; > + > +end: > + ff_mutex_unlock(&mutex); > + return res; > +} > + > + > +void ff_resman_uninit(void) > +{ > + ff_mutex_lock(&mutex); > + > + if (resman_ctx) { > + if (resman_ctx->resource_dic) > + av_dict_free(&resman_ctx->resource_dic); > + av_freep(&resman_ctx); > + } > + > + ff_mutex_unlock(&mutex); > +} > + > + > +char *ff_resman_get_string(FFResourceId resource_id) const char * > +{ > + ResourceManagerContext *ctx = get_resman_context(); > + FFResourceDefinition resource_definition = { 0 }; > + AVDictionaryEntry *dic_entry; > + char *res = NULL; > + > + if (!ctx) > + return NULL; > + > + for (unsigned i = 0; i < FF_ARRAY_ELEMS(resource_definitions); ++i) { > + FFResourceDefinition def = resource_definitions[i]; > + if (def.resource_id == resource_id) { > + resource_definition = def; > + break; > + } > + } > + > + if (!resource_definition.name) { > + av_log(ctx, AV_LOG_ERROR, "Unable to find resource with ID %d\n", resource_id); > + return NULL; > + } > + > + ff_mutex_lock(&mutex); > + > + dic_entry = av_dict_get(ctx->resource_dic, resource_definition.name, NULL, 0); > + > + if (!dic_entry) { > + int dict_ret; > + > +#if CONFIG_RESOURCE_COMPRESSION > + > + char *out = NULL; > + size_t out_len; > + > + int ret = decompress_gzip(ctx, (uint8_t *)resource_definition.data, *resource_definition.data_len, &out, &out_len); > + > + if (ret) { > + av_log(NULL, AV_LOG_ERROR, "Unable to decompress the resource with ID %d\n", resource_id); > + goto end; > + } > + > + dict_ret = av_dict_set(&ctx->resource_dic, resource_definition.name, out, 0); > + if (dict_ret < 0) { > + av_log(NULL, AV_LOG_ERROR, "Failed to store decompressed resource in dictionary: %d\n", dict_ret); > + av_freep(&out); > + goto end; > + } > + > + av_freep(&out); > +#else > + > + dict_ret = av_dict_set(&ctx->resource_dic, resource_definition.name, (const char *)resource_definition.data, 0); > + if (dict_ret < 0) { > + av_log(NULL, AV_LOG_ERROR, "Failed to store resource in dictionary: %d\n", dict_ret); > + goto end; > + } > + > +#endif > + dic_entry = av_dict_get(ctx->resource_dic, resource_definition.name, NULL, 0); > + > + if (!dic_entry) { > + av_log(NULL, AV_LOG_ERROR, "Failed to retrieve resource from dictionary after storing it\n"); > + goto end; > + } > + } > + > + res = dic_entry->value; > + > +end: > + ff_mutex_unlock(&mutex); > + return res; > +} > diff --git a/fftools/resources/resman.h b/fftools/resources/resman.h > new file mode 100644 > index 0000000000..6485db5091 > --- /dev/null > +++ b/fftools/resources/resman.h > @@ -0,0 +1,50 @@ > +/* > + * Copyright (c) 2025 - softworkz > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#ifndef FFTOOLS_RESOURCES_RESMAN_H > +#define FFTOOLS_RESOURCES_RESMAN_H > + > +#include <stdint.h> > + > +#include "config.h" > +#include "fftools/ffmpeg.h" > +#include "libavutil/avutil.h" > +#include "libavutil/bprint.h" > +#include "fftools/textformat/avtextformat.h" All includes in this file are unnecessary. > + > +typedef enum { > + FF_RESOURCE_GRAPH_CSS, > + FF_RESOURCE_GRAPH_HTML, > +} FFResourceId; > + > +typedef struct FFResourceDefinition { > + FFResourceId resource_id; > + const char *name; > + > + const unsigned char *data; > + const unsigned *data_len; > + > +} FFResourceDefinition; > + > +void ff_resman_uninit(void); > + > +char *ff_resman_get_string(FFResourceId resource_id); > + > +#endif /* FFTOOLS_RESOURCES_RESMAN_H */ _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next parent reply other threads:[~2025-05-30 11:24 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top [not found] <20250515211142.3D1624128D7@natalya.videolan.org> 2025-05-30 11:23 ` Ramiro Polla [this message] 2025-05-31 1:53 ` softworkz .
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=CALweWgAMMxGXrRmXMtLFtusSyRWZb+1RvrPH3R-wAv0tpDVgZg@mail.gmail.com \ --to=ramiro.polla@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git