[FFmpeg-devel] [PATCH] [2/??] [3/3] Filter graphs - Parser for a graph description
Michael Niedermayer
michaelni
Thu Apr 10 22:55:30 CEST 2008
On Thu, Apr 10, 2008 at 08:55:24PM +0200, Vitor Sessak wrote:
> Michael Niedermayer wrote:
>> On Sun, Apr 06, 2008 at 10:39:00PM +0200, Vitor Sessak wrote:
[...]
>> [...]
>>> /**
>>> * A linked-list of the inputs/outputs of the filter chain.
>>> */
>>> typedef struct AVFilterInOut {
>>> enum LinkType type;
>>> char *name;
>>> AVFilterContext *filter;
>>> int pad_idx;
>>>
>>> struct AVFilterInOut *next;
>>> } AVFilterInOut;
>> I wonder if an array would be simpler than a linked list ...
>
> I'm not sure it would be really simpler. For me, it will only save one or
> two malloc lines...
Well, i will think more about this, but as is the parser currently looks
too complex for what it supports ...
[...]
> Also, are you ok to commit it without svn history? It was rewritten from
> scratch...
Iam ok with ommiting unrelated history / what is prior to your rewrite ...
[...]
> /**
> * For use in av_log
> */
> static const char *log_name(void *p)
> {
> return "Filter parser";
> }
>
> static const AVClass filter_parser_class = {
> "Filter parser",
> log_name
> };
>
> static const AVClass *log_ctx = &filter_parser_class;
I do not like this. This is a hack not the correct way to use av_log()
>
> static AVFilterContext *create_filter(AVFilterGraph *ctx, int index,
> char *name, char *args)
shouldnt name and args be const
[...]
> /**
> * Consumes a string from *buf.
> * @return a copy of the consumed string, which should be free'd after use
> */
> static char *consume_string(const char **buf)
> {
> char *out = av_malloc(strlen(*buf) + 1);
> const char *in = *buf;
> char *ret = out;
>
> consume_whitespace(buf);
>
> do{
> char c = *in++;
you change buf but use in, also why arent you useing just one variable ...
> switch (c) {
> case '\\':
> *out++= *in++;
> break;
> case '\'':
> while(*in && *in != '\'')
> *out++= *in++;
> if(*in) in++;
> break;
> case 0:
> case ']':
> case '[':
> case '=':
> case ',':
> *out++= 0;
> break;
> default:
> *out++= c;
> }
> } while(out[-1]);
What about trailing whitespace?
>
> *buf = in-1;
> return ret;
> }
>
> /**
> * Parse "[linkname]"
> * @arg name a pointer (that need to be free'd after use) to the name between
> * parenthesis
> */
> static void parse_link_name(const char **buf, char **name)
> {
> const char *start = *buf;
> (*buf)++;
>
> *name = consume_string(buf);
>
> if(!*name[0]) {
> av_log(&log_ctx, AV_LOG_ERROR,
> "Bad (empty?) label found in the following: \"%s\".\n", start);
> goto fail;
> }
>
> if(*(*buf)++ != ']') {
> av_log(&log_ctx, AV_LOG_ERROR,
> "Mismatched '[' found in the following: \"%s\".\n", start);
> goto fail;
> }
>
> return;
>
> fail:
> av_freep(name);
> }
you can at least move the fail: free to where the second goto is, this also
makes the return redundant.
[...]
> /**
> * Parse "[a1][link2] ... [etc]"
> */
> static int parse_inouts(const char **buf, AVFilterInOut **inout, int pad,
> enum LinkType type, AVFilterContext *filter)
> {
> while (**buf == '[') {
> AVFilterInOut *inoutn = av_malloc(sizeof(AVFilterInOut));
> parse_link_name(buf, &inoutn->name);
>
> if (!inoutn->name) {
> av_free(inoutn);
> return -1;
> }
>
> inoutn->type = type;
> inoutn->filter = filter;
> inoutn->pad_idx = pad++;
> inoutn->next = *inout;
vertical align
[...]
> /**
> * Parse a string describing a filter graph.
> */
> int avfilter_parse_graph(AVFilterGraph *graph, const char *filters,
> AVFilterContext *in, int inpad,
> AVFilterContext *out, int outpad)
> {
> AVFilterInOut *inout=NULL;
> AVFilterInOut *head=NULL;
>
> int index = 0;
> char chr = 0;
> int pad = 0;
> int has_out = 0;
>
> AVFilterContext *last_filt = NULL;
>
> consume_whitespace(&filters);
>
> do {
> AVFilterContext *filter;
> int oldpad = pad;
> const char *inouts = filters;
>
> // We need to parse the inputs of the filter after we create it, so
> // skip it by now
> filters = skip_inouts(filters);
>
> if(!(filter = parse_filter(&filters, graph, index)))
> goto fail;
>
> pad = parse_inouts(&inouts, &inout, chr == ',', LinkTypeIn, filter);
>
> if(pad < 0)
> goto fail;
>
> // If the first filter has an input and none was given, it is
> // implicitly the input of the whole graph.
> if(pad == 0 && filter->input_count == 1) {
> if(link_filter(in, inpad, filter, 0))
> goto fail;
> }
>
> if(chr == ',') {
> if(link_filter(last_filt, oldpad, filter, 0) < 0)
> goto fail;
> }
>
> pad = parse_inouts(&filters, &inout, 0, LinkTypeOut, filter);
> chr = *filters++;
> index++;
> last_filt = filter;
> } while (chr == ',' || chr == ';');
>
> head = inout;
> for (; inout != NULL; inout = inout->next) {
Why dont you build the graph in 1 pass?
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes
-------------- 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/20080410/5e560ca2/attachment.pgp>
More information about the ffmpeg-devel
mailing list