Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
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
Show 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,14 +1021,8 @@ static int AVIInit( vlc_object_t * p_this )
...
@@ -1045,14 +1021,8 @@ 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
++
)
{
{
...
@@ -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
)
)
)
if
(
p_avi
->
i_movi_lastchunk_pos
>=
p_avi
->
i_movi_begin
)
{
{
return
(
0
);
AVI_SeekAbsolute
(
p_input
,
p_avi
->
i_movi_lastchunk_pos
);
}
if
(
!
AVI_PacketNext
(
p_input
)
)
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
);
return
(
0
);
}
}
if
(
(
i_size
&
1
)
&&
(
b_pad
)
)
{
b_pad
=
1
;
i_size
++
;
}
}
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
)
)
{
switch
(
avi_pk
.
i_fourcc
)
{
case
AVIFOURCC_LIST
:
AVI_SkipBytes
(
p_input
,
12
);
break
;
default:
if
(
!
AVI_PacketNext
(
p_input
)
)
{
{
(
*
pp_pes
)
->
p_first
=
return
(
0
);
(
*
pp_pes
)
->
p_last
=
p_data
;
}
(
*
pp_pes
)
->
i_nb_data
=
1
;
break
;
(
*
pp_pes
)
->
i_pes_size
=
i_read
;
}
}
}
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
;
}
}
while
(
((
*
pp_pes
)
->
i_pes_size
<
i_size
)
&&
(
i_read
)
);
if
(
b_pad
)
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
)
{
{
(
*
pp_pes
)
->
i_pes_size
--
;
return
(
1
);
(
*
pp_pes
)
->
p_last
->
p_payload_end
--
;
i_size
--
;
}
}
return
(
i_size
);
if
(
!
AVI_PacketNext
(
p_input
)
)
}
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
)
{
{
return
(
0
);
return
(
0
);
}
}
/* 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
,
/* be sure that i_ck will be a valid index entry */
AVIStreamInfo_t
*
p_other
)
static
int
AVI_SetStreamChunk
(
input_thread_t
*
p_input
,
int
i_stream
,
int
i_ck
)
{
{
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
);
p_stream
->
i_idxposc
=
p_stream
->
i_idxnb
-
1
;
}
do
/* 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
);
p_stream
->
i_idxposc
++
;
}
if
(
!
AVI_StreamChunkFind
(
p_input
,
i_stream
)
)
/* 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
);
return
(
0
);
}
}
/* KNOW for the 2 streams, the ck we want are after the last read
}
while
(
p_stream
->
i_idxposc
<
i_ck
);
or it's the first */
/* if the first ck_other we want isn't between ck_info_last
return
(
1
);
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
);
}
}
static
inline
int
__AVI_ChooseSize
(
int
l1
,
int
l2
)
/* XXX FIXME up to now, we assume that all chunk are one after one */
{
static
int
AVI_SetStreamBytes
(
input_thread_t
*
p_input
,
/* XXX l2 is prefered if 0 otherwise min not equal to 0 */
int
i_stream
,
if
(
!
l2
)
off_t
i_byte
)
{
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
)
{
{
demux_sys_t
*
p_avi
=
p_input
->
p_demux_data
;
avi_stream_t
*
p_stream
=
p_avi
->
pp_info
[
i_stream
];
pes_packet_t
*
p_pes
;
if
(
(
p_stream
->
i_idxnb
>
0
)
int
i_length
;
&&
(
i_byte
<
p_stream
->
p_index
[
p_stream
->
i_idxnb
-
1
].
i_lengthtotal
+
p_stream
->
p_index
[
p_stream
->
i_idxnb
-
1
].
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
);
/* index is valid to find the ck */
}
/* uses dichototmie to be fast enougth */
p_pes
->
p_first
->
p_payload_start
+=
8
;
int
i_idxposc
=
__MIN
(
p_stream
->
i_idxposc
,
p_stream
->
i_idxnb
-
1
);
p_pes
->
i_pes_size
-=
8
;
int
i_idxmax
=
p_stream
->
i_idxnb
;
int
i_idxmin
=
0
;
i_size
=
GetDWLE
(
p_pes
->
p_first
->
p_demux_start
+
4
);
for
(
;;
)
{
AVI_PESBuffer_Add
(
p_input
->
p_method_data
,
if
(
p_stream
->
p_index
[
i_idxposc
].
i_lengthtotal
>
i_byte
)
p_info
,
p_pes
,
i_ck
,
0
);
/* skip unwanted bytes */
if
(
i_length
!=
i_size
)
{
{
msg_Err
(
p_input
,
"Chunk Size mismatch"
);
i_idxmax
=
i_idxposc
;
AVI_SeekAbsolute
(
p_input
,
i_idxposc
=
(
i_idxmin
+
i_idxposc
)
/
2
;
__EVEN
(
AVI_TellAbsolute
(
p_input
)
+
i_size
-
i_length
)
);
}
}
return
(
1
);
else
}
/* 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
;
AVIStreamInfo_t
*
p_other
;
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
)
if
(
p_stream
->
p_index
[
i_idxposc
].
i_lengthtotal
+
&&
(
p_info
->
i_idxposb
>=
p_info
->
p_pes_first
->
i_posb
)
p_stream
->
p_index
[
i_idxposc
].
i_length
<=
i_byte
)
&&
(
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 */
i_idxmin
=
i_idxposc
;
i_idxposc
=
(
i_idxmax
+
i_idxposc
)
/
2
;
}
}
else
else
{
{
AVI_PESBuffer_Drop
(
p_input
->
p_method_data
,
p_info
);
p_stream
->
i_idxposc
=
i_idxposc
;
p_stream
->
i_idxposb
=
i_byte
-
p_stream
->
p_index
[
i_idxposc
].
i_lengthtotal
;
return
(
1
);
}
}
}
}
}
/* 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
(
!
i_method
)
{
/* 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 */
/* the position max we have already reached */
/* FIXME this isn't the better because sometime will fail to
put in buffer p_other since it could be too far */
AVIStreamInfo_t
*
p_info_max
=
p_info
;
for
(
i
=
0
;
i
<
p_avi
->
i_streams
;
i
++
)
{
if
(
p_info_i
->
i_idxnb
)
{
if
(
p_info_max
->
i_idxnb
)
{
if
(
p_info_i
->
p_index
[
p_info_i
->
i_idxnb
-
1
].
i_pos
>
p_info_max
->
p_index
[
p_info_max
->
i_idxnb
-
1
].
i_pos
)
{
p_info_max
=
p_info_i
;
}
}
else
{
p_info_max
=
p_info_i
;
}
}
}
if
(
p_info_max
->
i_idxnb
)
{
/* be carefull that size between index and ck can sometime be
different without any error (and other time it's an error) */
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
);
}
}
}
else
else
{
{
int
i_size
;
p_stream
->
i_idxposc
=
p_stream
->
i_idxnb
-
1
;
p_stream
->
i_idxposb
=
0
;
/* 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
)
{
return
(
1
);
}
else
{
p_info
->
i_idxposc
=
p_info
->
i_idxnb
-
1
;
do
do
{
{
p_
info
->
i_idxposc
++
;
p_
stream
->
i_idxposc
++
;
if
(
!
__AVI_GetChunk
(
p_input
,
p_info
,
0
)
)
if
(
!
AVI_StreamChunkFind
(
p_input
,
i_stream
)
)
{
{
return
(
0
);
return
(
0
);
}
}
}
while
(
p_info
->
i_idxposc
<
i_ck
);
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
);
}
}
}
}
}
while
(
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_lengthtotal
+
else
p_stream
->
p_index
[
p_stream
->
i_idxposc
].
i_length
<=
i_byte
);
{
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_
stream
->
i_idxposb
=
i_byte
-
p_
info
->
p_index
[
p_info
->
i_idxposc
].
i_lengthtotal
;
p_
stream
->
p_index
[
p_stream
->
i_idxposc
].
i_lengthtotal
;
return
(
1
);
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
)
&&
(
p_stream
->
i_idxposc
>
0
)
)
{
/* search before i_idxposc */
if
(
!
AVI_SetStreamChunk
(
p_input
,
if
(
!
AVI_SetStreamChunk
(
p_input
,
p_stream
,
p_stream
->
i_idxposc
-
1
)
)
i_stream
,
0
)
)
{
{
msg_Err
(
p_input
,
"cannot seek"
);
msg_Err
(
p_input
,
"cannot seek"
);
return
(
-
1
);
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,47 +1589,283 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
...
@@ -2152,47 +1589,283 @@ 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 */
for
(
i_stream
=
0
,
b_stream
=
0
;
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
/* init toread */
for
(
i_stream
=
0
;
i_stream
<
p_avi
->
i_streams
;
i_stream
++
)
{
{
#define p_stream p_avi->pp_info[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
(
;;
)
{
#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
;
if
(
!
p_stream
->
p_es
||
/* search for first chunk to be read */
!
p_stream
->
p_es
->
p_decoder_fifo
)
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
(
b_done
)
{
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
);
}
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
;
continue
;
}
}
if
(
p_avi
->
i_time
<=
AVI_GetPTS
(
p_stream
)
)
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
{
{
msg_Warn
(
p_input
,
"skeeping stream %d"
,
i_stream
);
if
(
!
AVI_PacketNext
(
p_input
)
)
b_stream
=
1
;
{
msg_Err
(
p_input
,
"cannot skip packet"
);
return
(
0
);
}
}
}
}
}
else
{
AVI_SeekAbsolute
(
p_input
,
i_pos
);
}
/* 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
--
;
}
}
#undef p_stream
// skip header
if
(
p_stream
->
i_idxposb
==
0
)
{
p_pes
->
p_first
->
p_payload_start
+=
8
;
p_pes
->
i_pes_size
-=
8
;
}
}
/* 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
;
...
@@ -53,7 +58,7 @@ typedef struct AVIStreamInfo_s
...
@@ -53,7 +58,7 @@ typedef struct AVIStreamInfo_s
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