extern tcconf_section_t * tcconf_nextsection(tcconf_section_t *ts, char *name, void **state) { tcconf_section_t *ns; v_state *vs; conf_section *sec = NULL; if(!(vs = vstate(ts, name, state))) return NULL; while(vs->ml){ tcconf_section_t *s = tcconf_nextsection(vs->sec, vs->n, &vs->vsr); if(!vs->vsr){ tcconf_section_t *ms = next_merge(vs->ts, vs); tcfree(vs->sec); if(ms){ vs->sec = ms; } else { vs->sec = vs->ts; } } if(s){ sec = s->sec; tcfree(s); break; } } if(!sec){ tcc_entry *te = tclist_prev_matched(vs->sec->sec->entries, &vs->li, vs->n, cmp_str_sec); if(!te){ *state = NULL; vsfree(vs); return NULL; } sec = te->section; } ns = tcallocd(sizeof(*ns), NULL, tcconf_free); ns->sec = tcref(sec); ns->parent = tcref(ts); return ns; }
extern tcvp_pipe_t * new_pipe(tcvp_player_t *sh, muxed_stream_t *ms, stream_t *s) { tcvp_pipe_t *pipe = NULL, *pp = NULL, *pn = NULL; tcconf_section_t *f, *mcf; tcconf_section_t *pr = NULL; void *cs = NULL; int skip = 0; switch(s->stream_type){ case STREAM_TYPE_VIDEO: pr = tcconf_getsection(sh->profile, "video"); break; case STREAM_TYPE_AUDIO: pr = tcconf_getsection(sh->profile, "audio"); break; case STREAM_TYPE_SUBTITLE: pr = tcconf_getsection(sh->profile, "subtitle"); break; } if(!pr) return NULL; while((f = tcconf_nextsection(pr, "filter", &cs))){ char *type, *id = NULL; filter_new_t fn; if(skip){ tcfree(f); continue; } pn = NULL; if(tcconf_getvalue(f, "type", "%s", &type) < 1){ tc2_print("STREAM", TC2_PRINT_WARNING, "bad filter specification\n"); continue; } if(tcconf_getvalue(f, "id", "%s", &id) > 0) tchash_find(sh->filters, id, -1, &pn); if(!pn){ tc2_print("STREAM", TC2_PRINT_DEBUG, "opening new filter: %s\n", type); if(!(fn = tc2_get_symbol(type, "new"))) break; mcf = tcconf_merge(NULL, f); tcconf_merge(mcf, sh->conf); if(sh->outfile) tcconf_setvalue(mcf, "mux/url", "%s", sh->outfile); if(!(pn = fn(pp? &pp->format: s, mcf, sh->timer, ms))){ tc2_print("STREAM", TC2_PRINT_WARNING, "error opening filter '%s'\n", type); break; } if(id){ char *cid = tcalloc(strlen(id) + 1); strcpy(cid, id); tcattr_set(cid, "stream-shared", sh, NULL, NULL); tcattr_set(pn, "id", cid, NULL, pid_free); tchash_replace(sh->filters, id, -1, pn, NULL); } tcfree(mcf); } else { tcref(pn); } if(id) free(id); if(!pipe) pipe = pn; if(pp) pp->next = pn; pp = pn; free(type); tcfree(f); if(pp->next){ while((pp = pp->next)) tcref(pp); skip = 1; } } if(!pn){ close_pipe(pipe); pipe = NULL; } tcfree(pr); return pipe; }