static void Del(sout_stream_t *p_stream, sout_stream_id_sys_t *id) { sout_stream_sys_t *p_sys = p_stream->p_sys; for (size_t i=0; i<p_sys->streams.size(); i++) { if ( p_sys->streams[i] == id ) { if ( p_sys->streams[i]->p_sub_id != NULL ) sout_StreamIdDel( p_sys->p_out, p_sys->streams[i]->p_sub_id ); es_format_Clean( &p_sys->streams[i]->fmt ); free( p_sys->streams[i] ); p_sys->streams.erase( p_sys->streams.begin() + i ); p_sys->es_changed = true; break; } } if ( p_sys->streams.empty() ) { p_sys->p_intf->requestPlayerStop(); sout_StreamChainDelete( p_sys->p_out, p_sys->p_out ); p_sys->p_out = NULL; p_sys->sout = ""; } }
static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) { sout_stream_sys_t *p_sys = p_stream->p_sys; if( !p_sys->p_out ) OutputStart( p_stream ); if( id->p_first ) block_ChainRelease( id->p_first ); assert( !id->id || p_sys->p_out ); if( id->id ) sout_StreamIdDel( p_sys->p_out, id->id ); es_format_Clean( &id->fmt ); TAB_REMOVE( p_sys->i_id, p_sys->id, id ); if( p_sys->i_id <= 0 ) { if( !p_sys->p_out ) p_sys->b_drop = false; } free( id ); return VLC_SUCCESS; }
static void Del( sout_stream_t *p_stream, sout_stream_id_sys_t *p_es ) { sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys; if( p_es->id != NULL ) sout_StreamIdDel( p_stream->p_next, p_es->id ); TAB_REMOVE( p_sys->i_es_num, p_sys->pp_es, p_es ); es_format_Clean( &p_es->fmt ); free( p_es ); }
static void DelStream(sout_stream_t *stream) { sout_stream_sys_t *sys = stream->p_sys; if (sys->stream == NULL) return; for (sout_stream_id_sys_t *id = sys->first; id != NULL; id = id->next) if (id->id != NULL) sout_StreamIdDel(sys->stream, id->id); sout_StreamChainDelete(sys->stream, NULL); sys->stream = NULL; }
/***************************************************************************** * Del: *****************************************************************************/ static void Del( sout_stream_t *p_stream, sout_stream_id_sys_t *id ) { sout_stream_sys_t *p_sys = p_stream->p_sys; int i_stream; for( i_stream = 0; i_stream < p_sys->i_nb_streams; i_stream++ ) { if( id->pp_ids[i_stream] ) { sout_stream_t *out = p_sys->pp_streams[i_stream]; sout_StreamIdDel( out, id->pp_ids[i_stream] ); } } free( id->pp_ids ); free( id ); }
/***************************************************************************** * Close: *****************************************************************************/ static void Close( vlc_object_t * p_this ) { sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_sys_t *p_sys = p_stream->p_sys; int i; for( i = 0; i < p_sys->i_id; i++ ) { sout_stream_id_sys_t *id = p_sys->id[i]; sout_StreamIdDel( p_stream->p_next, id->id ); es_format_Clean( &id->fmt ); free( id ); } TAB_CLEAN( p_sys->i_id, p_sys->id ); free( p_sys ); }
static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) { sout_stream_sys_t *p_sys = p_stream->p_sys; if( id->b_transcode ) { switch( id->p_decoder->fmt_in.i_cat ) { case AUDIO_ES: Send( p_stream, id, NULL ); transcode_audio_close( id ); break; case VIDEO_ES: Send( p_stream, id, NULL ); transcode_video_close( p_stream, id ); break; case SPU_ES: if( p_sys->b_osd ) transcode_osd_close( p_stream, id ); else transcode_spu_close( p_stream, id ); break; } } if( id->id ) sout_StreamIdDel( p_stream->p_next, (sout_stream_id_t *)id->id ); // sunqueen modify if( id->p_decoder ) { vlc_object_release( id->p_decoder ); id->p_decoder = NULL; } if( id->p_encoder ) { es_format_Clean( &id->p_encoder->fmt_out ); vlc_object_release( id->p_encoder ); id->p_encoder = NULL; } free( id ); return VLC_SUCCESS; }
static void Del(sout_stream_t *stream, sout_stream_id_sys_t *id) { sout_stream_sys_t *sys = stream->p_sys; if (id->prev != NULL) id->prev->next = id->next; else sys->first = id->next; if (id->next != NULL) id->next->prev = id->prev; else sys->last = id->prev; if (sys->stream != NULL) sout_StreamIdDel(sys->stream, id->id); es_format_Clean(&id->fmt); free(id); }
static void Del( sout_stream_t *p_stream, void *_id ) { sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys; sout_stream_id_sys_t *id = (sout_stream_id_sys_t *)_id; EndMD5( &id->hash ); char *outputhash = psz_md5_hash( &id->hash ); unsigned int num,den; vlc_ureduce( &num, &den, id->track_duration, id->segment_number, 0 ); msg_Dbg( p_stream, "%s: Removing track type:%s id:%d", p_sys->prefix, id->type, id->id ); if( p_sys->output ) { fprintf( p_sys->output,"#%s: final type:%s id:%d segments:%"PRIu64" total_duration:%"PRId64" avg_track:%d/%d md5:%16s\n", p_sys->prefix, id->type, id->id, id->segment_number, id->track_duration, num, den, outputhash ); } else { msg_Info( p_stream, "%s: final type:%s id:%d segments:%"PRIu64" total_duration:%"PRId64" avg_track:%d/%d md5:%16s", p_sys->prefix, id->type, id->id, id->segment_number, id->track_duration, num, den, outputhash ); } free( outputhash ); if( id->next_id ) sout_StreamIdDel( p_stream->p_next, id->next_id ); free( id ); }
static void OutputStart( sout_stream_t *p_stream ) { sout_stream_sys_t *p_sys = p_stream->p_sys; /* */ if( p_sys->b_drop ) return; /* From now on drop packet that cannot be handled */ p_sys->b_drop = true; /* Detect streams to smart select muxer */ const char *psz_muxer = NULL; const char *psz_extension = NULL; /* Look for preferred muxer * TODO we could insert transcode in a few cases like * s16l <-> s16b */ for( unsigned i = 0; i < sizeof(p_muxers) / sizeof(*p_muxers); i++ ) { bool b_ok; if( p_sys->i_id > p_muxers[i].i_es_max ) continue; b_ok = true; for( int j = 0; j < p_sys->i_id; j++ ) { es_format_t *p_fmt = &p_sys->id[j]->fmt; b_ok = false; for( int k = 0; p_muxers[i].codec[k] != 0; k++ ) { if( p_fmt->i_codec == p_muxers[i].codec[k] ) { b_ok = true; break; } } if( !b_ok ) break; } if( !b_ok ) continue; psz_muxer = p_muxers[i].psz_muxer; psz_extension = p_muxers[i].psz_extension; break; } /* If failed, brute force our demuxers and select the one that * keeps most of our stream */ if( !psz_muxer || !psz_extension ) { static const char ppsz_muxers[][2][4] = { { "avi", "avi" }, { "mp4", "mp4" }, { "ogg", "ogg" }, { "asf", "asf" }, { "ts", "ts" }, { "ps", "mpg" }, { "mkv", "mkv" }, #if 0 // XXX ffmpeg sefault really easily if you try an unsupported codec // mov and avi at least segfault { "avformat{mux=avi}", "avi" }, { "avformat{mux=mov}", "mov" }, { "avformat{mux=mp4}", "mp4" }, { "avformat{mux=nsv}", "nsv" }, { "avformat{mux=flv}", "flv" }, #endif }; int i_best = 0; int i_best_es = 0; msg_Warn( p_stream, "failed to find an adequate muxer, probing muxers" ); for( unsigned i = 0; i < sizeof(ppsz_muxers) / sizeof(*ppsz_muxers); i++ ) { char *psz_file; int i_es; psz_file = tempnam( NULL, "vlc" ); if( !psz_file ) continue; msg_Dbg( p_stream, "probing muxer %s", ppsz_muxers[i][0] ); i_es = OutputNew( p_stream, ppsz_muxers[i][0], psz_file, NULL ); if( i_es < 0 ) { vlc_unlink( psz_file ); free( psz_file ); continue; } /* */ for( int i = 0; i < p_sys->i_id; i++ ) { sout_stream_id_t *id = p_sys->id[i]; if( id->id ) sout_StreamIdDel( p_sys->p_out, id->id ); id->id = NULL; } if( p_sys->p_out ) sout_StreamChainDelete( p_sys->p_out, p_sys->p_out ); p_sys->p_out = NULL; if( i_es > i_best_es ) { i_best_es = i_es; i_best = i; if( i_best_es >= p_sys->i_id ) break; } vlc_unlink( psz_file ); free( psz_file ); } /* */ psz_muxer = ppsz_muxers[i_best][0]; psz_extension = ppsz_muxers[i_best][1]; msg_Dbg( p_stream, "using muxer %s with extension %s (%d/%d streams accepted)", psz_muxer, psz_extension, i_best_es, p_sys->i_id ); } /* Create the output */ if( OutputNew( p_stream, psz_muxer, p_sys->psz_prefix, psz_extension ) < 0 ) { msg_Err( p_stream, "failed to open output"); return; } /* Compute highest timestamp of first I over all streams */ p_sys->i_dts_start = 0; for( int i = 0; i < p_sys->i_id; i++ ) { sout_stream_id_t *id = p_sys->id[i]; block_t *p_block; if( !id->id || !id->p_first ) continue; mtime_t i_dts = id->p_first->i_dts; for( p_block = id->p_first; p_block != NULL; p_block = p_block->p_next ) { if( p_block->i_flags & BLOCK_FLAG_TYPE_I ) { i_dts = p_block->i_dts; break; } } if( i_dts > p_sys->i_dts_start ) p_sys->i_dts_start = i_dts; } /* Send buffered data */ for( int i = 0; i < p_sys->i_id; i++ ) { sout_stream_id_t *id = p_sys->id[i]; if( !id->id ) continue; block_t *p_block = id->p_first; while( p_block ) { block_t *p_next = p_block->p_next; p_block->p_next = NULL; OutputSend( p_stream, id, p_block ); p_block = p_next; } id->p_first = NULL; id->pp_last = &id->p_first; } }
/***************************************************************************** * Add: *****************************************************************************/ static sout_stream_id_sys_t * Add( sout_stream_t *p_stream, const es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_id_sys_t *id; int i; /* search a compatible output */ for( i = 0; i < p_sys->i_id; i++ ) { id = p_sys->id[i]; if( id->b_used ) continue; if( id->fmt.i_cat != p_fmt->i_cat || id->fmt.i_codec != p_fmt->i_codec ) continue; if( id->fmt.i_cat == AUDIO_ES ) { audio_format_t *p_a = &id->fmt.audio; if( p_a->i_rate != p_fmt->audio.i_rate || p_a->i_channels != p_fmt->audio.i_channels || p_a->i_blockalign != p_fmt->audio.i_blockalign ) continue; } else if( id->fmt.i_cat == VIDEO_ES ) { video_format_t *p_v = &id->fmt.video; if( p_v->i_width != p_fmt->video.i_width || p_v->i_height != p_fmt->video.i_height ) continue; } /* */ msg_Dbg( p_stream, "reusing already opened output" ); id->b_used = true; id->b_streamswap = true; return id; } /* destroy all outputs from the same category */ for( i = 0; i < p_sys->i_id; i++ ) { id = p_sys->id[i]; if( !id->b_used && id->fmt.i_cat == p_fmt->i_cat ) { TAB_REMOVE( p_sys->i_id, p_sys->id, id ); sout_StreamIdDel( p_stream->p_next, id->id ); es_format_Clean( &id->fmt ); free( id ); i = 0; continue; } } msg_Dbg( p_stream, "creating new output" ); id = malloc( sizeof( sout_stream_id_sys_t ) ); if( id == NULL ) return NULL; es_format_Copy( &id->fmt, p_fmt ); id->b_streamswap = false; id->b_used = true; id->id = sout_StreamIdAdd( p_stream->p_next, &id->fmt ); if( id->id == NULL ) { free( id ); return NULL; } TAB_APPEND( p_sys->i_id, p_sys->id, id ); return id; }
static void Del(sout_stream_t *p_stream, sout_stream_id_sys_t *id) { sout_stream_sys_t *p_sys = p_stream->p_sys; sout_StreamIdDel(p_sys->p_out, id); }