⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 vlc stand 0.1.99 ist sehr einfach
💻 C
📖 第 1 页 / 共 4 页
字号:
    /*     * 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 + -