3 * Copyright (c) 2003 The FFmpeg Project.
5 * This demuxer will generate a 1 byte extradata for VP6F content.
7 * - upper 4bits: difference between encoded width and visible width
8 * - lower 4bits: difference between encoded height and visible height
10 * This file is part of FFmpeg.
12 * FFmpeg is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * FFmpeg is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with FFmpeg; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 static int flv_probe(AVProbeData
*p
)
34 if (d
[0] == 'F' && d
[1] == 'L' && d
[2] == 'V' && d
[3] < 5 && d
[5]==0) {
35 return AVPROBE_SCORE_MAX
;
40 static void flv_set_audio_codec(AVFormatContext
*s
, AVStream
*astream
, int flv_codecid
) {
41 AVCodecContext
*acodec
= astream
->codec
;
43 //no distinction between S16 and S8 PCM codec flags
45 acodec
->codec_id
= acodec
->bits_per_sample
== 8 ? CODEC_ID_PCM_S8
:
46 #ifdef WORDS_BIGENDIAN
52 case FLV_CODECID_PCM_LE
:
53 acodec
->codec_id
= acodec
->bits_per_sample
== 8 ? CODEC_ID_PCM_S8
: CODEC_ID_PCM_S16LE
; break;
54 case FLV_CODECID_AAC
: acodec
->codec_id
= CODEC_ID_AAC
; break;
55 case FLV_CODECID_ADPCM
: acodec
->codec_id
= CODEC_ID_ADPCM_SWF
; break;
56 case FLV_CODECID_SPEEX
: acodec
->codec_id
= CODEC_ID_SPEEX
; break;
57 case FLV_CODECID_MP3
: acodec
->codec_id
= CODEC_ID_MP3
; astream
->need_parsing
= AVSTREAM_PARSE_FULL
; break;
58 case FLV_CODECID_NELLYMOSER_8HZ_MONO
:
59 acodec
->sample_rate
= 8000; //in case metadata does not otherwise declare samplerate
60 case FLV_CODECID_NELLYMOSER
:
61 acodec
->codec_id
= CODEC_ID_NELLYMOSER
;
64 av_log(s
, AV_LOG_INFO
, "Unsupported audio codec (%x)\n", flv_codecid
>> FLV_AUDIO_CODECID_OFFSET
);
65 acodec
->codec_tag
= flv_codecid
>> FLV_AUDIO_CODECID_OFFSET
;
69 static int flv_set_video_codec(AVFormatContext
*s
, AVStream
*vstream
, int flv_codecid
) {
70 AVCodecContext
*vcodec
= vstream
->codec
;
72 case FLV_CODECID_H263
: vcodec
->codec_id
= CODEC_ID_FLV1
; break;
73 case FLV_CODECID_SCREEN
: vcodec
->codec_id
= CODEC_ID_FLASHSV
; break;
74 case FLV_CODECID_VP6
: vcodec
->codec_id
= CODEC_ID_VP6F
;
75 case FLV_CODECID_VP6A
:
76 if(flv_codecid
== FLV_CODECID_VP6A
)
77 vcodec
->codec_id
= CODEC_ID_VP6A
;
78 if(vcodec
->extradata_size
!= 1) {
79 vcodec
->extradata_size
= 1;
80 vcodec
->extradata
= av_malloc(1);
82 vcodec
->extradata
[0] = get_byte(s
->pb
);
83 return 1; // 1 byte body size adjustment for flv_read_packet()
84 case FLV_CODECID_H264
:
85 vcodec
->codec_id
= CODEC_ID_H264
;
86 return 3; // not 4, reading packet type will consume one byte
88 av_log(s
, AV_LOG_INFO
, "Unsupported video codec (%x)\n", flv_codecid
);
89 vcodec
->codec_tag
= flv_codecid
;
95 static int amf_get_string(ByteIOContext
*ioc
, char *buffer
, int buffsize
) {
96 int length
= get_be16(ioc
);
97 if(length
>= buffsize
) {
98 url_fskip(ioc
, length
);
102 get_buffer(ioc
, buffer
, length
);
104 buffer
[length
] = '\0';
109 static int amf_parse_object(AVFormatContext
*s
, AVStream
*astream
, AVStream
*vstream
, const char *key
, unsigned int max_pos
, int depth
) {
110 AVCodecContext
*acodec
, *vcodec
;
112 AMFDataType amf_type
;
119 amf_type
= get_byte(ioc
);
122 case AMF_DATA_TYPE_NUMBER
:
123 num_val
= av_int2dbl(get_be64(ioc
)); break;
124 case AMF_DATA_TYPE_BOOL
:
125 num_val
= get_byte(ioc
); break;
126 case AMF_DATA_TYPE_STRING
:
127 if(amf_get_string(ioc
, str_val
, sizeof(str_val
)) < 0)
130 case AMF_DATA_TYPE_OBJECT
: {
133 while(url_ftell(ioc
) < max_pos
- 2 && (keylen
= get_be16(ioc
))) {
134 url_fskip(ioc
, keylen
); //skip key string
135 if(amf_parse_object(s
, NULL
, NULL
, NULL
, max_pos
, depth
+ 1) < 0)
136 return -1; //if we couldn't skip, bomb out.
138 if(get_byte(ioc
) != AMF_END_OF_OBJECT
)
142 case AMF_DATA_TYPE_NULL
:
143 case AMF_DATA_TYPE_UNDEFINED
:
144 case AMF_DATA_TYPE_UNSUPPORTED
:
145 break; //these take up no additional space
146 case AMF_DATA_TYPE_MIXEDARRAY
:
147 url_fskip(ioc
, 4); //skip 32-bit max array index
148 while(url_ftell(ioc
) < max_pos
- 2 && amf_get_string(ioc
, str_val
, sizeof(str_val
)) > 0) {
149 //this is the only case in which we would want a nested parse to not skip over the object
150 if(amf_parse_object(s
, astream
, vstream
, str_val
, max_pos
, depth
+ 1) < 0)
153 if(get_byte(ioc
) != AMF_END_OF_OBJECT
)
156 case AMF_DATA_TYPE_ARRAY
: {
157 unsigned int arraylen
, i
;
159 arraylen
= get_be32(ioc
);
160 for(i
= 0; i
< arraylen
&& url_ftell(ioc
) < max_pos
- 1; i
++) {
161 if(amf_parse_object(s
, NULL
, NULL
, NULL
, max_pos
, depth
+ 1) < 0)
162 return -1; //if we couldn't skip, bomb out.
166 case AMF_DATA_TYPE_DATE
:
167 url_fskip(ioc
, 8 + 2); //timestamp (double) and UTC offset (int16)
169 default: //unsupported type, we couldn't skip
173 if(depth
== 1 && key
) { //only look for metadata values when we are not nested and key != NULL
174 acodec
= astream
? astream
->codec
: NULL
;
175 vcodec
= vstream
? vstream
->codec
: NULL
;
177 if(amf_type
== AMF_DATA_TYPE_BOOL
) {
178 if(!strcmp(key
, "stereo") && acodec
) acodec
->channels
= num_val
> 0 ? 2 : 1;
179 } else if(amf_type
== AMF_DATA_TYPE_NUMBER
) {
180 if(!strcmp(key
, "duration")) s
->duration
= num_val
* AV_TIME_BASE
;
181 // else if(!strcmp(key, "width") && vcodec && num_val > 0) vcodec->width = num_val;
182 // else if(!strcmp(key, "height") && vcodec && num_val > 0) vcodec->height = num_val;
183 else if(!strcmp(key
, "audiocodecid") && acodec
&& 0 <= (int)num_val
)
184 flv_set_audio_codec(s
, astream
, (int)num_val
<< FLV_AUDIO_CODECID_OFFSET
);
185 else if(!strcmp(key
, "videocodecid") && vcodec
&& 0 <= (int)num_val
)
186 flv_set_video_codec(s
, vstream
, (int)num_val
);
187 else if(!strcmp(key
, "audiosamplesize") && acodec
&& 0 < (int)num_val
) {
188 acodec
->bits_per_sample
= num_val
;
189 //we may have to rewrite a previously read codecid because FLV only marks PCM endianness.
190 if(num_val
== 8 && (acodec
->codec_id
== CODEC_ID_PCM_S16BE
|| acodec
->codec_id
== CODEC_ID_PCM_S16LE
))
191 acodec
->codec_id
= CODEC_ID_PCM_S8
;
193 else if(!strcmp(key
, "audiosamplerate") && acodec
&& num_val
>= 0) {
194 //some tools, like FLVTool2, write consistently approximate metadata sample rates
195 if (!acodec
->sample_rate
) {
196 switch((int)num_val
) {
197 case 44000: acodec
->sample_rate
= 44100 ; break;
198 case 22000: acodec
->sample_rate
= 22050 ; break;
199 case 11000: acodec
->sample_rate
= 11025 ; break;
200 case 5000 : acodec
->sample_rate
= 5512 ; break;
201 default : acodec
->sample_rate
= num_val
;
211 static int flv_read_metabody(AVFormatContext
*s
, unsigned int next_pos
) {
213 AVStream
*stream
, *astream
, *vstream
;
216 char buffer
[11]; //only needs to hold the string "onMetaData". Anything longer is something we don't want.
223 //first object needs to be "onMetaData" string
224 type
= get_byte(ioc
);
225 if(type
!= AMF_DATA_TYPE_STRING
|| amf_get_string(ioc
, buffer
, sizeof(buffer
)) < 0 || strcmp(buffer
, "onMetaData"))
228 //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called.
229 for(i
= 0; i
< s
->nb_streams
; i
++) {
230 stream
= s
->streams
[i
];
231 if (stream
->codec
->codec_type
== CODEC_TYPE_AUDIO
) astream
= stream
;
232 else if(stream
->codec
->codec_type
== CODEC_TYPE_VIDEO
) vstream
= stream
;
235 //parse the second object (we want a mixed array)
236 if(amf_parse_object(s
, astream
, vstream
, buffer
, next_pos
, 0) < 0)
242 static AVStream
*create_stream(AVFormatContext
*s
, int is_audio
){
243 AVStream
*st
= av_new_stream(s
, is_audio
);
246 st
->codec
->codec_type
= is_audio
? CODEC_TYPE_AUDIO
: CODEC_TYPE_VIDEO
;
247 av_set_pts_info(st
, 32, 1, 1000); /* 32 bit pts in ms */
251 static int flv_read_header(AVFormatContext
*s
,
252 AVFormatParameters
*ap
)
257 flags
= get_byte(s
->pb
);
258 /* old flvtool cleared this field */
259 /* FIXME: better fix needed */
261 flags
= FLV_HEADER_FLAG_HASVIDEO
| FLV_HEADER_FLAG_HASAUDIO
;
262 av_log(s
, AV_LOG_WARNING
, "Broken FLV file, which says no streams present, this might fail\n");
265 if((flags
& (FLV_HEADER_FLAG_HASVIDEO
|FLV_HEADER_FLAG_HASAUDIO
))
266 != (FLV_HEADER_FLAG_HASVIDEO
|FLV_HEADER_FLAG_HASAUDIO
))
267 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
269 if(flags
& FLV_HEADER_FLAG_HASVIDEO
){
270 if(!create_stream(s
, 0))
271 return AVERROR(ENOMEM
);
273 if(flags
& FLV_HEADER_FLAG_HASAUDIO
){
274 if(!create_stream(s
, 1))
275 return AVERROR(ENOMEM
);
278 offset
= get_be32(s
->pb
);
279 url_fseek(s
->pb
, offset
, SEEK_SET
);
286 static int flv_get_extradata(AVFormatContext
*s
, AVStream
*st
, int size
)
288 av_free(st
->codec
->extradata
);
289 st
->codec
->extradata
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
290 if (!st
->codec
->extradata
)
291 return AVERROR(ENOMEM
);
292 st
->codec
->extradata_size
= size
;
293 get_buffer(s
->pb
, st
->codec
->extradata
, st
->codec
->extradata_size
);
297 static int flv_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
299 int ret
, i
, type
, size
, flags
, is_audio
, next
, pos
;
305 pos
= url_ftell(s
->pb
);
306 url_fskip(s
->pb
, 4); /* size of previous packet */
307 type
= get_byte(s
->pb
);
308 size
= get_be24(s
->pb
);
309 dts
= get_be24(s
->pb
);
310 dts
|= get_byte(s
->pb
) << 24;
311 // av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, dts:%d\n", type, size, dts);
314 url_fskip(s
->pb
, 3); /* stream id, always 0 */
320 next
= size
+ url_ftell(s
->pb
);
322 if (type
== FLV_TAG_TYPE_AUDIO
) {
324 flags
= get_byte(s
->pb
);
326 } else if (type
== FLV_TAG_TYPE_VIDEO
) {
328 flags
= get_byte(s
->pb
);
330 if ((flags
& 0xf0) == 0x50) /* video info / command frame */
333 if (type
== FLV_TAG_TYPE_META
&& size
> 13+1+4)
334 flv_read_metabody(s
, next
);
335 else /* skip packet */
336 av_log(s
, AV_LOG_ERROR
, "skipping flv packet: type %d, size %d, flags %d\n", type
, size
, flags
);
338 url_fseek(s
->pb
, next
, SEEK_SET
);
342 /* skip empty data packets */
346 /* now find stream */
347 for(i
=0;i
<s
->nb_streams
;i
++) {
349 if (st
->id
== is_audio
)
352 if(i
== s
->nb_streams
){
353 av_log(NULL
, AV_LOG_ERROR
, "invalid stream\n");
354 st
= create_stream(s
, is_audio
);
355 s
->ctx_flags
&= ~AVFMTCTX_NOHEADER
;
357 // av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard);
358 if( (st
->discard
>= AVDISCARD_NONKEY
&& !((flags
& FLV_VIDEO_FRAMETYPE_MASK
) == FLV_FRAME_KEY
|| is_audio
))
359 ||(st
->discard
>= AVDISCARD_BIDIR
&& ((flags
& FLV_VIDEO_FRAMETYPE_MASK
) == FLV_FRAME_DISP_INTER
&& !is_audio
))
360 || st
->discard
>= AVDISCARD_ALL
362 url_fseek(s
->pb
, next
, SEEK_SET
);
365 if ((flags
& FLV_VIDEO_FRAMETYPE_MASK
) == FLV_FRAME_KEY
)
366 av_add_index_entry(st
, pos
, dts
, size
, 0, AVINDEX_KEYFRAME
);
370 // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps
371 if(!url_is_streamed(s
->pb
) && s
->duration
==AV_NOPTS_VALUE
){
373 const int pos
= url_ftell(s
->pb
);
374 const int fsize
= url_fsize(s
->pb
);
375 url_fseek(s
->pb
, fsize
-4, SEEK_SET
);
376 size
= get_be32(s
->pb
);
377 url_fseek(s
->pb
, fsize
-3-size
, SEEK_SET
);
378 if(size
== get_be24(s
->pb
) + 11){
379 s
->duration
= get_be24(s
->pb
) * (int64_t)AV_TIME_BASE
/ 1000;
381 url_fseek(s
->pb
, pos
, SEEK_SET
);
385 if(!st
->codec
->sample_rate
|| !st
->codec
->bits_per_sample
|| (!st
->codec
->codec_id
&& !st
->codec
->codec_tag
)) {
386 st
->codec
->channels
= (flags
& FLV_AUDIO_CHANNEL_MASK
) == FLV_STEREO
? 2 : 1;
387 if((flags
& FLV_AUDIO_CODECID_MASK
) == FLV_CODECID_NELLYMOSER_8HZ_MONO
)
388 st
->codec
->sample_rate
= 8000;
390 st
->codec
->sample_rate
= (44100 << ((flags
& FLV_AUDIO_SAMPLERATE_MASK
) >> FLV_AUDIO_SAMPLERATE_OFFSET
) >> 3);
391 st
->codec
->bits_per_sample
= (flags
& FLV_AUDIO_SAMPLESIZE_MASK
) ? 16 : 8;
392 flv_set_audio_codec(s
, st
, flags
& FLV_AUDIO_CODECID_MASK
);
395 size
-= flv_set_video_codec(s
, st
, flags
& FLV_VIDEO_CODECID_MASK
);
398 if (st
->codec
->codec_id
== CODEC_ID_AAC
||
399 st
->codec
->codec_id
== CODEC_ID_H264
) {
400 int type
= get_byte(s
->pb
);
402 if (st
->codec
->codec_id
== CODEC_ID_H264
) {
403 // cts offset ignored because it might to be signed
404 // and would cause pts < dts
408 if ((ret
= flv_get_extradata(s
, st
, size
)) < 0)
414 ret
= av_get_packet(s
->pb
, pkt
, size
);
418 /* note: we need to modify the packet size here to handle the last
422 pkt
->stream_index
= st
->index
;
424 if (is_audio
|| ((flags
& FLV_VIDEO_FRAMETYPE_MASK
) == FLV_FRAME_KEY
))
425 pkt
->flags
|= PKT_FLAG_KEY
;
430 AVInputFormat flv_demuxer
= {
432 NULL_IF_CONFIG_SMALL("FLV format"),
438 .value
= CODEC_ID_FLV1
,