Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (8)
......@@ -121,9 +121,8 @@ typedef struct
typedef struct
{
vlc_fourcc_t i_id;
uint32_t i_flags;
uint64_t i_pos;
uint32_t i_flags;
uint32_t i_length;
uint64_t i_lengthtotal;
......@@ -145,8 +144,8 @@ typedef struct
bool b_activated;
bool b_eof;
unsigned int i_rate;
unsigned int i_scale;
unsigned int i_rate; /* for audio & video */
unsigned int i_scale;/* for audio & video */
unsigned int i_samplesize;
struct bitmapinfoheader_properties bihprops;
......@@ -158,6 +157,9 @@ typedef struct
int i_dv_audio_rate;
es_out_id_t *p_es_dv_audio;
/* SPU specific */
vlc_tick_t i_last_embedded_endtime;
vlc_tick_t i_next_embedded_time;
/* Avi Index */
avi_index_t idx;
......@@ -169,6 +171,17 @@ typedef struct
unsigned int i_blockno;
unsigned int i_blocksize;
struct
{
bool b_ok;
int64_t i_toread;
int64_t i_posf; /* where we will read :
if i_idxposb == 0 : beginning of chunk (+8 to access data)
else : point on data directly */
} demuxctx;
} avi_track_t;
typedef struct
......@@ -224,6 +237,8 @@ static void AVI_IndexLoad ( demux_t * );
static void AVI_IndexCreate ( demux_t * );
static void AVI_ExtractSubtitle( demux_t *, unsigned int i_stream, avi_chunk_list_t *, avi_chunk_STRING_t * );
static avi_track_t * AVI_GetVideoTrackForXsub( demux_sys_t * );
static int AVI_SeekSubtitleTrack( demux_sys_t *, avi_track_t * );
static void AVI_DvHandleAudio( demux_t *, avi_track_t *, block_t * );
......@@ -267,6 +282,45 @@ static bool IsQNAPCodec(uint32_t biCompression)
}
}
#define XSUB_HEADER_SIZE 0x1B
static int ExtractXsubSampleInfo( const uint8_t *p_buf,
vlc_tick_t *pi_start, vlc_tick_t *pi_end )
{
unsigned t[8];
char buffer[XSUB_HEADER_SIZE + 1];
memcpy( buffer, p_buf, XSUB_HEADER_SIZE );
buffer[XSUB_HEADER_SIZE] = '\0';
if( sscanf( buffer, "[%u:%2u:%2u.%3u-%u:%2u:%2u.%3u]",
&t[0], &t[1], &t[2], &t[3], &t[4], &t[5], &t[6], &t[7] ) != 8 )
return VLC_EGENERIC;
*pi_start = vlc_tick_from_sec( t[0] * 3600 + t[1] * 60 + t[2] ) +
VLC_TICK_FROM_MS(t[3]);
*pi_end = vlc_tick_from_sec( t[4] * 3600 + t[5] * 60 + t[6] ) +
VLC_TICK_FROM_MS(t[7]);
return VLC_SUCCESS;
}
static int AVI_PeekSample( stream_t *s, size_t i_skip,
const uint8_t **pp_peek, size_t i_peek )
{
ssize_t i_ret = vlc_stream_Peek( s, pp_peek, i_skip + i_peek );
*pp_peek += i_skip;
if ( i_ret < 0 || (size_t) i_ret != i_skip + i_peek )
return VLC_EGENERIC;
return VLC_SUCCESS;
}
static vlc_tick_t AVI_GetXsubSampleTimeAt( stream_t *s, uint64_t pos )
{
const uint8_t *p_peek;
vlc_tick_t i_nzstart, i_nzend;
if( vlc_stream_Seek( s, pos ) != VLC_SUCCESS ||
AVI_PeekSample( s, 8, &p_peek, XSUB_HEADER_SIZE ) ||
ExtractXsubSampleInfo( p_peek, &i_nzstart, &i_nzend ) )
return VLC_TICK_INVALID;
return VLC_TICK_0 + i_nzstart;
}
/*****************************************************************************
* Close: frees unused data
*****************************************************************************/
......@@ -484,11 +538,6 @@ static int Open( vlc_object_t * p_this )
tk->i_samplesize = p_strh->i_samplesize;
msg_Dbg( p_demux, "stream[%u] rate:%u scale:%u samplesize:%u",
i, tk->i_rate, tk->i_scale, tk->i_samplesize );
if( !tk->i_scale || !tk->i_rate || !(tk->i_rate * CLOCK_FREQ / tk->i_scale) )
{
free( tk );
continue;
}
switch( p_strh->i_type )
{
......@@ -608,10 +657,12 @@ static int Open( vlc_object_t * p_this )
case( AVIFOURCC_vids ):
{
if( p_vids->p_bih->biCompression == VLC_FOURCC( 'D', 'X', 'S', 'B' ) )
if( p_vids->p_bih->biCompression == FOURCC_DXSB )
{
msg_Dbg( p_demux, "stream[%u] subtitles", i );
es_format_Init( &tk->fmt, SPU_ES, p_vids->p_bih->biCompression );
tk->fmt.subs.spu.i_original_frame_width = p_vids->p_bih->biWidth;
tk->fmt.subs.spu.i_original_frame_height = p_vids->p_bih->biHeight;
break;
}
......@@ -629,7 +680,7 @@ static int Open( vlc_object_t * p_this )
!strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
{
tk->fmt.i_codec =
tk->fmt.i_original_fourcc = VLC_FOURCC( 'X', 'V', 'I', 'D' );
tk->fmt.i_original_fourcc = FOURCC_XVID;
}
if( IsQNAPCodec( p_vids->p_bih->biCompression ) )
......@@ -693,6 +744,16 @@ static int Open( vlc_object_t * p_this )
free( tk );
continue;
}
if( tk->fmt.i_cat != SPU_ES &&
(!tk->i_scale || !tk->i_rate || !(tk->i_rate * CLOCK_FREQ / tk->i_scale)) )
{
msg_Warn( p_demux, "stream[%u] has invalid timescale", i );
es_format_Clean(&tk->fmt);
free( tk );
continue;
}
tk->fmt.i_id = i;
if( p_strn && p_strn->p_str )
tk->fmt.psz_description = FromACP( p_strn->p_str );
......@@ -874,6 +935,17 @@ static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
if( i_osize == i_size - 1 )
p_frame->i_buffer--;
if( tk->fmt.i_codec == FOURCC_DXSB && p_frame->i_buffer > XSUB_HEADER_SIZE )
{
vlc_tick_t i_start, i_end;
if( !ExtractXsubSampleInfo( p_frame->p_buffer, &i_start, &i_end ) )
{
p_frame->i_dts = p_frame->i_pts = VLC_TICK_0 + i_start;
if( i_end > i_start )
p_frame->i_length = i_start - i_end;
}
}
if( tk->bihprops.i_stride > INT32_MAX - 3 )
{
p_frame->i_buffer = 0;
......@@ -1002,31 +1074,16 @@ static void AVI_SendFrame( demux_t *p_demux, avi_track_t *tk, block_t *p_frame )
*****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
*****************************************************************************/
typedef struct
{
bool b_ok;
int64_t i_toread;
int64_t i_posf; /* where we will read :
if i_idxposb == 0 : beginning of chunk (+8 to access 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;
/* 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++ )
for( unsigned int i = 0; i < p_sys->i_track; i++ )
{
avi_track_t *tk = p_sys->track[i_track];
avi_track_t *tk = p_sys->track[i];
bool b = false;
es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
......@@ -1040,7 +1097,7 @@ static int Demux_Seekable( demux_t *p_demux )
{
if( p_sys->b_seekable)
{
AVI_TrackSeek( p_demux, i_track, p_sys->i_time );
AVI_TrackSeek( p_demux, i, p_sys->i_time );
}
tk->b_activated = true;
}
......@@ -1072,29 +1129,46 @@ static int Demux_Seekable( demux_t *p_demux )
p_sys->i_time += p_sys->i_read_increment;
/* init toread */
for( i_track = 0; i_track < p_sys->i_track; i_track++ )
for( unsigned i = 0; i < p_sys->i_track; i++ )
{
avi_track_t *tk = p_sys->track[i_track];
avi_track_t *tk = p_sys->track[i];
toread[i_track].b_ok = tk->b_activated && !tk->b_eof;
tk->demuxctx.b_ok = tk->b_activated && !tk->b_eof;
if( tk->i_idxposc < tk->idx.i_size )
{
toread[i_track].i_posf = tk->idx.p_entry[tk->i_idxposc].i_pos;
tk->demuxctx.i_posf = tk->idx.p_entry[tk->i_idxposc].i_pos;
if( tk->i_idxposb > 0 )
{
toread[i_track].i_posf += 8 + tk->i_idxposb;
tk->demuxctx.i_posf += 8 + tk->i_idxposb;
}
}
else
{
toread[i_track].i_posf = -1;
tk->demuxctx.i_posf = -1;
}
/* Xsub specific. There's no possible chunk/byte<->time */
if( tk->fmt.i_codec == FOURCC_DXSB )
{
/* load spu times */
if( tk->i_next_embedded_time == VLC_TICK_INVALID && tk->demuxctx.i_posf != -1 )
tk->i_next_embedded_time = AVI_GetXsubSampleTimeAt(
p_demux->s, tk->idx.p_entry[ tk->i_idxposc].i_pos );
vlc_tick_t i_reftime = tk->i_next_embedded_time != VLC_TICK_INVALID
? tk->i_next_embedded_time : tk->i_last_embedded_endtime;
if( i_reftime != VLC_TICK_INVALID &&
p_sys->i_time - i_reftime > VLC_TICK_FROM_SEC(-2) )
tk->demuxctx.i_toread = 1;
else
tk->demuxctx.i_toread = -1;
continue;
}
vlc_tick_t i_dpts = p_sys->i_time - AVI_GetPTS( tk );
if( tk->i_samplesize )
{
toread[i_track].i_toread = AVI_PTSToByte( tk, i_dpts );
tk->demuxctx.i_toread = AVI_PTSToByte( tk, i_dpts );
}
else if ( i_dpts > VLC_TICK_FROM_SEC(-2) ) /* don't send a too early dts (low fps video) */
{
......@@ -1105,40 +1179,40 @@ static int Demux_Seekable( demux_t *p_demux )
* That does not even work when reading amount < scale / rate */
i_chunks_count++;
}
toread[i_track].i_toread = i_chunks_count;
tk->demuxctx.i_toread = i_chunks_count;
}
else
toread[i_track].i_toread = -1;
tk->demuxctx.i_toread = -1;
}
for( ;; )
{
avi_track_t *tk;
bool b_done;
bool b_done = true;
block_t *p_frame;
int64_t i_pos;
unsigned int i;
int64_t i_pos = -1;
unsigned int i_track = 0;
/* search for first chunk to be read */
for( i = 0, b_done = true, i_pos = -1; i < p_sys->i_track; i++ )
for( unsigned i = 0; i < p_sys->i_track; i++ )
{
if( !toread[i].b_ok ||
avi_track_t *tk = p_sys->track[i];
if( !tk->demuxctx.b_ok ||
( p_sys->b_fastseekable && p_sys->b_interleaved &&
AVI_GetDPTS( p_sys->track[i], toread[i].i_toread ) <= -p_sys->i_read_increment ) )
AVI_GetDPTS( tk, tk->demuxctx.i_toread ) <= -p_sys->i_read_increment ) )
{
continue;
}
if( toread[i].i_toread > 0 )
if( tk->demuxctx.i_toread > 0 )
{
b_done = false; /* not yet finished */
if( toread[i].i_posf > 0 )
if( tk->demuxctx.i_posf > 0 )
{
if( i_pos == -1 || i_pos > toread[i].i_posf )
if( i_pos == -1 || i_pos > tk->demuxctx.i_posf )
{
i_track = i;
i_pos = toread[i].i_posf;
i_pos = tk->demuxctx.i_posf;
}
}
}
......@@ -1146,9 +1220,10 @@ static int Demux_Seekable( demux_t *p_demux )
if( b_done )
{
for( i = 0; i < p_sys->i_track; i++ )
for( unsigned i = 0; i < p_sys->i_track; i++ )
{
if( toread[i].b_ok && toread[i].i_toread >= 0 )
const avi_track_t *tk = p_sys->track[i];
if( tk->demuxctx.b_ok && tk->demuxctx.i_toread >= 0 )
return VLC_DEMUXER_SUCCESS;
}
msg_Warn( p_demux, "all tracks have failed, exiting..." );
......@@ -1204,11 +1279,10 @@ static int Demux_Seekable( demux_t *p_demux )
else
{
i_track = avi_pk.i_stream;
tk = p_sys->track[i_track];
avi_track_t *tk = p_sys->track[i_track];
/* add this chunk to the index */
avi_entry_t index;
index.i_id = avi_pk.i_fourcc;
index.i_flags = AVI_GetKeyFlag(tk, avi_pk.i_peek);
index.i_pos = avi_pk.i_pos;
index.i_length = avi_pk.i_size;
......@@ -1217,7 +1291,7 @@ static int Demux_Seekable( demux_t *p_demux )
/* do we will read this data ? */
if( i_indexid >= 0 &&
AVI_GetDPTS( tk, toread[i_track].i_toread ) > -p_sys->i_read_increment )
AVI_GetDPTS( tk, tk->demuxctx.i_toread ) > -p_sys->i_read_increment )
{
tk->i_idxposc = (unsigned int) i_indexid;
tk->i_idxposb = 0;
......@@ -1243,7 +1317,7 @@ static int Demux_Seekable( demux_t *p_demux )
}
/* Set the track to use */
tk = p_sys->track[i_track];
avi_track_t *tk = p_sys->track[i_track];
size_t i_size;
unsigned i_ck_remaining_bytes = tk->idx.p_entry[tk->i_idxposc].i_length -
......@@ -1255,7 +1329,7 @@ static int Demux_Seekable( demux_t *p_demux )
int64_t i_toread;
/* remaining bytes to read inside the current read increment */
if( ( i_toread = toread[i_track].i_toread ) <= 0 )
if( ( i_toread = tk->demuxctx.i_toread ) <= 0 )
{
if( tk->i_samplesize > 1 )
{
......@@ -1283,11 +1357,15 @@ static int Demux_Seekable( demux_t *p_demux )
{
msg_Warn( p_demux, "failed reading data" );
tk->b_eof = false;
toread[i_track].b_ok = false;
tk->demuxctx.b_ok = false;
continue;
}
p_frame->i_pts = VLC_TICK_0 + AVI_GetPTS( tk );
if( p_frame->i_pts == VLC_TICK_INVALID )
p_frame->i_pts = VLC_TICK_0 + AVI_GetPTS( tk );
else
tk->i_last_embedded_endtime = p_frame->i_pts + p_frame->i_length;
if( tk->idx.p_entry[tk->i_idxposc].i_flags&AVIIF_KEYFRAME )
{
p_frame->i_flags = BLOCK_FLAG_TYPE_I;
......@@ -1300,7 +1378,7 @@ static int Demux_Seekable( demux_t *p_demux )
/* advance chunk/byte pointers */
if( tk->i_samplesize )
{
toread[i_track].i_toread -= i_size;
tk->demuxctx.i_toread -= i_size;
tk->i_idxposb += i_size;
if( tk->i_idxposb >=
tk->idx.p_entry[tk->i_idxposc].i_length )
......@@ -1317,23 +1395,27 @@ static int Demux_Seekable( demux_t *p_demux )
{
tk->i_blockno += tk->i_blocksize > 0 ? ( i_size + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
}
toread[i_track].i_toread--;
else if( tk->fmt.i_cat == SPU_ES )
{
tk->i_next_embedded_time = VLC_TICK_INVALID;
}
tk->demuxctx.i_toread--;
}
/* check new chunk and set new read pos */
if( tk->i_idxposc < tk->idx.i_size)
{
toread[i_track].i_posf =
tk->demuxctx.i_posf =
tk->idx.p_entry[tk->i_idxposc].i_pos;
if( tk->i_idxposb > 0 )
{
toread[i_track].i_posf += 8 + tk->i_idxposb;
tk->demuxctx.i_posf += 8 + tk->i_idxposb;
}
}
else /* all chunks read for this track */
{
toread[i_track].i_posf = -1;
tk->demuxctx.i_posf = -1;
}
AVI_SendFrame( p_demux, tk, p_frame );
......@@ -1452,7 +1534,11 @@ static int Demux_UnSeekable( demux_t *p_demux )
{
return VLC_DEMUXER_EGENERIC;
}
p_frame->i_pts = VLC_TICK_0 + AVI_GetPTS( p_stream );
if( p_frame->i_pts == VLC_TICK_INVALID )
p_frame->i_pts = VLC_TICK_0 + AVI_GetPTS( p_stream );
else
p_stream->i_last_embedded_endtime = p_frame->i_pts + p_frame->i_length;
AVI_SendFrame( p_demux, p_stream, p_frame );
}
......@@ -1476,6 +1562,7 @@ static int Demux_UnSeekable( demux_t *p_demux )
p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1;
}
p_stream->i_idxposc++;
p_stream->i_next_embedded_time = VLC_TICK_INVALID;
}
}
......@@ -1547,7 +1634,7 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_date, double f_ratio, bool b_acc
for( unsigned i = 0; i < p_sys->i_track; i++ )
{
avi_track_t *p_track = p_sys->track[i];
if( !p_track->b_activated )
if( !p_track->b_activated || p_stream->fmt.i_cat == SPU_ES )
continue;
p_stream = p_track;
......@@ -1905,7 +1992,6 @@ static int AVI_StreamChunkFind( demux_t *p_demux, avi_track_t *tk )
/* add this chunk to the index */
avi_entry_t index;
index.i_id = avi_pk.i_fourcc;
index.i_flags = AVI_GetKeyFlag(tk_pk, avi_pk.i_peek);
index.i_pos = avi_pk.i_pos;
index.i_length = avi_pk.i_size;
......@@ -2018,6 +2104,9 @@ static int AVI_TrackSeek( demux_t *p_demux,
avi_track_t *tk = p_sys->track[i_stream];
vlc_tick_t i_oldpts;
if( tk->fmt.i_cat == SPU_ES )
return AVI_SeekSubtitleTrack( p_sys, tk );
i_oldpts = AVI_GetPTS( tk );
if( !tk->i_samplesize )
......@@ -2469,7 +2558,6 @@ static int AVI_IndexLoad_idx1( demux_t *p_demux,
(i_cat == p_sys->track[i_stream]->fmt.i_cat || i_cat == UNKNOWN_ES ) )
{
avi_entry_t index;
index.i_id = p_idx1->entry[i_index].i_fourcc;
index.i_flags = p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
index.i_pos = p_idx1->entry[i_index].i_pos + i_offset;
index.i_length = p_idx1->entry[i_index].i_length;
......@@ -2515,7 +2603,6 @@ static void __Parse_indx( demux_t *p_demux, avi_index_t *p_index, uint64_t *pi_m
{
for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
{
index.i_id = p_indx->i_id;
index.i_flags = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
index.i_pos = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
index.i_length = p_indx->idx.std[i].i_size&0x7fffffff;
......@@ -2528,7 +2615,6 @@ static void __Parse_indx( demux_t *p_demux, avi_index_t *p_index, uint64_t *pi_m
{
for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
{
index.i_id = p_indx->i_id;
index.i_flags = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
index.i_pos = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
index.i_length = p_indx->idx.field[i].i_size;
......@@ -2730,7 +2816,6 @@ static void AVI_IndexCreate( demux_t *p_demux )
avi_track_t *tk = p_sys->track[pk.i_stream];
avi_entry_t index;
index.i_id = pk.i_fourcc;
index.i_flags = AVI_GetKeyFlag(tk, pk.i_peek);
index.i_pos = pk.i_pos;
index.i_length = pk.i_size;
......@@ -2909,6 +2994,22 @@ static void AVI_DvHandleAudio( demux_t *p_demux, avi_track_t *tk, block_t *p_fra
/*****************************************************************************
* Subtitles
*****************************************************************************/
/*
Subtitles only exists in a hackish way as AVI is samples rate based and
does not provide any way for variable rate or variable duration content.
Only 2 subtitles formats:
- Xsub from DivX
Samples are prefixed with a text formatted timestamp containing
start and stop times.
Track index provides sample location.
Chunk position is meaningless. All timings are within sample.
* - Txt
Samples are stored in a similar format as Xsub, but regrouped in a
single sample with metadata header. Location found using track index.
Those are extracted and exposed as attachment.
This track has to be ignored for playback.
*/
static void AVI_ExtractSubtitle( demux_t *p_demux,
unsigned int i_stream,
avi_chunk_list_t *p_strl,
......@@ -3041,6 +3142,56 @@ exit:
if( p_indx == &ck.indx )
AVI_ChunkClean( p_demux->s, &ck );
}
static avi_track_t * AVI_GetVideoTrackForXsub( demux_sys_t *p_sys )
{
for( unsigned i = 0; i < p_sys->i_track; i++ )
{
avi_track_t *p_stream = p_sys->track[i];
if( p_stream->b_activated &&
p_stream->fmt.i_cat == VIDEO_ES &&
p_stream->idx.i_size )
return p_stream;
}
return NULL;
}
static int AVI_SeekSubtitleTrack( demux_sys_t *p_sys, avi_track_t *tk )
{
if( tk->fmt.i_codec != FOURCC_DXSB )
return VLC_EGENERIC;
const avi_track_t *p_videotk = AVI_GetVideoTrackForXsub( p_sys );
if( !p_videotk )
return VLC_EGENERIC;
/* Seek into SPU index using video track */
unsigned idx = p_videotk->i_idxposc < p_videotk->idx.i_size
? p_videotk->i_idxposc : p_videotk->idx.i_size - 1;
uint64_t i_pos = p_videotk->idx.p_entry[idx].i_pos;
/* invalidate sample timestamp */
tk->i_next_embedded_time = VLC_TICK_INVALID;
tk->i_last_embedded_endtime = VLC_TICK_INVALID;
for( tk->i_idxposc = 0; tk->i_idxposc<tk->idx.i_size; tk->i_idxposc++ )
{
/* match next pos, or closest -256KB sample */
if( tk->idx.p_entry[tk->i_idxposc].i_pos > i_pos )
{
tk->b_eof = false;
break;
}
else if( tk->idx.p_entry[tk->i_idxposc].i_pos + (1 << 28) <= i_pos )
{
tk->b_eof = false;
}
}
tk->b_eof = tk->i_idxposc == tk->idx.i_size;
if(!tk->b_eof)
tk->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
return VLC_SUCCESS;
}
/*****************************************************************************
* Stream management
*****************************************************************************/
......
......@@ -364,6 +364,10 @@ int AVI_ChunkFetchIndexes( stream_t *, avi_chunk_t *p_riff );
/* *** codex stuff *** */
/* DivX */
#define FOURCC_DXSB VLC_FOURCC('D','X','S','B') /* xsub */
#define FOURCC_XVID VLC_FOURCC('X','V','I','D')
/* DV */
#define FOURCC_dvsd VLC_FOURCC('d','v','s','d')
#define FOURCC_dvhd VLC_FOURCC('d','v','h','d')
......