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
4ab56667
Commit
4ab56667
authored
Jul 20, 2015
by
Rodger Combs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavf/mov: add support for sidx fragment indexes
Fixes trac #3842
parent
cd847839
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
208 additions
and
39 deletions
+208
-39
isom.h
libavformat/isom.h
+2
-0
mov.c
libavformat/mov.c
+206
-39
No files found.
libavformat/isom.h
View file @
4ab56667
...
...
@@ -103,6 +103,7 @@ typedef struct MOVSbgp {
typedef
struct
MOVFragmentIndexItem
{
int64_t
moof_offset
;
int64_t
time
;
int
headers_read
;
}
MOVFragmentIndexItem
;
typedef
struct
MOVFragmentIndex
{
...
...
@@ -197,6 +198,7 @@ typedef struct MOVContext {
int
has_looked_for_mfra
;
MOVFragmentIndex
**
fragment_index_data
;
unsigned
fragment_index_count
;
int
fragment_index_complete
;
int
atom_depth
;
unsigned
int
aax_mode
;
///< 'aax' file has been detected
uint8_t
file_key
[
20
];
...
...
libavformat/mov.c
View file @
4ab56667
...
...
@@ -3349,7 +3349,7 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
MOVFragment
*
frag
=
&
c
->
fragment
;
MOVTrackExt
*
trex
=
NULL
;
MOVFragmentIndex
*
index
=
NULL
;
int
flags
,
track_id
,
i
;
int
flags
,
track_id
,
i
,
found
=
0
;
avio_r8
(
pb
);
/* version */
flags
=
avio_rb24
(
pb
);
...
...
@@ -3367,15 +3367,6 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_log
(
c
->
fc
,
AV_LOG_ERROR
,
"could not find corresponding trex
\n
"
);
return
AVERROR_INVALIDDATA
;
}
for
(
i
=
0
;
i
<
c
->
fragment_index_count
;
i
++
)
{
MOVFragmentIndex
*
candidate
=
c
->
fragment_index_data
[
i
];
if
(
candidate
->
track_id
==
frag
->
track_id
)
{
av_log
(
c
->
fc
,
AV_LOG_DEBUG
,
"found fragment index for track %u
\n
"
,
frag
->
track_id
);
index
=
candidate
;
break
;
}
}
frag
->
base_data_offset
=
flags
&
MOV_TFHD_BASE_DATA_OFFSET
?
avio_rb64
(
pb
)
:
flags
&
MOV_TFHD_DEFAULT_BASE_IS_MOOF
?
...
...
@@ -3389,24 +3380,33 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
frag
->
flags
=
flags
&
MOV_TFHD_DEFAULT_FLAGS
?
avio_rb32
(
pb
)
:
trex
->
flags
;
frag
->
time
=
AV_NOPTS_VALUE
;
if
(
index
)
{
int
i
,
found
=
0
;
for
(
i
=
index
->
current_item
;
i
<
index
->
item_count
;
i
++
)
{
if
(
frag
->
implicit_offset
==
index
->
items
[
i
].
moof_offset
)
{
av_log
(
c
->
fc
,
AV_LOG_DEBUG
,
"found fragment index entry "
"for track %u and moof_offset %"
PRId64
"
\n
"
,
frag
->
track_id
,
index
->
items
[
i
].
moof_offset
);
frag
->
time
=
index
->
items
[
i
].
time
;
index
->
current_item
=
i
+
1
;
found
=
1
;
for
(
i
=
0
;
i
<
c
->
fragment_index_count
;
i
++
)
{
int
j
;
MOVFragmentIndex
*
candidate
=
c
->
fragment_index_data
[
i
];
if
(
candidate
->
track_id
==
frag
->
track_id
)
{
av_log
(
c
->
fc
,
AV_LOG_DEBUG
,
"found fragment index for track %u
\n
"
,
frag
->
track_id
);
index
=
candidate
;
for
(
j
=
index
->
current_item
;
j
<
index
->
item_count
;
j
++
)
{
if
(
frag
->
implicit_offset
==
index
->
items
[
j
].
moof_offset
)
{
av_log
(
c
->
fc
,
AV_LOG_DEBUG
,
"found fragment index entry "
"for track %u and moof_offset %"
PRId64
"
\n
"
,
frag
->
track_id
,
index
->
items
[
j
].
moof_offset
);
frag
->
time
=
index
->
items
[
j
].
time
;
index
->
current_item
=
j
+
1
;
found
=
1
;
break
;
}
}
}
if
(
!
found
)
{
av_log
(
c
->
fc
,
AV_LOG_WARNING
,
"track %u has a fragment index "
"but it doesn't have an (in-order) entry for moof_offset "
"%"
PRId64
"
\n
"
,
frag
->
track_id
,
frag
->
implicit_offset
);
if
(
found
)
break
;
}
}
if
(
index
&&
!
found
)
{
av_log
(
c
->
fc
,
AV_LOG_DEBUG
,
"track %u has a fragment index but "
"it doesn't have an (in-order) entry for moof_offset "
"%"
PRId64
"
\n
"
,
frag
->
track_id
,
frag
->
implicit_offset
);
}
av_log
(
c
->
fc
,
AV_LOG_TRACE
,
"frag flags 0x%x
\n
"
,
frag
->
flags
);
return
0
;
}
...
...
@@ -3596,7 +3596,106 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return
AVERROR_EOF
;
frag
->
implicit_offset
=
offset
;
st
->
duration
=
sc
->
track_end
=
dts
+
sc
->
time_offset
;
sc
->
track_end
=
dts
+
sc
->
time_offset
;
if
(
st
->
duration
<
sc
->
track_end
)
st
->
duration
=
sc
->
track_end
;
return
0
;
}
static
int
mov_read_sidx
(
MOVContext
*
c
,
AVIOContext
*
pb
,
MOVAtom
atom
)
{
int64_t
offset
=
avio_tell
(
pb
)
+
atom
.
size
,
pts
;
uint8_t
version
;
unsigned
i
,
track_id
;
AVStream
*
st
=
NULL
;
MOVStreamContext
*
sc
;
MOVFragmentIndex
*
index
=
NULL
;
MOVFragmentIndex
**
tmp
;
AVRational
timescale
;
version
=
avio_r8
(
pb
);
if
(
version
>
1
)
{
avpriv_request_sample
(
c
->
fc
,
"sidx version %u"
,
version
);
return
AVERROR_PATCHWELCOME
;
}
avio_rb24
(
pb
);
// flags
track_id
=
avio_rb32
(
pb
);
// Reference ID
for
(
i
=
0
;
i
<
c
->
fc
->
nb_streams
;
i
++
)
{
if
(
c
->
fc
->
streams
[
i
]
->
id
==
track_id
)
{
st
=
c
->
fc
->
streams
[
i
];
break
;
}
}
if
(
!
st
)
{
av_log
(
c
->
fc
,
AV_LOG_ERROR
,
"could not find corresponding track id %d
\n
"
,
track_id
);
return
AVERROR_INVALIDDATA
;
}
sc
=
st
->
priv_data
;
timescale
=
av_make_q
(
1
,
avio_rb32
(
pb
));
if
(
version
==
0
)
{
pts
=
avio_rb32
(
pb
);
offset
+=
avio_rb32
(
pb
);
}
else
{
pts
=
avio_rb64
(
pb
);
offset
+=
avio_rb64
(
pb
);
}
avio_rb16
(
pb
);
// reserved
index
=
av_mallocz
(
sizeof
(
MOVFragmentIndex
));
if
(
!
index
)
return
AVERROR
(
ENOMEM
);
index
->
track_id
=
track_id
;
index
->
item_count
=
avio_rb16
(
pb
);
index
->
items
=
av_mallocz_array
(
index
->
item_count
,
sizeof
(
MOVFragmentIndexItem
));
if
(
!
index
->
items
)
{
av_freep
(
&
index
);
return
AVERROR
(
ENOMEM
);
}
for
(
i
=
0
;
i
<
index
->
item_count
;
i
++
)
{
uint32_t
size
=
avio_rb32
(
pb
);
uint32_t
duration
=
avio_rb32
(
pb
);
if
(
size
&
0x80000000
)
{
avpriv_request_sample
(
c
->
fc
,
"sidx reference_type 1"
);
av_freep
(
&
index
->
items
);
av_freep
(
&
index
);
return
AVERROR_PATCHWELCOME
;
}
avio_rb32
(
pb
);
// sap_flags
index
->
items
[
i
].
moof_offset
=
offset
;
index
->
items
[
i
].
time
=
av_rescale_q
(
pts
,
st
->
time_base
,
timescale
);
offset
+=
size
;
pts
+=
duration
;
}
st
->
duration
=
sc
->
track_end
=
pts
;
tmp
=
av_realloc_array
(
c
->
fragment_index_data
,
c
->
fragment_index_count
+
1
,
sizeof
(
MOVFragmentIndex
*
));
if
(
!
tmp
)
{
av_freep
(
&
index
->
items
);
av_freep
(
&
index
);
return
AVERROR
(
ENOMEM
);
}
c
->
fragment_index_data
=
tmp
;
c
->
fragment_index_data
[
c
->
fragment_index_count
++
]
=
index
;
if
(
offset
==
avio_size
(
pb
))
c
->
fragment_index_complete
=
1
;
return
0
;
}
...
...
@@ -3854,6 +3953,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{
MKTAG
(
'a'
,
'l'
,
'a'
,
'c'
),
mov_read_alac
},
/* alac specific atom */
{
MKTAG
(
'a'
,
'v'
,
'c'
,
'C'
),
mov_read_glbl
},
{
MKTAG
(
'p'
,
'a'
,
's'
,
'p'
),
mov_read_pasp
},
{
MKTAG
(
's'
,
'i'
,
'd'
,
'x'
),
mov_read_sidx
},
{
MKTAG
(
's'
,
't'
,
'b'
,
'l'
),
mov_read_default
},
{
MKTAG
(
's'
,
't'
,
'c'
,
'o'
),
mov_read_stco
},
{
MKTAG
(
's'
,
't'
,
'p'
,
's'
),
mov_read_stps
},
...
...
@@ -3978,9 +4078,9 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return
err
;
}
if
(
c
->
found_moov
&&
c
->
found_mdat
&&
((
!
pb
->
seekable
||
c
->
fc
->
flags
&
AVFMT_FLAG_IGNIDX
)
||
((
!
pb
->
seekable
||
c
->
fc
->
flags
&
AVFMT_FLAG_IGNIDX
||
c
->
fragment_index_complete
)
||
start_pos
+
a
.
size
==
avio_size
(
pb
)))
{
if
(
!
pb
->
seekable
||
c
->
fc
->
flags
&
AVFMT_FLAG_IGNIDX
)
if
(
!
pb
->
seekable
||
c
->
fc
->
flags
&
AVFMT_FLAG_IGNIDX
||
c
->
fragment_index_complete
)
c
->
next_root_atom
=
start_pos
+
a
.
size
;
c
->
atom_depth
--
;
return
0
;
...
...
@@ -4585,6 +4685,52 @@ static int should_retry(AVIOContext *pb, int error_code) {
return
1
;
}
static
int
mov_switch_root
(
AVFormatContext
*
s
,
int64_t
target
)
{
MOVContext
*
mov
=
s
->
priv_data
;
int
i
,
j
;
int
already_read
=
0
;
if
(
avio_seek
(
s
->
pb
,
target
,
SEEK_SET
)
!=
target
)
{
av_log
(
mov
->
fc
,
AV_LOG_ERROR
,
"root atom offset 0x%"
PRIx64
": partial file
\n
"
,
target
);
return
AVERROR_INVALIDDATA
;
}
mov
->
next_root_atom
=
0
;
for
(
i
=
0
;
i
<
mov
->
fragment_index_count
;
i
++
)
{
MOVFragmentIndex
*
index
=
mov
->
fragment_index_data
[
i
];
int
found
=
0
;
for
(
j
=
0
;
j
<
index
->
item_count
;
j
++
)
{
MOVFragmentIndexItem
*
item
=
&
index
->
items
[
j
];
if
(
found
)
{
mov
->
next_root_atom
=
item
->
moof_offset
;
break
;
// Advance to next index in outer loop
}
else
if
(
item
->
moof_offset
==
target
)
{
index
->
current_item
=
FFMIN
(
j
,
index
->
current_item
);
if
(
item
->
headers_read
)
already_read
=
1
;
item
->
headers_read
=
1
;
found
=
1
;
}
}
if
(
!
found
)
index
->
current_item
=
0
;
}
if
(
already_read
)
return
0
;
mov
->
found_mdat
=
0
;
if
(
mov_read_default
(
mov
,
s
->
pb
,
(
MOVAtom
){
AV_RL32
(
"root"
),
INT64_MAX
})
<
0
||
avio_feof
(
s
->
pb
))
return
AVERROR_EOF
;
av_log
(
s
,
AV_LOG_TRACE
,
"read fragments, offset 0x%"
PRIx64
"
\n
"
,
avio_tell
(
s
->
pb
));
return
1
;
}
static
int
mov_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
{
MOVContext
*
mov
=
s
->
priv_data
;
...
...
@@ -4595,19 +4741,11 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
mov
->
fc
=
s
;
retry:
sample
=
mov_find_next_sample
(
s
,
&
st
);
if
(
!
sample
)
{
mov
->
found_mdat
=
0
;
if
(
!
sample
||
(
mov
->
next_root_atom
&&
sample
->
pos
>
mov
->
next_root_atom
))
{
if
(
!
mov
->
next_root_atom
)
return
AVERROR_EOF
;
if
(
avio_seek
(
s
->
pb
,
mov
->
next_root_atom
,
SEEK_SET
)
!=
mov
->
next_root_atom
)
{
av_log
(
mov
->
fc
,
AV_LOG_ERROR
,
"next root atom offset 0x%"
PRIx64
": partial file
\n
"
,
mov
->
next_root_atom
);
return
AVERROR_INVALIDDATA
;
}
mov
->
next_root_atom
=
0
;
if
(
mov_read_default
(
mov
,
s
->
pb
,
(
MOVAtom
){
AV_RL32
(
"root"
),
INT64_MAX
})
<
0
||
avio_feof
(
s
->
pb
))
return
AVERROR_EOF
;
av_log
(
s
,
AV_LOG_TRACE
,
"read fragments, offset 0x%"
PRIx64
"
\n
"
,
avio_tell
(
s
->
pb
));
if
((
ret
=
mov_switch_root
(
s
,
mov
->
next_root_atom
))
<
0
)
return
ret
;
goto
retry
;
}
sc
=
st
->
priv_data
;
...
...
@@ -4685,12 +4823,41 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
return
0
;
}
static
int
mov_seek_fragment
(
AVFormatContext
*
s
,
AVStream
*
st
,
int64_t
timestamp
)
{
MOVContext
*
mov
=
s
->
priv_data
;
int
i
,
j
;
if
(
!
mov
->
fragment_index_complete
)
return
0
;
for
(
i
=
0
;
i
<
mov
->
fragment_index_count
;
i
++
)
{
if
(
mov
->
fragment_index_data
[
i
]
->
track_id
==
st
->
id
)
{
MOVFragmentIndex
*
index
=
index
=
mov
->
fragment_index_data
[
i
];
for
(
j
=
index
->
item_count
-
1
;
j
>=
0
;
j
--
)
{
if
(
index
->
items
[
j
].
time
<=
timestamp
)
{
if
(
index
->
items
[
j
].
headers_read
)
return
0
;
return
mov_switch_root
(
s
,
index
->
items
[
j
].
moof_offset
);
}
}
}
}
return
0
;
}
static
int
mov_seek_stream
(
AVFormatContext
*
s
,
AVStream
*
st
,
int64_t
timestamp
,
int
flags
)
{
MOVStreamContext
*
sc
=
st
->
priv_data
;
int
sample
,
time_sample
;
int
i
;
int
ret
=
mov_seek_fragment
(
s
,
st
,
timestamp
);
if
(
ret
<
0
)
return
ret
;
sample
=
av_index_search_timestamp
(
st
,
timestamp
,
flags
);
av_log
(
s
,
AV_LOG_TRACE
,
"stream %d, timestamp %"
PRId64
", sample %d
\n
"
,
st
->
index
,
timestamp
,
sample
);
if
(
sample
<
0
&&
st
->
nb_index_entries
&&
timestamp
<
st
->
index_entries
[
0
].
timestamp
)
...
...
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