📄 input.c
字号:
/* * Main loop */ intf_DbgMsg("\n"); while( !p_input->b_die && !p_input->b_error ) { /* Scatter read the UDP packet from the network or the file. */ if( (input_ReadPacket( p_input )) == (-1) ) { /* FIXME??: Normally, a thread can't kill itself, but we don't have * any method in case of an error condition ... */ p_input->b_error = 1; }#ifdef STATS p_input->c_loops++;#endif } /* * Error loop */ if( p_input->b_error ) { ErrorThread( p_input ); } /* End of thread */ EndThread( p_input ); intf_DbgMsg("thread end\n");}/***************************************************************************** * ErrorThread: RunThread() error loop ***************************************************************************** * This function is called when an error occured during thread main's loop. *****************************************************************************/static void ErrorThread( input_thread_t *p_input ){ /* Wait until a `die' order */ intf_DbgMsg("\n"); while( !p_input->b_die ) { /* Sleep a while */ msleep( VOUT_IDLE_SLEEP ); }}/***************************************************************************** * EndThread: end the input thread *****************************************************************************/static void EndThread( input_thread_t * p_input ){ int * pi_status; /* threas status */ int i_es_loop; /* es index */ /* Store status */ intf_DbgMsg("\n"); pi_status = p_input->pi_status; *pi_status = THREAD_END; /* Close input method */ p_input->p_Close( p_input ); /* Destroy all decoder threads */ for( i_es_loop = 0; (i_es_loop < INPUT_MAX_ES) && (p_input->pp_selected_es[i_es_loop] != NULL) ; i_es_loop++ ) { switch( p_input->pp_selected_es[i_es_loop]->i_type ) { case MPEG1_VIDEO_ES: case MPEG2_VIDEO_ES:#ifdef OLD_DECODER vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );#else vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );#endif break; case MPEG1_AUDIO_ES: case MPEG2_AUDIO_ES: adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) ); break; case AC3_AUDIO_ES: ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) ); break; case LPCM_AUDIO_ES: lpcmdec_DestroyThread((lpcmdec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) ); break; case DVD_SPU_ES: spudec_DestroyThread( (spudec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) ); break; case 0: /* Special streams for the PSI decoder, PID 0 and 1 */ break;#ifdef DEBUG default: intf_DbgMsg("error: unknown decoder type %d\n", p_input->pp_selected_es[i_es_loop]->i_type ); break;#endif } } input_NetlistEnd( p_input ); /* clean netlist */ input_PsiEnd( p_input ); /* clean PSI information */ input_PcrEnd( p_input ); /* clean PCR information */ free( p_input ); /* free input_thread structure */ /* Update status */ *pi_status = THREAD_OVER;}/***************************************************************************** * input_ReadPacket: reads a packet from the network or the file *****************************************************************************/static __inline__ int input_ReadPacket( input_thread_t *p_input ){ int i_base_index; /* index of the first free iovec */ int i_current_index; int i_packet_size;#ifdef INPUT_LIFO_TS_NETLIST int i_meanwhile_released; int i_currently_removed;#endif ts_packet_t * p_ts_packet; /* In this function, we only care about the TS netlist. PES netlist * is for the demultiplexer. */#ifdef INPUT_LIFO_TS_NETLIST i_base_index = p_input->netlist.i_ts_index; /* Verify that we still have packets in the TS netlist */ if( (INPUT_MAX_TS + INPUT_TS_READ_ONCE - 1 - p_input->netlist.i_ts_index) <= INPUT_TS_READ_ONCE ) { intf_ErrMsg("input error: TS netlist is empty !\n"); return( -1 ); }#else /* FIFO netlist */ i_base_index = p_input->netlist.i_ts_start; if( p_input->netlist.i_ts_start + INPUT_TS_READ_ONCE -1 > INPUT_MAX_TS ) { /* The netlist is splitted in 2 parts. We must gather them to consolidate the FIFO (we make the loop easily in having the same iovec at the far end and in the beginning of netlist_free). That's why the netlist is (INPUT_MAX_TS +1) + (INPUT_TS_READ_ONCE -1) large. */ memcpy( p_input->netlist.p_ts_free + INPUT_MAX_TS + 1, p_input->netlist.p_ts_free, (p_input->netlist.i_ts_start + INPUT_TS_READ_ONCE - 1 - INPUT_MAX_TS) * sizeof(struct iovec) ); } /* Verify that we still have packets in the TS netlist */ if( ((p_input->netlist.i_ts_end -1 - p_input->netlist.i_ts_start) & INPUT_MAX_TS) <= INPUT_TS_READ_ONCE ) { intf_ErrMsg("input error: TS netlist is empty !\n"); return( -1 ); }#endif /* FIFO netlist */ /* Scatter read the buffer. */ i_packet_size = (*p_input->p_Read)( p_input, &p_input->netlist.p_ts_free[i_base_index], INPUT_TS_READ_ONCE ); if( i_packet_size == (-1) ) {#if 0 intf_DbgMsg("Read packet %d %p %d %d\n", i_base_index, &p_input->netlist.p_ts_free[i_base_index], p_input->netlist.i_ts_start, p_input->netlist.i_ts_end);#endif intf_ErrMsg("input error: readv() failed (%s)\n", strerror(errno)); return( -1 ); } if( i_packet_size == 0 ) { /* No packet has been received, so stop here. */ return( 0 ); } /* Demultiplex the TS packets (1..INPUT_TS_READ_ONCE) received. */ for( i_current_index = i_base_index; (i_packet_size -= TS_PACKET_SIZE) >= 0; i_current_index++ ) { /* BTW, something REALLY bad could happen if we receive packets with a wrong size. */ p_ts_packet = (ts_packet_t*)(p_input->netlist.p_ts_free[i_current_index].iov_base); /* Don't cry :-), we are allowed to do that cast, because initially, our buffer was malloc'ed with sizeof(ts_packet_t) */ /* Find out if we need this packet and demultiplex. */ input_SortPacket( p_input /* for current PIDs and netlist */, p_ts_packet); } if( i_packet_size > 0 ) { intf_ErrMsg("input error: wrong size\n"); return( -1 ); } /* Remove the TS packets we have just filled from the netlist */#ifdef INPUT_LIFO_TS_NETLIST /* We need to take a lock here while we're calculating index positions. */ vlc_mutex_lock( &p_input->netlist.lock ); i_meanwhile_released = i_base_index - p_input->netlist.i_ts_index; if( i_meanwhile_released ) { /* That's where it becomes funny :-). Since we didn't take locks for efficiency reasons, other threads (including ourselves, with input_DemuxPacket) might have released packets to the netlist. So we have to copy these iovec where they should go. BTW, that explains why the TS netlist is (INPUT_MAX_TS +1) + (TS_READ_ONCE -1) large. */ i_currently_removed = i_current_index - i_base_index; if( i_meanwhile_released < i_currently_removed ) { /* Copy all iovecs in that case */ memcpy( &p_input->netlist.p_ts_free[p_input->netlist.i_ts_index] + i_currently_removed, &p_input->netlist.p_ts_free[p_input->netlist.i_ts_index], i_meanwhile_released * sizeof(struct iovec) ); } else { /* We have fewer places than items, so we only move i_currently_removed of them. */ memcpy( &p_input->netlist.p_ts_free[i_base_index], &p_input->netlist.p_ts_free[p_input->netlist.i_ts_index], i_currently_removed * sizeof(struct iovec) ); } /* Update i_netlist_index with the information gathered above. */ p_input->netlist.i_ts_index += i_currently_removed; } else { /* Nothing happened. */ p_input->netlist.i_ts_index = i_current_index; } vlc_mutex_unlock( &p_input->netlist.lock );#else /* FIFO netlist */ /* & is modulo ; that's where we make the loop. */ p_input->netlist.i_ts_start = i_current_index & INPUT_MAX_TS;#endif#ifdef STATS p_input->c_packets_read += i_current_index - i_base_index; p_input->c_bytes += (i_current_index - i_base_index) * TS_PACKET_SIZE;#endif return( 0 );}/***************************************************************************** * input_SortPacket: find out whether we need that packet *****************************************************************************/static __inline__ void input_SortPacket( input_thread_t *p_input, ts_packet_t *p_ts_packet ){ int i_current_pid; int i_es_loop; /* Verify that sync_byte, error_indicator and scrambling_control are what we expected. */ if( !(p_ts_packet->buffer[0] == 0x47) || (p_ts_packet->buffer[1] & 0x80) || (p_ts_packet->buffer[3] & 0xc0) ) { intf_DbgMsg("input debug: invalid TS header (%p)\n", p_ts_packet); } else { /* Get the PID of the packet. Note that ntohs is needed, for endianness purposes (see man page). */ i_current_pid = U16_AT(&p_ts_packet->buffer[1]) & 0x1fff; //intf_DbgMsg("input debug: pid %d received (%p)\n", // i_current_pid, p_ts_packet); /* Lock current ES state. */ vlc_mutex_lock( &p_input->es_lock ); /* Verify that we actually want this PID. */ for( i_es_loop = 0; i_es_loop < INPUT_MAX_SELECTED_ES; i_es_loop++ ) { if( p_input->pp_selected_es[i_es_loop] != NULL) { if( (*p_input->pp_selected_es[i_es_loop]).i_id == i_current_pid ) { /* Don't need the lock anymore, since the value pointed out by p_input->pp_selected_es[i_es_loop] can only be modified from inside the input_thread (by the PSI decoder): interface thread is only allowed to modify the pp_selected_es table */ vlc_mutex_unlock( &p_input->es_lock ); /* We're interested. Pass it to the demultiplexer. */ input_DemuxTS( p_input, p_ts_packet, p_input->pp_selected_es[i_es_loop] ); return; } } else { /* pp_selected_es should not contain any hole. */ break; } } vlc_mutex_unlock( &p_input->es_lock ); } /* We weren't interested in receiving this packet. Give it back to the netlist. */ //intf_DbgMsg("SortPacket: freeing unwanted TS %p (pid %d)\n", p_ts_packet, // U16_AT(&p_ts_packet->buffer[1]) & 0x1fff); input_NetlistFreeTS( p_input, p_ts_packet );#ifdef STATS p_input->c_packets_trashed++;#endif}/***************************************************************************** * input_DemuxTS: first step of demultiplexing: the TS header ***************************************************************************** * Stream must also only contain PES and PSI, so PID must have been filtered *****************************************************************************/static __inline__ void input_DemuxTS( input_thread_t *p_input, ts_packet_t *p_ts_packet, es_descriptor_t *p_es_descriptor ){ int i_dummy; boolean_t b_adaption; /* Adaption field is present */ boolean_t b_payload; /* Packet carries payload */ boolean_t b_unit_start; /* A PSI or a PES start in the packet */ boolean_t b_trash = 0; /* Must the packet be trashed ? */ boolean_t b_lost = 0; /* Was there a packet lost ? */ ASSERT(p_input); ASSERT(p_ts_packet); ASSERT(p_es_descriptor);#define p (p_ts_packet->buffer) //intf_DbgMsg("input debug: TS-demultiplexing packet %p, pid %d, number %d\n", // p_ts_packet, U16_AT(&p[1]) & 0x1fff, p[3] & 0x0f);#ifdef STATS p_es_descriptor->c_packets++; p_es_descriptor->c_bytes += TS_PACKET_SIZE;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -