Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
cdf8646f
Commit
cdf8646f
authored
Oct 27, 2002
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* all : rewrite demux part (simpler and cleaner). Please, tell me if you see
some regression.
parent
4a0ddd5b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
612 additions
and
922 deletions
+612
-922
modules/demux/avi/Modules.am
modules/demux/avi/Modules.am
+0
-2
modules/demux/avi/avi.c
modules/demux/avi/avi.c
+563
-887
modules/demux/avi/avi.h
modules/demux/avi/avi.h
+25
-29
modules/demux/avi/libavi.c
modules/demux/avi/libavi.c
+24
-4
No files found.
modules/demux/avi/Modules.am
View file @
cdf8646f
SOURCES_avi = \
SOURCES_avi = \
modules/demux/avi/avi.c \
modules/demux/avi/avi.c \
modules/demux/avi/libioRIFF.c \
modules/demux/avi/libavi.c
modules/demux/avi/libavi.c
noinst_HEADERS += \
noinst_HEADERS += \
modules/demux/avi/avi.h \
modules/demux/avi/avi.h \
modules/demux/avi/libioRIFF.h \
modules/demux/avi/libavi.h
modules/demux/avi/libavi.h
modules/demux/avi/avi.c
View file @
cdf8646f
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* avi.c : AVI file Stream input module for vlc
* avi.c : AVI file Stream input module for vlc
*****************************************************************************
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* Copyright (C) 2001 VideoLAN
* $Id: avi.c,v 1.
6 2002/10/15 00:55:07
fenrir Exp $
* $Id: avi.c,v 1.
7 2002/10/27 15:37:16
fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
...
@@ -33,7 +33,6 @@
...
@@ -33,7 +33,6 @@
#include "video.h"
#include "video.h"
#include "libioRIFF.h"
#include "libavi.h"
#include "libavi.h"
#include "avi.h"
#include "avi.h"
...
@@ -61,14 +60,13 @@ vlc_module_begin();
...
@@ -61,14 +60,13 @@ vlc_module_begin();
"force index creation"
);
"force index creation"
);
set_description
(
"avi demuxer"
);
set_description
(
"avi demuxer"
);
set_capability
(
"demux"
,
160
);
set_capability
(
"demux"
,
212
);
set_callbacks
(
AVIInit
,
__AVIEnd
);
set_callbacks
(
AVIInit
,
__AVIEnd
);
vlc_module_end
();
vlc_module_end
();
/*****************************************************************************
/*****************************************************************************
* Some usefull functions to manipulate memory
* Some usefull functions to manipulate memory
*****************************************************************************/
*****************************************************************************/
static
int
__AVI_GetDataInPES
(
input_thread_t
*
,
pes_packet_t
**
,
int
,
int
);
static
u16
GetWLE
(
byte_t
*
p_buff
)
static
u16
GetWLE
(
byte_t
*
p_buff
)
{
{
...
@@ -96,6 +94,66 @@ static inline off_t __EVEN( off_t i )
...
@@ -96,6 +94,66 @@ static inline off_t __EVEN( off_t i )
#define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
#define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
/* read data in a pes */
static
int
input_ReadInPES
(
input_thread_t
*
p_input
,
pes_packet_t
**
pp_pes
,
int
i_size
)
{
pes_packet_t
*
p_pes
;
data_packet_t
*
p_data
;
if
(
!
(
p_pes
=
input_NewPES
(
p_input
->
p_method_data
)
)
)
{
pp_pes
=
NULL
;
return
(
-
1
);
}
*
pp_pes
=
p_pes
;
if
(
!
i_size
)
{
p_pes
->
p_first
=
p_pes
->
p_last
=
input_NewPacket
(
p_input
->
p_method_data
,
0
);
p_pes
->
i_nb_data
=
1
;
p_pes
->
i_pes_size
=
0
;
return
(
0
);
}
p_pes
->
i_nb_data
=
0
;
p_pes
->
i_pes_size
=
0
;
while
(
p_pes
->
i_pes_size
<
i_size
)
{
int
i_read
;
i_read
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
i_size
-
p_pes
->
i_pes_size
,
1024
)
);
if
(
i_read
<=
0
)
{
return
(
p_pes
->
i_pes_size
);
}
if
(
!
p_pes
->
p_first
)
{
p_pes
->
p_first
=
p_data
;
}
else
{
p_pes
->
p_last
->
p_next
=
p_data
;
}
p_pes
->
p_last
=
p_data
;
p_pes
->
i_nb_data
++
;
p_pes
->
i_pes_size
+=
i_read
;
}
return
(
p_pes
->
i_pes_size
);
}
/* Test if it seems that it's a key frame */
/* Test if it seems that it's a key frame */
static
int
AVI_GetKeyFlag
(
vlc_fourcc_t
i_fourcc
,
u8
*
p_byte
)
static
int
AVI_GetKeyFlag
(
vlc_fourcc_t
i_fourcc
,
u8
*
p_byte
)
{
{
...
@@ -212,97 +270,6 @@ vlc_fourcc_t AVI_FourccGetCodec( int i_cat, vlc_fourcc_t i_codec )
...
@@ -212,97 +270,6 @@ vlc_fourcc_t AVI_FourccGetCodec( int i_cat, vlc_fourcc_t i_codec )
return
(
VLC_FOURCC
(
'u'
,
'n'
,
'd'
,
'f'
)
);
return
(
VLC_FOURCC
(
'u'
,
'n'
,
'd'
,
'f'
)
);
}
}
}
}
/*****************************************************************************
* Data and functions to manipulate pes buffer
*****************************************************************************/
#define BUFFER_MAXTOTALSIZE 500*1024
/* 1/2 Mo */
#define BUFFER_MAXSPESSIZE 200*1024
static
int
AVI_PESBuffer_IsFull
(
AVIStreamInfo_t
*
p_info
)
{
return
(
p_info
->
i_pes_totalsize
>
BUFFER_MAXTOTALSIZE
?
1
:
0
);
}
static
void
AVI_PESBuffer_Add
(
input_buffers_t
*
p_method_data
,
AVIStreamInfo_t
*
p_info
,
pes_packet_t
*
p_pes
,
int
i_posc
,
int
i_posb
)
{
AVIESBuffer_t
*
p_buffer_pes
;
if
(
p_info
->
i_pes_totalsize
>
BUFFER_MAXTOTALSIZE
)
{
input_DeletePES
(
p_method_data
,
p_pes
);
return
;
}
if
(
!
(
p_buffer_pes
=
malloc
(
sizeof
(
AVIESBuffer_t
)
)
)
)
{
input_DeletePES
(
p_method_data
,
p_pes
);
return
;
}
p_buffer_pes
->
p_next
=
NULL
;
p_buffer_pes
->
p_pes
=
p_pes
;
p_buffer_pes
->
i_posc
=
i_posc
;
p_buffer_pes
->
i_posb
=
i_posb
;
if
(
p_info
->
p_pes_last
)
{
p_info
->
p_pes_last
->
p_next
=
p_buffer_pes
;
}
p_info
->
p_pes_last
=
p_buffer_pes
;
if
(
!
p_info
->
p_pes_first
)
{
p_info
->
p_pes_first
=
p_buffer_pes
;
}
p_info
->
i_pes_count
++
;
p_info
->
i_pes_totalsize
+=
p_pes
->
i_pes_size
;
}
static
pes_packet_t
*
AVI_PESBuffer_Get
(
AVIStreamInfo_t
*
p_info
)
{
AVIESBuffer_t
*
p_buffer_pes
;
pes_packet_t
*
p_pes
;
if
(
p_info
->
p_pes_first
)
{
p_buffer_pes
=
p_info
->
p_pes_first
;
p_info
->
p_pes_first
=
p_buffer_pes
->
p_next
;
if
(
!
p_info
->
p_pes_first
)
{
p_info
->
p_pes_last
=
NULL
;
}
p_pes
=
p_buffer_pes
->
p_pes
;
free
(
p_buffer_pes
);
p_info
->
i_pes_count
--
;
p_info
->
i_pes_totalsize
-=
p_pes
->
i_pes_size
;
return
(
p_pes
);
}
else
{
return
(
NULL
);
}
}
static
int
AVI_PESBuffer_Drop
(
input_buffers_t
*
p_method_data
,
AVIStreamInfo_t
*
p_info
)
{
pes_packet_t
*
p_pes
=
AVI_PESBuffer_Get
(
p_info
);
if
(
p_pes
)
{
input_DeletePES
(
p_method_data
,
p_pes
);
return
(
1
);
}
else
{
return
(
0
);
}
}
static
void
AVI_PESBuffer_Flush
(
input_buffers_t
*
p_method_data
,
AVIStreamInfo_t
*
p_info
)
{
while
(
p_info
->
p_pes_first
)
{
AVI_PESBuffer_Drop
(
p_method_data
,
p_info
);
}
}
static
void
AVI_ParseStreamHeader
(
u32
i_id
,
int
*
pi_number
,
int
*
pi_type
)
static
void
AVI_ParseStreamHeader
(
u32
i_id
,
int
*
pi_number
,
int
*
pi_type
)
{
{
...
@@ -337,18 +304,6 @@ static void AVI_ParseStreamHeader( u32 i_id, int *pi_number, int *pi_type )
...
@@ -337,18 +304,6 @@ static void AVI_ParseStreamHeader( u32 i_id, int *pi_number, int *pi_type )
#undef SET_PTR
#undef SET_PTR
}
}
typedef
struct
avi_packet_s
{
u32
i_fourcc
;
off_t
i_pos
;
u32
i_size
;
u32
i_type
;
// only for AVIFOURCC_LIST
u8
i_peek
[
8
];
//first 8 bytes
int
i_stream
;
int
i_cat
;
}
avi_packet_t
;
static
int
AVI_PacketGetHeader
(
input_thread_t
*
p_input
,
avi_packet_t
*
p_pk
)
static
int
AVI_PacketGetHeader
(
input_thread_t
*
p_input
,
avi_packet_t
*
p_pk
)
{
{
u8
*
p_peek
;
u8
*
p_peek
;
...
@@ -396,14 +351,25 @@ static int AVI_PacketRead( input_thread_t *p_input,
...
@@ -396,14 +351,25 @@ static int AVI_PacketRead( input_thread_t *p_input,
avi_packet_t
*
p_pk
,
avi_packet_t
*
p_pk
,
pes_packet_t
**
pp_pes
)
pes_packet_t
**
pp_pes
)
{
{
int
i_size
;
int
b_pad
;
if
(
__AVI_GetDataInPES
(
p_input
,
pp_pes
,
p_pk
->
i_size
+
8
,
1
)
i_size
=
__EVEN
(
p_pk
->
i_size
+
8
);
!=
p_pk
->
i_size
+
8
)
b_pad
=
(
i_size
!=
p_pk
->
i_size
+
8
);
if
(
input_ReadInPES
(
p_input
,
pp_pes
,
i_size
)
!=
i_size
)
{
{
return
(
0
);
return
(
0
);
}
}
(
*
pp_pes
)
->
p_first
->
p_payload_start
+=
8
;
(
*
pp_pes
)
->
p_first
->
p_payload_start
+=
8
;
(
*
pp_pes
)
->
i_pes_size
-=
8
;
(
*
pp_pes
)
->
i_pes_size
-=
8
;
if
(
b_pad
)
{
(
*
pp_pes
)
->
p_last
->
p_payload_end
--
;
(
*
pp_pes
)
->
i_pes_size
--
;
}
return
(
1
);
return
(
1
);
}
}
...
@@ -435,7 +401,7 @@ static int AVI_PacketSearch( input_thread_t *p_input )
...
@@ -435,7 +401,7 @@ static int AVI_PacketSearch( input_thread_t *p_input )
}
}
static
void
__AVI_AddEntryIndex
(
AVIStreamInfo
_t
*
p_info
,
static
void
__AVI_AddEntryIndex
(
avi_stream
_t
*
p_info
,
AVIIndexEntry_t
*
p_index
)
AVIIndexEntry_t
*
p_index
)
{
{
if
(
p_info
->
p_index
==
NULL
)
if
(
p_info
->
p_index
==
NULL
)
...
@@ -472,6 +438,19 @@ static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
...
@@ -472,6 +438,19 @@ static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
p_info
->
p_index
[
p_info
->
i_idxnb
]
=
*
p_index
;
p_info
->
p_index
[
p_info
->
i_idxnb
]
=
*
p_index
;
p_info
->
i_idxnb
++
;
p_info
->
i_idxnb
++
;
}
static
void
AVI_IndexAddEntry
(
demux_sys_t
*
p_avi
,
int
i_stream
,
AVIIndexEntry_t
*
p_index
)
{
__AVI_AddEntryIndex
(
p_avi
->
pp_info
[
i_stream
],
p_index
);
if
(
p_avi
->
i_movi_lastchunk_pos
<
p_index
->
i_pos
)
{
p_avi
->
i_movi_lastchunk_pos
=
p_index
->
i_pos
;
}
}
}
static
void
AVI_IndexLoad
(
input_thread_t
*
p_input
)
static
void
AVI_IndexLoad
(
input_thread_t
*
p_input
)
...
@@ -526,11 +505,11 @@ static void AVI_IndexLoad( input_thread_t *p_input )
...
@@ -526,11 +505,11 @@ static void AVI_IndexLoad( input_thread_t *p_input )
{
{
AVIIndexEntry_t
index
;
AVIIndexEntry_t
index
;
index
.
i_id
=
p_idx1
->
entry
[
i_index
].
i_fourcc
;
index
.
i_id
=
p_idx1
->
entry
[
i_index
].
i_fourcc
;
index
.
i_flags
=
p_idx1
->
entry
[
i_index
].
i_flags
&
(
~
AVIIF_FIXKEYFRAME
);
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_pos
=
p_idx1
->
entry
[
i_index
].
i_pos
+
i_offset
;
index
.
i_length
=
p_idx1
->
entry
[
i_index
].
i_length
;
index
.
i_length
=
p_idx1
->
entry
[
i_index
].
i_length
;
__AVI_AddEntryIndex
(
p_avi
->
pp_info
[
i_stream
],
AVI_IndexAddEntry
(
p_avi
,
i_stream
,
&
index
);
&
index
);
}
}
}
}
for
(
i_stream
=
0
;
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
for
(
i_stream
=
0
;
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
...
@@ -591,8 +570,7 @@ static void AVI_IndexCreate( input_thread_t *p_input )
...
@@ -591,8 +570,7 @@ static void AVI_IndexCreate( input_thread_t *p_input )
AVI_GetKeyFlag
(
p_avi
->
pp_info
[
pk
.
i_stream
]
->
i_codec
,
pk
.
i_peek
);
AVI_GetKeyFlag
(
p_avi
->
pp_info
[
pk
.
i_stream
]
->
i_codec
,
pk
.
i_peek
);
index
.
i_pos
=
pk
.
i_pos
;
index
.
i_pos
=
pk
.
i_pos
;
index
.
i_length
=
pk
.
i_size
;
index
.
i_length
=
pk
.
i_size
;
__AVI_AddEntryIndex
(
p_avi
->
pp_info
[
pk
.
i_stream
],
AVI_IndexAddEntry
(
p_avi
,
pk
.
i_stream
,
&
index
);
&
index
);
}
}
else
else
{
{
...
@@ -659,8 +637,10 @@ static int AVI_StreamStart( input_thread_t *p_input,
...
@@ -659,8 +637,10 @@ static int AVI_StreamStart( input_thread_t *p_input,
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
}
}
p_stream
->
i_activated
=
p_stream
->
p_es
->
p_decoder_fifo
?
1
:
0
;
p_stream
->
i_activated
=
p_stream
->
p_es
->
p_decoder_fifo
?
1
:
0
;
if
(
p_stream
->
i_activated
)
AVI_StreamSeek
(
p_input
,
p_avi
,
i_stream
,
p_avi
->
i_time
);
{
AVI_StreamSeek
(
p_input
,
p_avi
,
i_stream
,
p_avi
->
i_time
);
}
return
(
p_stream
->
i_activated
);
return
(
p_stream
->
i_activated
);
#undef p_stream
#undef p_stream
...
@@ -677,8 +657,6 @@ static void AVI_StreamStop( input_thread_t *p_input,
...
@@ -677,8 +657,6 @@ static void AVI_StreamStop( input_thread_t *p_input,
return
;
return
;
}
}
// AVI_PESBuffer_Flush( p_input->p_method_data, p_stream );
if
(
p_stream
->
p_es
->
p_decoder_fifo
)
if
(
p_stream
->
p_es
->
p_decoder_fifo
)
{
{
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
...
@@ -747,8 +725,6 @@ static void __AVIEnd ( vlc_object_t * p_this )
...
@@ -747,8 +725,6 @@ static void __AVIEnd ( vlc_object_t * p_this )
int
i
;
int
i
;
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
if
(
p_avi
->
p_movi
)
RIFF_DeleteChunk
(
p_input
,
p_avi
->
p_movi
);
if
(
p_avi
->
pp_info
)
if
(
p_avi
->
pp_info
)
{
{
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
...
@@ -758,8 +734,6 @@ static void __AVIEnd ( vlc_object_t * p_this )
...
@@ -758,8 +734,6 @@ static void __AVIEnd ( vlc_object_t * p_this )
if
(
p_avi
->
pp_info
[
i
]
->
p_index
)
if
(
p_avi
->
pp_info
[
i
]
->
p_index
)
{
{
free
(
p_avi
->
pp_info
[
i
]
->
p_index
);
free
(
p_avi
->
pp_info
[
i
]
->
p_index
);
AVI_PESBuffer_Flush
(
p_input
->
p_method_data
,
p_avi
->
pp_info
[
i
]
);
}
}
free
(
p_avi
->
pp_info
[
i
]
);
free
(
p_avi
->
pp_info
[
i
]
);
}
}
...
@@ -787,6 +761,8 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -787,6 +761,8 @@ static int AVIInit( vlc_object_t * p_this )
es_descriptor_t
*
p_es
=
NULL
;
/* avoid warning */
es_descriptor_t
*
p_es
=
NULL
;
/* avoid warning */
int
i
;
int
i
;
int
b_stream_audio
,
b_stream_video
;
p_input
->
pf_demux
=
AVIDemux_Seekable
;
p_input
->
pf_demux
=
AVIDemux_Seekable
;
if
(
!
AVI_TestFile
(
p_input
)
)
if
(
!
AVI_TestFile
(
p_input
)
)
{
{
...
@@ -810,7 +786,6 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -810,7 +786,6 @@ static int AVIInit( vlc_object_t * p_this )
memset
(
p_avi
,
0
,
sizeof
(
demux_sys_t
)
);
memset
(
p_avi
,
0
,
sizeof
(
demux_sys_t
)
);
p_avi
->
i_time
=
0
;
p_avi
->
i_time
=
0
;
p_avi
->
i_pcr
=
0
;
p_avi
->
i_pcr
=
0
;
p_avi
->
i_rate
=
DEFAULT_RATE
;
p_avi
->
b_seekable
=
(
(
p_input
->
stream
.
b_seekable
)
p_avi
->
b_seekable
=
(
(
p_input
->
stream
.
b_seekable
)
&&
(
p_input
->
stream
.
i_method
==
INPUT_METHOD_FILE
)
);
&&
(
p_input
->
stream
.
i_method
==
INPUT_METHOD_FILE
)
);
/* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
/* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
...
@@ -900,10 +875,10 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -900,10 +875,10 @@ static int AVIInit( vlc_object_t * p_this )
/* now read info on each stream and create ES */
/* now read info on each stream and create ES */
p_avi
->
pp_info
=
calloc
(
p_avi
->
i_streams
,
p_avi
->
pp_info
=
calloc
(
p_avi
->
i_streams
,
sizeof
(
AVIStreamInfo
_t
*
)
);
sizeof
(
avi_stream
_t
*
)
);
memset
(
p_avi
->
pp_info
,
memset
(
p_avi
->
pp_info
,
0
,
0
,
sizeof
(
AVIStreamInfo
_t
*
)
*
p_avi
->
i_streams
);
sizeof
(
avi_stream
_t
*
)
*
p_avi
->
i_streams
);
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
{
{
...
@@ -914,15 +889,16 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -914,15 +889,16 @@ static int AVIInit( vlc_object_t * p_this )
int
i_init_size
;
int
i_init_size
;
void
*
p_init_data
;
void
*
p_init_data
;
#define p_info p_avi->pp_info[i]
#define p_info p_avi->pp_info[i]
p_info
=
malloc
(
sizeof
(
AVIStreamInfo
_t
)
);
p_info
=
malloc
(
sizeof
(
avi_stream
_t
)
);
memset
(
p_info
,
0
,
sizeof
(
AVIStreamInfo
_t
)
);
memset
(
p_info
,
0
,
sizeof
(
avi_stream
_t
)
);
p_avi_strl
=
(
avi_chunk_list_t
*
)
AVI_ChunkFind
(
p_hdrl
,
p_avi_strl
=
(
avi_chunk_list_t
*
)
AVI_ChunkFind
(
p_hdrl
,
AVIFOURCC_strl
,
i
);
AVIFOURCC_strl
,
i
);
p_avi_strh
=
(
avi_chunk_strh_t
*
)
AVI_ChunkFind
(
p_avi_strl
,
p_avi_strh
=
(
avi_chunk_strh_t
*
)
AVI_ChunkFind
(
p_avi_strl
,
AVIFOURCC_strh
,
0
);
AVIFOURCC_strh
,
0
);
p_avi_strf_auds
=
p_avi_strf_auds
=
(
avi_chunk_strf_auds_t
*
)
p_avi_strf_vids
=
AVI_ChunkFind
(
p_avi_strl
,
AVIFOURCC_strf
,
0
);
p_avi_strf_vids
=
(
avi_chunk_strf_vids_t
*
)
AVI_ChunkFind
(
p_avi_strl
,
AVIFOURCC_strf
,
0
);
if
(
!
p_avi_strl
||
!
p_avi_strh
||
if
(
!
p_avi_strl
||
!
p_avi_strh
||
(
!
p_avi_strf_auds
&&
!
p_avi_strf_vids
)
)
(
!
p_avi_strf_auds
&&
!
p_avi_strf_vids
)
)
...
@@ -1045,15 +1021,9 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -1045,15 +1021,9 @@ static int AVIInit( vlc_object_t * p_this )
}
}
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
/* create a pseudo p_movi */
b_stream_audio
=
0
;
p_avi
->
p_movi
=
malloc
(
sizeof
(
riffchunk_t
)
);
b_stream_video
=
0
;
p_avi
->
p_movi
->
i_id
=
AVIFOURCC_LIST
;
p_avi
->
p_movi
->
i_type
=
AVIFOURCC_movi
;
p_avi
->
p_movi
->
i_size
=
p_movi
->
i_chunk_size
;
p_avi
->
p_movi
->
i_pos
=
p_movi
->
i_chunk_pos
;
p_avi
->
p_movi
->
p_data
=
NULL
;
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
{
{
#define p_info p_avi->pp_info[i]
#define p_info p_avi->pp_info[i]
...
@@ -1061,19 +1031,16 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -1061,19 +1031,16 @@ static int AVIInit( vlc_object_t * p_this )
{
{
case
(
VIDEO_ES
):
case
(
VIDEO_ES
):
if
(
(
p_avi
->
p_info_video
==
NULL
)
)
if
(
!
b_stream_video
)
{
{
p_avi
->
p_info_video
=
p_info
;
b_stream_video
=
AVI_StreamStart
(
p_input
,
p_avi
,
i
);
/* TODO add test to see if a decoder has been found */
AVI_StreamStart
(
p_input
,
p_avi
,
i
);
}
}
break
;
break
;
case
(
AUDIO_ES
):
case
(
AUDIO_ES
):
if
(
(
p_avi
->
p_info_audio
==
NULL
)
)
if
(
!
b_stream_audio
)
{
{
p_avi
->
p_info_audio
=
p_info
;
b_stream_audio
=
AVI_StreamStart
(
p_input
,
p_avi
,
i
);
AVI_StreamStart
(
p_input
,
p_avi
,
i
);
}
}
break
;
break
;
default:
default:
...
@@ -1082,16 +1049,16 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -1082,16 +1049,16 @@ static int AVIInit( vlc_object_t * p_this )
#undef p_info
#undef p_info
}
}
/* we select the first audio and video ES */
if
(
!
b_stream_video
)
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
if
(
!
p_avi
->
p_info_video
)
{
{
msg_Warn
(
p_input
,
"no video stream found"
);
msg_Warn
(
p_input
,
"no video stream found"
);
}
}
if
(
!
p_avi
->
p_info
_audio
)
if
(
!
b_stream
_audio
)
{
{
msg_Warn
(
p_input
,
"no audio stream found!"
);
msg_Warn
(
p_input
,
"no audio stream found!"
);
}
}
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
p_input
->
stream
.
p_selected_program
->
b_is_ok
=
1
;
p_input
->
stream
.
p_selected_program
->
b_is_ok
=
1
;
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
...
@@ -1104,6 +1071,9 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -1104,6 +1071,9 @@ static int AVIInit( vlc_object_t * p_this )
// already at begining of p_movi
// already at begining of p_movi
}
}
AVI_SkipBytes
(
p_input
,
12
);
// enter in p_movi
AVI_SkipBytes
(
p_input
,
12
);
// enter in p_movi
p_avi
->
i_movi_begin
=
p_movi
->
i_chunk_pos
;
p_avi
->
i_movi_lastchunk_pos
=
0
;
return
(
0
);
return
(
0
);
}
}
...
@@ -1114,7 +1084,7 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -1114,7 +1084,7 @@ static int AVIInit( vlc_object_t * p_this )
* Function to convert pts to chunk or byte
* Function to convert pts to chunk or byte
*****************************************************************************/
*****************************************************************************/
static
inline
mtime_t
AVI_PTSToChunk
(
AVIStreamInfo
_t
*
p_info
,
static
inline
mtime_t
AVI_PTSToChunk
(
avi_stream
_t
*
p_info
,
mtime_t
i_pts
)
mtime_t
i_pts
)
{
{
return
(
(
mtime_t
)((
s64
)
i_pts
*
return
(
(
mtime_t
)((
s64
)
i_pts
*
...
@@ -1122,7 +1092,7 @@ static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
...
@@ -1122,7 +1092,7 @@ static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
(
s64
)
p_info
->
i_scale
/
(
s64
)
p_info
->
i_scale
/
(
s64
)
1000000
)
);
(
s64
)
1000000
)
);
}
}
static
inline
mtime_t
AVI_PTSToByte
(
AVIStreamInfo
_t
*
p_info
,
static
inline
mtime_t
AVI_PTSToByte
(
avi_stream
_t
*
p_info
,
mtime_t
i_pts
)
mtime_t
i_pts
)
{
{
return
(
(
mtime_t
)((
s64
)
i_pts
*
return
(
(
mtime_t
)((
s64
)
i_pts
*
...
@@ -1132,7 +1102,28 @@ static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
...
@@ -1132,7 +1102,28 @@ static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
(
s64
)
1000000
)
);
(
s64
)
1000000
)
);
}
}
static
mtime_t
AVI_GetPTS
(
AVIStreamInfo_t
*
p_info
)
static
mtime_t
AVI_GetDPTS
(
avi_stream_t
*
p_stream
,
int
i_count
)
{
if
(
p_stream
->
i_samplesize
)
{
return
(
(
mtime_t
)(
(
s64
)
1000000
*
(
s64
)
i_count
*
(
s64
)
p_stream
->
i_scale
/
(
s64
)
p_stream
->
i_rate
/
(
s64
)
p_stream
->
i_samplesize
)
);
}
else
{
return
(
(
mtime_t
)(
(
s64
)
1000000
*
(
s64
)
i_count
*
(
s64
)
p_stream
->
i_scale
/
(
s64
)
p_stream
->
i_rate
)
);
}
}
static
mtime_t
AVI_GetPTS
(
avi_stream_t
*
p_info
)
{
{
if
(
p_info
->
i_samplesize
)
if
(
p_info
->
i_samplesize
)
...
@@ -1175,712 +1166,175 @@ static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
...
@@ -1175,712 +1166,175 @@ static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
}
}
}
}
static
int
AVI_StreamChunkFind
(
input_thread_t
*
p_input
,
/*****************************************************************************
int
i_stream
)
* Functions to acces streams data
* Uses it, because i plane to read unseekable stream
* XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
*****************************************************************************/
/* FIXME FIXME change b_pad to number of bytes to skipp after reading */
static
int
__AVI_GetDataInPES
(
input_thread_t
*
p_input
,
pes_packet_t
**
pp_pes
,
int
i_size
,
int
b_pad
)
{
{
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
avi_packet_t
avi_pk
;
int
i_read
;
/* find first chunk of i_stream that isn't in index */
data_packet_t
*
p_data
;
if
(
!
(
*
pp_pes
=
input_NewPES
(
p_input
->
p_method_data
)
)
)
{
return
(
0
);
}
if
(
p_avi
->
i_movi_lastchunk_pos
>=
p_avi
->
i_movi_begin
)
if
(
!
i_size
)
{
p_data
=
input_NewPacket
(
p_input
->
p_method_data
,
0
);
(
*
pp_pes
)
->
p_first
=
(
*
pp_pes
)
->
p_last
=
p_data
;
(
*
pp_pes
)
->
i_nb_data
=
1
;
(
*
pp_pes
)
->
i_pes_size
=
0
;
return
(
0
);
}
if
(
(
i_size
&
1
)
&&
(
b_pad
)
)
{
{
b_pad
=
1
;
AVI_SeekAbsolute
(
p_input
,
p_avi
->
i_movi_lastchunk_pos
);
i_size
++
;
if
(
!
AVI_PacketNext
(
p_input
)
)
{
return
(
0
);
}
}
}
else
else
{
{
b_pad
=
0
;
AVI_SeekAbsolute
(
p_input
,
p_avi
->
i_movi_begin
)
;
}
}
do
for
(
;;
)
{
{
i_read
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
i_size
-
(
*
pp_pes
)
->
i_pes_size
,
1024
)
);
if
(
!
AVI_PacketGetHeader
(
p_input
,
&
avi_pk
)
)
if
(
i_read
<
0
)
{
{
return
(
(
*
pp_pes
)
->
i_pes_size
);
msg_Err
(
p_input
,
"cannot get packet header"
);
return
(
0
);
}
}
if
(
!
(
*
pp_pes
)
->
p_first
)
if
(
avi_pk
.
i_stream
>=
p_avi
->
i_streams
||
(
avi_pk
.
i_cat
!=
AUDIO_ES
&&
avi_pk
.
i_cat
!=
VIDEO_ES
)
)
{
{
(
*
pp_pes
)
->
p_first
=
switch
(
avi_pk
.
i_fourcc
)
(
*
pp_pes
)
->
p_last
=
p_data
;
{
(
*
pp_pes
)
->
i_nb_data
=
1
;
case
AVIFOURCC_LIST
:
(
*
pp_pes
)
->
i_pes_size
=
i_read
;
AVI_SkipBytes
(
p_input
,
12
);
break
;
default:
if
(
!
AVI_PacketNext
(
p_input
)
)
{
return
(
0
);
}
break
;
}
}
}
else
else
{
{
(
*
pp_pes
)
->
p_last
->
p_next
=
/* add this chunk to the index */
(
*
pp_pes
)
->
p_last
=
p_data
;
AVIIndexEntry_t
index
;
(
*
pp_pes
)
->
i_nb_data
++
;
(
*
pp_pes
)
->
i_pes_size
+=
i_read
;
index
.
i_id
=
avi_pk
.
i_fourcc
;
index
.
i_flags
=
AVI_GetKeyFlag
(
p_avi
->
pp_info
[
avi_pk
.
i_stream
]
->
i_codec
,
avi_pk
.
i_peek
);
index
.
i_pos
=
avi_pk
.
i_pos
;
index
.
i_length
=
avi_pk
.
i_size
;
AVI_IndexAddEntry
(
p_avi
,
avi_pk
.
i_stream
,
&
index
);
if
(
avi_pk
.
i_stream
==
i_stream
)
{
return
(
1
);
}
if
(
!
AVI_PacketNext
(
p_input
)
)
{
return
(
0
);
}
}
}
}
while
(
((
*
pp_pes
)
->
i_pes_size
<
i_size
)
&&
(
i_read
)
);
if
(
b_pad
)
{
(
*
pp_pes
)
->
i_pes_size
--
;
(
*
pp_pes
)
->
p_last
->
p_payload_end
--
;
i_size
--
;
}
}
return
(
i_size
);
}
}
static
int
__AVI_SeekAndGetChunk
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
)
{
pes_packet_t
*
p_pes
;
int
i_length
,
i_ret
;
i_length
=
__MIN
(
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_length
-
p_info
->
i_idxposb
,
BUFFER_MAXSPESSIZE
);
AVI_SeekAbsolute
(
p_input
,
(
off_t
)
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_pos
+
p_info
->
i_idxposb
+
8
);
i_ret
=
__AVI_GetDataInPES
(
p_input
,
&
p_pes
,
i_length
,
0
);
if
(
i_ret
!=
i_length
)
/* be sure that i_ck will be a valid index entry */
{
static
int
AVI_SetStreamChunk
(
input_thread_t
*
p_input
,
return
(
0
);
int
i_stream
,
}
int
i_ck
)
/* TODO test key frame if i_idxposb == 0*/
AVI_PESBuffer_Add
(
p_input
->
p_method_data
,
p_info
,
p_pes
,
p_info
->
i_idxposc
,
p_info
->
i_idxposb
);
return
(
1
);
}
/* TODO check if it's correct (humm...) and optimisation ... */
/* return 0 if we choose to get only the ck we want
* 1 if index is invalid
* 2 if there is a ck_other before ck_info and the last proced ck_info*/
/* XXX XXX XXX avi file is some BIG shit, and sometime index give
* a refenrence to the same chunk BUT with a different size ( usually 0 )
*/
static
inline
int
__AVI_GetChunkMethod
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
AVIStreamInfo_t
*
p_other
)
{
{
int
i_info_pos
;
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
int
i_other_pos
;
avi_stream_t
*
p_stream
=
p_avi
->
pp_info
[
i_stream
]
;
int
i_info_pos_last
;
p_stream
->
i_idxposc
=
i_ck
;
int
i_other_pos_last
;
p_stream
->
i_idxposb
=
0
;
/*If we don't have a valid entry we need to parse from last
if
(
i_ck
<
p_stream
->
i_idxnb
)
defined chunk and it's the only way that we return 1*/
if
(
p_info
->
i_idxposc
>=
p_info
->
i_idxnb
)
{
{
return
(
1
);
return
(
1
);
}
}
else
/* KNOW we have a valid entry for p_info */
/* we return 0 if we haven't an valid entry for p_other */
if
(
(
!
p_other
)
||
(
p_other
->
i_idxposc
>=
p_other
->
i_idxnb
)
)
{
return
(
0
);
}
/* KNOW there are 2 streams with valid entry */
/* we return 0 if for one of the two streams we will not read
chunk-aligned */
if
(
(
p_info
->
i_idxposb
)
||
(
p_other
->
i_idxposb
)
)
{
return
(
0
);
}
/* KNOW we have a valid entry for the 2 streams
and for the 2 we want an aligned chunk (given by i_idxposc )*/
/* if in stream, the next chunk is back than the one we
have just read, it's useless to parse */
i_info_pos
=
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_pos
;
i_other_pos
=
p_other
->
p_index
[
p_other
->
i_idxposc
].
i_pos
;
i_info_pos_last
=
p_info
->
i_idxposc
?
p_info
->
p_index
[
p_info
->
i_idxposc
-
1
].
i_pos
:
0
;
i_other_pos_last
=
p_other
->
i_idxposc
?
p_other
->
p_index
[
p_other
->
i_idxposc
-
1
].
i_pos
:
0
;
if
(
(
(
p_info
->
i_idxposc
)
&&
(
i_info_pos
<=
i_info_pos_last
)
)
||
(
(
p_other
->
i_idxposc
)
&&
(
i_other_pos
<=
i_other_pos_last
)
)
)
{
{
return
(
0
);
p_stream
->
i_idxposc
=
p_stream
->
i_idxnb
-
1
;
}
do
{
/* KNOW for the 2 streams, the ck we want are after the last read
p_stream
->
i_idxposc
++
;
or it's the first */
if
(
!
AVI_StreamChunkFind
(
p_input
,
i_stream
)
)
{
return
(
0
);
}
/* if the first ck_other we want isn't between ck_info_last
}
while
(
p_stream
->
i_idxposc
<
i_ck
);
and ck_info, don't parse */
/* TODO fix this, use also number in buffered PES */
if
(
(
i_other_pos
>
i_info_pos
)
/* ck_other too far */
||
(
i_other_pos
<
i_info_pos_last
)
)
/* it's too late for ck_other */
{
return
(
0
);
}
/* we Know we will find ck_other, and before ck_info
"if ck_info is too far" will be handle after */
return
(
2
);
}
return
(
1
);
static
inline
int
__AVI_ChooseSize
(
int
l1
,
int
l2
)
{
/* XXX l2 is prefered if 0 otherwise min not equal to 0 */
if
(
!
l2
)
{
return
(
0
);
}
}
return
(
!
l1
?
l2
:
__MIN
(
l1
,
l2
)
);
}
}
/* We know we will read chunk align */
static
int
__AVI_GetAndPutChunkInBuffer
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
int
i_size
,
int
i_ck
)
{
pes_packet_t
*
p_pes
;
int
i_length
;
i_length
=
__MIN
(
i_size
,
BUFFER_MAXSPESSIZE
);
/* Skip chunk header */
if
(
__AVI_GetDataInPES
(
p_input
,
&
p_pes
,
i_length
+
8
,
1
)
!=
i_length
+
8
)
{
return
(
0
);
}
p_pes
->
p_first
->
p_payload_start
+=
8
;
p_pes
->
i_pes_size
-=
8
;
i_size
=
GetDWLE
(
p_pes
->
p_first
->
p_demux_start
+
4
);
AVI_PESBuffer_Add
(
p_input
->
p_method_data
,
/* XXX FIXME up to now, we assume that all chunk are one after one */
p_info
,
static
int
AVI_SetStreamBytes
(
input_thread_t
*
p_input
,
p_pes
,
int
i_stream
,
i_ck
,
off_t
i_byte
)
0
);
/* skip unwanted bytes */
if
(
i_length
!=
i_size
)
{
msg_Err
(
p_input
,
"Chunk Size mismatch"
);
AVI_SeekAbsolute
(
p_input
,
__EVEN
(
AVI_TellAbsolute
(
p_input
)
+
i_size
-
i_length
)
);
}
return
(
1
);
}
/* XXX Don't use this function directly ! XXX */
static
int
__AVI_GetChunk
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
int
b_load
)
{
{
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
AVIStreamInfo_t
*
p_other
;
avi_stream_t
*
p_stream
=
p_avi
->
pp_info
[
i_stream
];
int
i_method
;
off_t
i_posmax
;
int
i
;
#define p_info_i p_avi->pp_info[i]
while
(
p_info
->
p_pes_first
)
{
if
(
(
p_info
->
p_pes_first
->
i_posc
==
p_info
->
i_idxposc
)
&&
(
p_info
->
i_idxposb
>=
p_info
->
p_pes_first
->
i_posb
)
&&
(
p_info
->
i_idxposb
<
p_info
->
p_pes_first
->
i_posb
+
p_info
->
p_pes_first
->
p_pes
->
i_pes_size
)
)
{
return
(
1
);
/* we have it in buffer */
}
else
{
AVI_PESBuffer_Drop
(
p_input
->
p_method_data
,
p_info
);
}
}
/* up to now we handle only one audio and video streams at the same time */
p_other
=
(
p_info
==
p_avi
->
p_info_video
)
?
p_avi
->
p_info_audio
:
p_avi
->
p_info_video
;
i_method
=
__AVI_GetChunkMethod
(
p_input
,
p_info
,
p_other
);
if
(
(
p_stream
->
i_idxnb
>
0
)
&&
(
i_byte
<
p_stream
->
p_index
[
p_stream
->
i_idxnb
-
1
].
i_lengthtotal
+
if
(
!
i_method
)
p_stream
->
p_index
[
p_stream
->
i_idxnb
-
1
].
i_length
)
)
{
/* get directly the good chunk */
return
(
b_load
?
__AVI_SeekAndGetChunk
(
p_input
,
p_info
)
:
1
);
}
/* We will parse
* because invalid index
* or will find ck_other before ck_info
*/
/* msg_Warn( p_input, "method %d", i_method ); */
/* we will calculate the better position we have to reach */
if
(
i_method
==
1
)
{
{
/* invalid index */
/* index is valid to find the ck */
/* the position max we have already reached */
/* uses dichototmie to be fast enougth */
/* FIXME this isn't the better because sometime will fail to
int
i_idxposc
=
__MIN
(
p_stream
->
i_idxposc
,
p_stream
->
i_idxnb
-
1
);
put in buffer p_other since it could be too far */
int
i_idxmax
=
p_stream
->
i_idxnb
;
AVIStreamInfo_t
*
p_info_max
=
p_info
;
int
i_idxmin
=
0
;
for
(
;;
)
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
{
{
if
(
p_info_i
->
i_idxnb
)
if
(
p_stream
->
p_index
[
i_idxposc
].
i_lengthtotal
>
i_byte
)
{
i_idxmax
=
i_idxposc
;
i_idxposc
=
(
i_idxmin
+
i_idxposc
)
/
2
;
}
else
{
{
if
(
p_info_max
->
i_idxnb
)
if
(
p_stream
->
p_index
[
i_idxposc
].
i_lengthtotal
+
p_stream
->
p_index
[
i_idxposc
].
i_length
<=
i_byte
)
{
{
if
(
p_info_i
->
p_index
[
p_info_i
->
i_idxnb
-
1
].
i_pos
>
i_idxmin
=
i_idxposc
;
p_info_max
->
p_index
[
p_info_max
->
i_idxnb
-
1
].
i_pos
)
i_idxposc
=
(
i_idxmax
+
i_idxposc
)
/
2
;
{
p_info_max
=
p_info_i
;
}
}
}
else
else
{
{
p_info_max
=
p_info_i
;
p_stream
->
i_idxposc
=
i_idxposc
;
p_stream
->
i_idxposb
=
i_byte
-
p_stream
->
p_index
[
i_idxposc
].
i_lengthtotal
;
return
(
1
);
}
}
}
}
}
}
if
(
p_info_max
->
i_idxnb
)
}
else
{
p_stream
->
i_idxposc
=
p_stream
->
i_idxnb
-
1
;
p_stream
->
i_idxposb
=
0
;
do
{
{
/* be carefull that size between index and ck can sometime be
p_stream
->
i_idxposc
++
;
different without any error (and other time it's an error) */
if
(
!
AVI_StreamChunkFind
(
p_input
,
i_stream
)
)
i_posmax
=
p_info_max
->
p_index
[
p_info_max
->
i_idxnb
-
1
].
i_pos
;
/* so choose this, and I know that we have already reach it */
}
else
{
i_posmax
=
p_avi
->
p_movi
->
i_pos
+
12
;
}
}
else
{
if
(
!
b_load
)
{
return
(
1
);
/* all is ok */
}
/* valid index */
/* we know that the entry and the last one are valid for the 2 stream */
/* and ck_other will come *before* index so go directly to it*/
i_posmax
=
p_other
->
p_index
[
p_other
->
i_idxposc
].
i_pos
;
}
AVI_SeekAbsolute
(
p_input
,
i_posmax
);
/* the first chunk we will see is :
* the last chunk that we have already seen for broken index
* the first ck for other with good index */
for
(
;
;
)
/* infinite parsing until the ck we want */
{
riffchunk_t
*
p_ck
;
int
i_type
;
/* Get the actual chunk in the stream */
if
(
!
(
p_ck
=
RIFF_ReadChunk
(
p_input
))
)
{
return
(
0
);
}
/* msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size ); */
/* special case for LIST-rec chunk */
if
(
(
p_ck
->
i_id
==
AVIFOURCC_LIST
)
&&
(
p_ck
->
i_type
==
AVIFOURCC_rec
)
)
{
AVI_SkipBytes
(
p_input
,
12
);
// RIFF_DescendChunk( p_input );
RIFF_DeleteChunk
(
p_input
,
p_ck
);
continue
;
}
AVI_ParseStreamHeader
(
p_ck
->
i_id
,
&
i
,
&
i_type
);
/* littles checks but not too much if you want to read all file */
if
(
i
>=
p_avi
->
i_streams
)
{
RIFF_DeleteChunk
(
p_input
,
p_ck
);
if
(
RIFF_NextChunk
(
p_input
,
p_avi
->
p_movi
)
!=
0
)
{
{
return
(
0
);
return
(
0
);
}
}
}
else
{
int
i_size
;
/* have we found a new entry (not present in index)? */
if
(
(
!
p_info_i
->
i_idxnb
)
||
(
p_info_i
->
p_index
[
p_info_i
->
i_idxnb
-
1
].
i_pos
<
p_ck
->
i_pos
))
{
AVIIndexEntry_t
index
;
index
.
i_id
=
p_ck
->
i_id
;
index
.
i_flags
=
AVI_GetKeyFlag
(
p_info_i
->
i_codec
,
(
u8
*
)
&
p_ck
->
i_8bytes
);
index
.
i_pos
=
p_ck
->
i_pos
;
index
.
i_length
=
p_ck
->
i_size
;
__AVI_AddEntryIndex
(
p_info_i
,
&
index
);
}
/* TODO check if p_other is full and then if is possible
go directly to the good chunk */
if
(
(
p_info_i
==
p_other
)
&&
(
!
AVI_PESBuffer_IsFull
(
p_other
)
)
&&
(
(
!
p_other
->
p_pes_last
)
||
(
p_other
->
p_pes_last
->
p_pes
->
i_pes_size
!=
BUFFER_MAXSPESSIZE
)
)
)
{
int
i_ck
=
p_other
->
p_pes_last
?
p_other
->
p_pes_last
->
i_posc
+
1
:
p_other
->
i_idxposc
;
i_size
=
__AVI_ChooseSize
(
p_ck
->
i_size
,
p_other
->
p_index
[
i_ck
].
i_length
);
if
(
p_other
->
p_index
[
i_ck
].
i_pos
==
p_ck
->
i_pos
)
{
if
(
!
__AVI_GetAndPutChunkInBuffer
(
p_input
,
p_other
,
i_size
,
i_ck
)
)
{
RIFF_DeleteChunk
(
p_input
,
p_ck
);
return
(
0
);
}
}
else
{
if
(
RIFF_NextChunk
(
p_input
,
p_avi
->
p_movi
)
!=
0
)
{
RIFF_DeleteChunk
(
p_input
,
p_ck
);
return
(
0
);
}
}
RIFF_DeleteChunk
(
p_input
,
p_ck
);
}
else
if
(
(
p_info_i
==
p_info
)
&&
(
p_info
->
i_idxposc
<
p_info
->
i_idxnb
)
)
{
/* the first ck_info is ok otherwise it should be
loaded without parsing */
i_size
=
__AVI_ChooseSize
(
p_ck
->
i_size
,
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_length
);
RIFF_DeleteChunk
(
p_input
,
p_ck
);
return
(
b_load
?
__AVI_GetAndPutChunkInBuffer
(
p_input
,
p_info
,
i_size
,
p_info
->
i_idxposc
)
:
1
);
}
else
{
/* skip it */
RIFF_DeleteChunk
(
p_input
,
p_ck
);
if
(
RIFF_NextChunk
(
p_input
,
p_avi
->
p_movi
)
!=
0
)
{
return
(
0
);
}
}
}
}
#undef p_info_i
}
/* be sure that i_ck will be a valid index entry */
static
int
AVI_SetStreamChunk
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
int
i_ck
)
{
p_info
->
i_idxposc
=
i_ck
;
p_info
->
i_idxposb
=
0
;
if
(
i_ck
<
p_info
->
i_idxnb
)
}
while
(
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_lengthtotal
+
{
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
<=
i_byte
);
return
(
1
);
}
else
{
p_info
->
i_idxposc
=
p_info
->
i_idxnb
-
1
;
do
{
p_info
->
i_idxposc
++
;
if
(
!
__AVI_GetChunk
(
p_input
,
p_info
,
0
)
)
{
return
(
0
);
}
}
while
(
p_info
->
i_idxposc
<
i_ck
);
p_stream
->
i_idxposb
=
i_byte
-
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_lengthtotal
;
return
(
1
);
return
(
1
);
}
}
}
}
/* XXX FIXME up to now, we assume that all chunk are one after one */
static
int
AVI_SetStreamBytes
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
off_t
i_byte
)
{
if
(
(
p_info
->
i_idxnb
>
0
)
&&
(
i_byte
<
p_info
->
p_index
[
p_info
->
i_idxnb
-
1
].
i_lengthtotal
+
p_info
->
p_index
[
p_info
->
i_idxnb
-
1
].
i_length
)
)
{
/* index is valid to find the ck */
/* uses dichototmie to be fast enougth */
int
i_idxposc
=
__MIN
(
p_info
->
i_idxposc
,
p_info
->
i_idxnb
-
1
);
int
i_idxmax
=
p_info
->
i_idxnb
;
int
i_idxmin
=
0
;
for
(
;;
)
{
if
(
p_info
->
p_index
[
i_idxposc
].
i_lengthtotal
>
i_byte
)
{
i_idxmax
=
i_idxposc
;
i_idxposc
=
(
i_idxmin
+
i_idxposc
)
/
2
;
}
else
{
if
(
p_info
->
p_index
[
i_idxposc
].
i_lengthtotal
+
p_info
->
p_index
[
i_idxposc
].
i_length
<=
i_byte
)
{
i_idxmin
=
i_idxposc
;
i_idxposc
=
(
i_idxmax
+
i_idxposc
)
/
2
;
}
else
{
p_info
->
i_idxposc
=
i_idxposc
;
p_info
->
i_idxposb
=
i_byte
-
p_info
->
p_index
[
i_idxposc
].
i_lengthtotal
;
return
(
1
);
}
}
}
}
else
{
p_info
->
i_idxposc
=
p_info
->
i_idxnb
-
1
;
p_info
->
i_idxposb
=
0
;
do
{
p_info
->
i_idxposc
++
;
if
(
!
__AVI_GetChunk
(
p_input
,
p_info
,
0
)
)
{
return
(
0
);
}
}
while
(
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_lengthtotal
+
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_length
<=
i_byte
);
p_info
->
i_idxposb
=
i_byte
-
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_lengthtotal
;
return
(
1
);
}
}
static
pes_packet_t
*
AVI_ReadStreamChunkInPES
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
)
{
if
(
p_info
->
i_idxposc
>
p_info
->
i_idxnb
)
{
return
(
NULL
);
}
/* we want chunk (p_info->i_idxposc,0) */
p_info
->
i_idxposb
=
0
;
if
(
!
__AVI_GetChunk
(
p_input
,
p_info
,
1
)
)
{
msg_Err
(
p_input
,
"Got one chunk : failed"
);
return
(
NULL
);
}
p_info
->
i_idxposc
++
;
return
(
AVI_PESBuffer_Get
(
p_info
)
);
}
static
pes_packet_t
*
AVI_ReadStreamBytesInPES
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
int
i_byte
)
{
pes_packet_t
*
p_pes
;
data_packet_t
*
p_data
;
int
i_count
=
0
;
int
i_read
;
if
(
!
(
p_pes
=
input_NewPES
(
p_input
->
p_method_data
)
)
)
{
return
(
NULL
);
}
if
(
!
(
p_data
=
input_NewPacket
(
p_input
->
p_method_data
,
i_byte
)
)
)
{
input_DeletePES
(
p_input
->
p_method_data
,
p_pes
);
return
(
NULL
);
}
p_pes
->
p_first
=
p_pes
->
p_last
=
p_data
;
p_pes
->
i_nb_data
=
1
;
p_pes
->
i_pes_size
=
i_byte
;
while
(
i_byte
>
0
)
{
if
(
!
__AVI_GetChunk
(
p_input
,
p_info
,
1
)
)
{
msg_Err
(
p_input
,
"Got one chunk : failed"
);
input_DeletePES
(
p_input
->
p_method_data
,
p_pes
);
return
(
NULL
);
}
i_read
=
__MIN
(
p_info
->
p_pes_first
->
p_pes
->
i_pes_size
-
(
p_info
->
i_idxposb
-
p_info
->
p_pes_first
->
i_posb
),
i_byte
);
/* FIXME FIXME FIXME follow all data packet */
memcpy
(
p_data
->
p_payload_start
+
i_count
,
p_info
->
p_pes_first
->
p_pes
->
p_first
->
p_payload_start
+
p_info
->
i_idxposb
-
p_info
->
p_pes_first
->
i_posb
,
i_read
);
AVI_PESBuffer_Drop
(
p_input
->
p_method_data
,
p_info
);
i_byte
-=
i_read
;
i_count
+=
i_read
;
p_info
->
i_idxposb
+=
i_read
;
if
(
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_length
<=
p_info
->
i_idxposb
)
{
p_info
->
i_idxposb
-=
p_info
->
p_index
[
p_info
->
i_idxposc
].
i_length
;
p_info
->
i_idxposc
++
;
}
}
return
(
p_pes
);
}
/*****************************************************************************
* AVI_GetFrameInPES : get dpts length(s) in pes from stream
*****************************************************************************
* Handle multiple pes, and set pts to the good value
*****************************************************************************/
static
pes_packet_t
*
AVI_GetFrameInPES
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
mtime_t
i_dpts
)
{
int
i
;
pes_packet_t
*
p_pes
=
NULL
;
pes_packet_t
*
p_pes_tmp
=
NULL
;
pes_packet_t
*
p_pes_first
=
NULL
;
mtime_t
i_pts
;
if
(
i_dpts
<
1000
)
{
return
(
NULL
)
;
}
if
(
!
p_info
->
i_samplesize
)
{
int
i_chunk
=
__MAX
(
AVI_PTSToChunk
(
p_info
,
i_dpts
),
1
);
p_pes_first
=
NULL
;
for
(
i
=
0
;
i
<
i_chunk
;
i
++
)
{
/* get pts while is valid */
i_pts
=
AVI_GetPTS
(
p_info
);
p_pes_tmp
=
AVI_ReadStreamChunkInPES
(
p_input
,
p_info
);
if
(
!
p_pes_tmp
)
{
return
(
p_pes_first
);
}
p_pes_tmp
->
i_pts
=
i_pts
;
if
(
!
p_pes_first
)
{
p_pes_first
=
p_pes_tmp
;
}
else
{
p_pes
->
p_next
=
p_pes_tmp
;
}
p_pes
=
p_pes_tmp
;
}
return
(
p_pes_first
);
}
else
{
/* stream is byte based */
int
i_byte
=
AVI_PTSToByte
(
p_info
,
i_dpts
);
if
(
i_byte
<
50
)
/* to avoid some problem with audio */
{
return
(
NULL
);
}
i_pts
=
AVI_GetPTS
(
p_info
);
/* ok even with broken index */
p_pes
=
AVI_ReadStreamBytesInPES
(
p_input
,
p_info
,
i_byte
);
if
(
p_pes
)
{
p_pes
->
i_pts
=
i_pts
;
}
return
(
p_pes
);
}
}
/*****************************************************************************
* AVI_DecodePES : send a pes to decoder
*****************************************************************************
* Handle multiple pes, and update pts to the good value
*****************************************************************************/
static
inline
void
AVI_DecodePES
(
input_thread_t
*
p_input
,
AVIStreamInfo_t
*
p_info
,
pes_packet_t
*
p_pes
)
{
pes_packet_t
*
p_pes_next
;
/* input_decode want only one pes, but AVI_GetFrameInPES give
multiple pes so send one by one */
while
(
p_pes
)
{
p_pes_next
=
p_pes
->
p_next
;
p_pes
->
p_next
=
NULL
;
p_pes
->
i_pts
=
input_ClockGetTS
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_pes
->
i_pts
*
9
/
100
);
input_DecodePES
(
p_info
->
p_es
->
p_decoder_fifo
,
p_pes
);
p_pes
=
p_pes_next
;
}
}
static
int
AVI_StreamSeek
(
input_thread_t
*
p_input
,
static
int
AVI_StreamSeek
(
input_thread_t
*
p_input
,
demux_sys_t
*
p_avi
,
demux_sys_t
*
p_avi
,
int
i_stream
,
int
i_stream
,
...
@@ -1889,14 +1343,17 @@ static int AVI_StreamSeek( input_thread_t *p_input,
...
@@ -1889,14 +1343,17 @@ static int AVI_StreamSeek( input_thread_t *p_input,
#define p_stream p_avi->pp_info[i_stream]
#define p_stream p_avi->pp_info[i_stream]
mtime_t
i_oldpts
;
mtime_t
i_oldpts
;
AVI_PESBuffer_Flush
(
p_input
->
p_method_data
,
p_stream
);
i_oldpts
=
AVI_GetPTS
(
p_stream
);
i_oldpts
=
AVI_GetPTS
(
p_stream
);
if
(
!
p_stream
->
i_samplesize
)
if
(
!
p_stream
->
i_samplesize
)
{
{
AVI_SetStreamChunk
(
p_input
,
if
(
!
AVI_SetStreamChunk
(
p_input
,
p_stream
,
i_stream
,
AVI_PTSToChunk
(
p_stream
,
i_date
)
);
AVI_PTSToChunk
(
p_stream
,
i_date
)
)
)
{
return
(
0
);
}
/* search key frame */
/* search key frame */
msg_Dbg
(
p_input
,
msg_Dbg
(
p_input
,
"old:%lld %s new %lld"
,
"old:%lld %s new %lld"
,
...
@@ -1911,7 +1368,7 @@ static int AVI_StreamSeek( input_thread_t *p_input,
...
@@ -1911,7 +1368,7 @@ static int AVI_StreamSeek( input_thread_t *p_input,
AVIIF_KEYFRAME
)
)
AVIIF_KEYFRAME
)
)
{
{
if
(
!
AVI_SetStreamChunk
(
p_input
,
if
(
!
AVI_SetStreamChunk
(
p_input
,
p
_stream
,
i
_stream
,
p_stream
->
i_idxposc
-
1
)
)
p_stream
->
i_idxposc
-
1
)
)
{
{
return
(
0
);
return
(
0
);
...
@@ -1920,11 +1377,12 @@ static int AVI_StreamSeek( input_thread_t *p_input,
...
@@ -1920,11 +1377,12 @@ static int AVI_StreamSeek( input_thread_t *p_input,
}
}
else
else
{
{
while
(
!
(
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_flags
&
while
(
p_stream
->
i_idxposc
<
p_stream
->
i_idxnb
&&
!
(
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_flags
&
AVIIF_KEYFRAME
)
)
AVIIF_KEYFRAME
)
)
{
{
if
(
!
AVI_SetStreamChunk
(
p_input
,
if
(
!
AVI_SetStreamChunk
(
p_input
,
p
_stream
,
i
_stream
,
p_stream
->
i_idxposc
+
1
)
)
p_stream
->
i_idxposc
+
1
)
)
{
{
return
(
0
);
return
(
0
);
...
@@ -1934,9 +1392,12 @@ static int AVI_StreamSeek( input_thread_t *p_input,
...
@@ -1934,9 +1392,12 @@ static int AVI_StreamSeek( input_thread_t *p_input,
}
}
else
else
{
{
AVI_SetStreamBytes
(
p_input
,
if
(
!
AVI_SetStreamBytes
(
p_input
,
p_stream
,
i_stream
,
AVI_PTSToByte
(
p_stream
,
i_date
)
);
AVI_PTSToByte
(
p_stream
,
i_date
)
)
)
{
return
(
0
);
}
}
}
return
(
1
);
return
(
1
);
#undef p_stream
#undef p_stream
...
@@ -1962,8 +1423,7 @@ static int AVISeek ( input_thread_t *p_input,
...
@@ -1962,8 +1423,7 @@ static int AVISeek ( input_thread_t *p_input,
{
{
if
(
!
p_avi
->
i_length
)
if
(
!
p_avi
->
i_length
)
{
{
int
i_index
;
avi_stream_t
*
p_stream
;
AVIStreamInfo_t
*
p_stream
;
u64
i_pos
;
u64
i_pos
;
/* use i_percent to create a true i_date */
/* use i_percent to create a true i_date */
...
@@ -1981,41 +1441,38 @@ static int AVISeek ( input_thread_t *p_input,
...
@@ -1981,41 +1441,38 @@ static int AVISeek ( input_thread_t *p_input,
/* try to find chunk that is at i_percent or the file */
/* try to find chunk that is at i_percent or the file */
i_pos
=
__MAX
(
i_percent
*
i_pos
=
__MAX
(
i_percent
*
p_input
->
stream
.
p_selected_area
->
i_size
/
100
,
p_input
->
stream
.
p_selected_area
->
i_size
/
100
,
p_avi
->
p_movi
->
i_pos
);
p_avi
->
i_movi_begin
);
/* search first selected stream */
/* search first selected stream */
for
(
i_
index
=
0
,
p_stream
=
NULL
;
for
(
i_
stream
=
0
,
p_stream
=
NULL
;
i_index
<
p_avi
->
i_streams
;
i_stream
++
)
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
{
{
p_stream
=
p_avi
->
pp_info
[
i_
index
];
p_stream
=
p_avi
->
pp_info
[
i_
stream
];
if
(
p_stream
->
i_activated
)
if
(
p_stream
->
i_activated
)
{
{
break
;
break
;
}
}
}
}
if
(
!
p_stream
||
!
p_stream
->
p_index
)
if
(
!
p_stream
||
!
p_stream
->
i_activated
)
{
{
msg_Err
(
p_input
,
"cannot find any selected stream"
);
msg_Err
(
p_input
,
"cannot find any selected stream"
);
return
(
-
1
);
return
(
-
1
);
}
}
/* search chunk */
p_stream
->
i_idxposc
=
__MAX
(
p_stream
->
i_idxposc
-
1
,
0
);
/* be sure that the index exit */
while
(
(
i_pos
<
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_pos
)
if
(
!
AVI_SetStreamChunk
(
p_input
,
&&
(
p_stream
->
i_idxposc
>
0
)
)
i_stream
,
0
)
)
{
{
/* search before i_idxposc */
msg_Err
(
p_input
,
"cannot seek"
);
if
(
!
AVI_SetStreamChunk
(
p_input
,
return
(
-
1
);
p_stream
,
p_stream
->
i_idxposc
-
1
)
)
{
msg_Err
(
p_input
,
"cannot seek"
);
return
(
-
1
);
}
}
}
while
(
i_pos
>=
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_pos
+
while
(
i_pos
>=
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_pos
+
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
+
8
)
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
+
8
)
{
{
/* search after i_idxposc */
/* search after i_idxposc */
if
(
!
AVI_SetStreamChunk
(
p_input
,
if
(
!
AVI_SetStreamChunk
(
p_input
,
p
_stream
,
p_stream
->
i_idxposc
+
1
)
)
i
_stream
,
p_stream
->
i_idxposc
+
1
)
)
{
{
msg_Err
(
p_input
,
"cannot seek"
);
msg_Err
(
p_input
,
"cannot seek"
);
return
(
-
1
);
return
(
-
1
);
...
@@ -2076,16 +1533,26 @@ static int AVISeek ( input_thread_t *p_input,
...
@@ -2076,16 +1533,26 @@ static int AVISeek ( input_thread_t *p_input,
* AVIDemux: reads and demuxes data packets
* AVIDemux: reads and demuxes data packets
*****************************************************************************
*****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
* TODO add support for unstreable file, just read a chunk and send it
* to the right decoder, very easy
*****************************************************************************/
*****************************************************************************/
typedef
struct
avi_stream_toread_s
{
int
i_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_stream_toread_t
;
static
int
AVIDemux_Seekable
(
input_thread_t
*
p_input
)
static
int
AVIDemux_Seekable
(
input_thread_t
*
p_input
)
{
{
int
i
;
int
i_stream
;
int
i_stream
;
int
b_stream
;
int
b_stream
;
// cannot be more than 100 stream (dcXX or wbXX)
avi_stream_toread_t
toread
[
100
];
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
/* detect new selected/unselected streams */
/* detect new selected/unselected streams */
...
@@ -2108,43 +1575,13 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
...
@@ -2108,43 +1575,13 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
}
}
#undef p_stream
#undef p_stream
}
}
/* search new video and audio stream selected
if current have been unselected*/
if
(
(
!
p_avi
->
p_info_video
)
||
(
!
p_avi
->
p_info_video
->
p_es
->
p_decoder_fifo
)
)
{
p_avi
->
p_info_video
=
NULL
;
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
{
if
(
(
p_avi
->
pp_info
[
i
]
->
i_cat
==
VIDEO_ES
)
&&
(
p_avi
->
pp_info
[
i
]
->
p_es
->
p_decoder_fifo
)
)
{
p_avi
->
p_info_video
=
p_avi
->
pp_info
[
i
];
break
;
}
}
}
if
(
(
!
p_avi
->
p_info_audio
)
||
(
!
p_avi
->
p_info_audio
->
p_es
->
p_decoder_fifo
)
)
{
p_avi
->
p_info_audio
=
NULL
;
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
{
if
(
(
p_avi
->
pp_info
[
i
]
->
i_cat
==
AUDIO_ES
)
&&
(
p_avi
->
pp_info
[
i
]
->
p_es
->
p_decoder_fifo
)
)
{
p_avi
->
p_info_audio
=
p_avi
->
pp_info
[
i
];
break
;
}
}
}
if
(
p_input
->
stream
.
p_selected_program
->
i_synchro_state
==
SYNCHRO_REINIT
)
if
(
p_input
->
stream
.
p_selected_program
->
i_synchro_state
==
SYNCHRO_REINIT
)
{
{
mtime_t
i_date
;
mtime_t
i_date
;
int
i_percent
;
int
i_percent
;
/* first wait for empty buffer, arbitrary time FIXME */
/* first wait for empty buffer, arbitrary time FIXME */
msleep
(
DEFAULT_PTS_DELAY
);
//
msleep( DEFAULT_PTS_DELAY );
i_date
=
(
mtime_t
)
1000000
*
i_date
=
(
mtime_t
)
1000000
*
(
mtime_t
)
p_avi
->
i_length
*
(
mtime_t
)
p_avi
->
i_length
*
...
@@ -2152,48 +1589,284 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
...
@@ -2152,48 +1589,284 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
(
mtime_t
)
p_input
->
stream
.
p_selected_area
->
i_size
;
(
mtime_t
)
p_input
->
stream
.
p_selected_area
->
i_size
;
i_percent
=
100
*
AVI_TellAbsolute
(
p_input
)
/
i_percent
=
100
*
AVI_TellAbsolute
(
p_input
)
/
p_input
->
stream
.
p_selected_area
->
i_size
;
p_input
->
stream
.
p_selected_area
->
i_size
;
AVISeek
(
p_input
,
i_date
,
i_percent
);
// input_ClockInit( p_input->stream.p_selected_program );
// input_ClockInit( p_input->stream.p_selected_program );
AVISeek
(
p_input
,
i_date
,
i_percent
);
}
}
/* wait for the good time */
/* wait for the good time */
p_avi
->
i_pcr
=
p_avi
->
i_time
*
9
/
100
;
input_ClockManageRef
(
p_input
,
input_ClockManageRef
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_input
->
stream
.
p_selected_program
,
p_avi
->
i_pcr
);
p_avi
->
i_pcr
);
p_avi
->
i_pcr
=
p_avi
->
i_time
*
9
/
100
;
p_avi
->
i_time
+=
100
*
1000
;
/* read 100ms */
p_avi
->
i_time
+=
100
*
1000
;
/* read 100ms */
/* init toread */
for
(
i_stream
=
0
;
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
{
#define p_stream p_avi->pp_info[i_stream]
mtime_t
i_dpts
;
toread
[
i_stream
].
i_ok
=
p_stream
->
i_activated
;
if
(
p_stream
->
i_idxposc
<
p_stream
->
i_idxnb
)
{
toread
[
i_stream
].
i_posf
=
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_pos
;
if
(
p_stream
->
i_idxposb
>
0
)
{
toread
[
i_stream
].
i_posf
+=
8
+
p_stream
->
i_idxposb
;
}
}
else
{
toread
[
i_stream
].
i_posf
=
-
1
;
}
i_dpts
=
p_avi
->
i_time
-
AVI_GetPTS
(
p_stream
);
if
(
p_stream
->
i_samplesize
)
{
toread
[
i_stream
].
i_toread
=
AVI_PTSToByte
(
p_stream
,
__ABS
(
i_dpts
)
);
}
else
{
toread
[
i_stream
].
i_toread
=
AVI_PTSToChunk
(
p_stream
,
__ABS
(
i_dpts
)
);
}
if
(
i_dpts
<
0
)
{
toread
[
i_stream
].
i_toread
*=
-
1
;
}
#undef p_stream
}
b_stream
=
0
;
for
(
i_stream
=
0
,
b_stream
=
0
;
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
for
(
;;
)
{
{
#define p_stream p_avi->pp_info[i_stream]
#define p_stream p_avi->pp_info[i_stream]
int
b_done
;
pes_packet_t
*
p_pes
;
pes_packet_t
*
p_pes
;
off_t
i_pos
;
int
i
;
int
i_size
;
/* search for first chunk to be read */
for
(
i
=
0
,
b_done
=
1
,
i_pos
=
-
1
;
i
<
p_avi
->
i_streams
;
i
++
)
{
if
(
!
toread
[
i
].
i_ok
||
AVI_GetDPTS
(
p_avi
->
pp_info
[
i
],
toread
[
i
].
i_toread
)
<=
-
25
*
1000
)
{
continue
;
}
if
(
toread
[
i
].
i_toread
>
0
)
{
b_done
=
0
;
// not yet finished
}
if
(
toread
[
i
].
i_posf
>
0
)
{
i_stream
=
i
;
if
(
i_pos
==
-
1
)
{
i_pos
=
toread
[
i_stream
].
i_posf
;
}
else
{
i_pos
=
__MIN
(
i_pos
,
toread
[
i_stream
].
i_posf
);
}
}
}
if
(
!
p_stream
->
p_es
||
if
(
b_done
)
!
p_stream
->
p_es
->
p_decoder_fifo
)
{
{
return
(
b_stream
?
1
:
0
);
}
if
(
i_pos
==
-
1
)
{
/* no valid index, we will parse directly the stream */
if
(
p_avi
->
i_movi_lastchunk_pos
>=
p_avi
->
i_movi_begin
)
{
AVI_SeekAbsolute
(
p_input
,
p_avi
->
i_movi_lastchunk_pos
);
if
(
!
AVI_PacketNext
(
p_input
)
)
{
return
(
0
);
}
}
else
{
AVI_SeekAbsolute
(
p_input
,
p_avi
->
i_movi_begin
);
}
continue
;
for
(
;;
)
{
avi_packet_t
avi_pk
;
if
(
!
AVI_PacketGetHeader
(
p_input
,
&
avi_pk
)
)
{
msg_Err
(
p_input
,
"cannot get packet header"
);
return
(
0
);
}
if
(
avi_pk
.
i_stream
>=
p_avi
->
i_streams
||
(
avi_pk
.
i_cat
!=
AUDIO_ES
&&
avi_pk
.
i_cat
!=
VIDEO_ES
)
)
{
switch
(
avi_pk
.
i_fourcc
)
{
case
AVIFOURCC_LIST
:
AVI_SkipBytes
(
p_input
,
12
);
break
;
default:
if
(
!
AVI_PacketNext
(
p_input
)
)
{
msg_Err
(
p_input
,
"cannot skip packet"
);
return
(
0
);
}
break
;
}
continue
;
}
else
{
/* add this chunk to the index */
AVIIndexEntry_t
index
;
index
.
i_id
=
avi_pk
.
i_fourcc
;
index
.
i_flags
=
AVI_GetKeyFlag
(
p_avi
->
pp_info
[
avi_pk
.
i_stream
]
->
i_codec
,
avi_pk
.
i_peek
);
index
.
i_pos
=
avi_pk
.
i_pos
;
index
.
i_length
=
avi_pk
.
i_size
;
AVI_IndexAddEntry
(
p_avi
,
avi_pk
.
i_stream
,
&
index
);
i_stream
=
avi_pk
.
i_stream
;
/* do we will read this data ? */
if
(
AVI_GetDPTS
(
p_stream
,
toread
[
i_stream
].
i_toread
)
>
-
25
*
1000
)
{
break
;
}
else
{
if
(
!
AVI_PacketNext
(
p_input
)
)
{
msg_Err
(
p_input
,
"cannot skip packet"
);
return
(
0
);
}
}
}
}
}
}
if
(
p_avi
->
i_time
<=
AVI_GetPTS
(
p_stream
)
)
else
{
{
msg_Warn
(
p_input
,
"skeeping stream %d"
,
i_stream
);
AVI_SeekAbsolute
(
p_input
,
i_pos
);
b_stream
=
1
;
}
/* read thoses data */
if
(
p_stream
->
i_samplesize
)
{
i_size
=
__MIN
(
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
-
p_stream
->
i_idxposb
,
100
*
1024
);
// 10Ko max
// toread[i_stream].i_toread );
}
else
{
i_size
=
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
;
}
if
(
p_stream
->
i_idxposb
==
0
)
{
i_size
+=
8
;
// need to read and skip header
}
if
(
input_ReadInPES
(
p_input
,
&
p_pes
,
__EVEN
(
i_size
)
)
<
0
)
{
msg_Err
(
p_input
,
"failled reading data"
);
toread
[
i_stream
].
i_ok
=
0
;
continue
;
continue
;
}
}
p_pes
=
AVI_GetFrameInPES
(
p_input
,
p_stream
,
if
(
i_size
%
2
)
// read was padded on word boundary
p_avi
->
i_time
-
AVI_GetPTS
(
p_stream
)
);
if
(
p_pes
)
{
{
AVI_DecodePES
(
p_input
,
p_stream
,
p_pes
);
p_pes
->
p_last
->
p_payload_end
--
;
b_stream
=
1
;
p_pes
->
i_pes_size
--
;
}
// skip header
if
(
p_stream
->
i_idxposb
==
0
)
{
p_pes
->
p_first
->
p_payload_start
+=
8
;
p_pes
->
i_pes_size
-=
8
;
}
}
#undef p_stream
}
/* at the end ? */
p_pes
->
i_pts
=
AVI_GetPTS
(
p_stream
);
return
(
b_stream
?
1
:
0
);
/* read data */
if
(
p_stream
->
i_samplesize
)
{
if
(
p_stream
->
i_idxposb
==
0
)
{
i_size
-=
8
;
}
toread
[
i_stream
].
i_toread
-=
i_size
;
p_stream
->
i_idxposb
+=
i_size
;
if
(
p_stream
->
i_idxposb
>=
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
)
{
p_stream
->
i_idxposb
=
0
;
p_stream
->
i_idxposc
++
;
}
}
else
{
toread
[
i_stream
].
i_toread
--
;
p_stream
->
i_idxposc
++
;
}
if
(
p_stream
->
i_idxposc
<
p_stream
->
i_idxnb
)
{
toread
[
i_stream
].
i_posf
=
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_pos
;
if
(
p_stream
->
i_idxposb
>
0
)
{
toread
[
i_stream
].
i_posf
+=
8
+
p_stream
->
i_idxposb
;
}
}
else
{
toread
[
i_stream
].
i_posf
=
-
1
;
}
b_stream
=
1
;
// at least one read succeed
if
(
p_stream
->
p_es
&&
p_stream
->
p_es
->
p_decoder_fifo
)
{
p_pes
->
i_dts
=
p_pes
->
i_pts
=
input_ClockGetTS
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_pes
->
i_pts
*
9
/
100
);
input_DecodePES
(
p_stream
->
p_es
->
p_decoder_fifo
,
p_pes
);
}
else
{
input_DeletePES
(
p_input
->
p_method_data
,
p_pes
);
}
}
}
}
...
@@ -2206,7 +1879,7 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
...
@@ -2206,7 +1879,7 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
static
int
AVIDemux_UnSeekable
(
input_thread_t
*
p_input
)
static
int
AVIDemux_UnSeekable
(
input_thread_t
*
p_input
)
{
{
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
AVIStreamInfo
_t
*
p_stream_master
;
avi_stream
_t
*
p_stream_master
;
int
i_stream
;
int
i_stream
;
int
b_audio
;
int
b_audio
;
int
i_packet
;
int
i_packet
;
...
@@ -2308,8 +1981,11 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input )
...
@@ -2308,8 +1981,11 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input )
{
{
return
(
-
1
);
return
(
-
1
);
}
}
p_pes
->
i_pts
=
AVI_GetPTS
(
p_stream
);
p_pes
->
i_pts
=
AVI_DecodePES
(
p_input
,
p_stream
,
p_pes
);
input_ClockGetTS
(
p_input
,
p_input
->
stream
.
p_selected_program
,
AVI_GetPTS
(
p_stream
)
*
9
/
100
);
input_DecodePES
(
p_stream
->
p_es
->
p_decoder_fifo
,
p_pes
);
}
}
else
else
{
{
...
...
modules/demux/avi/avi.h
View file @
cdf8646f
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* avi.h : AVI file Stream input module for vlc
* avi.h : AVI file Stream input module for vlc
*****************************************************************************
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* Copyright (C) 2001 VideoLAN
* $Id: avi.h,v 1.
4 2002/10/15 00:55:07
fenrir Exp $
* $Id: avi.h,v 1.
5 2002/10/27 15:37:16
fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
...
@@ -20,7 +20,20 @@
...
@@ -20,7 +20,20 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
*****************************************************************************/
#define MAX_PACKETS_IN_FIFO 2
typedef
struct
avi_packet_s
{
u32
i_fourcc
;
off_t
i_pos
;
u32
i_size
;
u32
i_type
;
// only for AVIFOURCC_LIST
u8
i_peek
[
8
];
//first 8 bytes
int
i_stream
;
int
i_cat
;
}
avi_packet_t
;
typedef
struct
AVIIndexEntry_s
typedef
struct
AVIIndexEntry_s
{
{
...
@@ -29,22 +42,14 @@ typedef struct AVIIndexEntry_s
...
@@ -29,22 +42,14 @@ typedef struct AVIIndexEntry_s
u32
i_pos
;
u32
i_pos
;
u32
i_length
;
u32
i_length
;
u32
i_lengthtotal
;
u32
i_lengthtotal
;
}
AVIIndexEntry_t
;
}
AVIIndexEntry_t
;
typedef
struct
AVIESBuffer
_s
typedef
struct
avi_stream
_s
{
{
struct
AVIESBuffer_s
*
p_next
;
int
i_activated
;
pes_packet_t
*
p_pes
;
int
i_posc
;
int
i_posb
;
}
AVIESBuffer_t
;
typedef
struct
AVIStreamInfo_s
{
int
i_cat
;
/* AUDIO_ES, VIDEO_ES */
int
i_cat
;
/* AUDIO_ES, VIDEO_ES */
int
i_activated
;
vlc_fourcc_t
i_fourcc
;
vlc_fourcc_t
i_fourcc
;
vlc_fourcc_t
i_codec
;
vlc_fourcc_t
i_codec
;
...
@@ -52,8 +57,8 @@ typedef struct AVIStreamInfo_s
...
@@ -52,8 +57,8 @@ typedef struct AVIStreamInfo_s
int
i_scale
;
int
i_scale
;
int
i_samplesize
;
int
i_samplesize
;
es_descriptor_t
*
p_es
;
es_descriptor_t
*
p_es
;
int
b_selected
;
/* newly selected */
AVIIndexEntry_t
*
p_index
;
AVIIndexEntry_t
*
p_index
;
int
i_idxnb
;
int
i_idxnb
;
int
i_idxmax
;
int
i_idxmax
;
...
@@ -61,32 +66,23 @@ typedef struct AVIStreamInfo_s
...
@@ -61,32 +66,23 @@ typedef struct AVIStreamInfo_s
int
i_idxposc
;
/* numero of chunk */
int
i_idxposc
;
/* numero of chunk */
int
i_idxposb
;
/* byte in the current chunk */
int
i_idxposb
;
/* byte in the current chunk */
/* add some buffering */
}
avi_stream_t
;
AVIESBuffer_t
*
p_pes_first
;
AVIESBuffer_t
*
p_pes_last
;
int
i_pes_count
;
int
i_pes_totalsize
;
}
AVIStreamInfo_t
;
struct
demux_sys_t
struct
demux_sys_t
{
{
mtime_t
i_time
;
mtime_t
i_time
;
mtime_t
i_length
;
mtime_t
i_length
;
mtime_t
i_pcr
;
mtime_t
i_pcr
;
int
i_rate
;
riffchunk_t
*
p_movi
;
int
b_seekable
;
int
b_seekable
;
avi_chunk_t
ck_root
;
avi_chunk_t
ck_root
;
/* Info extrated from avih */
off_t
i_movi_begin
;
off_t
i_movi_lastchunk_pos
;
/* XXX position of last valid chunk */
/* number of stream and informations*/
/* number of stream and informations*/
int
i_streams
;
int
i_streams
;
AVIStreamInfo_t
**
pp_info
;
avi_stream_t
**
pp_info
;
/* current audio and video es */
AVIStreamInfo_t
*
p_info_video
;
AVIStreamInfo_t
*
p_info_audio
;
};
};
modules/demux/avi/libavi.c
View file @
cdf8646f
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* libavi.c :
* libavi.c :
*****************************************************************************
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* Copyright (C) 2001 VideoLAN
* $Id: libavi.c,v 1.
2 2002/10/26 19:14:45
fenrir Exp $
* $Id: libavi.c,v 1.
3 2002/10/27 15:37:16
fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
...
@@ -109,14 +109,33 @@ int AVI_SeekAbsolute( input_thread_t *p_input,
...
@@ -109,14 +109,33 @@ int AVI_SeekAbsolute( input_thread_t *p_input,
}
}
else
else
{
{
int
i_peek
;
data_packet_t
*
p_data
;
int
i_skip
=
i_pos
-
i_filepos
;
int
i_skip
=
i_pos
-
i_filepos
;
u8
*
p_peek
;
msg_Warn
(
p_input
,
"will skip %d bytes, slow"
,
i_skip
);
msg_Warn
(
p_input
,
"will skip %d bytes, slow"
,
i_skip
);
if
(
i_skip
<
0
)
if
(
i_skip
<
0
)
{
{
return
(
0
);
// failed
return
(
0
);
// failed
}
}
while
(
i_skip
>
0
)
{
int
i_read
;
i_read
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
4096
,
i_skip
)
);
if
(
i_read
<
0
)
{
return
(
0
);
}
i_skip
-=
i_read
;
input_DeletePacket
(
p_input
->
p_method_data
,
p_data
);
if
(
i_read
==
0
&&
i_skip
>
0
)
{
return
(
0
);
}
}
#if 0
while( i_skip > 0 )
while( i_skip > 0 )
{
{
i_peek = input_Peek( p_input, &p_peek, i_skip+1 );
i_peek = input_Peek( p_input, &p_peek, i_skip+1 );
...
@@ -130,6 +149,7 @@ int AVI_SeekAbsolute( input_thread_t *p_input,
...
@@ -130,6 +149,7 @@ int AVI_SeekAbsolute( input_thread_t *p_input,
return( 0);
return( 0);
}
}
}
}
#endif
return
(
1
);
return
(
1
);
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment