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
e4529df9
Commit
e4529df9
authored
Jul 31, 2013
by
Diego Biurrun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
flvdec: K&R formatting cosmetics
parent
390b4d70
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
386 additions
and
323 deletions
+386
-323
flvdec.c
libavformat/flvdec.c
+386
-323
No files found.
libavformat/flvdec.c
View file @
e4529df9
...
...
@@ -64,7 +64,11 @@ static int flv_probe(AVProbeData *p)
const
uint8_t
*
d
;
d
=
p
->
buf
;
if
(
d
[
0
]
==
'F'
&&
d
[
1
]
==
'L'
&&
d
[
2
]
==
'V'
&&
d
[
3
]
<
5
&&
d
[
5
]
==
0
&&
AV_RB32
(
d
+
5
)
>
8
)
{
if
(
d
[
0
]
==
'F'
&&
d
[
1
]
==
'L'
&&
d
[
2
]
==
'V'
&&
d
[
3
]
<
5
&&
d
[
5
]
==
0
&&
AV_RB32
(
d
+
5
)
>
8
)
{
return
AVPROBE_SCORE_MAX
;
}
return
0
;
...
...
@@ -79,6 +83,7 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type)
avpriv_set_pts_info
(
st
,
32
,
1
,
1000
);
/* 32 bit pts in ms */
return
st
;
}
static
int
flv_same_audio_codec
(
AVCodecContext
*
acodec
,
int
flags
)
{
int
bits_per_coded_sample
=
(
flags
&
FLV_AUDIO_SAMPLESIZE_MASK
)
?
16
:
8
;
...
...
@@ -91,18 +96,21 @@ static int flv_same_audio_codec(AVCodecContext *acodec, int flags)
if
(
acodec
->
bits_per_coded_sample
!=
bits_per_coded_sample
)
return
0
;
switch
(
flv_codecid
)
{
//
no distinction between S16 and S8 PCM codec flags
switch
(
flv_codecid
)
{
//
no distinction between S16 and S8 PCM codec flags
case
FLV_CODECID_PCM
:
codec_id
=
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
:
codec_id
=
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
#if HAVE_BIGENDIAN
AV_CODEC_ID_PCM_S16BE
;
:
AV_CODEC_ID_PCM_S16BE
;
#else
AV_CODEC_ID_PCM_S16LE
;
:
AV_CODEC_ID_PCM_S16LE
;
#endif
return
codec_id
==
acodec
->
codec_id
;
case
FLV_CODECID_PCM_LE
:
codec_id
=
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
:
AV_CODEC_ID_PCM_S16LE
;
codec_id
=
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
:
AV_CODEC_ID_PCM_S16LE
;
return
codec_id
==
acodec
->
codec_id
;
case
FLV_CODECID_AAC
:
return
acodec
->
codec_id
==
AV_CODEC_ID_AAC
;
...
...
@@ -127,28 +135,42 @@ static int flv_same_audio_codec(AVCodecContext *acodec, int flags)
}
}
static
void
flv_set_audio_codec
(
AVFormatContext
*
s
,
AVStream
*
astream
,
AVCodecContext
*
acodec
,
int
flv_codecid
)
{
switch
(
flv_codecid
)
{
//no distinction between S16 and S8 PCM codec flags
static
void
flv_set_audio_codec
(
AVFormatContext
*
s
,
AVStream
*
astream
,
AVCodecContext
*
acodec
,
int
flv_codecid
)
{
switch
(
flv_codecid
)
{
// no distinction between S16 and S8 PCM codec flags
case
FLV_CODECID_PCM
:
acodec
->
codec_id
=
acodec
->
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
:
acodec
->
codec_id
=
acodec
->
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
#if HAVE_BIGENDIAN
AV_CODEC_ID_PCM_S16BE
;
:
AV_CODEC_ID_PCM_S16BE
;
#else
AV_CODEC_ID_PCM_S16LE
;
:
AV_CODEC_ID_PCM_S16LE
;
#endif
break
;
case
FLV_CODECID_PCM_LE
:
acodec
->
codec_id
=
acodec
->
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
:
AV_CODEC_ID_PCM_S16LE
;
break
;
case
FLV_CODECID_AAC
:
acodec
->
codec_id
=
AV_CODEC_ID_AAC
;
break
;
case
FLV_CODECID_ADPCM
:
acodec
->
codec_id
=
AV_CODEC_ID_ADPCM_SWF
;
break
;
acodec
->
codec_id
=
acodec
->
bits_per_coded_sample
==
8
?
AV_CODEC_ID_PCM_U8
:
AV_CODEC_ID_PCM_S16LE
;
break
;
case
FLV_CODECID_AAC
:
acodec
->
codec_id
=
AV_CODEC_ID_AAC
;
break
;
case
FLV_CODECID_ADPCM
:
acodec
->
codec_id
=
AV_CODEC_ID_ADPCM_SWF
;
break
;
case
FLV_CODECID_SPEEX
:
acodec
->
codec_id
=
AV_CODEC_ID_SPEEX
;
acodec
->
sample_rate
=
16000
;
break
;
case
FLV_CODECID_MP3
:
acodec
->
codec_id
=
AV_CODEC_ID_MP3
;
astream
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
break
;
case
FLV_CODECID_MP3
:
acodec
->
codec_id
=
AV_CODEC_ID_MP3
;
astream
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
break
;
case
FLV_CODECID_NELLYMOSER_8KHZ_MONO
:
acodec
->
sample_rate
=
8000
;
//in case metadata does not otherwise declare samplerate
// in case metadata does not otherwise declare samplerate
acodec
->
sample_rate
=
8000
;
acodec
->
codec_id
=
AV_CODEC_ID_NELLYMOSER
;
break
;
case
FLV_CODECID_NELLYMOSER_16KHZ_MONO
:
...
...
@@ -167,7 +189,8 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecCo
acodec
->
codec_id
=
AV_CODEC_ID_PCM_ALAW
;
break
;
default:
av_log
(
s
,
AV_LOG_INFO
,
"Unsupported audio codec (%x)
\n
"
,
flv_codecid
>>
FLV_AUDIO_CODECID_OFFSET
);
av_log
(
s
,
AV_LOG_INFO
,
"Unsupported audio codec (%x)
\n
"
,
flv_codecid
>>
FLV_AUDIO_CODECID_OFFSET
);
acodec
->
codec_tag
=
flv_codecid
>>
FLV_AUDIO_CODECID_OFFSET
;
}
}
...
...
@@ -197,15 +220,24 @@ static int flv_same_video_codec(AVCodecContext *vcodec, int flags)
}
}
static
int
flv_set_video_codec
(
AVFormatContext
*
s
,
AVStream
*
vstream
,
int
flv_codecid
,
int
read
)
{
static
int
flv_set_video_codec
(
AVFormatContext
*
s
,
AVStream
*
vstream
,
int
flv_codecid
,
int
read
)
{
AVCodecContext
*
vcodec
=
vstream
->
codec
;
switch
(
flv_codecid
)
{
case
FLV_CODECID_H263
:
vcodec
->
codec_id
=
AV_CODEC_ID_FLV1
;
break
;
case
FLV_CODECID_SCREEN
:
vcodec
->
codec_id
=
AV_CODEC_ID_FLASHSV
;
break
;
case
FLV_CODECID_SCREEN2
:
vcodec
->
codec_id
=
AV_CODEC_ID_FLASHSV2
;
break
;
case
FLV_CODECID_VP6
:
vcodec
->
codec_id
=
AV_CODEC_ID_VP6F
;
case
FLV_CODECID_VP6A
:
if
(
flv_codecid
==
FLV_CODECID_VP6A
)
switch
(
flv_codecid
)
{
case
FLV_CODECID_H263
:
vcodec
->
codec_id
=
AV_CODEC_ID_FLV1
;
break
;
case
FLV_CODECID_SCREEN
:
vcodec
->
codec_id
=
AV_CODEC_ID_FLASHSV
;
break
;
case
FLV_CODECID_SCREEN2
:
vcodec
->
codec_id
=
AV_CODEC_ID_FLASHSV2
;
break
;
case
FLV_CODECID_VP6
:
vcodec
->
codec_id
=
AV_CODEC_ID_VP6F
;
case
FLV_CODECID_VP6A
:
if
(
flv_codecid
==
FLV_CODECID_VP6A
)
vcodec
->
codec_id
=
AV_CODEC_ID_VP6A
;
if
(
read
)
{
if
(
vcodec
->
extradata_size
!=
1
)
{
...
...
@@ -230,9 +262,10 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_co
return
0
;
}
static
int
amf_get_string
(
AVIOContext
*
ioc
,
char
*
buffer
,
int
buffsize
)
{
static
int
amf_get_string
(
AVIOContext
*
ioc
,
char
*
buffer
,
int
buffsize
)
{
int
length
=
avio_rb16
(
ioc
);
if
(
length
>=
buffsize
)
{
if
(
length
>=
buffsize
)
{
avio_skip
(
ioc
,
length
);
return
-
1
;
}
...
...
@@ -244,7 +277,9 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) {
return
length
;
}
static
int
parse_keyframes_index
(
AVFormatContext
*
s
,
AVIOContext
*
ioc
,
AVStream
*
vstream
,
int64_t
max_pos
)
{
static
int
parse_keyframes_index
(
AVFormatContext
*
s
,
AVIOContext
*
ioc
,
AVStream
*
vstream
,
int64_t
max_pos
)
{
FLVContext
*
flv
=
s
->
priv_data
;
unsigned
int
arraylen
=
0
,
timeslen
=
0
,
fileposlen
=
0
,
i
;
double
num_val
;
...
...
@@ -257,8 +292,9 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
if
(
s
->
flags
&
AVFMT_FLAG_IGNIDX
)
return
0
;
while
(
avio_tell
(
ioc
)
<
max_pos
-
2
&&
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
>
0
)
{
int64_t
*
current_array
;
while
(
avio_tell
(
ioc
)
<
max_pos
-
2
&&
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
>
0
)
{
int64_t
*
current_array
;
// Expect array object in context
if
(
avio_r8
(
ioc
)
!=
AMF_DATA_TYPE_ARRAY
)
...
...
@@ -268,10 +304,8 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
if
(
arraylen
>>
28
)
break
;
/*
* Expect only 'times' or 'filepositions' sub-arrays in other case refuse to use such metadata
* for indexing
*/
/* Expect only 'times' or 'filepositions' sub-arrays in other
* case refuse to use such metadata for indexing. */
if
(
!
strcmp
(
KEYFRAMES_TIMESTAMP_TAG
,
str_val
)
&&
!
times
)
{
if
(
!
(
times
=
av_mallocz
(
sizeof
(
*
times
)
*
arraylen
)))
{
ret
=
AVERROR
(
ENOMEM
);
...
...
@@ -279,14 +313,17 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
}
timeslen
=
arraylen
;
current_array
=
times
;
}
else
if
(
!
strcmp
(
KEYFRAMES_BYTEOFFSET_TAG
,
str_val
)
&&
!
filepositions
)
{
}
else
if
(
!
strcmp
(
KEYFRAMES_BYTEOFFSET_TAG
,
str_val
)
&&
!
filepositions
)
{
if
(
!
(
filepositions
=
av_mallocz
(
sizeof
(
*
filepositions
)
*
arraylen
)))
{
ret
=
AVERROR
(
ENOMEM
);
goto
finish
;
}
fileposlen
=
arraylen
;
current_array
=
filepositions
;
}
else
// unexpected metatag inside keyframes, will not use such metadata for indexing
}
else
// unexpected metatag inside keyframes, will not use such
// metadata for indexing
break
;
for
(
i
=
0
;
i
<
arraylen
&&
avio_tell
(
ioc
)
<
max_pos
-
1
;
i
++
)
{
...
...
@@ -305,7 +342,7 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
if
(
!
ret
&&
timeslen
==
fileposlen
)
{
for
(
i
=
0
;
i
<
fileposlen
;
i
++
)
{
av_add_index_entry
(
vstream
,
filepositions
[
i
],
times
[
i
]
*
1000
,
av_add_index_entry
(
vstream
,
filepositions
[
i
],
times
[
i
]
*
1000
,
0
,
0
,
AVINDEX_KEYFRAME
);
if
(
i
<
2
)
{
flv
->
validate_index
[
i
].
pos
=
filepositions
[
i
];
...
...
@@ -326,7 +363,10 @@ finish:
return
ret
;
}
static
int
amf_parse_object
(
AVFormatContext
*
s
,
AVStream
*
astream
,
AVStream
*
vstream
,
const
char
*
key
,
int64_t
max_pos
,
int
depth
)
{
static
int
amf_parse_object
(
AVFormatContext
*
s
,
AVStream
*
astream
,
AVStream
*
vstream
,
const
char
*
key
,
int64_t
max_pos
,
int
depth
)
{
AVCodecContext
*
acodec
,
*
vcodec
;
FLVContext
*
flv
=
s
->
priv_data
;
AVIOContext
*
ioc
;
...
...
@@ -336,72 +376,82 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
num_val
=
0
;
ioc
=
s
->
pb
;
amf_type
=
avio_r8
(
ioc
);
switch
(
amf_type
)
{
switch
(
amf_type
)
{
case
AMF_DATA_TYPE_NUMBER
:
num_val
=
av_int2double
(
avio_rb64
(
ioc
));
break
;
num_val
=
av_int2double
(
avio_rb64
(
ioc
));
break
;
case
AMF_DATA_TYPE_BOOL
:
num_val
=
avio_r8
(
ioc
);
break
;
num_val
=
avio_r8
(
ioc
);
break
;
case
AMF_DATA_TYPE_STRING
:
if
(
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
<
0
)
if
(
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
<
0
)
return
-
1
;
break
;
case
AMF_DATA_TYPE_OBJECT
:
if
((
vstream
||
astream
)
&&
key
&&
!
strcmp
(
KEYFRAMES_TAG
,
key
)
&&
depth
==
1
)
if
((
vstream
||
astream
)
&&
key
&&
!
strcmp
(
KEYFRAMES_TAG
,
key
)
&&
depth
==
1
)
if
(
parse_keyframes_index
(
s
,
ioc
,
vstream
?
vstream
:
astream
,
max_pos
)
<
0
)
return
-
1
;
while
(
avio_tell
(
ioc
)
<
max_pos
-
2
&&
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
>
0
)
{
if
(
amf_parse_object
(
s
,
astream
,
vstream
,
str_val
,
max_pos
,
depth
+
1
)
<
0
)
return
-
1
;
//if we couldn't skip, bomb out.
}
if
(
avio_r8
(
ioc
)
!=
AMF_END_OF_OBJECT
)
while
(
avio_tell
(
ioc
)
<
max_pos
-
2
&&
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
>
0
)
if
(
amf_parse_object
(
s
,
astream
,
vstream
,
str_val
,
max_pos
,
depth
+
1
)
<
0
)
return
-
1
;
// if we couldn't skip, bomb out.
if
(
avio_r8
(
ioc
)
!=
AMF_END_OF_OBJECT
)
return
-
1
;
break
;
case
AMF_DATA_TYPE_NULL
:
case
AMF_DATA_TYPE_UNDEFINED
:
case
AMF_DATA_TYPE_UNSUPPORTED
:
break
;
//
these take up no additional space
break
;
//
these take up no additional space
case
AMF_DATA_TYPE_MIXEDARRAY
:
avio_skip
(
ioc
,
4
);
//skip 32-bit max array index
while
(
avio_tell
(
ioc
)
<
max_pos
-
2
&&
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
>
0
)
{
//this is the only case in which we would want a nested parse to not skip over the object
if
(
amf_parse_object
(
s
,
astream
,
vstream
,
str_val
,
max_pos
,
depth
+
1
)
<
0
)
avio_skip
(
ioc
,
4
);
// skip 32-bit max array index
while
(
avio_tell
(
ioc
)
<
max_pos
-
2
&&
amf_get_string
(
ioc
,
str_val
,
sizeof
(
str_val
))
>
0
)
// this is the only case in which we would want a nested
// parse to not skip over the object
if
(
amf_parse_object
(
s
,
astream
,
vstream
,
str_val
,
max_pos
,
depth
+
1
)
<
0
)
return
-
1
;
}
if
(
avio_r8
(
ioc
)
!=
AMF_END_OF_OBJECT
)
if
(
avio_r8
(
ioc
)
!=
AMF_END_OF_OBJECT
)
return
-
1
;
break
;
case
AMF_DATA_TYPE_ARRAY
:
{
case
AMF_DATA_TYPE_ARRAY
:
{
unsigned
int
arraylen
,
i
;
arraylen
=
avio_rb32
(
ioc
);
for
(
i
=
0
;
i
<
arraylen
&&
avio_tell
(
ioc
)
<
max_pos
-
1
;
i
++
)
{
if
(
amf_parse_object
(
s
,
NULL
,
NULL
,
NULL
,
max_pos
,
depth
+
1
)
<
0
)
return
-
1
;
//if we couldn't skip, bomb out.
}
for
(
i
=
0
;
i
<
arraylen
&&
avio_tell
(
ioc
)
<
max_pos
-
1
;
i
++
)
if
(
amf_parse_object
(
s
,
NULL
,
NULL
,
NULL
,
max_pos
,
depth
+
1
)
<
0
)
return
-
1
;
// if we couldn't skip, bomb out.
}
break
;
case
AMF_DATA_TYPE_DATE
:
avio_skip
(
ioc
,
8
+
2
);
//
timestamp (double) and UTC offset (int16)
avio_skip
(
ioc
,
8
+
2
);
//
timestamp (double) and UTC offset (int16)
break
;
default:
//
unsupported type, we couldn't skip
default:
//
unsupported type, we couldn't skip
return
-
1
;
}
if
(
depth
==
1
&&
key
)
{
//only look for metadata values when we are not nested and key != NULL
// only look for metadata values when we are not nested and key != NULL
if
(
depth
==
1
&&
key
)
{
acodec
=
astream
?
astream
->
codec
:
NULL
;
vcodec
=
vstream
?
vstream
->
codec
:
NULL
;
if
(
amf_type
==
AMF_DATA_TYPE_NUMBER
||
amf_type
==
AMF_DATA_TYPE_BOOL
)
{
if
(
amf_type
==
AMF_DATA_TYPE_NUMBER
||
amf_type
==
AMF_DATA_TYPE_BOOL
)
{
if
(
!
strcmp
(
key
,
"duration"
))
s
->
duration
=
num_val
*
AV_TIME_BASE
;
else
if
(
!
strcmp
(
key
,
"videodatarate"
)
&&
vcodec
&&
0
<=
(
int
)(
num_val
*
1024
.
0
))
else
if
(
!
strcmp
(
key
,
"videodatarate"
)
&&
vcodec
&&
0
<=
(
int
)(
num_val
*
1024
.
0
))
vcodec
->
bit_rate
=
num_val
*
1024
.
0
;
else
if
(
!
strcmp
(
key
,
"audiodatarate"
)
&&
acodec
&&
0
<=
(
int
)(
num_val
*
1024
.
0
))
else
if
(
!
strcmp
(
key
,
"audiodatarate"
)
&&
acodec
&&
0
<=
(
int
)(
num_val
*
1024
.
0
))
acodec
->
bit_rate
=
num_val
*
1024
.
0
;
else
if
(
!
strcmp
(
key
,
"datastream"
))
{
AVStream
*
st
=
create_stream
(
s
,
AVMEDIA_TYPE_DATA
);
...
...
@@ -411,12 +461,10 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
}
else
if
(
flv
->
trust_metadata
)
{
if
(
!
strcmp
(
key
,
"videocodecid"
)
&&
vcodec
)
{
flv_set_video_codec
(
s
,
vstream
,
num_val
,
0
);
}
else
if
(
!
strcmp
(
key
,
"audiocodecid"
)
&&
acodec
)
{
}
else
if
(
!
strcmp
(
key
,
"audiocodecid"
)
&&
acodec
)
{
int
id
=
((
int
)
num_val
)
<<
FLV_AUDIO_CODECID_OFFSET
;
flv_set_audio_codec
(
s
,
astream
,
acodec
,
id
);
}
else
if
(
!
strcmp
(
key
,
"audiosamplerate"
)
&&
acodec
)
{
}
else
if
(
!
strcmp
(
key
,
"audiosamplerate"
)
&&
acodec
)
{
acodec
->
sample_rate
=
num_val
;
}
else
if
(
!
strcmp
(
key
,
"audiosamplesize"
)
&&
acodec
)
{
acodec
->
bits_per_coded_sample
=
num_val
;
...
...
@@ -425,11 +473,9 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
acodec
->
channel_layout
=
acodec
->
channels
==
2
?
AV_CH_LAYOUT_STEREO
:
AV_CH_LAYOUT_MONO
;
}
else
if
(
!
strcmp
(
key
,
"width"
)
&&
vcodec
)
{
}
else
if
(
!
strcmp
(
key
,
"width"
)
&&
vcodec
)
{
vcodec
->
width
=
num_val
;
}
else
if
(
!
strcmp
(
key
,
"height"
)
&&
vcodec
)
{
}
else
if
(
!
strcmp
(
key
,
"height"
)
&&
vcodec
)
{
vcodec
->
height
=
num_val
;
}
}
...
...
@@ -449,10 +495,11 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
!
strcmp
(
key
,
"audiocodecid"
))
return
0
;
if
(
amf_type
==
AMF_DATA_TYPE_BOOL
)
{
av_strlcpy
(
str_val
,
num_val
>
0
?
"true"
:
"false"
,
sizeof
(
str_val
));
if
(
amf_type
==
AMF_DATA_TYPE_BOOL
)
{
av_strlcpy
(
str_val
,
num_val
>
0
?
"true"
:
"false"
,
sizeof
(
str_val
));
av_dict_set
(
&
s
->
metadata
,
key
,
str_val
,
0
);
}
else
if
(
amf_type
==
AMF_DATA_TYPE_NUMBER
)
{
}
else
if
(
amf_type
==
AMF_DATA_TYPE_NUMBER
)
{
snprintf
(
str_val
,
sizeof
(
str_val
),
"%.f"
,
num_val
);
av_dict_set
(
&
s
->
metadata
,
key
,
str_val
,
0
);
}
else
if
(
amf_type
==
AMF_DATA_TYPE_STRING
)
...
...
@@ -462,18 +509,21 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
return
0
;
}
static
int
flv_read_metabody
(
AVFormatContext
*
s
,
int64_t
next_pos
)
{
static
int
flv_read_metabody
(
AVFormatContext
*
s
,
int64_t
next_pos
)
{
AMFDataType
type
;
AVStream
*
stream
,
*
astream
,
*
vstream
;
AVIOContext
*
ioc
;
int
i
;
char
buffer
[
11
];
//only needs to hold the string "onMetaData". Anything longer is something we don't want.
// only needs to hold the string "onMetaData".
// Anything longer is something we don't want.
char
buffer
[
11
];
astream
=
NULL
;
vstream
=
NULL
;
ioc
=
s
->
pb
;
//first object needs to be "onMetaData" string
//
first object needs to be "onMetaData" string
type
=
avio_r8
(
ioc
);
if
(
type
!=
AMF_DATA_TYPE_STRING
||
amf_get_string
(
ioc
,
buffer
,
sizeof
(
buffer
))
<
0
)
...
...
@@ -485,15 +535,18 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
if
(
strcmp
(
buffer
,
"onMetaData"
))
return
-
1
;
//find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called.
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
// find the streams now so that amf_parse_object doesn't need to do
// the lookup every time it is called.
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
stream
=
s
->
streams
[
i
];
if
(
stream
->
codec
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
astream
=
stream
;
else
if
(
stream
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
vstream
=
stream
;
if
(
stream
->
codec
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
astream
=
stream
;
else
if
(
stream
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
vstream
=
stream
;
}
//parse the second object (we want a mixed array)
if
(
amf_parse_object
(
s
,
astream
,
vstream
,
buffer
,
next_pos
,
0
)
<
0
)
//
parse the second object (we want a mixed array)
if
(
amf_parse_object
(
s
,
astream
,
vstream
,
buffer
,
next_pos
,
0
)
<
0
)
return
-
1
;
return
0
;
...
...
@@ -509,19 +562,19 @@ static int flv_read_header(AVFormatContext *s)
/* FIXME: better fix needed */
if
(
!
flags
)
{
flags
=
FLV_HEADER_FLAG_HASVIDEO
|
FLV_HEADER_FLAG_HASAUDIO
;
av_log
(
s
,
AV_LOG_WARNING
,
"Broken FLV file, which says no streams present, this might fail
\n
"
);
av_log
(
s
,
AV_LOG_WARNING
,
"Broken FLV file, which says no streams present, "
"this might fail
\n
"
);
}
s
->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
if
(
flags
&
FLV_HEADER_FLAG_HASVIDEO
){
if
(
!
create_stream
(
s
,
AVMEDIA_TYPE_VIDEO
))
if
(
flags
&
FLV_HEADER_FLAG_HASVIDEO
)
if
(
!
create_stream
(
s
,
AVMEDIA_TYPE_VIDEO
))
return
AVERROR
(
ENOMEM
);
}
if
(
flags
&
FLV_HEADER_FLAG_HASAUDIO
){
if
(
!
create_stream
(
s
,
AVMEDIA_TYPE_AUDIO
))
if
(
flags
&
FLV_HEADER_FLAG_HASAUDIO
)
if
(
!
create_stream
(
s
,
AVMEDIA_TYPE_AUDIO
))
return
AVERROR
(
ENOMEM
);
}
offset
=
avio_rb32
(
s
->
pb
);
avio_seek
(
s
->
pb
,
offset
,
SEEK_SET
);
...
...
@@ -555,7 +608,8 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
int
size
)
{
av_free
(
flv
->
new_extradata
[
stream
]);
flv
->
new_extradata
[
stream
]
=
av_mallocz
(
size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
flv
->
new_extradata
[
stream
]
=
av_mallocz
(
size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
flv
->
new_extradata
[
stream
])
return
AVERROR
(
ENOMEM
);
flv
->
new_extradata_size
[
stream
]
=
size
;
...
...
@@ -566,20 +620,19 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
static
void
clear_index_entries
(
AVFormatContext
*
s
,
int64_t
pos
)
{
int
i
,
j
,
out
;
av_log
(
s
,
AV_LOG_WARNING
,
"Found invalid index entries, clearing the index.
\n
"
);
av_log
(
s
,
AV_LOG_WARNING
,
"Found invalid index entries, clearing the index.
\n
"
);
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
AVStream
*
st
=
s
->
streams
[
i
];
/* Remove all index entries that point to >= pos */
out
=
0
;
for
(
j
=
0
;
j
<
st
->
nb_index_entries
;
j
++
)
{
for
(
j
=
0
;
j
<
st
->
nb_index_entries
;
j
++
)
if
(
st
->
index_entries
[
j
].
pos
<
pos
)
st
->
index_entries
[
out
++
]
=
st
->
index_entries
[
j
];
}
st
->
nb_index_entries
=
out
;
}
}
static
int
flv_data_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
,
int64_t
dts
,
int64_t
next
)
{
...
...
@@ -601,7 +654,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
goto
out
;
amf_get_string
(
pb
,
buf
,
sizeof
(
buf
));
//FIXME parse it as codec_id
//
FIXME parse it as codec_id
amf_get_string
(
pb
,
buf
,
sizeof
(
buf
));
if
(
strcmp
(
buf
,
"text"
)
||
avio_r8
(
pb
)
!=
AMF_DATA_TYPE_STRING
)
goto
out
;
...
...
@@ -634,6 +687,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
pkt
->
flags
|=
AV_PKT_FLAG_KEY
;
avio_seek
(
s
->
pb
,
next
+
4
,
SEEK_SET
);
out:
return
ret
;
}
...
...
@@ -647,7 +701,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
int
sample_rate
=
0
,
channels
=
0
;
AVStream
*
st
=
NULL
;
for
(;;
avio_skip
(
s
->
pb
,
4
)){
/* pkt size is repeated at end. skip it */
/* pkt size is repeated at end. skip it */
for
(;;
avio_skip
(
s
->
pb
,
4
))
{
pos
=
avio_tell
(
s
->
pb
);
type
=
avio_r8
(
s
->
pb
);
size
=
avio_rb24
(
s
->
pb
);
...
...
@@ -675,29 +730,31 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
}
}
if
(
size
==
0
)
if
(
size
==
0
)
continue
;
next
=
size
+
avio_tell
(
s
->
pb
);
next
=
size
+
avio_tell
(
s
->
pb
);
if
(
type
==
FLV_TAG_TYPE_AUDIO
)
{
is_audio
=
1
;
is_audio
=
1
;
flags
=
avio_r8
(
s
->
pb
);
size
--
;
}
else
if
(
type
==
FLV_TAG_TYPE_VIDEO
)
{
is_audio
=
0
;
is_audio
=
0
;
flags
=
avio_r8
(
s
->
pb
);
size
--
;
if
((
flags
&
0xf0
)
==
0x50
)
/* video info / command frame */
goto
skip
;
}
else
{
if
(
type
==
FLV_TAG_TYPE_META
&&
size
>
13
+
1
+
4
)
if
(
type
==
FLV_TAG_TYPE_META
&&
size
>
13
+
1
+
4
)
if
(
flv_read_metabody
(
s
,
next
)
>
0
)
{
return
flv_data_packet
(
s
,
pkt
,
dts
,
next
);
}
else
/* skip packet */
av_log
(
s
,
AV_LOG_DEBUG
,
"skipping flv packet: type %d, size %d, flags %d
\n
"
,
type
,
size
,
flags
);
skip:
}
else
/* skip packet */
av_log
(
s
,
AV_LOG_DEBUG
,
"skipping flv packet: type %d, size %d, flags %d
\n
"
,
type
,
size
,
flags
);
skip:
avio_seek
(
s
->
pb
,
next
,
SEEK_SET
);
continue
;
}
...
...
@@ -707,28 +764,26 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
continue
;
/* now find stream */
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
st
=
s
->
streams
[
i
];
if
(
is_audio
&&
st
->
codec
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
{
if
(
flv_same_audio_codec
(
st
->
codec
,
flags
))
{
if
(
flv_same_audio_codec
(
st
->
codec
,
flags
))
break
;
}
}
else
if
(
!
is_audio
&&
st
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
if
(
flv_same_video_codec
(
st
->
codec
,
flags
))
{
}
else
if
(
!
is_audio
&&
st
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
if
(
flv_same_video_codec
(
st
->
codec
,
flags
))
break
;
}
}
}
if
(
i
==
s
->
nb_streams
){
st
=
create_stream
(
s
,
is_audio
?
AVMEDIA_TYPE_AUDIO
:
AVMEDIA_TYPE_VIDEO
);
}
if
(
i
==
s
->
nb_streams
)
st
=
create_stream
(
s
,
is_audio
?
AVMEDIA_TYPE_AUDIO
:
AVMEDIA_TYPE_VIDEO
);
av_dlog
(
s
,
"%d %X %d
\n
"
,
is_audio
,
flags
,
st
->
discard
);
if
(
(
st
->
discard
>=
AVDISCARD_NONKEY
&&
!
((
flags
&
FLV_VIDEO_FRAMETYPE_MASK
)
==
FLV_FRAME_KEY
||
is_audio
))
||
(
st
->
discard
>=
AVDISCARD_BIDIR
&&
((
flags
&
FLV_VIDEO_FRAMETYPE_MASK
)
==
FLV_FRAME_DISP_INTER
&&
!
is_audio
))
||
st
->
discard
>=
AVDISCARD_ALL
){
if
((
st
->
discard
>=
AVDISCARD_NONKEY
&&
!
((
flags
&
FLV_VIDEO_FRAMETYPE_MASK
)
==
FLV_FRAME_KEY
||
is_audio
))
||
(
st
->
discard
>=
AVDISCARD_BIDIR
&&
((
flags
&
FLV_VIDEO_FRAMETYPE_MASK
)
==
FLV_FRAME_DISP_INTER
&&
!
is_audio
))
||
st
->
discard
>=
AVDISCARD_ALL
)
{
avio_seek
(
s
->
pb
,
next
,
SEEK_SET
);
continue
;
}
...
...
@@ -737,15 +792,16 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
break
;
}
// if not streamed and no duration from metadata then seek to end to find the duration from the timestamps
if
(
s
->
pb
->
seekable
&&
(
!
s
->
duration
||
s
->
duration
==
AV_NOPTS_VALUE
)){
// if not streamed and no duration from metadata then seek to end to find
// the duration from the timestamps
if
(
s
->
pb
->
seekable
&&
(
!
s
->
duration
||
s
->
duration
==
AV_NOPTS_VALUE
))
{
int
size
;
const
int64_t
pos
=
avio_tell
(
s
->
pb
);
const
int64_t
fsize
=
avio_size
(
s
->
pb
);
avio_seek
(
s
->
pb
,
fsize
-
4
,
SEEK_SET
);
size
=
avio_rb32
(
s
->
pb
);
avio_seek
(
s
->
pb
,
fsize
-
3
-
size
,
SEEK_SET
);
if
(
size
==
avio_rb24
(
s
->
pb
)
+
11
)
{
const
int64_t
pos
=
avio_tell
(
s
->
pb
);
const
int64_t
fsize
=
avio_size
(
s
->
pb
);
avio_seek
(
s
->
pb
,
fsize
-
4
,
SEEK_SET
);
size
=
avio_rb32
(
s
->
pb
);
avio_seek
(
s
->
pb
,
fsize
-
3
-
size
,
SEEK_SET
);
if
(
size
==
avio_rb24
(
s
->
pb
)
+
11
)
{
uint32_t
ts
=
avio_rb24
(
s
->
pb
);
ts
|=
avio_r8
(
s
->
pb
)
<<
24
;
s
->
duration
=
ts
*
(
int64_t
)
AV_TIME_BASE
/
1000
;
...
...
@@ -753,29 +809,35 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
avio_seek
(
s
->
pb
,
pos
,
SEEK_SET
);
}
if
(
is_audio
)
{
if
(
is_audio
)
{
int
bits_per_coded_sample
;
channels
=
(
flags
&
FLV_AUDIO_CHANNEL_MASK
)
==
FLV_STEREO
?
2
:
1
;
sample_rate
=
(
44100
<<
((
flags
&
FLV_AUDIO_SAMPLERATE_MASK
)
>>
FLV_AUDIO_SAMPLERATE_OFFSET
)
>>
3
);
sample_rate
=
44100
<<
((
flags
&
FLV_AUDIO_SAMPLERATE_MASK
)
>>
FLV_AUDIO_SAMPLERATE_OFFSET
)
>>
3
;
bits_per_coded_sample
=
(
flags
&
FLV_AUDIO_SAMPLESIZE_MASK
)
?
16
:
8
;
if
(
!
st
->
codec
->
channels
||
!
st
->
codec
->
sample_rate
||
!
st
->
codec
->
bits_per_coded_sample
)
{
if
(
!
st
->
codec
->
channels
||
!
st
->
codec
->
sample_rate
||
!
st
->
codec
->
bits_per_coded_sample
)
{
st
->
codec
->
channels
=
channels
;
st
->
codec
->
channel_layout
=
channels
==
1
?
AV_CH_LAYOUT_MONO
:
AV_CH_LAYOUT_STEREO
;
st
->
codec
->
channel_layout
=
channels
==
1
?
AV_CH_LAYOUT_MONO
:
AV_CH_LAYOUT_STEREO
;
st
->
codec
->
sample_rate
=
sample_rate
;
st
->
codec
->
bits_per_coded_sample
=
bits_per_coded_sample
;
}
if
(
!
st
->
codec
->
codec_id
){
flv_set_audio_codec
(
s
,
st
,
st
->
codec
,
flags
&
FLV_AUDIO_CODECID_MASK
);
flv
->
last_sample_rate
=
sample_rate
=
st
->
codec
->
sample_rate
;
flv
->
last_channels
=
channels
=
st
->
codec
->
channels
;
if
(
!
st
->
codec
->
codec_id
)
{
flv_set_audio_codec
(
s
,
st
,
st
->
codec
,
flags
&
FLV_AUDIO_CODECID_MASK
);
flv
->
last_sample_rate
=
sample_rate
=
st
->
codec
->
sample_rate
;
flv
->
last_channels
=
channels
=
st
->
codec
->
channels
;
}
else
{
AVCodecContext
ctx
;
ctx
.
sample_rate
=
sample_rate
;
flv_set_audio_codec
(
s
,
st
,
&
ctx
,
flags
&
FLV_AUDIO_CODECID_MASK
);
sample_rate
=
ctx
.
sample_rate
;
}
}
else
{
}
else
{
size
-=
flv_set_video_codec
(
s
,
st
,
flags
&
FLV_VIDEO_CODECID_MASK
,
1
);
}
...
...
@@ -784,11 +846,13 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
int
type
=
avio_r8
(
s
->
pb
);
size
--
;
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_H264
)
{
int32_t
cts
=
(
avio_rb24
(
s
->
pb
)
+
0xff800000
)
^
0xff800000
;
// sign extension
// sign extension
int32_t
cts
=
(
avio_rb24
(
s
->
pb
)
+
0xff800000
)
^
0xff800000
;
pts
=
dts
+
cts
;
if
(
cts
<
0
)
{
// dts are wrong
flv
->
wrong_dts
=
1
;
av_log
(
s
,
AV_LOG_WARNING
,
"negative cts, previous timestamps might be wrong
\n
"
);
av_log
(
s
,
AV_LOG_WARNING
,
"negative cts, previous timestamps might be wrong
\n
"
);
}
if
(
flv
->
wrong_dts
)
dts
=
AV_NOPTS_VALUE
;
...
...
@@ -827,12 +891,11 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
goto
leave
;
}
ret
=
av_get_packet
(
s
->
pb
,
pkt
,
size
);
if
(
ret
<
0
)
{
ret
=
av_get_packet
(
s
->
pb
,
pkt
,
size
);
if
(
ret
<
0
)
return
AVERROR
(
EIO
);
}
/* note: we need to modify the packet size here to handle the last
packet */
*
packet */
pkt
->
size
=
ret
;
pkt
->
dts
=
dts
;
pkt
->
pts
=
pts
==
AV_NOPTS_VALUE
?
dts
:
pts
;
...
...
@@ -873,7 +936,7 @@ static int flv_read_seek(AVFormatContext *s, int stream_index,
#define OFFSET(x) offsetof(FLVContext, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static
const
AVOption
options
[]
=
{
{
"flv_metadata"
,
"Allocate streams according the onMetaData array"
,
OFFSET
(
trust_metadata
),
AV_OPT_TYPE_INT
,
{
.
i64
=
0
},
0
,
1
,
VD
},
{
"flv_metadata"
,
"Allocate streams according the onMetaData array"
,
OFFSET
(
trust_metadata
),
AV_OPT_TYPE_INT
,
{
.
i64
=
0
},
0
,
1
,
VD
},
{
NULL
}
};
...
...
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