[FFmpeg-devel] [PATCH] [2/??] [3/3] Filter graphs - Parser for a graph description
Vitor Sessak
vitor1001
Fri May 9 20:44:23 CEST 2008
Hi
Michael Niedermayer wrote:
> On Mon, May 05, 2008 at 10:01:36PM +0200, Vitor Sessak wrote:
>> Michael Niedermayer wrote:
>>> On Wed, Apr 23, 2008 at 11:05:37PM +0200, Vitor Sessak wrote:
>>>> Hi and thanks for the review
>>> [...]
>>>>>> p->filter = filter;
>>>>>> p->pad_idx = pad;
>>>>>> p->next = *openLinks;
>>>>>> *openLinks = p;
>>>>>> }
>>>>>> }
>>>>>>
>>>>>>
>>>>>> if(*currInputs) {
>>>>>> av_log(log_ctx, AV_LOG_ERROR,
>>>>>> "Too many inputs specified for the \"%s\" filter.\n",
>>>>>> filter->name);
>>>>>> return -1;
>>>>>> }
>>>>>>
>>>>>> pad = filter->output_count;
>>>>>> while(pad) {
>>>>>> AVFilterInOut *currlinkn = av_malloc(sizeof(AVFilterInOut));
>>>>>> pad--;
>>>>>> currlinkn->name = NULL;
>>>>>> currlinkn->type = LinkTypeOut;
>>>>>> currlinkn->filter = filter;
>>>>>> currlinkn->pad_idx = pad;
>>>>>> currlinkn->next = *currInputs;
>>>>>> *currInputs = currlinkn;
>>>>> somehow i thik this can be factored with the above as well
>>>> Maybe, but without worsening a lot readability?
>>> We need to find a way to simplify the whole parser without reducing
>>> readability.
>>> Its much more complex than i would like ...
>> Do you really think it can be so much more simpler? The "complex" part
>> of it (free_inout(), extract_inout(), link_filter_inouts(),
>> parse_inputs(), parse_outputs(), avfilter_parse_graph()) make 240 lines
>> of code.
>
> What i really dont like on the code is that it is complex and at the
> same time only supports a small subset of what we wanted to support.
> 300 lines would be fine for a complete implemantation with ; * () user
> defined filters, and all the other things discussed
> Saying ok to the code to then see it grow to 3 times that to support
> everything is something i really dont want to see ...
>
> Also when i just look at the API i cant help but it feels quite hostile
> to an implemantation of "user defined filters", and not only that.
>
>
> [...]
>>>>>> AVFilterInOut *currlinkn =
>>>>>> av_malloc(sizeof(AVFilterInOut));
>>>>>>
>>>>>> currlinkn->name = name;
>>>>>> currlinkn->type = LinkTypeIn;
>>>>>> currlinkn->filter = NULL;
>>>>>> currlinkn->pad_idx = pad;
>>>>>> currlinkn->next = *currInputs;
>>>>>> *currInputs = currlinkn;
>>>>> Ive seen similar code a few times already here somewhere ...
>>>> This code appears three times. But doing something like
>>>>
>>>> currlinkn = new_link(NULL, LinkTypeOut, filter, pad, *currInputs);
>>>>
>>>> wouldn't make this new_link() function a senseless wrapper?
>>> maybe iam not sure, do what you prefer
>> I did instead
>>
>> AVFilterInOut tmp_link = { LinkTypeIn,
>> name,
>> NULL,
>> pad,
>> *currInputs,
>> };
>> AVFilterInOut *currlinkn = av_malloc(sizeof(AVFilterInOut));
>> *currlinkn = tmp_link;
>>
>> I think it is more readable.
>
> I dont, i prefered the original
>
> also
> currlinkn->next = *currInputs;
> *currInputs = currlinkn;
>
> is duplicated, its a insert_blah()
done
>>> Also name could be moved to AVFilterLink, that way we would still have
>>> the names after the filter graph is build as a sideeffect.
>> I agree that would be a nice side-effect (that could be done even
>> without changing AVFilterInOut).
>
> What i was aiming at was to remove the AVFilterInOut struct completely.
> I just am not sure yet if its a good idea or not, but moving name out is a
> good idea even on its own.
> Leaving it in AVFilterInOut while adding it to AVFilterLink would be just
> a duplicate field.
Yes, but I find ugly to make a linked list of AVFilterLink to use either
only src and srcpad or only dst and dstpad. And I don't see a non-ugly
way to use both...
>> /**
>> * 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, AVClass *log_ctx)
>> {
>> 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);
>> fail:
>> av_freep(name);
>> }
>> }
>
> this function should return char * not void.
done
>> static void free_inout(AVFilterInOut *head)
>> {
>> while(head) {
>> AVFilterInOut *next = head->next;
>> av_free(head);
>> head = next;
>> }
>> }
>>
>
>> static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
>> {
>> AVFilterInOut *ret;
>>
>> while(*links && strcmp((*links)->name, label))
>> links = &((*links)->next);
>>
>> ret = *links;
>>
>> if(ret)
>> *links = ret->next;
>>
>> return ret;
>> }
>
> Maybe it would be cleaner to split this in find and remove ?
Why? Also it forces the use of (*match)->field which is more ugly...
>
> static AVFilterInOut **find_inout(const char *label, AVFilterInOut **links)
> {
> while(*links && strcmp((*links)->name, label))
> links = &((*links)->next);
>
> return links;
> }
>
> x= find_inout()
> if(*x)
> *x = (*x)->next;
>
> the if() exists already after all extract_inout() calls
>>
>> static int link_filter_inouts(AVFilterContext *filter,
>> AVFilterInOut **currInputs,
>> AVFilterInOut **openLinks, AVClass *log_ctx)
>> {
>> int pad = filter->input_count;
>>
>> while(pad--) {
>
>> AVFilterInOut *p = *currInputs;
>> *currInputs = (*currInputs)->next;
>> if(!p) {
>
>> av_log(log_ctx, AV_LOG_ERROR,
>
> unreachable, this would have segfaulted already
fixed
> [...]
>> static int parse_inputs(const char **buf, AVFilterInOut **currInputs,
>> AVFilterInOut **openLinks, AVClass *log_ctx)
>> {
>> int pad = 0;
>>
>> while(**buf == '[') {
>> char *name;
>> AVFilterInOut *link_to_add;
>> AVFilterInOut *match;
>>
>> parse_link_name(buf, &name, log_ctx);
>>
>> if(!name)
>> return -1;
>>
>> /* First check if the label is not in the openLinks list */
>> match = extract_inout(name, openLinks);
>>
>> if(match) {
>> /* A label of a open link. Make it one of the inputs of the next
>> filter */
>> if(match->type != LinkTypeOut) {
>> av_log(log_ctx, AV_LOG_ERROR,
>> "Label \"%s\" appears twice as input!\n", match->name);
>> return -1;
>> }
>
> Just a totally wild idea, what about spliting openLinks into a list of
> open inputs and a list of open outputs? that would avoid these type checks
> and possibly the type field as well?
That was a good idea. Done, and it simplified slightly the code.
-Vitor
-------------- next part --------------
A non-text attachment was scrubbed...
Name: graphparser.c
Type: text/x-csrc
Size: 10604 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080509/35f11354/attachment.c>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: graphparser.h
Type: text/x-chdr
Size: 1701 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080509/35f11354/attachment.h>
More information about the ffmpeg-devel
mailing list