vlc_module_begin();
set_description( _("AVI demuxer") );
set_capability( "demux2", 212 );
+ set_category( CAT_INPUT );
+ set_subcategory( SUBCAT_INPUT_DEMUX );
add_bool( "avi-interleaved", 0, NULL,
INTERLEAVE_TEXT, INTERLEAVE_LONGTEXT, VLC_TRUE );
avi_chunk_avih_t *p_avih;
unsigned int i_track;
- unsigned int i;
+ unsigned int i, i_peeker;
uint8_t *p_peek;
-
/* Is it an avi file ? */
- if( stream_Peek( p_demux->s, &p_peek, 12 ) < 12 )
+ if( stream_Peek( p_demux->s, &p_peek, 200 ) < 200 ) return VLC_EGENERIC;
+
+ for( i_peeker = 0; i_peeker < 188; i_peeker++ )
{
- msg_Err( p_demux, "cannot peek()" );
- return VLC_EGENERIC;
+ if( !strncmp( &p_peek[0], "RIFF", 4 ) &&
+ !strncmp( &p_peek[8], "AVI ", 4 ) ) break;
+ p_peek++;
}
- if( strncmp( &p_peek[0], "RIFF", 4 ) || strncmp( &p_peek[8], "AVI ", 4 ) )
+ if( i_peeker == 188 )
{
- msg_Warn( p_demux, "avi module discarded (invalid header)" );
return VLC_EGENERIC;
}
p_demux->pf_demux = Demux_UnSeekable;
}
+ if( i_peeker > 0 )
+ {
+ stream_Read( p_demux->s, NULL, i_peeker );
+ }
+
if( AVI_ChunkReadRoot( p_demux->s, &p_sys->ck_root ) )
{
msg_Err( p_demux, "avi module discarded (invalid file)" );
goto error;
}
- /* print informations on streams */
+ /* print information on streams */
msg_Dbg( p_demux, "AVIH: %d stream, flags %s%s%s%s ",
i_track,
p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
avi_track_t *tk = malloc( sizeof( avi_track_t ) );
avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
avi_chunk_strh_t *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
+ avi_chunk_STRING_t *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0 );
avi_chunk_strf_auds_t *p_auds;
avi_chunk_strf_vids_t *p_vids;
es_format_t fmt;
break;
}
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 ) )
+ if( tk->i_codec == FOURCC_mp4v &&
+ !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
{
fmt.i_codec = VLC_FOURCC( 'X', 'V', 'I', 'D' );
}
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);
+ }
+ 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( 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 );
+ return 0;
}
/* wait for the good time */
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_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 */
}
else
{
- i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 );
+ i_toread = AVI_PTSToByte( tk, 20 * 1000 );
+ i_toread = __MAX( i_toread, 100 );
}
}
i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -
p_frame->p_buffer += 8;
p_frame->i_buffer -= 8;
}
- p_frame->i_pts = AVI_GetPTS( tk );
+ p_frame->i_pts = AVI_GetPTS( tk ) + 1;
if( tk->p_index[tk->i_idxposc].i_flags&AVIIF_KEYFRAME )
{
p_frame->i_flags = BLOCK_FLAG_TYPE_I;
unsigned int i_stream;
unsigned int i_packet;
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 );
/* *** find master stream for data packet skipping algo *** */
/* *** -> first video, if any, or first audio ES *** */
{
return( -1 );
}
- p_frame->i_pts = AVI_GetPTS( p_stream );
+ p_frame->i_pts = AVI_GetPTS( p_stream ) + 1;
if( avi_pk.i_cat != VIDEO_ES )
p_frame->i_dts = p_frame->i_pts;
/*****************************************************************************
* Seek: goto to i_date or i_percent
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
*****************************************************************************/
static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent )
{
if( i_percent >= 100 )
{
msg_Warn( p_demux, "cannot seek so far !" );
- return( -1 );
+ return VLC_EGENERIC;
}
i_percent = __MAX( i_percent, 0 );
if( !p_stream || !p_stream->b_activated )
{
msg_Warn( p_demux, "cannot find any selected stream" );
- return( -1 );
+ return VLC_EGENERIC;
}
/* be sure that the index exist */
if( AVI_StreamChunkSet( p_demux, i_stream, 0 ) )
{
msg_Warn( p_demux, "cannot seek" );
- return( -1 );
+ return VLC_EGENERIC;
}
while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
i_stream, p_stream->i_idxposc + 1 ) )
{
msg_Warn( p_demux, "cannot seek" );
- return( -1 );
+ return VLC_EGENERIC;
}
}
p_sys->i_time = i_date;
}
#undef p_stream
- return( 1 );
+ return VLC_SUCCESS;
}
else
{
msg_Err( p_demux, "shouldn't yet be executed" );
- return( -1 );
+ return VLC_EGENERIC;
}
}
if( p_sys->b_seekable )
{
i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );
- return Seek( p_demux, i64, (int)(f * 100) ) < 0 ? VLC_EGENERIC : VLC_SUCCESS;
+ return Seek( p_demux, i64, (int)(f * 100) );
}
else
{
*/
return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
case FOURCC_mp4v:
- /* we should find first occurence of 0x000001b6 (32bits)
+ /* we should find first occurrence of 0x000001b6 (32bits)
* startcode: 0x000001b6 32bits
* piture type 0(I),1(P) 2bits
*/
off_t i_offset;
unsigned int i;
+ vlc_bool_t b_keyset[100];
+
p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
}
}
+ /* Reset b_keyset */
+ for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
+ b_keyset[i_stream] = VLC_FALSE;
+
for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
{
unsigned int i_cat;
index.i_pos = p_idx1->entry[i_index].i_pos + i_offset;
index.i_length = p_idx1->entry[i_index].i_length;
AVI_IndexAddEntry( p_sys, i_stream, &index );
+
+ if( index.i_flags&AVIIF_KEYFRAME )
+ b_keyset[i_stream] = VLC_TRUE;
+ }
+ }
+
+ for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
+ {
+ if( !b_keyset[i_stream] )
+ {
+ avi_track_t *tk = p_sys->track[i_stream];
+
+ msg_Dbg( p_demux, "no key frame set for track %d", i_stream );
+ for( i_index = 0; i_index < tk->i_idxnb; i_index++ )
+ tk->p_index[i_index].i_flags |= AVIIF_KEYFRAME;
}
}
return VLC_SUCCESS;
}
else
{
- msg_Warn( p_demux, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
+ msg_Warn( p_demux, "unknown subtype index(0x%x)", p_indx->i_indexsubtype );
}
}
}
else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
{
- avi_chunk_indx_t ck_sub;
+ avi_chunk_t ck_sub;
for( i = 0; i < p_indx->i_entriesinuse; i++ )
{
if( stream_Seek( p_demux->s, p_indx->idx.super[i].i_offset )||
{
break;
}
- __Parse_indx( p_demux, i_stream, &ck_sub );
+ __Parse_indx( p_demux, i_stream, &ck_sub.indx );
}
}
else
{
- msg_Warn( p_demux, "unknow type index(0x%x)", p_indx->i_indextype );
+ msg_Warn( p_demux, "unknown type index(0x%x)", p_indx->i_indextype );
}
#undef p_stream
}