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
d4c9eced
Commit
d4c9eced
authored
Jun 20, 2015
by
Rodger Combs
Committed by
Michael Niedermayer
Jun 20, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavf/brstm: support little-endian files (BCSTM; 3DS)
Signed-off-by:
Michael Niedermayer
<
michaelni@gmx.at
>
parent
8e7a06aa
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
63 additions
and
39 deletions
+63
-39
Changelog
Changelog
+1
-1
brstm.c
libavformat/brstm.c
+62
-38
No files found.
Changelog
View file @
d4c9eced
...
@@ -3,7 +3,7 @@ releases are sorted from youngest to oldest.
...
@@ -3,7 +3,7 @@ releases are sorted from youngest to oldest.
version <next>:
version <next>:
- colorkey video filter
- colorkey video filter
- BFSTM demuxer
- BFSTM
/BCSTM
demuxer
- little-endian ADPCM_THP decoder
- little-endian ADPCM_THP decoder
...
...
libavformat/brstm.c
View file @
d4c9eced
...
@@ -33,6 +33,7 @@ typedef struct BRSTMDemuxContext {
...
@@ -33,6 +33,7 @@ typedef struct BRSTMDemuxContext {
uint8_t
*
table
;
uint8_t
*
table
;
uint8_t
*
adpc
;
uint8_t
*
adpc
;
int
bfstm
;
int
bfstm
;
int
little_endian
;
}
BRSTMDemuxContext
;
}
BRSTMDemuxContext
;
static
int
probe
(
AVProbeData
*
p
)
static
int
probe
(
AVProbeData
*
p
)
...
@@ -46,7 +47,8 @@ static int probe(AVProbeData *p)
...
@@ -46,7 +47,8 @@ static int probe(AVProbeData *p)
static
int
probe_bfstm
(
AVProbeData
*
p
)
static
int
probe_bfstm
(
AVProbeData
*
p
)
{
{
if
(
AV_RL32
(
p
->
buf
)
==
MKTAG
(
'F'
,
'S'
,
'T'
,
'M'
)
&&
if
((
AV_RL32
(
p
->
buf
)
==
MKTAG
(
'F'
,
'S'
,
'T'
,
'M'
)
||
AV_RL32
(
p
->
buf
)
==
MKTAG
(
'C'
,
'S'
,
'T'
,
'M'
))
&&
(
AV_RL16
(
p
->
buf
+
4
)
==
0xFFFE
||
(
AV_RL16
(
p
->
buf
+
4
)
==
0xFFFE
||
AV_RL16
(
p
->
buf
+
4
)
==
0xFEFF
))
AV_RL16
(
p
->
buf
+
4
)
==
0xFEFF
))
return
AVPROBE_SCORE_MAX
/
3
*
2
;
return
AVPROBE_SCORE_MAX
/
3
*
2
;
...
@@ -63,6 +65,24 @@ static int read_close(AVFormatContext *s)
...
@@ -63,6 +65,24 @@ static int read_close(AVFormatContext *s)
return
0
;
return
0
;
}
}
static
av_always_inline
unsigned
int
read16
(
AVFormatContext
*
s
)
{
BRSTMDemuxContext
*
b
=
s
->
priv_data
;
if
(
b
->
little_endian
)
return
avio_rl16
(
s
->
pb
);
else
return
avio_rb16
(
s
->
pb
);
}
static
av_always_inline
unsigned
int
read32
(
AVFormatContext
*
s
)
{
BRSTMDemuxContext
*
b
=
s
->
priv_data
;
if
(
b
->
little_endian
)
return
avio_rl32
(
s
->
pb
);
else
return
avio_rb32
(
s
->
pb
);
}
static
int
read_header
(
AVFormatContext
*
s
)
static
int
read_header
(
AVFormatContext
*
s
)
{
{
BRSTMDemuxContext
*
b
=
s
->
priv_data
;
BRSTMDemuxContext
*
b
=
s
->
priv_data
;
...
@@ -86,16 +106,15 @@ static int read_header(AVFormatContext *s)
...
@@ -86,16 +106,15 @@ static int read_header(AVFormatContext *s)
av_log
(
s
,
AV_LOG_ERROR
,
"invalid byte order: %X
\n
"
,
bom
);
av_log
(
s
,
AV_LOG_ERROR
,
"invalid byte order: %X
\n
"
,
bom
);
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
}
}
if
(
bom
==
0xFFFE
)
{
avpriv_request_sample
(
s
,
"little endian byte order"
);
if
(
bom
==
0xFFFE
)
return
AVERROR_PATCHWELCOME
;
b
->
little_endian
=
1
;
}
if
(
!
b
->
bfstm
)
{
if
(
!
b
->
bfstm
)
{
major
=
avio_r8
(
s
->
pb
);
major
=
avio_r8
(
s
->
pb
);
minor
=
avio_r8
(
s
->
pb
);
minor
=
avio_r8
(
s
->
pb
);
avio_skip
(
s
->
pb
,
4
);
// size of file
avio_skip
(
s
->
pb
,
4
);
// size of file
size
=
avio_rb16
(
s
->
pb
);
size
=
read16
(
s
);
if
(
size
<
14
)
if
(
size
<
14
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
...
@@ -107,30 +126,31 @@ static int read_header(AVFormatContext *s)
...
@@ -107,30 +126,31 @@ static int read_header(AVFormatContext *s)
uint32_t
info_offset
=
0
,
info_size
;
uint32_t
info_offset
=
0
,
info_size
;
uint16_t
section_count
,
header_size
,
i
;
uint16_t
section_count
,
header_size
,
i
;
header_size
=
avio_rb16
(
s
->
pb
);
// 6
header_size
=
read16
(
s
);
// 6
avio_skip
(
s
->
pb
,
4
);
// Unknown constant 0x00030000
avio_skip
(
s
->
pb
,
4
);
// Unknown constant 0x00030000
avio_skip
(
s
->
pb
,
4
);
// size of file
avio_skip
(
s
->
pb
,
4
);
// size of file
section_count
=
avio_rb16
(
s
->
pb
);
section_count
=
read16
(
s
);
avio_skip
(
s
->
pb
,
2
);
// padding
avio_skip
(
s
->
pb
,
2
);
// padding
for
(
i
=
0
;
avio_tell
(
s
->
pb
)
<
header_size
for
(
i
=
0
;
avio_tell
(
s
->
pb
)
<
header_size
&&
!
(
data_offset
&&
info_offset
)
&&
!
(
data_offset
&&
info_offset
)
&&
i
<
section_count
;
i
++
)
{
&&
i
<
section_count
;
i
++
)
{
uint32_t
flag
=
avio_rb32
(
s
->
pb
);
uint16_t
flag
=
read16
(
s
);
avio_skip
(
s
->
pb
,
2
);
switch
(
flag
)
{
switch
(
flag
)
{
case
0x4000
0000
:
case
0x4000
:
info_offset
=
avio_rb32
(
s
->
pb
);
info_offset
=
read32
(
s
);
info_size
=
avio_rb32
(
s
->
pb
);
info_size
=
read32
(
s
);
break
;
break
;
case
0x4001
0000
:
case
0x4001
:
avio_skip
(
s
->
pb
,
4
);
// seek offset
avio_skip
(
s
->
pb
,
4
);
// seek offset
avio_skip
(
s
->
pb
,
4
);
// seek size
avio_skip
(
s
->
pb
,
4
);
// seek size
break
;
break
;
case
0x4002
0000
:
case
0x4002
:
data_offset
=
avio_rb32
(
s
->
pb
);
data_offset
=
read32
(
s
);
avio_skip
(
s
->
pb
,
4
);
//data_size =
avio_rb32(s->pb
);
avio_skip
(
s
->
pb
,
4
);
//data_size =
read32(s
);
break
;
break
;
case
0x4003
0000
:
case
0x4003
:
avio_skip
(
s
->
pb
,
4
);
// REGN offset
avio_skip
(
s
->
pb
,
4
);
// REGN offset
avio_skip
(
s
->
pb
,
4
);
// REGN size
avio_skip
(
s
->
pb
,
4
);
// REGN size
break
;
break
;
...
@@ -148,15 +168,15 @@ static int read_header(AVFormatContext *s)
...
@@ -148,15 +168,15 @@ static int read_header(AVFormatContext *s)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
}
}
size
=
avio_rb32
(
s
->
pb
);
size
=
read32
(
s
);
if
(
size
<
192
)
if
(
size
<
192
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
avio_skip
(
s
->
pb
,
4
);
// unknown
avio_skip
(
s
->
pb
,
4
);
// unknown
h1offset
=
avio_rb32
(
s
->
pb
);
h1offset
=
read32
(
s
);
if
(
h1offset
>
size
)
if
(
h1offset
>
size
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
avio_skip
(
s
->
pb
,
12
);
avio_skip
(
s
->
pb
,
12
);
toffset
=
avio_rb32
(
s
->
pb
)
+
16LL
;
toffset
=
read32
(
s
)
+
16LL
;
if
(
toffset
>
size
)
if
(
toffset
>
size
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
...
@@ -166,7 +186,9 @@ static int read_header(AVFormatContext *s)
...
@@ -166,7 +186,9 @@ static int read_header(AVFormatContext *s)
switch
(
codec
)
{
switch
(
codec
)
{
case
0
:
codec
=
AV_CODEC_ID_PCM_S8_PLANAR
;
break
;
case
0
:
codec
=
AV_CODEC_ID_PCM_S8_PLANAR
;
break
;
case
1
:
codec
=
AV_CODEC_ID_PCM_S16BE_PLANAR
;
break
;
case
1
:
codec
=
AV_CODEC_ID_PCM_S16BE_PLANAR
;
break
;
case
2
:
codec
=
AV_CODEC_ID_ADPCM_THP
;
break
;
case
2
:
codec
=
b
->
little_endian
?
AV_CODEC_ID_ADPCM_THP_LE
:
AV_CODEC_ID_ADPCM_THP
;
break
;
default:
default:
avpriv_request_sample
(
s
,
"codec %d"
,
codec
);
avpriv_request_sample
(
s
,
"codec %d"
,
codec
);
return
AVERROR_PATCHWELCOME
;
return
AVERROR_PATCHWELCOME
;
...
@@ -179,10 +201,8 @@ static int read_header(AVFormatContext *s)
...
@@ -179,10 +201,8 @@ static int read_header(AVFormatContext *s)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
avio_skip
(
s
->
pb
,
1
);
// padding
avio_skip
(
s
->
pb
,
1
);
// padding
if
(
b
->
bfstm
)
avio_skip
(
s
->
pb
,
2
);
// padding
st
->
codec
->
sample_rate
=
avio_rb16
(
s
->
pb
);
st
->
codec
->
sample_rate
=
b
->
bfstm
?
read32
(
s
)
:
read16
(
s
);
if
(
!
st
->
codec
->
sample_rate
)
if
(
!
st
->
codec
->
sample_rate
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
...
@@ -190,25 +210,25 @@ static int read_header(AVFormatContext *s)
...
@@ -190,25 +210,25 @@ static int read_header(AVFormatContext *s)
avio_skip
(
s
->
pb
,
2
);
// padding
avio_skip
(
s
->
pb
,
2
);
// padding
avio_skip
(
s
->
pb
,
4
);
// loop start sample
avio_skip
(
s
->
pb
,
4
);
// loop start sample
st
->
start_time
=
0
;
st
->
start_time
=
0
;
st
->
duration
=
avio_rb32
(
s
->
pb
);
st
->
duration
=
read32
(
s
);
avpriv_set_pts_info
(
st
,
64
,
1
,
st
->
codec
->
sample_rate
);
avpriv_set_pts_info
(
st
,
64
,
1
,
st
->
codec
->
sample_rate
);
if
(
!
b
->
bfstm
)
if
(
!
b
->
bfstm
)
start
=
avio_rb32
(
s
->
pb
);
start
=
read32
(
s
);
b
->
current_block
=
0
;
b
->
current_block
=
0
;
b
->
block_count
=
avio_rb32
(
s
->
pb
);
b
->
block_count
=
read32
(
s
);
if
(
b
->
block_count
>
UINT16_MAX
)
{
if
(
b
->
block_count
>
UINT16_MAX
)
{
av_log
(
s
,
AV_LOG_WARNING
,
"too many blocks: %u
\n
"
,
b
->
block_count
);
av_log
(
s
,
AV_LOG_WARNING
,
"too many blocks: %u
\n
"
,
b
->
block_count
);
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
}
}
b
->
block_size
=
avio_rb32
(
s
->
pb
);
b
->
block_size
=
read32
(
s
);
if
(
b
->
block_size
>
UINT16_MAX
/
st
->
codec
->
channels
)
if
(
b
->
block_size
>
UINT16_MAX
/
st
->
codec
->
channels
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
b
->
block_size
*=
st
->
codec
->
channels
;
b
->
block_size
*=
st
->
codec
->
channels
;
b
->
samples_per_block
=
avio_rb32
(
s
->
pb
);
b
->
samples_per_block
=
read32
(
s
);
b
->
last_block_used_bytes
=
avio_rb32
(
s
->
pb
);
b
->
last_block_used_bytes
=
read32
(
s
);
if
(
b
->
last_block_used_bytes
>
UINT16_MAX
/
st
->
codec
->
channels
)
if
(
b
->
last_block_used_bytes
>
UINT16_MAX
/
st
->
codec
->
channels
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
b
->
last_block_used_bytes
*=
st
->
codec
->
channels
;
b
->
last_block_used_bytes
*=
st
->
codec
->
channels
;
...
@@ -216,14 +236,14 @@ static int read_header(AVFormatContext *s)
...
@@ -216,14 +236,14 @@ static int read_header(AVFormatContext *s)
avio_skip
(
s
->
pb
,
4
);
// last block samples
avio_skip
(
s
->
pb
,
4
);
// last block samples
avio_skip
(
s
->
pb
,
4
);
// last block size
avio_skip
(
s
->
pb
,
4
);
// last block size
if
(
codec
==
AV_CODEC_ID_ADPCM_THP
)
{
if
(
codec
==
AV_CODEC_ID_ADPCM_THP
||
codec
==
AV_CODEC_ID_ADPCM_THP_LE
)
{
int
ch
;
int
ch
;
avio_skip
(
s
->
pb
,
pos
+
toffset
-
avio_tell
(
s
->
pb
));
avio_skip
(
s
->
pb
,
pos
+
toffset
-
avio_tell
(
s
->
pb
));
if
(
!
b
->
bfstm
)
if
(
!
b
->
bfstm
)
toffset
=
avio_rb32
(
s
->
pb
)
+
16LL
;
toffset
=
read32
(
s
)
+
16LL
;
else
else
toffset
=
toffset
+
avio_rb32
(
s
->
pb
)
+
st
->
codec
->
channels
*
8
-
8
;
toffset
=
toffset
+
read32
(
s
)
+
st
->
codec
->
channels
*
8
-
8
;
if
(
toffset
>
size
)
if
(
toffset
>
size
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
...
@@ -261,7 +281,7 @@ static int read_header(AVFormatContext *s)
...
@@ -261,7 +281,7 @@ static int read_header(AVFormatContext *s)
while
(
!
avio_feof
(
s
->
pb
))
{
while
(
!
avio_feof
(
s
->
pb
))
{
chunk
=
avio_rl32
(
s
->
pb
);
chunk
=
avio_rl32
(
s
->
pb
);
size
=
avio_rb32
(
s
->
pb
);
size
=
read32
(
s
);
if
(
size
<
8
)
{
if
(
size
<
8
)
{
ret
=
AVERROR_INVALIDDATA
;
ret
=
AVERROR_INVALIDDATA
;
goto
fail
;
goto
fail
;
...
@@ -269,7 +289,8 @@ static int read_header(AVFormatContext *s)
...
@@ -269,7 +289,8 @@ static int read_header(AVFormatContext *s)
size
-=
8
;
size
-=
8
;
switch
(
chunk
)
{
switch
(
chunk
)
{
case
MKTAG
(
'A'
,
'D'
,
'P'
,
'C'
):
case
MKTAG
(
'A'
,
'D'
,
'P'
,
'C'
):
if
(
codec
!=
AV_CODEC_ID_ADPCM_THP
)
if
(
codec
!=
AV_CODEC_ID_ADPCM_THP
&&
codec
!=
AV_CODEC_ID_ADPCM_THP_LE
)
goto
skip
;
goto
skip
;
asize
=
b
->
block_count
*
st
->
codec
->
channels
*
4
;
asize
=
b
->
block_count
*
st
->
codec
->
channels
*
4
;
...
@@ -292,7 +313,9 @@ static int read_header(AVFormatContext *s)
...
@@ -292,7 +313,9 @@ static int read_header(AVFormatContext *s)
break
;
break
;
case
MKTAG
(
'D'
,
'A'
,
'T'
,
'A'
):
case
MKTAG
(
'D'
,
'A'
,
'T'
,
'A'
):
if
((
start
<
avio_tell
(
s
->
pb
))
||
if
((
start
<
avio_tell
(
s
->
pb
))
||
(
!
b
->
adpc
&&
codec
==
AV_CODEC_ID_ADPCM_THP
&&
!
b
->
bfstm
))
{
(
!
b
->
adpc
&&
(
codec
==
AV_CODEC_ID_ADPCM_THP
||
codec
==
AV_CODEC_ID_ADPCM_THP_LE
)
&&
!
b
->
bfstm
))
{
ret
=
AVERROR_INVALIDDATA
;
ret
=
AVERROR_INVALIDDATA
;
goto
fail
;
goto
fail
;
}
}
...
@@ -335,7 +358,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
...
@@ -335,7 +358,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
return
AVERROR_EOF
;
return
AVERROR_EOF
;
}
}
if
(
codec
->
codec_id
==
AV_CODEC_ID_ADPCM_THP
&&
!
codec
->
extradata
)
{
if
((
codec
->
codec_id
==
AV_CODEC_ID_ADPCM_THP
||
codec
->
codec_id
==
AV_CODEC_ID_ADPCM_THP_LE
)
&&
!
codec
->
extradata
)
{
uint8_t
*
dst
;
uint8_t
*
dst
;
if
(
av_new_packet
(
pkt
,
8
+
(
32
+
4
)
*
codec
->
channels
+
size
)
<
0
)
if
(
av_new_packet
(
pkt
,
8
+
(
32
+
4
)
*
codec
->
channels
+
size
)
<
0
)
...
@@ -382,5 +406,5 @@ AVInputFormat ff_bfstm_demuxer = {
...
@@ -382,5 +406,5 @@ AVInputFormat ff_bfstm_demuxer = {
.
read_header
=
read_header
,
.
read_header
=
read_header
,
.
read_packet
=
read_packet
,
.
read_packet
=
read_packet
,
.
read_close
=
read_close
,
.
read_close
=
read_close
,
.
extensions
=
"bfstm"
,
.
extensions
=
"bfstm
,bcstm
"
,
};
};
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