Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
155e9ee9
Commit
155e9ee9
authored
Nov 10, 2003
by
Fabrice Bellard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial seek support
Originally committed as revision 2502 to
svn://svn.ffmpeg.org/ffmpeg/trunk
parent
27f388aa
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
294 additions
and
26 deletions
+294
-26
avi.h
libavformat/avi.h
+3
-0
avidec.c
libavformat/avidec.c
+291
-26
No files found.
libavformat/avi.h
View file @
155e9ee9
...
...
@@ -13,6 +13,9 @@
#define AVI_MAX_RIFF_SIZE 0x40000000LL
#define AVI_MASTER_INDEX_SIZE 256
/* index flags */
#define AVIIF_INDEX 0x10
offset_t
start_tag
(
ByteIOContext
*
pb
,
const
char
*
tag
);
void
end_tag
(
ByteIOContext
*
pb
,
offset_t
start
);
...
...
libavformat/avidec.c
View file @
155e9ee9
...
...
@@ -21,18 +21,33 @@
#include "dv.h"
//#define DEBUG
typedef
struct
AVIIndex
{
unsigned
char
tag
[
4
];
unsigned
int
flags
,
pos
,
len
;
struct
AVIIndex
*
next
;
}
AVIIndex
;
//#define DEBUG_SEEK
typedef
struct
AVIIndexEntry
{
unsigned
int
flags
;
unsigned
int
pos
;
unsigned
int
cum_len
;
/* sum of all lengths before this packet */
}
AVIIndexEntry
;
typedef
struct
AVIStream
{
AVIIndexEntry
*
index_entries
;
int
nb_index_entries
;
int
index_entries_allocated_size
;
int
frame_offset
;
/* current frame (video) or byte (audio) counter
(used to compute the pts) */
int
scale
;
int
rate
;
int
sample_size
;
/* audio only data */
int
new_frame_offset
;
/* temporary storage (used during seek) */
int
cum_len
;
/* temporary storage (used during seek) */
}
AVIStream
;
typedef
struct
{
int64_t
riff_end
;
int64_t
movi_end
;
offset_t
movi_list
;
AVIIndex
*
first
,
*
last
;
int
index_loaded
;
DVDemuxContext
*
dv_demux
;
}
AVIContext
;
...
...
@@ -74,8 +89,11 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
unsigned
int
size
,
nb_frames
;
int
i
,
n
;
AVStream
*
st
;
AVIStream
*
ast
;
int
xan_video
=
0
;
/* hack to support Xan A/V */
av_set_pts_info
(
s
,
64
,
1
,
AV_TIME_BASE
);
if
(
get_riff
(
avi
,
pb
)
<
0
)
return
-
1
;
...
...
@@ -100,7 +118,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
print_tag
(
"list"
,
tag1
,
0
);
#endif
if
(
tag1
==
MKTAG
(
'm'
,
'o'
,
'v'
,
'i'
))
{
avi
->
movi_end
=
url_ftell
(
pb
)
+
size
-
4
;
avi
->
movi_list
=
url_ftell
(
pb
)
-
4
;
avi
->
movi_end
=
avi
->
movi_list
+
size
;
#ifdef DEBUG
printf
(
"movi end=%Lx
\n
"
,
avi
->
movi_end
);
#endif
...
...
@@ -115,9 +134,14 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
url_fskip
(
pb
,
4
*
4
);
n
=
get_le32
(
pb
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
AVIStream
*
ast
;
st
=
av_new_stream
(
s
,
i
);
if
(
!
st
)
goto
fail
;
ast
=
av_mallocz
(
sizeof
(
AVIStream
));
if
(
!
ast
)
goto
fail
;
st
->
priv_data
=
ast
;
}
url_fskip
(
pb
,
size
-
7
*
4
);
break
;
...
...
@@ -159,7 +183,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
st
=
s
->
streams
[
stream_index
];
ast
=
st
->
priv_data
;
get_le32
(
pb
);
/* flags */
get_le16
(
pb
);
/* priority */
get_le16
(
pb
);
/* language */
...
...
@@ -168,27 +193,28 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
rate
=
get_le32
(
pb
);
/* rate */
if
(
scale
&&
rate
){
st
->
codec
.
frame_rate
=
rate
;
st
->
codec
.
frame_rate_base
=
scale
;
}
else
if
(
frame_period
){
st
->
codec
.
frame_
rate
=
1000000
;
s
t
->
codec
.
frame_rate_bas
e
=
frame_period
;
rate
=
1000000
;
s
cal
e
=
frame_period
;
}
else
{
st
->
codec
.
frame_
rate
=
25
;
s
t
->
codec
.
frame_rate_bas
e
=
1
;
rate
=
25
;
s
cal
e
=
1
;
}
ast
->
rate
=
rate
;
ast
->
scale
=
scale
;
st
->
codec
.
frame_rate
=
rate
;
st
->
codec
.
frame_rate_base
=
scale
;
get_le32
(
pb
);
/* start */
nb_frames
=
get_le32
(
pb
);
st
->
start_time
=
0
;
st
->
duration
=
(
double
)
nb_frames
*
st
->
codec
.
frame_rate_base
*
AV_TIME_BASE
/
st
->
codec
.
frame_rate
;
url_fskip
(
pb
,
size
-
9
*
4
);
break
;
case
MKTAG
(
'a'
,
'u'
,
'd'
,
's'
):
{
unsigned
int
length
,
rate
;
unsigned
int
length
;
codec_type
=
CODEC_TYPE_AUDIO
;
...
...
@@ -197,19 +223,23 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
break
;
}
st
=
s
->
streams
[
stream_index
];
ast
=
st
->
priv_data
;
get_le32
(
pb
);
/* flags */
get_le16
(
pb
);
/* priority */
get_le16
(
pb
);
/* language */
get_le32
(
pb
);
/* initial frame */
get_le32
(
pb
);
/* scale */
rate
=
get_le32
(
pb
);
ast
->
scale
=
get_le32
(
pb
);
/* scale */
ast
->
rate
=
get_le32
(
pb
);
get_le32
(
pb
);
/* start */
length
=
get_le32
(
pb
);
/* length, in samples or bytes */
get_le32
(
pb
);
/* buffer size */
get_le32
(
pb
);
/* quality */
ast
->
sample_size
=
get_le32
(
pb
);
/* sample ssize */
st
->
start_time
=
0
;
if
(
rate
!=
0
)
st
->
duration
=
(
int64_t
)
length
*
AV_TIME_BASE
/
rate
;
url_fskip
(
pb
,
size
-
9
*
4
);
if
(
ast
->
rate
!=
0
)
st
->
duration
=
(
int64_t
)
length
*
AV_TIME_BASE
/
ast
->
rate
;
url_fskip
(
pb
,
size
-
12
*
4
);
}
break
;
default:
...
...
@@ -274,6 +304,9 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
url_fskip
(
pb
,
1
);
/* special case time: To support Xan DPCM, hardcode
* the format if Xxan is the video codec */
st
->
need_parsing
=
1
;
/* force parsing as several audio frames can be in
one packet */
if
(
xan_video
)
st
->
codec
.
codec_id
=
CODEC_ID_XAN_DPCM
;
break
;
...
...
@@ -377,10 +410,31 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
size
=
dv_produce_packet
(
avi
->
dv_demux
,
pkt
,
pkt
->
data
,
pkt
->
size
);
pkt
->
destruct
=
dstr
;
pkt
->
flags
|=
PKT_FLAG_KEY
;
}
else
{
AVStream
*
st
;
AVIStream
*
ast
;
st
=
s
->
streams
[
n
];
ast
=
st
->
priv_data
;
/* XXX: how to handle B frames in avi ? */
pkt
->
pts
=
((
int64_t
)
ast
->
frame_offset
*
ast
->
scale
*
AV_TIME_BASE
)
/
ast
->
rate
;
pkt
->
stream_index
=
n
;
pkt
->
flags
|=
PKT_FLAG_KEY
;
// FIXME: We really should read
// index for that
/* FIXME: We really should read index for that */
if
(
st
->
codec
.
codec_type
==
CODEC_TYPE_VIDEO
)
{
if
(
ast
->
frame_offset
<
ast
->
nb_index_entries
)
{
if
(
ast
->
index_entries
[
ast
->
frame_offset
].
flags
&
AVIIF_INDEX
)
pkt
->
flags
|=
PKT_FLAG_KEY
;
}
else
{
/* if no index, better to say that all frames
are key frames */
pkt
->
flags
|=
PKT_FLAG_KEY
;
}
ast
->
frame_offset
++
;
}
else
{
ast
->
frame_offset
+=
pkt
->
size
;
pkt
->
flags
|=
PKT_FLAG_KEY
;
}
}
return
size
;
}
...
...
@@ -388,6 +442,214 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
return
-
1
;
}
/* XXX: we make the implicit supposition that the position are sorted
for each stream */
static
int
avi_read_idx1
(
AVFormatContext
*
s
,
int
size
)
{
ByteIOContext
*
pb
=
&
s
->
pb
;
int
nb_index_entries
,
i
;
AVStream
*
st
;
AVIStream
*
ast
;
AVIIndexEntry
*
ie
,
*
entries
;
unsigned
int
index
,
tag
,
flags
,
pos
,
len
;
nb_index_entries
=
size
/
16
;
if
(
nb_index_entries
<=
0
)
return
-
1
;
/* read the entries and sort them in each stream component */
for
(
i
=
0
;
i
<
nb_index_entries
;
i
++
)
{
tag
=
get_le32
(
pb
);
flags
=
get_le32
(
pb
);
pos
=
get_le32
(
pb
);
len
=
get_le32
(
pb
);
#if defined(DEBUG_SEEK) && 0
printf
(
"%d: tag=0x%x flags=0x%x pos=0x%x len=%d
\n
"
,
i
,
tag
,
flags
,
pos
,
len
);
#endif
index
=
((
tag
&
0xff
)
-
'0'
)
*
10
;
index
+=
((
tag
>>
8
)
&
0xff
)
-
'0'
;
if
(
index
>=
s
->
nb_streams
)
continue
;
st
=
s
->
streams
[
index
];
ast
=
st
->
priv_data
;
entries
=
av_fast_realloc
(
ast
->
index_entries
,
&
ast
->
index_entries_allocated_size
,
(
ast
->
nb_index_entries
+
1
)
*
sizeof
(
AVIIndexEntry
));
if
(
entries
)
{
ast
->
index_entries
=
entries
;
ie
=
&
entries
[
ast
->
nb_index_entries
++
];
ie
->
flags
=
flags
;
ie
->
pos
=
pos
;
ie
->
cum_len
=
ast
->
cum_len
;
ast
->
cum_len
+=
len
;
}
}
return
0
;
}
static
int
avi_load_index
(
AVFormatContext
*
s
)
{
AVIContext
*
avi
=
s
->
priv_data
;
ByteIOContext
*
pb
=
&
s
->
pb
;
uint32_t
tag
,
size
;
url_fseek
(
pb
,
avi
->
movi_end
,
SEEK_SET
);
#ifdef DEBUG_SEEK
printf
(
"movi_end=0x%llx
\n
"
,
avi
->
movi_end
);
#endif
for
(;;)
{
if
(
url_feof
(
pb
))
break
;
tag
=
get_le32
(
pb
);
size
=
get_le32
(
pb
);
#ifdef DEBUG_SEEK
printf
(
"tag=%c%c%c%c size=0x%x
\n
"
,
tag
&
0xff
,
(
tag
>>
8
)
&
0xff
,
(
tag
>>
16
)
&
0xff
,
(
tag
>>
24
)
&
0xff
,
size
);
#endif
switch
(
tag
)
{
case
MKTAG
(
'i'
,
'd'
,
'x'
,
'1'
):
if
(
avi_read_idx1
(
s
,
size
)
<
0
)
goto
skip
;
else
goto
the_end
;
break
;
default:
skip:
size
+=
(
size
&
1
);
url_fskip
(
pb
,
size
);
break
;
}
}
the_end:
return
0
;
}
/* return the index entry whose position is immediately >= 'wanted_pos' */
static
int
locate_frame_in_index
(
AVIIndexEntry
*
entries
,
int
nb_entries
,
int
wanted_pos
)
{
int
a
,
b
,
m
,
pos
;
a
=
0
;
b
=
nb_entries
-
1
;
while
(
a
<=
b
)
{
m
=
(
a
+
b
)
>>
1
;
pos
=
entries
[
m
].
pos
;
if
(
pos
==
wanted_pos
)
goto
found
;
else
if
(
pos
>
wanted_pos
)
{
b
=
m
-
1
;
}
else
{
a
=
m
+
1
;
}
}
m
=
a
;
if
(
m
>
0
)
m
--
;
found:
return
m
;
}
static
int
avi_read_seek
(
AVFormatContext
*
s
,
int
stream_index
,
int64_t
timestamp
)
{
AVIContext
*
avi
=
s
->
priv_data
;
AVStream
*
st
;
AVIStream
*
ast
;
int
frame_number
,
i
;
int64_t
pos
;
if
(
!
avi
->
index_loaded
)
{
/* we only load the index on demand */
avi_load_index
(
s
);
avi
->
index_loaded
=
1
;
}
if
(
stream_index
<
0
)
{
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
st
=
s
->
streams
[
i
];
if
(
st
->
codec
.
codec_type
==
CODEC_TYPE_VIDEO
)
goto
found
;
}
return
-
1
;
found:
stream_index
=
i
;
}
st
=
s
->
streams
[
stream_index
];
if
(
st
->
codec
.
codec_type
!=
CODEC_TYPE_VIDEO
)
return
-
1
;
ast
=
st
->
priv_data
;
/* compute the frame number */
frame_number
=
(
timestamp
*
ast
->
rate
)
/
(
ast
->
scale
*
(
int64_t
)
AV_TIME_BASE
);
#ifdef DEBUG_SEEK
printf
(
"timestamp=%0.3f nb_indexes=%d frame_number=%d
\n
"
,
(
double
)
timestamp
/
AV_TIME_BASE
,
ast
->
nb_index_entries
,
frame_number
);
#endif
/* find a closest key frame before */
if
(
frame_number
>=
ast
->
nb_index_entries
)
return
-
1
;
while
(
frame_number
>=
0
&&
!
(
ast
->
index_entries
[
frame_number
].
flags
&
AVIIF_INDEX
))
frame_number
--
;
if
(
frame_number
<
0
)
return
-
1
;
ast
->
new_frame_offset
=
frame_number
;
/* find the position */
pos
=
ast
->
index_entries
[
frame_number
].
pos
;
#ifdef DEBUG_SEEK
printf
(
"key_frame_number=%d pos=0x%llx
\n
"
,
frame_number
,
pos
);
#endif
/* update the frame counters for all the other stream by looking
at the positions just after the one found */
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
int
j
;
if
(
i
!=
stream_index
)
{
st
=
s
->
streams
[
i
];
ast
=
st
->
priv_data
;
if
(
ast
->
nb_index_entries
<=
0
)
return
-
1
;
j
=
locate_frame_in_index
(
ast
->
index_entries
,
ast
->
nb_index_entries
,
pos
);
/* get next frame */
if
((
j
+
1
)
<
ast
->
nb_index_entries
)
j
++
;
/* extract the current frame number */
if
(
st
->
codec
.
codec_type
==
CODEC_TYPE_VIDEO
)
ast
->
new_frame_offset
=
j
;
else
ast
->
new_frame_offset
=
ast
->
index_entries
[
j
].
cum_len
;
}
}
/* everything is OK now. We can update the frame offsets */
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
st
=
s
->
streams
[
i
];
ast
=
st
->
priv_data
;
ast
->
frame_offset
=
ast
->
new_frame_offset
;
#ifdef DEBUG_SEEK
printf
(
"%d: frame_offset=%d
\n
"
,
i
,
ast
->
frame_offset
);
#endif
}
/* do the seek */
pos
+=
avi
->
movi_list
;
url_fseek
(
&
s
->
pb
,
pos
,
SEEK_SET
);
return
0
;
}
static
int
avi_read_close
(
AVFormatContext
*
s
)
{
int
i
;
...
...
@@ -395,7 +657,9 @@ static int avi_read_close(AVFormatContext *s)
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
AVStream
*
st
=
s
->
streams
[
i
];
// av_free(st->priv_data);
AVIStream
*
ast
=
st
->
priv_data
;
av_free
(
ast
->
index_entries
);
av_free
(
ast
);
av_free
(
st
->
codec
.
extradata
);
av_free
(
st
->
codec
.
palctrl
);
}
...
...
@@ -428,6 +692,7 @@ static AVInputFormat avi_iformat = {
avi_read_header
,
avi_read_packet
,
avi_read_close
,
avi_read_seek
,
};
int
avidec_init
(
void
)
...
...
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