📄 shout.c
字号:
if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the shoutcast streaming format" ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } /* Don't force bitrate to 0 but only use when specified. This will otherwise show an empty field on icecast directory listing instead of NA */ var_Get( p_access, SOUT_CFG_PREFIX "bitrate", &val ); if( *val.psz_string ) { i_ret = shout_set_audio_info( p_shout, SHOUT_AI_BITRATE, val.psz_string ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the information about the bitrate" ); free( val.psz_string ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } } else { /* Bitrate information is used for icecast/shoutcast servers directory listings (sorting, stream info etc.) */ msg_Warn( p_access, "no bitrate information specified (required for listing " \ "the server as public on the shoutcast website)" ); free( val.psz_string ); } /* Information about samplerate, channels and quality will not be propagated through the YP protocol for icecast to the public directory listing when the icecast server is operating in shoutcast compatibility mode */ var_Get( p_access, SOUT_CFG_PREFIX "samplerate", &val ); if( *val.psz_string ) { i_ret = shout_set_audio_info( p_shout, SHOUT_AI_SAMPLERATE, val.psz_string ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the information about the samplerate" ); free( val.psz_string ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } } else free( val.psz_string ); var_Get( p_access, SOUT_CFG_PREFIX "channels", &val ); if( *val.psz_string ) { i_ret = shout_set_audio_info( p_shout, SHOUT_AI_CHANNELS, val.psz_string ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the information about the number of channels" ); free( val.psz_string ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } } else free( val.psz_string ); var_Get( p_access, SOUT_CFG_PREFIX "quality", &val ); if( *val.psz_string ) { i_ret = shout_set_audio_info( p_shout, SHOUT_AI_QUALITY, val.psz_string ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the information about Ogg Vorbis quality" ); free( val.psz_string ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } } else free( val.psz_string ); var_Get( p_access, SOUT_CFG_PREFIX "public", &val ); if( val.b_bool == true ) { i_ret = shout_set_public( p_shout, 1 ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the server status setting to public" ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } } /* Connect at startup. Cycle through the possible protocols. */ i_ret = shout_get_connected( p_shout ); while ( i_ret != SHOUTERR_CONNECTED ) { /* Shout parameters cannot be changed on an open connection */ i_ret = shout_close( p_shout ); if( i_ret == SHOUTERR_SUCCESS ) { i_ret = SHOUTERR_UNCONNECTED; } /* Re-initialize for Shoutcast using ICY protocol. Not needed for initial connection but it is when we are reconnecting after other protocol was tried. */ i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_ICY ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the protocol to 'icy'" ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } i_ret = shout_open( p_shout ); if( i_ret == SHOUTERR_SUCCESS ) { i_ret = SHOUTERR_CONNECTED; msg_Dbg( p_access, "connected using 'icy' (shoutcast) protocol" ); } else { msg_Warn( p_access, "failed to connect using 'icy' (shoutcast) protocol" ); /* Shout parameters cannot be changed on an open connection */ i_ret = shout_close( p_shout ); if( i_ret == SHOUTERR_SUCCESS ) { i_ret = SHOUTERR_UNCONNECTED; } /* IceCAST using HTTP protocol */ i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_HTTP ); if( i_ret != SHOUTERR_SUCCESS ) { msg_Err( p_access, "failed to set the protocol to 'http'" ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } i_ret = shout_open( p_shout ); if( i_ret == SHOUTERR_SUCCESS ) { i_ret = SHOUTERR_CONNECTED; msg_Dbg( p_access, "connected using 'http' (icecast 2.x) protocol" ); } else msg_Warn( p_access, "failed to connect using 'http' (icecast 2.x) protocol " ); }/* for non-blocking, use: while( i_ret == SHOUTERR_BUSY ) { sleep( 1 ); i_ret = shout_get_connected( p_shout ); }*/ if ( i_ret != SHOUTERR_CONNECTED ) { msg_Warn( p_access, "unable to establish connection, retrying..." ); msleep( 30000000 ); } } if( i_ret != SHOUTERR_CONNECTED ) { msg_Err( p_access, "failed to open shout stream to %s:%i/%s: %s", psz_host, i_port, psz_mount, shout_get_error(p_shout) ); free( p_access->p_sys ); free( psz_accessname ); return VLC_EGENERIC; } p_access->pf_write = Write; p_access->pf_seek = Seek; msg_Dbg( p_access, "shout access output opened (%s@%s:%i/%s)", psz_user, psz_host, i_port, psz_mount ); /* Update pace control flag */ if( p_access->psz_access && !strcmp( p_access->psz_access, "stream" ) ) { p_access->p_sout->i_out_pace_nocontrol++; } free( psz_accessname ); return VLC_SUCCESS;}/***************************************************************************** * Close: close the target *****************************************************************************/static void Close( vlc_object_t * p_this ){ sout_access_out_t *p_access = (sout_access_out_t*)p_this; if( p_access->p_sys && p_access->p_sys->p_shout ) { shout_close( p_access->p_sys->p_shout ); shout_shutdown(); } free( p_access->p_sys ); /* Update pace control flag */ if( p_access->psz_access && !strcmp( p_access->psz_access, "stream" ) ) { p_access->p_sout->i_out_pace_nocontrol--; } msg_Dbg( p_access, "shout access output closed" );}/***************************************************************************** * Write: standard write *****************************************************************************/static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer ){ size_t i_write = 0; shout_sync( p_access->p_sys->p_shout ); while( p_buffer ) { block_t *p_next = p_buffer->p_next; if( shout_send( p_access->p_sys->p_shout, p_buffer->p_buffer, p_buffer->i_buffer ) == SHOUTERR_SUCCESS ) { i_write += p_buffer->i_buffer; } else { msg_Err( p_access, "cannot write to stream: %s", shout_get_error(p_access->p_sys->p_shout) ); /* The most common cause seems to be a server disconnect, resulting in a Socket Error which can only be fixed by closing and reconnecting. Since we already began with a working connection, the most feasable approach to get out of this error status is a (timed) reconnect approach. */ shout_close( p_access->p_sys->p_shout ); msg_Warn( p_access, "server unavailable? trying to reconnect..." ); /* Re-open the connection (protocol params have already been set) and re-sync */ if( shout_open( p_access->p_sys->p_shout ) == SHOUTERR_SUCCESS ) { shout_sync( p_access->p_sys->p_shout ); msg_Warn( p_access, "reconnected to server" ); } else { msg_Err( p_access, "failed to reconnect to server" ); block_ChainRelease (p_buffer); return VLC_EGENERIC; } } block_Release( p_buffer ); /* XXX: Unsure if that's the cause for some audio trouble... */ p_buffer = p_next; } return i_write;}/***************************************************************************** * Seek: seek to a specific location -- not supported *****************************************************************************/static int Seek( sout_access_out_t *p_access, off_t i_pos ){ msg_Err( p_access, "cannot seek on shout" ); return VLC_EGENERIC;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -