DirectorConference::~DirectorConference() { // 释放所有 sources, sinks, ... do { ost::MutexLock al(cs_graphics_); GRAPHICS::iterator it; for (it = graphics_.begin(); it != graphics_.end(); ++it) { delete *it; } graphics_.clear(); } while (0); do { ost::MutexLock al(cs_sinks_); SINKS::iterator it; for (it = sinks_.begin(); it != sinks_.end(); ++it) { del_sink(*it); delete *it; } sinks_.clear(); } while (0); do { ost::MutexLock al(cs_streams_); STREAMS::iterator it; for (it = streams_.begin(); it != streams_.end(); ++it) { del_stream(*it); delete *it; } streams_.clear(); } while (0); do { ost::MutexLock al(cs_sources_); SOURCES::iterator it; for (it = sources_.begin(); it != sources_.end(); ++it) { del_source(*it); delete *it; } sources_.clear(); } while (0); pause_audio(); pause_video(); ms_ticker_destroy(audio_ticker_); ms_ticker_destroy(video_ticker_); ms_filter_destroy(audio_resample_); ms_filter_destroy(audio_encoder_); ms_filter_destroy(audio_mixer_); ms_filter_destroy(video_mixer_); ms_filter_destroy(audio_publisher_); ms_filter_destroy(video_publisher_); ms_filter_destroy(video_tee_); if (filter_tee_) ms_filter_destroy(filter_tee_); if (filter_sink_) ms_filter_destroy(filter_sink_); }
static void * play_stream(void *p) { struct sp_stream *str = p; stream_player_t *sp = str->sp; int six = str - sp->streams; int shs = sp->smap[six]; tcvp_packet_t *pk; tc2_print("STREAM", TC2_PRINT_DEBUG, "[%i] starting player thread\n", shs); while(waitplay(sp, six)){ pthread_mutex_lock(&sp->lock); pk = tclist_shift(str->packets); if(pk && pk->type == TCVP_PKT_TYPE_DATA && pk->data.flags & TCVP_PKT_FLAG_PTS) str->tailtime = pk->data.pts; if((tclist_items(str->packets) < min_packets || str->headtime - str->tailtime < buffertime) && sp->ms->used_streams[six]){ if(!(sp->ms->streams[six].common.flags & TCVP_STREAM_FLAG_NOBUFFER)) sp->nbuf |= 1ULL << six; pthread_cond_broadcast(&sp->cond); } pthread_mutex_unlock(&sp->lock); if(!pk){ tc2_print("STREAM", TC2_PRINT_DEBUG, "null packet on stream %i\n", shs); break; } if(str->pipe->input(str->pipe, pk)){ tc2_print("STREAM", TC2_PRINT_ERROR, "stream %i pipeline error\n", shs); break; } } tc2_print("STREAM", TC2_PRINT_DEBUG, "stream %i %s\n", shs, sp->state == STOP? "stopped": "end"); pk = tcallocz(sizeof(*pk)); pk->data.stream = shs; pk->data.data = NULL; if(str->end->start) str->end->start(str->end); str->pipe->flush(str->pipe, sp->state == STOP); str->pipe->input(str->pipe, pk); del_stream(sp, six); 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; }