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

📄 avi.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 5 页
字号:
                    es_format_Init( &fmt, VIDEO_ES, tk->i_codec );                    if( p_vids->p_bih->biBitCount == 24 )                    {                        /* This is in BGR format */                        fmt.video.i_bmask = 0x00ff0000;                        fmt.video.i_gmask = 0x0000ff00;                        fmt.video.i_rmask = 0x000000ff;                    }                }                else                {                    es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression );                    if( tk->i_codec == FOURCC_mp4v &&                        !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )                    {                        fmt.i_codec = VLC_FOURCC( 'X', 'V', 'I', 'D' );                    }                }                tk->i_samplesize = 0;                fmt.video.i_width  = p_vids->p_bih->biWidth;                fmt.video.i_height = p_vids->p_bih->biHeight;                fmt.video.i_bits_per_pixel = p_vids->p_bih->biBitCount;                fmt.video.i_frame_rate = tk->i_rate;                fmt.video.i_frame_rate_base = tk->i_scale;                fmt.i_extra =                    __MIN( p_vids->p_bih->biSize - sizeof( BITMAPINFOHEADER ),                           p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER) );                fmt.p_extra = &p_vids->p_bih[1];                msg_Dbg( p_demux, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",                         i, (char*)&p_vids->p_bih->biCompression,                         p_vids->p_bih->biWidth,                         p_vids->p_bih->biHeight,                         p_vids->p_bih->biBitCount,                         (float)tk->i_rate/(float)tk->i_scale );                if( p_vids->p_bih->biCompression == 0x00 )                {                    /* RGB DIB are coded from bottom to top */                    fmt.video.i_height =                        (unsigned int)(-(int)p_vids->p_bih->biHeight);                }                /* Extract palette from extradata if bpp <= 8                 * (assumes that extradata contains only palette but appears                 *  to be true for all palettized codecs we support) */                if( fmt.i_extra && fmt.video.i_bits_per_pixel <= 8 &&                    fmt.video.i_bits_per_pixel > 0 )                {                    int i;                    fmt.video.p_palette = calloc( sizeof(video_palette_t), 1 );                    fmt.video.p_palette->i_entries = 1;		    /* Apparently this is necessary. But why ? */		    fmt.i_extra =		        p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER);                    for( i = 0; i < __MIN(fmt.i_extra/4, 256); i++ )		    {                        ((uint32_t *)&fmt.video.p_palette->palette[0][0])[i] =                            GetDWLE((uint32_t*)fmt.p_extra + i);		    }                }                break;            case( AVIFOURCC_txts):                tk->i_cat   = SPU_ES;                tk->i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );                msg_Dbg( p_demux, "stream[%d] subtitles", i );                es_format_Init( &fmt, SPU_ES, tk->i_codec );                break;                            case( AVIFOURCC_mids):                msg_Dbg( p_demux, "stream[%d] midi is UNSUPPORTED", i );            default:                msg_Warn( p_demux, "stream[%d] unknown type", i );                free( tk );                continue;        }        if( p_strn )        {            fmt.psz_description = strdup( p_strn->p_str );        }        tk->p_es = es_out_Add( p_demux->out, &fmt );        TAB_APPEND( p_sys->i_track, p_sys->track, tk );    }    if( p_sys->i_track <= 0 )    {        msg_Err( p_demux, "no valid track" );        goto error;    }    if( config_GetInt( p_demux, "avi-index" ) )    {        if( p_sys->b_seekable )        {            AVI_IndexCreate( p_demux );        }        else        {            msg_Warn( p_demux, "cannot create index (unseekable stream)" );            AVI_IndexLoad( p_demux );        }    }    else    {        AVI_IndexLoad( p_demux );    }    /* *** movie length in sec *** */    p_sys->i_length = AVI_MovieGetLength( p_demux );    if( p_sys->i_length < (mtime_t)p_avih->i_totalframes *                          (mtime_t)p_avih->i_microsecperframe /                          (mtime_t)1000000 )    {        msg_Warn( p_demux, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );    }    /* fix some BeOS MediaKit generated file */    for( i = 0 ; i < p_sys->i_track; i++ )    {        avi_track_t         *tk = p_sys->track[i];        avi_chunk_list_t    *p_strl;        avi_chunk_strh_t    *p_strh;        avi_chunk_strf_auds_t    *p_auds;        if( tk->i_cat != AUDIO_ES )        {            continue;        }        if( tk->i_idxnb < 1 ||            tk->i_scale != 1 ||            tk->i_samplesize != 0 )        {            continue;        }        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );        p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );        if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&            (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec )        {            int64_t i_track_length =                tk->p_index[tk->i_idxnb-1].i_length +                tk->p_index[tk->i_idxnb-1].i_lengthtotal;            mtime_t i_length = (mtime_t)p_avih->i_totalframes *                               (mtime_t)p_avih->i_microsecperframe;            if( i_length == 0 )            {                msg_Warn( p_demux, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );                continue;            }            tk->i_samplesize = 1;            tk->i_rate       = i_track_length  * (int64_t)1000000/ i_length;            msg_Warn( p_demux, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );        }    }    if( p_sys->b_seekable )    {        /* we have read all chunk so go back to movi */        stream_Seek( p_demux->s, p_movi->i_chunk_pos );    }    /* Skip movi header */    stream_Read( p_demux->s, NULL, 12 );    p_sys->i_movi_begin = p_movi->i_chunk_pos;    return VLC_SUCCESS;error:    if( p_sys->meta )    {        vlc_meta_Delete( p_sys->meta );    }    AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root );    free( p_sys );    return VLC_EGENERIC;}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close ( vlc_object_t * p_this ){    demux_t *    p_demux = (demux_t *)p_this;    unsigned int i;    demux_sys_t *p_sys = p_demux->p_sys  ;    for( i = 0; i < p_sys->i_track; i++ )    {        if( p_sys->track[i] )        {            FREE( p_sys->track[i]->p_index );            free( p_sys->track[i] );        }    }    FREE( p_sys->track );    AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root );    vlc_meta_Delete( p_sys->meta );    free( p_sys );}/***************************************************************************** * Demux_Seekable: reads and demuxes data packets for stream seekable ***************************************************************************** * AVIDemux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/typedef struct{    vlc_bool_t b_ok;    int i_toread;    off_t i_posf; /* where we will read :                   if i_idxposb == 0 : begining of chunk (+8 to acces data)                   else : point on data directly */} avi_track_toread_t;static int Demux_Seekable( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    unsigned int i_track_count = 0;    unsigned int i_track;    vlc_bool_t b_stream;    /* cannot be more than 100 stream (dcXX or wbXX) */    avi_track_toread_t toread[100];    /* detect new selected/unselected streams */    for( i_track = 0; i_track < p_sys->i_track; i_track++ )    {        avi_track_t *tk = p_sys->track[i_track];        vlc_bool_t  b;        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );        if( b && !tk->b_activated )        {            if( p_sys->b_seekable)            {                AVI_TrackSeek( p_demux, i_track, p_sys->i_time );            }            tk->b_activated = VLC_TRUE;        }        else if( !b && tk->b_activated )        {            tk->b_activated = VLC_FALSE;        }        if( b )        {            i_track_count++;        }    }    if( i_track_count <= 0 )    {        int64_t i_length = p_sys->i_length * (mtime_t)1000000;        p_sys->i_time += 25*1000;  /* read 25ms */        if( i_length > 0 )        {            if( p_sys->i_time >= i_length )                return 0;            return 1;        }        msg_Warn( p_demux, "no track selected, exiting..." );        return 0;    }    /* wait for the good time */    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 );    p_sys->i_time += 25*1000;  /* read 25ms */    /* init toread */    for( i_track = 0; i_track < p_sys->i_track; i_track++ )    {        avi_track_t *tk = p_sys->track[i_track];        mtime_t i_dpts;        toread[i_track].b_ok = tk->b_activated;        if( tk->i_idxposc < tk->i_idxnb )        {            toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos;           if( tk->i_idxposb > 0 )           {                toread[i_track].i_posf += 8 + tk->i_idxposb;           }        }        else        {            toread[i_track].i_posf = -1;        }        i_dpts = p_sys->i_time - AVI_GetPTS( tk  );        if( tk->i_samplesize )        {            toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) );        }        else        {            toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) );        }        if( i_dpts < 0 )        {            toread[i_track].i_toread *= -1;        }    }    b_stream = VLC_FALSE;    for( ;; )    {        avi_track_t     *tk;        vlc_bool_t       b_done;        block_t         *p_frame;        off_t i_pos;        unsigned int i;        size_t i_size;        /* search for first chunk to be read */        for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ )        {            if( !toread[i].b_ok ||                AVI_GetDPTS( p_sys->track[i],                             toread[i].i_toread ) <= -25 * 1000 )            {                continue;            }            if( toread[i].i_toread > 0 )            {                b_done = VLC_FALSE; /* not yet finished */            }            if( toread[i].i_posf > 0 )            {                if( i_pos == -1 || i_pos > toread[i_track].i_posf )                {                    i_track = i;                    i_pos = toread[i].i_posf;                }            }        }        if( b_done )        {            return( 1 );        }        if( i_pos == -1 )        {            int i_loop_count = 0;            /* no valid index, we will parse directly the stream             * in case we fail we will disable all finished stream */            if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )            {                stream_Seek( p_demux->s, p_sys->i_movi_lastchunk_pos );                if( AVI_PacketNext( p_demux ) )                {                    return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );                }            }            else            {                stream_Seek( p_demux->s, p_sys->i_movi_begin + 12 );            }            for( ;; )            {                avi_packet_t avi_pk;                if( AVI_PacketGetHeader( p_demux, &avi_pk ) )                {                    msg_Warn( p_demux,                             "cannot get packet header, track disabled" );                    return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );                }                if( avi_pk.i_stream >= p_sys->i_track ||                    ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )                {                    if( AVI_PacketNext( p_demux ) )                    {                        msg_Warn( p_demux,                                  "cannot skip packet, track disabled" );                        return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );                    }                    /* Prevents from eating all the CPU with broken files.                     * This value should be low enough so that it doesn't                     * affect the reading speed too much. */                    if( !(++i_loop_count % 1024) )                    {                        if( p_demux->b_die ) return -1;                        msleep( 10000 );                        if( !(i_loop_count % (1024 * 10)) )                            msg_Warn( p_demux,                                      "don't seem to find any data..." );                    }                    continue;                }                else                {                    /* add this chunk to the index */

⌨️ 快捷键说明

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