extern int tcc_addfloat(tcc_entry *te, double f) { if(te->type == TCC_VALUE){ tcc_value *tv = malloc(sizeof(tcc_value)); tv->type = TCC_FLOAT; tv->value.floating = f; tclist_push(te->value.values, tv); } return 0; }
extern int tcc_addref(tcc_entry *te, char *ref) { if(te->type == TCC_VALUE){ tcc_value *tv = malloc(sizeof(*tv)); tv->type = TCC_REF; tv->value.string = ref; tclist_push(te->value.values, tv); } return 0; }
extern int tcc_addint(tcc_entry *te, long long n) { if(te->type == TCC_VALUE){ tcc_value *tv = malloc(sizeof(tcc_value)); tv->type = TCC_INTEGER; tv->value.integer = n; tclist_push(te->value.values, tv); } return 0; }
extern int tcc_addbool(tcc_entry *te, int n) { if(te->type == TCC_VALUE){ tcc_value *tv = malloc(sizeof(tcc_value)); tv->type = TCC_BOOLEAN; tv->value.boolean = n; tclist_push(te->value.values, tv); } return 0; }
extern int tcc_addstring(tcc_entry *te, char *s, int exp) { if(te->type == TCC_VALUE){ tcc_value *tv = malloc(sizeof(tcc_value)); tv->type = TCC_STRING; if(exp) tv->type |= TCC_EXPAND; tv->value.string = s; tclist_push(te->value.values, tv); } return 0; }
extern tcconf_section_t * tcconf_merge(tcconf_section_t *sec, tcconf_section_t *s2) { tclist_item_t *li = NULL; tcc_entry *te; char *m; if(!sec){ sec = tcconf_new(NULL); if(s2->parent) sec->parent = tcref(s2->parent); /* if(s2->sec->parent) */ /* sec->sec->parent = tcref(s2->sec->parent); */ sec->sec->parent = s2->sec->parent; } while((te = tclist_next(s2->sec->entries, &li))) tclist_push(sec->sec->entries, tcref(te)); while((m = tclist_next(s2->sec->merge, &li))) tclist_push(sec->sec->merge, strdup(m)); return sec; }
static void * read_stream(void *p) { stream_player_t *sp = p; tc2_print("STREAM", TC2_PRINT_DEBUG, "read_stream starting\n"); while(waitbuf(sp)){ tcvp_packet_t *tpk = NULL; if(sp->pstreams) tpk = (tcvp_packet_t *) sp->ms->next_packet(sp->ms, -1); if(!tpk){ int i; tc2_print("STREAM", TC2_PRINT_DEBUG, "end of stream\n"); pthread_mutex_lock(&sp->lock); for(i = 0; i < sp->nstreams; i++) if(sp->streams[i].packets) tclist_push(sp->streams[i].packets, NULL); pthread_cond_broadcast(&sp->cond); pthread_mutex_unlock(&sp->lock); break; } switch(tpk->type){ case TCVP_PKT_TYPE_DATA: do_data_packet(sp, &tpk->data); break; case TCVP_PKT_TYPE_FLUSH: if(tpk->flush.stream < 0){ int i; for(i = 0; i < sp->nstreams; i++) flush_stream(sp, i, tpk->flush.discard); } else { flush_stream(sp, tpk->flush.stream, tpk->flush.discard); } tcfree(tpk); break; case TCVP_PKT_TYPE_STILL: tc2_print("STREAM", TC2_PRINT_DEBUG, "still\n"); tcfree(tpk); break; case TCVP_PKT_TYPE_TIMER: if(sp->shared->synctime) sp->shared->timer->reset(sp->shared->timer, tpk->timer.time); tcfree(tpk); break; } } pthread_mutex_lock(&sp->lock); sp->nbuf = 0; pthread_cond_broadcast(&sp->cond); pthread_mutex_unlock(&sp->lock); tc2_print("STREAM", TC2_PRINT_DEBUG, "read_stream done\n"); return NULL; }
static int do_data_packet(stream_player_t *sp, tcvp_data_packet_t *pk) { tcvp_player_t *sh = sp->shared; struct sp_stream *str; int ps; ps = pk->stream; if(pk->stream >= sp->nstreams || sp->smap[ps] < 0){ if(add_stream(sp, ps)){ del_stream(sp, ps); return -1; } } str = sp->streams + ps; pk->stream = sp->smap[ps]; if(pk->flags & TCVP_PKT_FLAG_PTS){ if(sh->starttime == -1LL){ pthread_mutex_lock(&sh->lock); if(sh->starttime == -1LL){ sh->starttime = pk->pts; if(sh->playtime != -1LL) sh->endtime = sh->starttime + sh->playtime; sh->timer->reset(sh->timer, sh->starttime); tc2_print("STREAM", TC2_PRINT_DEBUG, "start %llu, end %llu\n", sh->starttime / 27, sh->endtime / 27); } pthread_mutex_unlock(&sh->lock); } if(pk->pts > sh->endtime){ tc2_print("STREAM", TC2_PRINT_DEBUG, "[%i] end time reached\n", pk->stream); tcfree(pk); pk = NULL; pthread_mutex_lock(&sp->lock); sp->ms->used_streams[ps] = 0; sp->nbuf &= ~(1ULL << ps); pthread_cond_broadcast(&sp->cond); pthread_mutex_unlock(&sp->lock); } else if(str->starttime == -1LL){ tc2_print("STREAM", TC2_PRINT_DEBUG, "[%i] start %llu\n", pk->stream, pk->pts / 27); sp->ms->streams[ps].common.start_time = pk->pts; str->starttime = pk->pts; } /* } else if(str->starttime == -1){ */ /* tcfree(pk); */ /* return 0; */ } switch(str->probe){ case PROBE_AGAIN: case PROBE_DISCARD: tc2_print("STREAM", TC2_PRINT_DEBUG, "[%i] probing\n", pk->stream); sp->ms->streams[ps].common.index = pk->stream; str->probe = str->pipe->probe(str->pipe, pk, sp->ms->streams + ps); if(str->probe == PROBE_FAIL || str->nprobe++ > tcvp_player_conf_max_probe){ tc2_print("STREAM", TC2_PRINT_DEBUG, "[%i] failed probe\n", pk->stream); sp->fail++; del_stream(sp, ps); tcfree(pk); break; } else if(str->probe == PROBE_OK){ stream_time(sp->ms, ps, str->pipe); tcvp_event_send(sh->sq, TCVP_LOAD, sp->ms); pthread_create(&str->th, NULL, play_stream, str); pthread_mutex_lock(&sp->lock); if(str->end->start && str->run) str->end->start(str->end); pthread_mutex_unlock(&sp->lock); } else if(str->probe == PROBE_DISCARD){ flush_stream(sp, ps, 1); tcfree(pk); break; } case PROBE_OK: pthread_mutex_lock(&sp->lock); if(str->packets){ int np; tclist_push(str->packets, pk); if(pk && pk->flags & TCVP_PKT_FLAG_PTS) str->headtime = pk->pts; np = tclist_items(str->packets); if(str->probe == PROBE_OK && (np > max_packets || ((str->headtime - str->tailtime > buffertime) && np > min_packets))) sp->nbuf &= ~(1ULL << ps); } pthread_cond_broadcast(&sp->cond); pthread_mutex_unlock(&sp->lock); break; } return 0; }