📄 jack.c
字号:
}/***************************************************************************** * Close: Disconnect from jack server and release associated resources *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = ( demux_t* )p_this; demux_sys_t *p_sys = p_demux->p_sys; msg_Dbg( p_demux,"Module unloaded" ); if( p_sys->p_block_audio ) block_Release( p_sys->p_block_audio ); if( p_sys->p_jack_client ) jack_client_close( p_sys->p_jack_client ); if( p_sys->p_jack_ringbuffer ) jack_ringbuffer_free( p_sys->p_jack_ringbuffer ); free( p_sys->pp_jack_port_input ); free( p_sys->pp_jack_buffer ); free( p_sys->pp_jack_port_table ); free( p_sys );}/***************************************************************************** * Control *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){ bool *pb; int64_t *pi64; demux_sys_t *p_sys = p_demux->p_sys; switch( i_query ) { /* Special for access_demux */ case DEMUX_CAN_PAUSE: case DEMUX_CAN_SEEK: pb = (bool *)va_arg( args, bool * ); *pb = true; return VLC_SUCCESS; case DEMUX_SET_PAUSE_STATE: return VLC_SUCCESS; case DEMUX_CAN_CONTROL_PACE: pb = ( bool* )va_arg( args, bool * ); *pb = var_GetBool( p_demux, "jack-input-use-vlc-pace" ); return VLC_SUCCESS; case DEMUX_GET_PTS_DELAY: pi64 = ( int64_t* )va_arg( args, int64_t * ); *pi64 = ( int64_t )var_GetInteger( p_demux, "jack-input-caching" ) * 1000; return VLC_SUCCESS; case DEMUX_GET_TIME: pi64 = ( int64_t* )va_arg( args, int64_t * ); *pi64 = date_Get(&p_sys->pts); return VLC_SUCCESS; /* TODO implement others */ default: return VLC_EGENERIC; } return VLC_EGENERIC;}/***************************************************************************** * Demux *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys; es_out_id_t *p_es; block_t *p_block; p_sys = p_demux->p_sys; p_es = p_sys->p_es_audio; p_block = GrabJack( p_demux ); if( p_block ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts ); es_out_Send( p_demux->out, p_es, p_block ); } return 1;}/***************************************************************************** * Process Callback : fill ringbuffer with Jack audio data *****************************************************************************/int Process( jack_nframes_t i_frames, void *p_arg ){ demux_t *p_demux = ( demux_t* )p_arg; demux_sys_t *p_sys = p_demux->p_sys; unsigned int i, j; size_t i_write; /* Get and interlace buffers */ for ( i = 0; i < p_sys->i_channels ; i++ ) { p_sys->pp_jack_buffer[i] = jack_port_get_buffer( p_sys->pp_jack_port_input[i], i_frames ); } /* fill ring buffer with signal */ for( j = 0; j < i_frames; j++ ) { for( i = 0; i <p_sys->i_channels; i++ ) { if( jack_ringbuffer_write_space( p_sys->p_jack_ringbuffer ) < p_sys->jack_sample_size ) { msg_Err( p_demux, "buffer overflow"); return 0; // buffer overflow } i_write = jack_ringbuffer_write( p_sys->p_jack_ringbuffer, ( char * ) (p_sys->pp_jack_buffer[i]+j), p_sys->jack_sample_size ); if (i_write != p_sys->jack_sample_size ) { msg_Warn( p_demux, "error writing on ring buffer"); } } } return 1;}/***************************************************************************** * GrabJack: grab audio data in the Jack buffer *****************************************************************************/static block_t *GrabJack( demux_t *p_demux ){ size_t i_read; demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; /* read signal from ring buffer */ i_read = jack_ringbuffer_read_space( p_sys->p_jack_ringbuffer ); if( i_read < 100 ) /* avoid small read */ { /* vlc has too much free time on its hands? */ msleep(1000); return NULL; } if( p_sys->p_block_audio ) { p_block = p_sys->p_block_audio; } else { p_block = block_New( p_demux, i_read ); } if( !p_block ) { msg_Warn( p_demux, "cannot get block" ); return 0; } //Find the previous power of 2, this algo assumes size_t has the same size on all arch i_read >>= 1; i_read--; i_read |= i_read >> 1; i_read |= i_read >> 2; i_read |= i_read >> 4; i_read |= i_read >> 8; i_read |= i_read >> 16; i_read++; i_read = jack_ringbuffer_read( p_sys->p_jack_ringbuffer, ( char * ) p_block->p_buffer, i_read ); p_block->i_dts = p_block->i_pts = date_Increment( &p_sys->pts, i_read/(p_sys->i_channels * p_sys->jack_sample_size) ); p_sys->p_block_audio = p_block; p_block->i_buffer = i_read; p_sys->p_block_audio = 0; return p_block;}/***************************************************************************** * Port_finder: compare ports with the regexp entered *****************************************************************************/static void Port_finder( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; char *psz_expr = p_sys->psz_ports; char *token = NULL; char *state = NULL; char *psz_uri = NULL; const char **pp_jack_port_output = NULL; int i_out_ports = 0; int i_total_out_ports =0; p_sys->pp_jack_port_table = NULL; /* parse the ports part of the MRL */ for( token = strtok_r( psz_expr, ",", &state ); token; token = strtok_r( NULL, ",", &state ) ) { psz_uri = decode_URI_duplicate( token ); /* get the ports which match the regexp */ pp_jack_port_output = jack_get_ports( p_sys->p_jack_client, psz_uri, NULL, JackPortIsOutput ); if( pp_jack_port_output == NULL ) { msg_Err( p_demux, "port(s) asked not found:%s", psz_uri ); free( pp_jack_port_output ); } else { while( pp_jack_port_output && pp_jack_port_output[i_out_ports] ) { i_out_ports++; } /* alloc an array to store all the matched ports */ p_sys->pp_jack_port_table = realloc( p_sys->pp_jack_port_table, (i_out_ports * sizeof( char * ) + i_total_out_ports * sizeof( char * ) ) ); for(int i=0; i<i_out_ports;i++) { p_sys->pp_jack_port_table[i_total_out_ports+i] = ( char * ) pp_jack_port_output[i]; } i_total_out_ports += i_out_ports; } } free( pp_jack_port_output ); p_sys->i_match_ports = i_total_out_ports;}/***************************************************************************** * Parse: Parse the MRL *****************************************************************************/static void Parse( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; char *psz_dup = strdup( p_demux->psz_path ); char *psz_parser = psz_dup; if( !strncmp( psz_parser, "channels=", strlen( "channels=" ) ) ) { p_sys->i_channels = abs( strtol( psz_parser + strlen( "channels=" ), &psz_parser, 0 ) ); } else if( !strncmp( psz_parser, "ports=", strlen( "ports=" ) ) ) { int i_len; psz_parser += strlen( "ports=" ); if( strchr( psz_parser, ':' ) ) { i_len = strchr( psz_parser, ':' ) - psz_parser; } else { i_len = strlen( psz_parser ); } p_sys->psz_ports = strndup( psz_parser, i_len ); psz_parser += i_len; } else { msg_Warn( p_demux, "unknown option" ); } while( *psz_parser && *psz_parser != ':' ) { psz_parser++; } if( *psz_parser == ':' ) { for( ;; ) { *psz_parser++ = '\0'; if( !strncmp( psz_parser, "channels=", strlen( "channels=" ) ) ) { p_sys->i_channels = abs( strtol( psz_parser + strlen( "channels=" ), &psz_parser, 0 ) ); } else if( !strncmp( psz_parser, "ports=", strlen( "ports=" ) ) ) { int i_len; psz_parser += strlen( "ports=" ); if( strchr( psz_parser, ':' ) ) { i_len = strchr( psz_parser, ':' ) - psz_parser; } else { i_len = strlen( psz_parser ); } p_sys->psz_ports = strndup( psz_parser, i_len ); psz_parser += i_len; } else { msg_Warn( p_demux, "unknown option" ); } while( *psz_parser && *psz_parser != ':' ) { psz_parser++; } if( *psz_parser == '\0' ) { break; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -