/***************************************************************************** * sout_MuxDeleteStream: *****************************************************************************/ void sout_MuxDeleteStream( sout_mux_t *p_mux, sout_input_t *p_input ) { int i_index; if( p_mux->b_waiting_stream && block_FifoCount( p_input->p_fifo ) > 0 ) { /* We stop waiting, and call the muxer for taking care of the data * before we remove this es */ p_mux->b_waiting_stream = false; p_mux->pf_mux( p_mux ); } TAB_FIND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input, i_index ); if( i_index >= 0 ) { p_mux->pf_delstream( p_mux, p_input ); /* remove the entry */ TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input ); if( p_mux->i_nb_inputs == 0 ) { msg_Warn( p_mux, "no more input streams for this mux" ); } block_FifoRelease( p_input->p_fifo ); es_format_Clean( &p_input->fmt ); free( p_input ); } }
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; }
/***************************************************************************** * sout_MuxAddStream: *****************************************************************************/ sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux, es_format_t *p_fmt ) { sout_input_t *p_input; if( !p_mux->b_add_stream_any_time && !p_mux->b_waiting_stream ) { msg_Err( p_mux, "cannot add a new stream (unsupported while muxing " "to this format). You can try increasing sout-mux-caching value" ); return NULL; } msg_Dbg( p_mux, "adding a new input" ); /* create a new sout input */ p_input = malloc( sizeof( sout_input_t ) ); if( !p_input ) return NULL; p_input->p_fmt = p_fmt; p_input->p_fifo = block_FifoNew(); p_input->p_sys = NULL; TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input ); if( p_mux->pf_addstream( p_mux, p_input ) < 0 ) { msg_Err( p_mux, "cannot add this stream" ); TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input ); block_FifoRelease( p_input->p_fifo ); free( p_input ); return NULL; } return p_input; }
static vlm_media_instance_t *libvlc_vlm_get_media_instance( libvlc_instance_t *p_instance, char *psz_name, int i_minstance_idx, libvlc_exception_t *p_exception ) { #ifdef ENABLE_VLM vlm_t *p_vlm; vlm_media_instance_t **pp_minstance; vlm_media_instance_t *p_minstance; int i_minstance; int64_t id; VLM_RET(p_vlm, NULL); if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) || vlm_Control( p_vlm, VLM_GET_MEDIA_INSTANCES, id, &pp_minstance, &i_minstance ) ) { libvlc_exception_raise( p_exception, "Unable to get %s instances", psz_name ); return NULL; } p_minstance = NULL; if( i_minstance_idx >= 0 && i_minstance_idx < i_minstance ) { p_minstance = pp_minstance[i_minstance_idx]; TAB_REMOVE( i_minstance, pp_minstance, p_minstance ); } while( i_minstance > 0 ) vlm_media_instance_Delete( pp_minstance[--i_minstance] ); TAB_CLEAN( i_minstance, pp_minstance ); return p_minstance; #else libvlc_exception_raise( p_exception, "VLM has been disabled in this libvlc." ); return VLC_EGENERIC; #endif }
static vlm_media_instance_t * libvlc_vlm_get_media_instance( libvlc_instance_t *p_instance, const char *psz_name, int i_minstance_idx ) { vlm_t *p_vlm; vlm_media_instance_t **pp_minstance; vlm_media_instance_t *p_minstance; int i_minstance; int64_t id; VLM_RET(p_vlm, NULL); if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) || vlm_Control( p_vlm, VLM_GET_MEDIA_INSTANCES, id, &pp_minstance, &i_minstance ) ) { libvlc_printerr( "%s: media instances not found", psz_name ); return NULL; } p_minstance = NULL; if( i_minstance_idx >= 0 && i_minstance_idx < i_minstance ) { p_minstance = pp_minstance[i_minstance_idx]; TAB_REMOVE( i_minstance, pp_minstance, p_minstance ); } while( i_minstance > 0 ) vlm_media_instance_Delete( pp_minstance[--i_minstance] ); TAB_CLEAN( i_minstance, pp_minstance ); return p_minstance; }
/** * Unsubscribe from the message queue. * This function waits for the message callback to return if needed. */ void msg_Unsubscribe (msg_subscription_t *sub) { msg_bank_t *bank = libvlc_bank (sub->instance); vlc_rwlock_wrlock (&bank->lock); TAB_REMOVE (bank->i_sub, bank->pp_sub, sub); vlc_rwlock_unlock (&bank->lock); free (sub); }
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 ); }
/** rtsp must be locked */ static void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session ) { int i; TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session ); for( i = 0; i < session->trackc; i++ ) rtp_del_sink( session->trackv[i].id, session->trackv[i].fd ); free( session->trackv ); free( session ); }
static int Del( sout_stream_t *p_stream, sout_stream_id_t *p_es ) { sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys; sout_stream_id_t *id = p_es->id; TAB_REMOVE( p_sys->i_es_num, p_sys->pp_es, p_es ); free( p_es ); if ( id != NULL ) return p_stream->p_next->pf_del( p_stream->p_next, id ); else return VLC_SUCCESS; }
/** * Unsubscribe from the message queue. * This function waits for the message callback to return if needed. */ void msg_Unsubscribe (msg_subscription_t *sub) { msg_bank_t *bank = libvlc_bank (sub->instance); /* TODO: flush support? */ vlc_cancel (sub->thread); vlc_mutex_lock (&bank->lock); TAB_REMOVE (bank->i_sub, bank->pp_sub, sub); vlc_mutex_unlock (&bank->lock); vlc_join (sub->thread, NULL); /* Free dangling (not flushed) messages. */ /* NOTE: no locking, only this thread can refer to the subscription now. */ while (sub->begin != sub->end) { msg_Release (sub->items[sub->begin]); if (++sub->begin == VLC_MSG_QSIZE) sub->begin = 0; } free (sub); }
static vout_thread_t *RequestVout( input_resource_t *p_resource, vout_thread_t *p_vout, video_format_t *p_fmt, unsigned dpb_size, bool b_recycle ) { vlc_assert_locked( &p_resource->lock ); if( !p_vout && !p_fmt ) { if( p_resource->p_vout_free ) { msg_Dbg( p_resource->p_vout_free, "destroying useless vout" ); vout_CloseAndRelease( p_resource->p_vout_free ); p_resource->p_vout_free = NULL; } return NULL; } if( p_fmt ) { /* */ if( !p_vout && p_resource->p_vout_free ) { msg_Dbg( p_resource->p_parent, "trying to reuse free vout" ); p_vout = p_resource->p_vout_free; p_resource->p_vout_free = NULL; } else if( p_vout ) { assert( p_vout != p_resource->p_vout_free ); vlc_mutex_lock( &p_resource->lock_hold ); TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout ); vlc_mutex_unlock( &p_resource->lock_hold ); } /* */ vout_configuration_t cfg = { // sunqueen modify start /* .vout =*/ p_vout, /* .input =*/ VLC_OBJECT(p_resource->p_input), /* .change_fmt =*/ true, /* .fmt =*/ p_fmt, /* .dpb_size =*/ dpb_size, // sunqueen modify end }; p_vout = vout_Request( p_resource->p_parent, &cfg ); if( !p_vout ) return NULL; DisplayVoutTitle( p_resource, p_vout ); vlc_mutex_lock( &p_resource->lock_hold ); TAB_APPEND( (vout_thread_t **), p_resource->i_vout, p_resource->pp_vout, p_vout ); // sunqueen modify vlc_mutex_unlock( &p_resource->lock_hold ); return p_vout; } else {
static vout_thread_t *RequestVout( input_resource_t *p_resource, vout_thread_t *p_vout, video_format_t *p_fmt, unsigned dpb_size, bool b_recycle ) { vlc_assert_locked( &p_resource->lock ); if( !p_vout && !p_fmt ) { if( p_resource->p_vout_free ) { msg_Dbg( p_resource->p_vout_free, "destroying useless vout" ); vout_CloseAndRelease( p_resource->p_vout_free ); p_resource->p_vout_free = NULL; } return NULL; } assert( p_resource->p_input ); if( p_fmt ) { /* */ if( !p_vout && p_resource->p_vout_free ) { msg_Dbg( p_resource->p_parent, "trying to reuse free vout" ); p_vout = p_resource->p_vout_free; p_resource->p_vout_free = NULL; } else if( p_vout ) { assert( p_vout != p_resource->p_vout_free ); vlc_mutex_lock( &p_resource->lock_hold ); TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout ); vlc_mutex_unlock( &p_resource->lock_hold ); } /* */ vout_configuration_t cfg = { .vout = p_vout, .input = VLC_OBJECT(p_resource->p_input), .change_fmt = true, .fmt = p_fmt, .dpb_size = dpb_size, }; p_vout = vout_Request( p_resource->p_parent, &cfg ); if( !p_vout ) return NULL; DisplayVoutTitle( p_resource, p_vout ); vlc_mutex_lock( &p_resource->lock_hold ); TAB_APPEND( p_resource->i_vout, p_resource->pp_vout, p_vout ); vlc_mutex_unlock( &p_resource->lock_hold ); return p_vout; } else { assert( p_vout ); vlc_mutex_lock( &p_resource->lock_hold ); TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout ); const int i_vout_active = p_resource->i_vout; vlc_mutex_unlock( &p_resource->lock_hold ); if( p_resource->p_vout_free || i_vout_active > 0 || !b_recycle ) { if( b_recycle ) msg_Dbg( p_resource->p_parent, "detroying vout (already one saved or active)" ); vout_CloseAndRelease( p_vout ); } else { msg_Dbg( p_resource->p_parent, "saving a free vout" ); vout_Flush( p_vout, 1 ); vout_FlushSubpictureChannel( p_vout, -1 ); vout_configuration_t cfg = { .vout = p_vout, .input = NULL, .change_fmt = false, .fmt = NULL, .dpb_size = 0, }; p_resource->p_vout_free = vout_Request( p_resource->p_parent, &cfg ); } return NULL; } } static vout_thread_t *HoldVout( input_resource_t *p_resource ) { /* TODO FIXME: p_resource->pp_vout order is NOT stable */ vlc_mutex_lock( &p_resource->lock_hold ); vout_thread_t *p_vout = p_resource->i_vout > 0 ? p_resource->pp_vout[0] : NULL; if( p_vout ) vlc_object_hold( p_vout ); vlc_mutex_unlock( &p_resource->lock_hold ); return p_vout; }
/**************************************************************************** * HandlerCallback: **************************************************************************** * call the external handler and parse vlc macros if Content-Type is HTML ****************************************************************************/ int HandlerCallback( httpd_handler_sys_t *p_args, httpd_handler_t *p_handler, char *_p_url, uint8_t *_p_request, int i_type, uint8_t *_p_in, int i_in, char *psz_remote_addr, char *psz_remote_host, uint8_t **_pp_data, int *pi_data ) { VLC_UNUSED(p_handler); VLC_UNUSED(_p_in); char *p_url = (char *)_p_url; char *p_request = (char *)_p_request; char **pp_data = (char **)_pp_data; char *p_in = (char *)_p_in; int i_request = p_request != NULL ? strlen( p_request ) : 0; char *p; int i_env = 0; char **ppsz_env = NULL; char *psz_tmp; size_t i_buffer; char *p_buffer; char *psz_cwd, *psz_file = NULL; int i_ret; /* Create environment for the CGI */ TAB_APPEND( i_env, ppsz_env, strdup("GATEWAY_INTERFACE=CGI/1.1") ); TAB_APPEND( i_env, ppsz_env, strdup("SERVER_PROTOCOL=HTTP/1.1") ); TAB_APPEND( i_env, ppsz_env, strdup("SERVER_SOFTWARE=VLC "VERSION) ); switch( i_type ) { case HTTPD_MSG_GET: TAB_APPEND( i_env, ppsz_env, strdup("REQUEST_METHOD=GET") ); break; case HTTPD_MSG_POST: TAB_APPEND( i_env, ppsz_env, strdup("REQUEST_METHOD=POST") ); break; case HTTPD_MSG_HEAD: TAB_APPEND( i_env, ppsz_env, strdup("REQUEST_METHOD=HEAD") ); break; default: break; } if( i_request ) { if( -1==asprintf( &psz_tmp, "QUERY_STRING=%s", p_request ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); if( -1==asprintf( &psz_tmp, "REQUEST_URI=%s?%s", p_url, p_request ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); } else { if( -1==asprintf( &psz_tmp, "REQUEST_URI=%s", p_url ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); } if( -1==asprintf( &psz_tmp, "SCRIPT_NAME=%s", p_url ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); #define p_sys p_args->file.p_intf->p_sys if( -1==asprintf( &psz_tmp, "SERVER_NAME=%s", p_sys->psz_address ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); if( -1==asprintf( &psz_tmp, "SERVER_PORT=%u", p_sys->i_port ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); #undef p_sys p = getenv( "PATH" ); if( p != NULL ) { if( -1==asprintf( &psz_tmp, "PATH=%s", p ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); } #ifdef WIN32 p = getenv( "windir" ); if( p != NULL ) { if( -1==asprintf( &psz_tmp, "SYSTEMROOT=%s", p ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); } #endif if( psz_remote_addr != NULL && *psz_remote_addr ) { if( -1==asprintf( &psz_tmp, "REMOTE_ADDR=%s", psz_remote_addr ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); } if( psz_remote_host != NULL && *psz_remote_host ) { if( -1==asprintf( &psz_tmp, "REMOTE_HOST=%s", psz_remote_host ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); } if( i_in ) { p = p_in; for ( ; ; ) { if( !strncasecmp( p, "Content-Type: ", strlen("Content-Type: ") ) ) { char *end = strchr( p, '\r' ); if( end == NULL ) break; *end = '\0'; if( -1==asprintf( &psz_tmp, "CONTENT_TYPE=%s", p ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); *end = '\r'; } if( !strncasecmp( p, "Content-Length: ", strlen("Content-Length: ") ) ) { char *end = strchr( p, '\r' ); if( end == NULL ) break; *end = '\0'; if( -1==asprintf( &psz_tmp, "CONTENT_LENGTH=%s", p ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); *end = '\r'; } p = strchr( p, '\n' ); if( p == NULL || p[1] == '\r' ) { p = NULL; break; } p++; } } psz_file = strrchr( p_args->file.file, DIR_SEP_CHAR ); if( psz_file != NULL ) { psz_file++; if( -1==asprintf( &psz_tmp, "SCRIPT_FILENAME=%s", psz_file ) ) psz_tmp = NULL; TAB_APPEND( i_env, ppsz_env, psz_tmp ); TAB_APPEND( p_args->p_association->i_argc, p_args->p_association->ppsz_argv, psz_file ); } TAB_APPEND( i_env, ppsz_env, NULL ); TAB_APPEND( p_args->p_association->i_argc, p_args->p_association->ppsz_argv, NULL ); psz_tmp = strdup( p_args->file.file ); p = strrchr( psz_tmp, DIR_SEP_CHAR ); if( p != NULL ) { *p = '\0'; psz_cwd = psz_tmp; } else { free( psz_tmp ); psz_cwd = NULL; } i_ret = vlc_execve( p_args->file.p_intf, p_args->p_association->i_argc, p_args->p_association->ppsz_argv, ppsz_env, psz_cwd, (char *)p_in, i_in, &p_buffer, &i_buffer ); TAB_REMOVE( p_args->p_association->i_argc, p_args->p_association->ppsz_argv, NULL ); TAB_REMOVE( p_args->p_association->i_argc, p_args->p_association->ppsz_argv, psz_file ); free( psz_cwd ); while( i_env ) TAB_REMOVE( i_env, ppsz_env, ppsz_env[0] ); if( i_ret == -1 ) { Callback404( (httpd_file_sys_t *)p_args, pp_data, pi_data ); return VLC_SUCCESS; } p = p_buffer; while( strncasecmp( p, "Content-Type: text/html", strlen("Content-Type: text/html") ) ) { p = strchr( p, '\n' ); if( p == NULL || p[1] == '\r' ) { p = NULL; break; } p++; } if( p == NULL ) { *pp_data = p_buffer; *pi_data = i_buffer; } else { ParseExecute( (httpd_file_sys_t *)p_args, p_buffer, i_buffer, p_request, pp_data, pi_data ); free( p_buffer ); } return VLC_SUCCESS; }
/***************************************************************************** * Run: main loop *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { intf_sys_t *p_sys = p_intf->p_sys; struct timeval timeout; char *psz_password; psz_password = config_GetPsz( p_intf, "telnet-password" ); while( !p_intf->b_die ) { fd_set fds_read, fds_write; int i_handle_max = 0; int i_ret, i_len, fd, i; /* if a new client wants to communicate */ fd = net_Accept( p_intf, p_sys->pi_fd, p_sys->i_clients > 0 ? 0 : -1 ); if( fd > 0 ) { telnet_client_t *cl; /* to be non blocking */ #if defined( WIN32 ) || defined( UNDER_CE ) { unsigned long i_dummy = 1; ioctlsocket( fd, FIONBIO, &i_dummy ); } #else fcntl( fd, F_SETFL, O_NONBLOCK ); #endif cl = malloc( sizeof( telnet_client_t )); cl->i_tel_cmd = 0; cl->fd = fd; cl->buffer_write = NULL; cl->p_buffer_write = cl->buffer_write; Write_message( cl, NULL, "Password: \xff\xfb\x01", WRITE_MODE_PWD ); TAB_APPEND( p_sys->i_clients, p_sys->clients, cl ); } /* to do a proper select */ FD_ZERO( &fds_read ); FD_ZERO( &fds_write ); for( i = 0 ; i < p_sys->i_clients ; i++ ) { telnet_client_t *cl = p_sys->clients[i]; if( cl->i_mode == WRITE_MODE_PWD || cl->i_mode == WRITE_MODE_CMD ) { FD_SET( cl->fd , &fds_write ); } else { FD_SET( cl->fd , &fds_read ); } i_handle_max = __MAX( i_handle_max, cl->fd ); } timeout.tv_sec = 0; timeout.tv_usec = 500*1000; i_ret = select( i_handle_max + 1, &fds_read, &fds_write, 0, &timeout ); if( i_ret == -1 && errno != EINTR ) { msg_Warn( p_intf, "cannot select sockets" ); msleep( 1000 ); continue; } else if( i_ret <= 0 ) { continue; } /* check if there is something to do with the socket */ for( i = 0 ; i < p_sys->i_clients ; i++ ) { telnet_client_t *cl = p_sys->clients[i]; if( FD_ISSET(cl->fd , &fds_write) && cl->i_buffer_write > 0 ) { i_len = send( cl->fd , cl->p_buffer_write , cl->i_buffer_write , 0 ); if( i_len > 0 ) { cl->p_buffer_write += i_len; cl->i_buffer_write -= i_len; } } else if( FD_ISSET( cl->fd, &fds_read) ) { int i_end = 0; int i_recv; while( (i_recv=recv( cl->fd, cl->p_buffer_read, 1, 0 )) > 0 && cl->p_buffer_read - cl->buffer_read < 999 ) { switch( cl->i_tel_cmd ) { case 0: switch( *(uint8_t *)cl->p_buffer_read ) { case '\r': break; case '\n': *cl->p_buffer_read = '\n'; i_end = 1; break; case TEL_IAC: // telnet specific command cl->i_tel_cmd = 1; cl->p_buffer_read++; break; default: cl->p_buffer_read++; break; } break; case 1: switch( *(uint8_t *)cl->p_buffer_read ) { case TEL_WILL: case TEL_WONT: case TEL_DO: case TEL_DONT: cl->i_tel_cmd++; cl->p_buffer_read++; break; default: cl->i_tel_cmd = 0; cl->p_buffer_read--; break; } break; case 2: cl->i_tel_cmd = 0; cl->p_buffer_read -= 2; break; } if( i_end != 0 ) break; } if( cl->p_buffer_read - cl->buffer_read == 999 ) { Write_message( cl, NULL, "Line too long\r\n", cl->i_mode + 2 ); } if( i_recv == 0 || ( i_recv == -1 && errno != EAGAIN && errno != 0 ) ) { net_Close( cl->fd ); TAB_REMOVE( p_intf->p_sys->i_clients , p_intf->p_sys->clients , cl ); free( cl ); } } } /* and now we should bidouille the data we received / send */ for( i = 0 ; i < p_sys->i_clients ; i++ ) { telnet_client_t *cl = p_sys->clients[i]; if( cl->i_mode >= WRITE_MODE_PWD && cl->i_buffer_write == 0 ) { // we have finished to send cl->i_mode -= 2; // corresponding READ MODE } else if( cl->i_mode == READ_MODE_PWD && *cl->p_buffer_read == '\n' ) { *cl->p_buffer_read = '\0'; if( strcmp( psz_password, cl->buffer_read ) == 0 ) { Write_message( cl, NULL, "\xff\xfc\x01\r\nWelcome, " "Master\r\n> ", WRITE_MODE_CMD ); } else { /* wrong password */ Write_message( cl, NULL, "\r\nWrong password.\r\nPassword: "******"logout", 6 ) || !strncmp( cl->buffer_read, "quit", 4 ) || !strncmp( cl->buffer_read, "exit", 4 ) ) { net_Close( cl->fd ); TAB_REMOVE( p_intf->p_sys->i_clients , p_intf->p_sys->clients , cl ); free( cl ); } else if( !strncmp( cl->buffer_read, "shutdown", 8 ) ) { msg_Err( p_intf, "shutdown requested" ); p_intf->p_vlc->b_die = VLC_TRUE; } else { vlm_message_t *message; /* create a standard string */ *cl->p_buffer_read = '\0'; vlm_ExecuteCommand( p_sys->mediatheque, cl->buffer_read, &message ); Write_message( cl, message, NULL, WRITE_MODE_CMD ); vlm_MessageDelete( message ); } } } } }
/***************************************************************************** * 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; }