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

📄 ogg.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 4 页
字号:
    return 1;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){    demux_sys_t *p_sys  = p_demux->p_sys;    int64_t *pi64;    int i;    switch( i_query )    {        case DEMUX_GET_TIME:            pi64 = (int64_t*)va_arg( args, int64_t * );            *pi64 = p_sys->i_pcr;            return VLC_SUCCESS;        case DEMUX_SET_TIME:            return VLC_EGENERIC;        case DEMUX_SET_POSITION:            for( i = 0; i < p_sys->i_streams; i++ )            {                logical_stream_t *p_stream = p_sys->pp_stream[i];                /* we'll trash all the data until we find the next pcr */                p_stream->b_reinit = 1;                p_stream->i_pcr = -1;                p_stream->i_interpolated_pcr = -1;                ogg_stream_reset( &p_stream->os );            }            ogg_sync_reset( &p_sys->oy );        default:            return demux2_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,                                           1, i_query, args );    }}/**************************************************************************** * Ogg_ReadPage: Read a full Ogg page from the physical bitstream. **************************************************************************** * Returns VLC_SUCCESS if a page has been read. An error might happen if we * are at the end of stream. ****************************************************************************/static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage ){    demux_sys_t *p_ogg = p_demux->p_sys  ;    int i_read = 0;    byte_t *p_buffer;    while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )    {        p_buffer = ogg_sync_buffer( &p_ogg->oy, OGG_BLOCK_SIZE );        i_read = stream_Read( p_demux->s, p_buffer, OGG_BLOCK_SIZE );        if( i_read <= 0 )            return VLC_EGENERIC;        ogg_sync_wrote( &p_ogg->oy, i_read );    }    return VLC_SUCCESS;}/**************************************************************************** * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the *                current stream. ****************************************************************************/static void Ogg_UpdatePCR( logical_stream_t *p_stream,                           ogg_packet *p_oggpacket ){    /* Convert the granulepos into a pcr */    if( p_oggpacket->granulepos >= 0 )    {        if( p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) )        {            p_stream->i_pcr = p_oggpacket->granulepos * I64C(1000000)                              / p_stream->f_rate;        }        else        {            ogg_int64_t iframe = p_oggpacket->granulepos >>              p_stream->i_theora_keyframe_granule_shift;            ogg_int64_t pframe = p_oggpacket->granulepos -              ( iframe << p_stream->i_theora_keyframe_granule_shift );            p_stream->i_pcr = ( iframe + pframe ) * I64C(1000000)                              / p_stream->f_rate;        }        p_stream->i_interpolated_pcr = p_stream->i_pcr;    }    else    {        p_stream->i_pcr = -1;        /* no granulepos available, try to interpolate the pcr.         * If we can't then don't touch the old value. */        if( p_stream->fmt.i_cat == VIDEO_ES )            /* 1 frame per packet */            p_stream->i_interpolated_pcr += (I64C(1000000) / p_stream->f_rate);        else if( p_stream->fmt.i_bitrate )            p_stream->i_interpolated_pcr +=                ( p_oggpacket->bytes * I64C(1000000) /                  p_stream->fmt.i_bitrate / 8 );    }}/**************************************************************************** * Ogg_DecodePacket: Decode an Ogg packet. ****************************************************************************/static void Ogg_DecodePacket( demux_t *p_demux,                              logical_stream_t *p_stream,                              ogg_packet *p_oggpacket ){    block_t *p_block;    vlc_bool_t b_selected;    int i_header_len = 0;    mtime_t i_pts = -1, i_interpolated_pts;    /* Sanity check */    if( !p_oggpacket->bytes )    {        msg_Dbg( p_demux, "discarding 0 sized packet" );        return;    }    if( p_oggpacket->bytes >= 7 &&        ! strncmp ( &p_oggpacket->packet[0], "Annodex", 7 ) )    {        /* it's an Annodex packet -- skip it (do nothing) */        return;     }    else if( p_oggpacket->bytes >= 7 &&        ! strncmp ( &p_oggpacket->packet[0], "AnxData", 7 ) )    {        /* it's an AnxData packet -- skip it (do nothing) */        return;     }    /* Check the ES is selected */    es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,                    p_stream->p_es, &b_selected );    if( p_stream->b_force_backup )    {        uint8_t *p_extra;        vlc_bool_t b_store_size = VLC_TRUE;        p_stream->i_packets_backup++;        switch( p_stream->fmt.i_codec )        {        case VLC_FOURCC( 'v','o','r','b' ):        case VLC_FOURCC( 's','p','x',' ' ):        case VLC_FOURCC( 't','h','e','o' ):          if( p_stream->i_packets_backup == 3 ) p_stream->b_force_backup = 0;          break;        case VLC_FOURCC( 'f','l','a','c' ):          if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 )          {              Ogg_ReadFlacHeader( p_demux, p_stream, p_oggpacket );              p_stream->b_force_backup = 0;          }          else if( p_stream->fmt.audio.i_rate )          {              p_stream->b_force_backup = 0;              p_oggpacket->packet += 9; p_oggpacket->bytes -= 9;          }          b_store_size = VLC_FALSE;          break;        default:          p_stream->b_force_backup = 0;          break;        }        /* Backup the ogg packet (likely an header packet) */        p_stream->p_headers =            realloc( p_stream->p_headers, p_stream->i_headers +                     p_oggpacket->bytes + (b_store_size ? 2 : 0) );        p_extra = p_stream->p_headers + p_stream->i_headers;        if( b_store_size )        {            *(p_extra++) = p_oggpacket->bytes >> 8;            *(p_extra++) = p_oggpacket->bytes & 0xFF;        }        memcpy( p_extra, p_oggpacket->packet, p_oggpacket->bytes );        p_stream->i_headers += p_oggpacket->bytes + (b_store_size ? 2 : 0);        if( !p_stream->b_force_backup )        {            /* Last header received, commit changes */            p_stream->fmt.i_extra = p_stream->i_headers;            p_stream->fmt.p_extra =                realloc( p_stream->fmt.p_extra, p_stream->i_headers );            memcpy( p_stream->fmt.p_extra, p_stream->p_headers,                    p_stream->i_headers );            es_out_Control( p_demux->out, ES_OUT_SET_FMT,                            p_stream->p_es, &p_stream->fmt );        }        b_selected = VLC_FALSE; /* Discard the header packet */    }    /* Convert the pcr into a pts */    if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) ||        p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) ||        p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) )    {        if( p_stream->i_pcr >= 0 )        {            /* This is for streams where the granulepos of the header packets             * doesn't match these of the data packets (eg. ogg web radios). */            if( p_stream->i_previous_pcr == 0 &&                p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY )            {                es_out_Control( p_demux->out, ES_OUT_RESET_PCR );                /* Call the pace control */                es_out_Control( p_demux->out, ES_OUT_SET_PCR,                                p_stream->i_pcr );            }            p_stream->i_previous_pcr = p_stream->i_pcr;            /* The granulepos is the end date of the sample */            i_pts =  p_stream->i_pcr;        }    }    /* Convert the granulepos into the next pcr */    i_interpolated_pts = p_stream->i_interpolated_pcr;    Ogg_UpdatePCR( p_stream, p_oggpacket );    if( p_stream->i_pcr >= 0 )    {        /* This is for streams where the granulepos of the header packets         * doesn't match these of the data packets (eg. ogg web radios). */        if( p_stream->i_previous_pcr == 0 &&            p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY )        {            es_out_Control( p_demux->out, ES_OUT_RESET_PCR );            /* Call the pace control */            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_stream->i_pcr );        }    }    if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) &&        p_stream->i_pcr >= 0 )    {        p_stream->i_previous_pcr = p_stream->i_pcr;        /* The granulepos is the start date of the sample */        i_pts = p_stream->i_pcr;    }    if( !b_selected )    {        /* This stream isn't currently selected so we don't need to decode it,         * but we did need to store its pcr as it might be selected later on */        return;    }    if( !( p_block = block_New( p_demux, p_oggpacket->bytes ) ) ) return;    /* Normalize PTS */    if( i_pts == 0 ) i_pts = 1;    else if( i_pts == -1 && i_interpolated_pts == 0 ) i_pts = 1;    else if( i_pts == -1 ) i_pts = 0;    if( p_stream->fmt.i_cat == AUDIO_ES )        p_block->i_dts = p_block->i_pts = i_pts;    else if( p_stream->fmt.i_cat == SPU_ES )    {        p_block->i_dts = p_block->i_pts = i_pts;        p_block->i_length = 0;    }    else if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) )        p_block->i_dts = p_block->i_pts = i_pts;    else    {        p_block->i_dts = i_pts;        p_block->i_pts = 0;    }    if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 't','a','r','k' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) &&        p_stream->fmt.i_codec != VLC_FOURCC( 'c','m','m','l' ) )    {        /* We remove the header from the packet */        i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;        i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;        if( p_stream->fmt.i_codec == VLC_FOURCC( 's','u','b','t' ))        {            /* But with subtitles we need to retrieve the duration first */            int i, lenbytes = 0;                    if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )            {                for( i = 0, lenbytes = 0; i < i_header_len; i++ )                {                    lenbytes = lenbytes << 8;                    lenbytes += *(p_oggpacket->packet + i_header_len - i);                }            }            if( p_oggpacket->bytes - 1 - i_header_len > 2 ||                ( p_oggpacket->packet[i_header_len + 1] != ' ' &&                  p_oggpacket->packet[i_header_len + 1] != 0 &&                   p_oggpacket->packet[i_header_len + 1] != '\n' &&                  p_oggpacket->packet[i_header_len + 1] != '\r' ) )            {                p_block->i_length = (mtime_t)lenbytes * 1000;            }        }        i_header_len++;        p_block->i_buffer -= i_header_len;    }    if( p_stream->fmt.i_codec == VLC_FOURCC( 't','a','r','k' ) )    {        /* FIXME: the biggest hack I've ever done */        msg_Warn( p_demux, "tarkin pts: "I64Fd", granule: "I64Fd,                  p_block->i_pts, p_block->i_dts );        msleep(10000);    }    memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,            p_oggpacket->bytes - i_header_len );    es_out_Send( p_demux->out, p_stream->p_es, p_block );}/**************************************************************************** * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical *                         stream and fill p_ogg. ***************************************************************************** * The initial page of a logical stream is marked as a 'bos' page. * Furthermore, the Ogg specification mandates that grouped bitstreams begin * together and all of the initial pages must appear before any data pages.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -