X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Favi%2Favi.c;h=2efb5ea652e028907256180569900946654c4b89;hb=0ade81b0ebaa94d8529e4784b460bc921be70f54;hp=caad59b93124527ce9519f6a9229bd4e3f797b81;hpb=764aab71ffb34c3a458ce5fb343bbc68dce323e5;p=vlc diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c index caad59b931..2efb5ea652 100644 --- a/modules/demux/avi/avi.c +++ b/modules/demux/avi/avi.c @@ -1,7 +1,7 @@ /***************************************************************************** * avi.c : AVI file Stream input module for vlc ***************************************************************************** - * Copyright (C) 2001-2004 VideoLAN + * Copyright (C) 2001-2004 the VideoLAN team * $Id$ * Authors: Laurent Aimar * @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -28,6 +28,8 @@ #include #include +#include + #include "vlc_meta.h" #include "codecs.h" @@ -38,23 +40,27 @@ *****************************************************************************/ #define INTERLEAVE_TEXT N_("Force interleaved method" ) -#define INTERLEAVE_LONGTEXT N_( "Force interleaved method" ) +#define INTERLEAVE_LONGTEXT N_( "Force interleaved method." ) #define INDEX_TEXT N_("Force index creation") #define INDEX_LONGTEXT N_( \ - "Recreate a index for the AVI file so we can seek trough it more reliably." ) + "Recreate a index for the AVI file. Use this if your AVI file is damaged "\ + "or incomplete (not seekable)." ) static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); vlc_module_begin(); + set_shortname( "AVI" ); 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 ); add_bool( "avi-index", 0, NULL, - INDEX_TEXT, INDEX_LONGTEXT, VLC_TRUE ); + INDEX_TEXT, INDEX_LONGTEXT, VLC_FALSE ); set_callbacks( Open, Close ); vlc_module_end(); @@ -138,6 +144,10 @@ struct demux_sys_t /* meta */ vlc_meta_t *meta; + + /* Progress box */ + mtime_t last_update; + int i_dialog_id; }; static inline off_t __EVEN( off_t i ) @@ -194,6 +204,8 @@ static int Open( vlc_object_t * p_this ) demux_t *p_demux = (demux_t *)p_this; demux_sys_t *p_sys; + vlc_bool_t b_index = VLC_FALSE; + avi_chunk_t ck_riff; avi_chunk_list_t *p_riff = (avi_chunk_list_t*)&ck_riff; avi_chunk_list_t *p_hdrl, *p_movi; @@ -204,24 +216,17 @@ static int Open( vlc_object_t * p_this ) uint8_t *p_peek; - /* Is it an avi file ? */ - if( stream_Peek( p_demux->s, &p_peek, 200 ) < 200 ) - { - msg_Dbg( p_demux, "cannot peek()" ); - return VLC_EGENERIC; - } + if( stream_Peek( p_demux->s, &p_peek, 200 ) < 200 ) return VLC_EGENERIC; + for( i_peeker = 0; i_peeker < 188; i_peeker++ ) { - if( !strncmp( &p_peek[0], "RIFF", 4 ) && !strncmp( &p_peek[8], "AVI ", 4 ) ) - { - break; - } + if( !strncmp( (char *)&p_peek[0], "RIFF", 4 ) && + !strncmp( (char *)&p_peek[8], "AVI ", 4 ) ) break; p_peek++; } if( i_peeker == 188 ) { - msg_Warn( p_demux, "avi module discarded (invalid header)" ); return VLC_EGENERIC; } @@ -240,6 +245,7 @@ static int Open( vlc_object_t * p_this ) p_demux->pf_control = Control; p_demux->pf_demux = Demux_Seekable; + /* For unseekable stream, automaticaly use Demux_UnSeekable */ if( !p_sys->b_seekable || config_GetInt( p_demux, "avi-interleaved" ) ) { @@ -248,7 +254,7 @@ static int Open( vlc_object_t * p_this ) if( i_peeker > 0 ) { - stream_Read( p_demux->s, NULL, i_peeker ); + stream_Read( p_demux->s, NULL, i_peeker ); } if( AVI_ChunkReadRoot( p_demux->s, &p_sys->ck_root ) ) @@ -329,6 +335,7 @@ static int Open( vlc_object_t * p_this ) 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; @@ -437,13 +444,14 @@ static int Open( vlc_object_t * p_this ) 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, + i, (char*)&p_vids->p_bih->biCompression, p_vids->p_bih->biWidth, p_vids->p_bih->biHeight, p_vids->p_bih->biBitCount, @@ -455,12 +463,50 @@ static int Open( vlc_object_t * p_this ) 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 ) + { + /* The charset of p_strn is undefined */ + EnsureUTF8( p_strn->p_str ); + 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 ); } @@ -473,6 +519,7 @@ static int Open( vlc_object_t * p_this ) if( config_GetInt( p_demux, "avi-index" ) ) { +aviindex: if( p_sys->b_seekable ) { AVI_IndexCreate( p_demux ); @@ -494,8 +541,30 @@ static int Open( vlc_object_t * p_this ) (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" ); + msg_Warn( p_demux, "broken or missing index, 'seek' will be " + "axproximative or will have strange behaviour" ); + if( !b_index ) + { + int i_create; + i_create = intf_UserYesNo( p_demux, _("AVI Index") , + _( "This AVI file is broken. Seeking will not " + "work correctly.\nDo you want to " + "try to repair it (this might take a long time) ?" ) ); + if( i_create == DIALOG_OK_YES ) + { + b_index = VLC_TRUE; + msg_Dbg( p_demux, "Fixing AVI index" ); + goto aviindex; + } + else if( i_create == DIALOG_CANCELLED ) + { + /* Kill input */ + p_demux->p_parent->b_die = VLC_TRUE; + goto error; + } + } } + /* fix some BeOS MediaKit generated file */ for( i = 0 ; i < p_sys->i_track; i++ ) { @@ -860,7 +929,7 @@ static int Demux_Seekable( demux_t *p_demux ) if( ( p_frame = stream_Block( p_demux->s, __EVEN( i_size ) ) )==NULL ) { - msg_Warn( p_demux, "failled reading data" ); + msg_Warn( p_demux, "failed reading data" ); tk->b_activated = VLC_FALSE; toread[i_track].b_ok = VLC_FALSE; continue; @@ -1098,8 +1167,8 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent ) int64_t i_pos; /* use i_percent to create a true i_date */ - msg_Warn( p_demux, "mmh, seeking without index at %d%%" - " work only for interleaved file", i_percent ); + msg_Warn( p_demux, "seeking without index at %d%%" + " only works for interleaved files", i_percent ); if( i_percent >= 100 ) { msg_Warn( p_demux, "cannot seek so far !" ); @@ -1314,6 +1383,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts ) { + if( !tk->i_scale ) + return (mtime_t)0; + return (mtime_t)((int64_t)i_pts * (int64_t)tk->i_rate / (int64_t)tk->i_scale / @@ -1321,6 +1393,9 @@ static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts ) } static mtime_t AVI_PTSToByte( avi_track_t *tk, mtime_t i_pts ) { + if( !tk->i_scale || !tk->i_samplesize ) + return (mtime_t)0; + return (mtime_t)((int64_t)i_pts * (int64_t)tk->i_rate / (int64_t)tk->i_scale / @@ -1330,7 +1405,10 @@ static mtime_t AVI_PTSToByte( avi_track_t *tk, mtime_t i_pts ) static mtime_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count ) { - mtime_t i_dpts; + mtime_t i_dpts = 0; + + if( !tk->i_rate ) + return i_dpts; i_dpts = (mtime_t)( (int64_t)1000000 * (int64_t)i_count * @@ -1455,7 +1533,6 @@ static int AVI_StreamChunkFind( demux_t *p_demux, unsigned int i_stream ) } } - /* be sure that i_ck will be a valid index entry */ static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream, unsigned int i_ck ) @@ -1483,7 +1560,6 @@ static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream, return VLC_SUCCESS; } - /* XXX FIXME up to now, we assume that all chunk are one after one */ static int AVI_StreamBytesSet( demux_t *p_demux, unsigned int i_stream, @@ -1846,6 +1922,7 @@ static int AVI_PacketNext( demux_t *p_demux ) } return VLC_SUCCESS; } + static int AVI_PacketRead( demux_t *p_demux, avi_packet_t *p_pk, block_t **pp_frame ) @@ -2066,7 +2143,7 @@ static void __Parse_indx( demux_t *p_demux, } 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 ); } } @@ -2093,7 +2170,8 @@ static void AVI_IndexLoad_indx( demux_t *p_demux ) if( !p_indx ) { - msg_Warn( p_demux, "cannot find indx (misdetect/broken OpenDML file?)" ); + msg_Warn( p_demux, "cannot find indx (misdetect/broken OpenDML " + "file?)" ); continue; } @@ -2103,7 +2181,7 @@ static void AVI_IndexLoad_indx( demux_t *p_demux ) } 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 )|| @@ -2111,12 +2189,12 @@ static void AVI_IndexLoad_indx( demux_t *p_demux ) { 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 } @@ -2181,6 +2259,19 @@ static void AVI_IndexCreate( demux_t *p_demux ) stream_Seek( p_demux->s, p_movi->i_chunk_pos + 12 ); msg_Warn( p_demux, "creating index from LIST-movi, will take time !" ); + + + /* Only show dialog if AVI is > 10MB */ + p_demux->p_sys->i_dialog_id = -1; + if( stream_Size( p_demux->s ) > 10000000 ) + { + p_demux->p_sys->i_dialog_id = intf_UserProgress( p_demux, + _( "Fixing AVI Index" ), + _( "Creating AVI Index ..." ), + 0.0 ); + p_demux->p_sys->last_update = mdate(); + } + for( ;; ) { avi_packet_t pk; @@ -2190,6 +2281,18 @@ static void AVI_IndexCreate( demux_t *p_demux ) return; } + /* Don't update dialog too often */ + if( p_demux->p_sys->i_dialog_id > 0 && + mdate() - p_demux->p_sys->last_update > 100000 ) + { + int64_t i_pos = stream_Tell( p_demux->s )* 100 / + stream_Size( p_demux->s ); + float f_pos = (float)i_pos; + p_demux->p_sys->last_update = mdate(); + intf_UserProgressUpdate( p_demux, p_demux->p_sys->i_dialog_id, + _( "Creating AVI Index ..." ), f_pos ); + } + if( AVI_PacketGetHeader( p_demux, &pk ) ) { break; @@ -2247,6 +2350,11 @@ static void AVI_IndexCreate( demux_t *p_demux ) } print_stat: + if( p_demux->p_sys->i_dialog_id > 0 ) + { + intf_UserHide( p_demux, p_demux->p_sys->i_dialog_id ); + } + for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { msg_Dbg( p_demux, @@ -2322,5 +2430,3 @@ static mtime_t AVI_MovieGetLength( demux_t *p_demux ) return i_maxlength; } - -