[FFmpeg-devel] AVWriter API

Nicolas George george at nsup.org
Sun Dec 8 16:25:43 EET 2019


Hi.

[ TL;DR: a lightweight oo API for functions that need to return a
string, designed to be as convenient as possible. ]

Yesterday, in my comments about the new channel layout API:
https://ffmpeg.org/pipermail/ffmpeg-devel/2019-December/254020.html
I evoked the following issue:

We have many functions that return strings to the caller:

char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt);
const char *av_get_media_type_string(enum AVMediaType media_type);
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
int av_dict_get_string(const AVDictionary *m, char **buffer,
                       const char key_val_sep, const char pairs_sep);
int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size);
const char *av_get_known_color_name(int color_idx, const uint8_t **rgb);
const char *av_color_range_name(enum AVColorRange range);
char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit);
static inline char *av_ts_make_string(char *buf, int64_t ts)
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);

The simplest of them are "enum → static string" functions, but what do
they do with an invalid value: return NULL or a meaningful string like
"unknown"?

A lot of them demand a pair of "char *buf, size_t buf_size" arguments to
return the string. What is a reasonable size for the buffer? How do we
handle the cases where the buffer is too small?

When the string is likely to be long, they dynamically allocate the
buffer.

This is an inconsistent mess. And unsatisfactory on top of it: most of
the time, we will just copy the buffer to another buffer, write it to a
file or dump it to a log. The string function may need a big buffer to
build the string while it is at no point necessary to have it in full.

I have been wanting to find a clean solution for this issue for a long
time. And now I have. (The AVBPrint was a preliminary attempt at that.)

But before polishing it, I wanted to know the opinions of my fellow
developers on this issue. The design is a bit unconventional (which is
what enables it to be convenient), I suspect some people may object
because of that.

I have attached the header file so people can have a look at it.

The idea is to implement the bare minimum of a very simple object
system. 

To return a string (or a binary blob, that changes nothing), the
functions take an AVWriter object and just write to it using a
fprintf()-like function or other useful functions.

The AVWriter object is abstract and can actually write in several
different ways. av_buf_writer_array(buf) will just wrap "char buf[42]"
and write in it. av_dynbuf_writer() prepares a dynamic buffer.
av_log_writer(obj) writes to av_log().

User application can implement their own AVWriter types: write directly
in a GUI text buffer or to syslog.

I wanted to avoid as much as possible adding new necessary error checks.
I think I have succeeded.

	av_foobar_to_string(buf, sizeof(buf), foobar);

becomes

	av_foobar_write(av_buf_writer_array(buf), foobar);

which has a little more letters but is actually simpler.

But it is really more interesting than that because if we keep the same
AVWriter for several call, it will just concatenate, allowing to build a
message.

Another thing that is not yet in the header: have all the
av_foobar_write() function take an extra "unsigned flags" argument. And
have a few transverse flags, especially:

#define AV_WRITER_FALLBACK (1U << 16)

When this flag is set, the function writes a fall-back string for
unknown values ("unknown", "?", "invalid", depends on the type).
Otherwise, it prints nothing.

Before working more on integrating this, I would like a little feedback,
please.

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: writer.h
Type: text/x-chdr
Size: 10995 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20191208/24864cc1/attachment.h>
-------------- 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/20191208/24864cc1/attachment.sig>


More information about the ffmpeg-devel mailing list