Commit | Line | Data |
---|---|---|
d4f5d74a | 1 | /* |
7fbde343 | 2 | * FLV demuxer |
2912e87a | 3 | * Copyright (c) 2003 The Libav Project |
d4f5d74a | 4 | * |
7b94177e DB |
5 | * This demuxer will generate a 1 byte extradata for VP6F content. |
6 | * It is composed of: | |
41ed7ab4 VG |
7 | * - upper 4 bits: difference between encoded width and visible width |
8 | * - lower 4 bits: difference between encoded height and visible height | |
7b94177e | 9 | * |
2912e87a | 10 | * This file is part of Libav. |
b78e7197 | 11 | * |
2912e87a | 12 | * Libav is free software; you can redistribute it and/or |
d4f5d74a GM |
13 | * modify it under the terms of the GNU Lesser General Public |
14 | * License as published by the Free Software Foundation; either | |
b78e7197 | 15 | * version 2.1 of the License, or (at your option) any later version. |
d4f5d74a | 16 | * |
2912e87a | 17 | * Libav is distributed in the hope that it will be useful, |
d4f5d74a GM |
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. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
2912e87a | 23 | * License along with Libav; if not, write to the Free Software |
5509bffa | 24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
d4f5d74a | 25 | */ |
d2718187 | 26 | |
df2bd71a | 27 | #include "libavutil/avstring.h" |
644d8d2e | 28 | #include "libavutil/channel_layout.h" |
d2d67e42 | 29 | #include "libavutil/dict.h" |
5b54a90c | 30 | #include "libavutil/opt.h" |
3383a53e | 31 | #include "libavutil/intfloat.h" |
d3f751e6 | 32 | #include "libavutil/mathematics.h" |
c1c206b3 | 33 | #include "libavcodec/bytestream.h" |
d2718187 | 34 | #include "libavcodec/mpeg4audio.h" |
d4f5d74a | 35 | #include "avformat.h" |
c3f9ebf7 | 36 | #include "internal.h" |
933e90a6 | 37 | #include "avio_internal.h" |
6cac3a3b | 38 | #include "flv.h" |
d4f5d74a | 39 | |
cb7e2c1c KA |
40 | #define KEYFRAMES_TAG "keyframes" |
41 | #define KEYFRAMES_TIMESTAMP_TAG "times" | |
42 | #define KEYFRAMES_BYTEOFFSET_TAG "filepositions" | |
43 | ||
7e297a46 MS |
44 | #define VALIDATE_INDEX_TS_THRESH 2500 |
45 | ||
daf8cf35 | 46 | typedef struct FLVContext { |
5b54a90c | 47 | const AVClass *class; ///< Class for private options. |
e4529df9 DB |
48 | int trust_metadata; ///< configure streams according onMetaData |
49 | int wrong_dts; ///< wrong dts due to negative cts | |
251f320f | 50 | uint8_t *new_extradata[2]; |
e4529df9 DB |
51 | int new_extradata_size[2]; |
52 | int last_sample_rate; | |
53 | int last_channels; | |
7e297a46 MS |
54 | struct { |
55 | int64_t dts; | |
56 | int64_t pos; | |
57 | } validate_index[2]; | |
58 | int validate_next; | |
59 | int validate_count; | |
09f4822e | 60 | int searched_for_end; |
628ce8b8 | 61 | AVRational framerate; |
ebd61055 BC |
62 | } FLVContext; |
63 | ||
d4f5d74a GM |
64 | static int flv_probe(AVProbeData *p) |
65 | { | |
66 | const uint8_t *d; | |
67 | ||
d4f5d74a | 68 | d = p->buf; |
e4529df9 DB |
69 | if (d[0] == 'F' && |
70 | d[1] == 'L' && | |
71 | d[2] == 'V' && | |
72 | d[3] < 5 && d[5] == 0 && | |
73 | AV_RB32(d + 5) > 8) { | |
74248229 | 74 | return AVPROBE_SCORE_MAX; |
d4f5d74a GM |
75 | } |
76 | return 0; | |
77 | } | |
78 | ||
41f43202 | 79 | static AVStream *create_stream(AVFormatContext *s, int codec_type) |
21e2dc9f | 80 | { |
628ce8b8 | 81 | FLVContext *flv = s->priv_data; |
21e2dc9f LB |
82 | AVStream *st = avformat_new_stream(s, NULL); |
83 | if (!st) | |
84 | return NULL; | |
9200514a | 85 | st->codecpar->codec_type = codec_type; |
628ce8b8 CEH |
86 | if (codec_type == AVMEDIA_TYPE_VIDEO) |
87 | st->avg_frame_rate = flv->framerate; | |
88 | ||
21e2dc9f LB |
89 | avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ |
90 | return st; | |
91 | } | |
e4529df9 | 92 | |
9200514a | 93 | static int flv_same_audio_codec(AVCodecParameters *apar, int flags) |
09a445ce LB |
94 | { |
95 | int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; | |
e4529df9 | 96 | int flv_codecid = flags & FLV_AUDIO_CODECID_MASK; |
09a445ce LB |
97 | int codec_id; |
98 | ||
9200514a | 99 | if (!apar->codec_id && !apar->codec_tag) |
09a445ce LB |
100 | return 1; |
101 | ||
9200514a | 102 | if (apar->bits_per_coded_sample != bits_per_coded_sample) |
09a445ce LB |
103 | return 0; |
104 | ||
e4529df9 DB |
105 | switch (flv_codecid) { |
106 | // no distinction between S16 and S8 PCM codec flags | |
09a445ce | 107 | case FLV_CODECID_PCM: |
e4529df9 DB |
108 | codec_id = bits_per_coded_sample == 8 |
109 | ? AV_CODEC_ID_PCM_U8 | |
09a445ce | 110 | #if HAVE_BIGENDIAN |
e4529df9 | 111 | : AV_CODEC_ID_PCM_S16BE; |
09a445ce | 112 | #else |
e4529df9 | 113 | : AV_CODEC_ID_PCM_S16LE; |
09a445ce | 114 | #endif |
9200514a | 115 | return codec_id == apar->codec_id; |
09a445ce | 116 | case FLV_CODECID_PCM_LE: |
e4529df9 DB |
117 | codec_id = bits_per_coded_sample == 8 |
118 | ? AV_CODEC_ID_PCM_U8 | |
119 | : AV_CODEC_ID_PCM_S16LE; | |
9200514a | 120 | return codec_id == apar->codec_id; |
09a445ce | 121 | case FLV_CODECID_AAC: |
9200514a | 122 | return apar->codec_id == AV_CODEC_ID_AAC; |
09a445ce | 123 | case FLV_CODECID_ADPCM: |
9200514a | 124 | return apar->codec_id == AV_CODEC_ID_ADPCM_SWF; |
09a445ce | 125 | case FLV_CODECID_SPEEX: |
9200514a | 126 | return apar->codec_id == AV_CODEC_ID_SPEEX; |
09a445ce | 127 | case FLV_CODECID_MP3: |
9200514a | 128 | return apar->codec_id == AV_CODEC_ID_MP3; |
09a445ce | 129 | case FLV_CODECID_NELLYMOSER_8KHZ_MONO: |
09a445ce | 130 | case FLV_CODECID_NELLYMOSER_16KHZ_MONO: |
09a445ce | 131 | case FLV_CODECID_NELLYMOSER: |
9200514a | 132 | return apar->codec_id == AV_CODEC_ID_NELLYMOSER; |
09a445ce | 133 | case FLV_CODECID_PCM_MULAW: |
9200514a AK |
134 | return apar->sample_rate == 8000 && |
135 | apar->codec_id == AV_CODEC_ID_PCM_MULAW; | |
09a445ce | 136 | case FLV_CODECID_PCM_ALAW: |
9200514a AK |
137 | return apar->sample_rate == 8000 && |
138 | apar->codec_id == AV_CODEC_ID_PCM_ALAW; | |
09a445ce | 139 | default: |
9200514a | 140 | return apar->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET); |
09a445ce | 141 | } |
09a445ce | 142 | } |
21e2dc9f | 143 | |
e4529df9 | 144 | static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, |
9200514a | 145 | AVCodecParameters *apar, int flv_codecid) |
e4529df9 DB |
146 | { |
147 | switch (flv_codecid) { | |
148 | // no distinction between S16 and S8 PCM codec flags | |
149 | case FLV_CODECID_PCM: | |
9200514a | 150 | apar->codec_id = apar->bits_per_coded_sample == 8 |
e4529df9 | 151 | ? AV_CODEC_ID_PCM_U8 |
63613fe6 | 152 | #if HAVE_BIGENDIAN |
e4529df9 | 153 | : AV_CODEC_ID_PCM_S16BE; |
58293e57 | 154 | #else |
e4529df9 | 155 | : AV_CODEC_ID_PCM_S16LE; |
58293e57 | 156 | #endif |
e4529df9 DB |
157 | break; |
158 | case FLV_CODECID_PCM_LE: | |
9200514a | 159 | apar->codec_id = apar->bits_per_coded_sample == 8 |
e4529df9 DB |
160 | ? AV_CODEC_ID_PCM_U8 |
161 | : AV_CODEC_ID_PCM_S16LE; | |
162 | break; | |
163 | case FLV_CODECID_AAC: | |
9200514a | 164 | apar->codec_id = AV_CODEC_ID_AAC; |
e4529df9 DB |
165 | break; |
166 | case FLV_CODECID_ADPCM: | |
9200514a | 167 | apar->codec_id = AV_CODEC_ID_ADPCM_SWF; |
e4529df9 DB |
168 | break; |
169 | case FLV_CODECID_SPEEX: | |
9200514a AK |
170 | apar->codec_id = AV_CODEC_ID_SPEEX; |
171 | apar->sample_rate = 16000; | |
e4529df9 DB |
172 | break; |
173 | case FLV_CODECID_MP3: | |
9200514a | 174 | apar->codec_id = AV_CODEC_ID_MP3; |
e4529df9 DB |
175 | astream->need_parsing = AVSTREAM_PARSE_FULL; |
176 | break; | |
177 | case FLV_CODECID_NELLYMOSER_8KHZ_MONO: | |
178 | // in case metadata does not otherwise declare samplerate | |
9200514a AK |
179 | apar->sample_rate = 8000; |
180 | apar->codec_id = AV_CODEC_ID_NELLYMOSER; | |
e4529df9 DB |
181 | break; |
182 | case FLV_CODECID_NELLYMOSER_16KHZ_MONO: | |
9200514a AK |
183 | apar->sample_rate = 16000; |
184 | apar->codec_id = AV_CODEC_ID_NELLYMOSER; | |
e4529df9 DB |
185 | break; |
186 | case FLV_CODECID_NELLYMOSER: | |
9200514a | 187 | apar->codec_id = AV_CODEC_ID_NELLYMOSER; |
e4529df9 DB |
188 | break; |
189 | case FLV_CODECID_PCM_MULAW: | |
9200514a AK |
190 | apar->sample_rate = 8000; |
191 | apar->codec_id = AV_CODEC_ID_PCM_MULAW; | |
e4529df9 DB |
192 | break; |
193 | case FLV_CODECID_PCM_ALAW: | |
9200514a AK |
194 | apar->sample_rate = 8000; |
195 | apar->codec_id = AV_CODEC_ID_PCM_ALAW; | |
e4529df9 DB |
196 | break; |
197 | default: | |
198 | av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", | |
199 | flv_codecid >> FLV_AUDIO_CODECID_OFFSET); | |
9200514a | 200 | apar->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; |
428cc588 AH |
201 | } |
202 | } | |
203 | ||
9200514a | 204 | static int flv_same_video_codec(AVCodecParameters *vpar, int flags) |
09a445ce LB |
205 | { |
206 | int flv_codecid = flags & FLV_VIDEO_CODECID_MASK; | |
207 | ||
9200514a | 208 | if (!vpar->codec_id && !vpar->codec_tag) |
09a445ce LB |
209 | return 1; |
210 | ||
211 | switch (flv_codecid) { | |
e4529df9 | 212 | case FLV_CODECID_H263: |
9200514a | 213 | return vpar->codec_id == AV_CODEC_ID_FLV1; |
e4529df9 | 214 | case FLV_CODECID_SCREEN: |
9200514a | 215 | return vpar->codec_id == AV_CODEC_ID_FLASHSV; |
e4529df9 | 216 | case FLV_CODECID_SCREEN2: |
9200514a | 217 | return vpar->codec_id == AV_CODEC_ID_FLASHSV2; |
e4529df9 | 218 | case FLV_CODECID_VP6: |
9200514a | 219 | return vpar->codec_id == AV_CODEC_ID_VP6F; |
e4529df9 | 220 | case FLV_CODECID_VP6A: |
9200514a | 221 | return vpar->codec_id == AV_CODEC_ID_VP6A; |
e4529df9 | 222 | case FLV_CODECID_H264: |
9200514a | 223 | return vpar->codec_id == AV_CODEC_ID_H264; |
e4529df9 | 224 | default: |
9200514a | 225 | return vpar->codec_tag == flv_codecid; |
09a445ce | 226 | } |
09a445ce LB |
227 | } |
228 | ||
e4529df9 DB |
229 | static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, |
230 | int flv_codecid, int read) | |
231 | { | |
9200514a | 232 | AVCodecParameters *par = vstream->codecpar; |
e4529df9 DB |
233 | switch (flv_codecid) { |
234 | case FLV_CODECID_H263: | |
9200514a | 235 | par->codec_id = AV_CODEC_ID_FLV1; |
e4529df9 DB |
236 | break; |
237 | case FLV_CODECID_SCREEN: | |
9200514a | 238 | par->codec_id = AV_CODEC_ID_FLASHSV; |
e4529df9 DB |
239 | break; |
240 | case FLV_CODECID_SCREEN2: | |
9200514a | 241 | par->codec_id = AV_CODEC_ID_FLASHSV2; |
e4529df9 DB |
242 | break; |
243 | case FLV_CODECID_VP6: | |
9200514a | 244 | par->codec_id = AV_CODEC_ID_VP6F; |
e4529df9 DB |
245 | case FLV_CODECID_VP6A: |
246 | if (flv_codecid == FLV_CODECID_VP6A) | |
9200514a | 247 | par->codec_id = AV_CODEC_ID_VP6A; |
e4529df9 | 248 | if (read) { |
9200514a AK |
249 | if (par->extradata_size != 1) { |
250 | par->extradata = av_malloc(1); | |
251 | if (par->extradata) | |
252 | par->extradata_size = 1; | |
428cc588 | 253 | } |
9200514a AK |
254 | if (par->extradata) |
255 | par->extradata[0] = avio_r8(s->pb); | |
e4529df9 DB |
256 | else |
257 | avio_skip(s->pb, 1); | |
258 | } | |
259 | return 1; // 1 byte body size adjustment for flv_read_packet() | |
260 | case FLV_CODECID_H264: | |
9200514a | 261 | par->codec_id = AV_CODEC_ID_H264; |
e4529df9 DB |
262 | return 3; // not 4, reading packet type will consume one byte |
263 | default: | |
264 | av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); | |
9200514a | 265 | par->codec_tag = flv_codecid; |
428cc588 AH |
266 | } |
267 | ||
268 | return 0; | |
269 | } | |
270 | ||
e4529df9 DB |
271 | static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) |
272 | { | |
b7effd4e | 273 | int length = avio_rb16(ioc); |
e4529df9 | 274 | if (length >= buffsize) { |
45a8a02a | 275 | avio_skip(ioc, length); |
cc38e063 MN |
276 | return -1; |
277 | } | |
896bcd2e | 278 | |
b7effd4e | 279 | avio_read(ioc, buffer, length); |
896bcd2e | 280 | |
cc38e063 | 281 | buffer[length] = '\0'; |
896bcd2e | 282 | |
cc38e063 | 283 | return length; |
896bcd2e MN |
284 | } |
285 | ||
e4529df9 DB |
286 | static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, |
287 | AVStream *vstream, int64_t max_pos) | |
288 | { | |
289 | FLVContext *flv = s->priv_data; | |
cb7e2c1c KA |
290 | unsigned int arraylen = 0, timeslen = 0, fileposlen = 0, i; |
291 | double num_val; | |
292 | char str_val[256]; | |
e4529df9 | 293 | int64_t *times = NULL; |
cb7e2c1c | 294 | int64_t *filepositions = NULL; |
e4529df9 DB |
295 | int ret = AVERROR(ENOSYS); |
296 | int64_t initial_pos = avio_tell(ioc); | |
cb7e2c1c | 297 | |
b70f04c2 MS |
298 | if (s->flags & AVFMT_FLAG_IGNIDX) |
299 | return 0; | |
300 | ||
e4529df9 DB |
301 | while (avio_tell(ioc) < max_pos - 2 && |
302 | amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { | |
303 | int64_t *current_array; | |
cb7e2c1c KA |
304 | |
305 | // Expect array object in context | |
306 | if (avio_r8(ioc) != AMF_DATA_TYPE_ARRAY) | |
307 | break; | |
308 | ||
309 | arraylen = avio_rb32(ioc); | |
a246cefa MN |
310 | if (arraylen >> 28) |
311 | break; | |
312 | ||
e4529df9 DB |
313 | /* Expect only 'times' or 'filepositions' sub-arrays in other |
314 | * case refuse to use such metadata for indexing. */ | |
cb7e2c1c KA |
315 | if (!strcmp(KEYFRAMES_TIMESTAMP_TAG, str_val) && !times) { |
316 | if (!(times = av_mallocz(sizeof(*times) * arraylen))) { | |
317 | ret = AVERROR(ENOMEM); | |
318 | goto finish; | |
319 | } | |
e4529df9 | 320 | timeslen = arraylen; |
cb7e2c1c | 321 | current_array = times; |
e4529df9 DB |
322 | } else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) && |
323 | !filepositions) { | |
cb7e2c1c KA |
324 | if (!(filepositions = av_mallocz(sizeof(*filepositions) * arraylen))) { |
325 | ret = AVERROR(ENOMEM); | |
326 | goto finish; | |
327 | } | |
e4529df9 | 328 | fileposlen = arraylen; |
cb7e2c1c | 329 | current_array = filepositions; |
e4529df9 DB |
330 | } else |
331 | // unexpected metatag inside keyframes, will not use such | |
332 | // metadata for indexing | |
cb7e2c1c KA |
333 | break; |
334 | ||
335 | for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) { | |
336 | if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER) | |
337 | goto finish; | |
e4529df9 | 338 | num_val = av_int2double(avio_rb64(ioc)); |
cb7e2c1c KA |
339 | current_array[i] = num_val; |
340 | } | |
578d6861 MS |
341 | if (times && filepositions) { |
342 | // All done, exiting at a position allowing amf_parse_object | |
343 | // to finish parsing the object | |
344 | ret = 0; | |
345 | break; | |
346 | } | |
cb7e2c1c KA |
347 | } |
348 | ||
7e297a46 MS |
349 | if (!ret && timeslen == fileposlen) { |
350 | for (i = 0; i < fileposlen; i++) { | |
e4529df9 | 351 | av_add_index_entry(vstream, filepositions[i], times[i] * 1000, |
0a7ce3ca | 352 | 0, 0, AVINDEX_KEYFRAME); |
7e297a46 MS |
353 | if (i < 2) { |
354 | flv->validate_index[i].pos = filepositions[i]; | |
355 | flv->validate_index[i].dts = times[i] * 1000; | |
e4529df9 | 356 | flv->validate_count = i + 1; |
7e297a46 MS |
357 | } |
358 | } | |
359 | } else | |
cb7e2c1c KA |
360 | av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n"); |
361 | ||
362 | finish: | |
363 | av_freep(×); | |
364 | av_freep(&filepositions); | |
578d6861 MS |
365 | // If we got unexpected data, but successfully reset back to |
366 | // the start pos, the caller can continue parsing | |
367 | if (ret < 0 && avio_seek(ioc, initial_pos, SEEK_SET) > 0) | |
368 | return 0; | |
cb7e2c1c KA |
369 | return ret; |
370 | } | |
371 | ||
e4529df9 DB |
372 | static int amf_parse_object(AVFormatContext *s, AVStream *astream, |
373 | AVStream *vstream, const char *key, | |
374 | int64_t max_pos, int depth) | |
375 | { | |
9200514a | 376 | AVCodecParameters *apar, *vpar; |
5b54a90c | 377 | FLVContext *flv = s->priv_data; |
ae628ec1 | 378 | AVIOContext *ioc; |
428cc588 | 379 | AMFDataType amf_type; |
cc38e063 | 380 | char str_val[256]; |
428cc588 AH |
381 | double num_val; |
382 | ||
e4529df9 DB |
383 | num_val = 0; |
384 | ioc = s->pb; | |
b7effd4e | 385 | amf_type = avio_r8(ioc); |
428cc588 | 386 | |
e4529df9 DB |
387 | switch (amf_type) { |
388 | case AMF_DATA_TYPE_NUMBER: | |
389 | num_val = av_int2double(avio_rb64(ioc)); | |
390 | break; | |
391 | case AMF_DATA_TYPE_BOOL: | |
392 | num_val = avio_r8(ioc); | |
393 | break; | |
394 | case AMF_DATA_TYPE_STRING: | |
395 | if (amf_get_string(ioc, str_val, sizeof(str_val)) < 0) | |
396 | return -1; | |
397 | break; | |
398 | case AMF_DATA_TYPE_OBJECT: | |
399 | if ((vstream || astream) && key && | |
400 | !strcmp(KEYFRAMES_TAG, key) && depth == 1) | |
401 | if (parse_keyframes_index(s, ioc, vstream ? vstream : astream, | |
402 | max_pos) < 0) | |
428cc588 | 403 | return -1; |
428cc588 | 404 | |
e4529df9 DB |
405 | while (avio_tell(ioc) < max_pos - 2 && |
406 | amf_get_string(ioc, str_val, sizeof(str_val)) > 0) | |
407 | if (amf_parse_object(s, astream, vstream, str_val, max_pos, | |
408 | depth + 1) < 0) | |
409 | return -1; // if we couldn't skip, bomb out. | |
410 | if (avio_r8(ioc) != AMF_END_OF_OBJECT) | |
428cc588 | 411 | return -1; |
e4529df9 DB |
412 | break; |
413 | case AMF_DATA_TYPE_NULL: | |
414 | case AMF_DATA_TYPE_UNDEFINED: | |
415 | case AMF_DATA_TYPE_UNSUPPORTED: | |
416 | break; // these take up no additional space | |
417 | case AMF_DATA_TYPE_MIXEDARRAY: | |
418 | avio_skip(ioc, 4); // skip 32-bit max array index | |
419 | while (avio_tell(ioc) < max_pos - 2 && | |
420 | amf_get_string(ioc, str_val, sizeof(str_val)) > 0) | |
421 | // this is the only case in which we would want a nested | |
422 | // parse to not skip over the object | |
423 | if (amf_parse_object(s, astream, vstream, str_val, max_pos, | |
424 | depth + 1) < 0) | |
425 | return -1; | |
426 | if (avio_r8(ioc) != AMF_END_OF_OBJECT) | |
427 | return -1; | |
428 | break; | |
429 | case AMF_DATA_TYPE_ARRAY: | |
430 | { | |
431 | unsigned int arraylen, i; | |
432 | ||
433 | arraylen = avio_rb32(ioc); | |
434 | for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) | |
435 | if (amf_parse_object(s, NULL, NULL, NULL, max_pos, | |
436 | depth + 1) < 0) | |
437 | return -1; // if we couldn't skip, bomb out. | |
438 | } | |
439 | break; | |
440 | case AMF_DATA_TYPE_DATE: | |
441 | avio_skip(ioc, 8 + 2); // timestamp (double) and UTC offset (int16) | |
442 | break; | |
443 | default: // unsupported type, we couldn't skip | |
444 | return -1; | |
428cc588 AH |
445 | } |
446 | ||
93c04e09 AS |
447 | if (key) { |
448 | // stream info doesn't live any deeper than the first object | |
449 | if (depth == 1) { | |
9200514a AK |
450 | apar = astream ? astream->codecpar : NULL; |
451 | vpar = vstream ? vstream->codecpar : NULL; | |
93c04e09 AS |
452 | |
453 | if (amf_type == AMF_DATA_TYPE_NUMBER || | |
454 | amf_type == AMF_DATA_TYPE_BOOL) { | |
455 | if (!strcmp(key, "duration")) | |
456 | s->duration = num_val * AV_TIME_BASE; | |
9200514a | 457 | else if (!strcmp(key, "videodatarate") && vpar && |
93c04e09 | 458 | 0 <= (int)(num_val * 1024.0)) |
9200514a AK |
459 | vpar->bit_rate = num_val * 1024.0; |
460 | else if (!strcmp(key, "audiodatarate") && apar && | |
93c04e09 | 461 | 0 <= (int)(num_val * 1024.0)) |
9200514a | 462 | apar->bit_rate = num_val * 1024.0; |
93c04e09 AS |
463 | else if (!strcmp(key, "datastream")) { |
464 | AVStream *st = create_stream(s, AVMEDIA_TYPE_DATA); | |
465 | if (!st) | |
466 | return AVERROR(ENOMEM); | |
9200514a | 467 | st->codecpar->codec_id = AV_CODEC_ID_TEXT; |
628ce8b8 CEH |
468 | } else if (!strcmp(key, "framerate")) { |
469 | flv->framerate = av_d2q(num_val, 1000); | |
470 | if (vstream) | |
471 | vstream->avg_frame_rate = flv->framerate; | |
93c04e09 | 472 | } else if (flv->trust_metadata) { |
9200514a | 473 | if (!strcmp(key, "videocodecid") && vpar) { |
93c04e09 | 474 | flv_set_video_codec(s, vstream, num_val, 0); |
9200514a | 475 | } else if (!strcmp(key, "audiocodecid") && apar) { |
93c04e09 | 476 | int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET; |
9200514a AK |
477 | flv_set_audio_codec(s, astream, apar, id); |
478 | } else if (!strcmp(key, "audiosamplerate") && apar) { | |
479 | apar->sample_rate = num_val; | |
480 | } else if (!strcmp(key, "audiosamplesize") && apar) { | |
481 | apar->bits_per_coded_sample = num_val; | |
482 | } else if (!strcmp(key, "stereo") && apar) { | |
483 | apar->channels = num_val + 1; | |
484 | apar->channel_layout = apar->channels == 2 ? | |
485 | AV_CH_LAYOUT_STEREO : | |
486 | AV_CH_LAYOUT_MONO; | |
487 | } else if (!strcmp(key, "width") && vpar) { | |
488 | vpar->width = num_val; | |
489 | } else if (!strcmp(key, "height") && vpar) { | |
490 | vpar->height = num_val; | |
93c04e09 | 491 | } |
5b54a90c | 492 | } |
21e2dc9f | 493 | } |
b204c46d MS |
494 | } |
495 | ||
5e87222f MS |
496 | if (!strcmp(key, "duration") || |
497 | !strcmp(key, "filesize") || | |
498 | !strcmp(key, "width") || | |
499 | !strcmp(key, "height") || | |
500 | !strcmp(key, "videodatarate") || | |
501 | !strcmp(key, "framerate") || | |
502 | !strcmp(key, "videocodecid") || | |
503 | !strcmp(key, "audiodatarate") || | |
504 | !strcmp(key, "audiosamplerate") || | |
505 | !strcmp(key, "audiosamplesize") || | |
506 | !strcmp(key, "stereo") || | |
0a9425d7 LB |
507 | !strcmp(key, "audiocodecid") || |
508 | !strcmp(key, "datastream")) | |
5e87222f MS |
509 | return 0; |
510 | ||
0f789322 | 511 | s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; |
e4529df9 DB |
512 | if (amf_type == AMF_DATA_TYPE_BOOL) { |
513 | av_strlcpy(str_val, num_val > 0 ? "true" : "false", | |
514 | sizeof(str_val)); | |
d2d67e42 | 515 | av_dict_set(&s->metadata, key, str_val, 0); |
e4529df9 | 516 | } else if (amf_type == AMF_DATA_TYPE_NUMBER) { |
cc38e063 | 517 | snprintf(str_val, sizeof(str_val), "%.f", num_val); |
d2d67e42 | 518 | av_dict_set(&s->metadata, key, str_val, 0); |
df2bd71a | 519 | } else if (amf_type == AMF_DATA_TYPE_STRING) |
d2d67e42 | 520 | av_dict_set(&s->metadata, key, str_val, 0); |
428cc588 AH |
521 | } |
522 | ||
523 | return 0; | |
524 | } | |
525 | ||
e4529df9 DB |
526 | static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) |
527 | { | |
428cc588 AH |
528 | AMFDataType type; |
529 | AVStream *stream, *astream, *vstream; | |
ae628ec1 | 530 | AVIOContext *ioc; |
4eec2606 | 531 | int i; |
e4529df9 DB |
532 | // only needs to hold the string "onMetaData". |
533 | // Anything longer is something we don't want. | |
534 | char buffer[11]; | |
428cc588 AH |
535 | |
536 | astream = NULL; | |
537 | vstream = NULL; | |
e4529df9 | 538 | ioc = s->pb; |
428cc588 | 539 | |
e4529df9 | 540 | // first object needs to be "onMetaData" string |
b7effd4e | 541 | type = avio_r8(ioc); |
21e2dc9f LB |
542 | if (type != AMF_DATA_TYPE_STRING || |
543 | amf_get_string(ioc, buffer, sizeof(buffer)) < 0) | |
544 | return -1; | |
545 | ||
546 | if (!strcmp(buffer, "onTextData")) | |
547 | return 1; | |
548 | ||
93c04e09 | 549 | if (strcmp(buffer, "onMetaData") && strcmp(buffer, "onCuePoint")) |
428cc588 AH |
550 | return -1; |
551 | ||
e4529df9 DB |
552 | // find the streams now so that amf_parse_object doesn't need to do |
553 | // the lookup every time it is called. | |
554 | for (i = 0; i < s->nb_streams; i++) { | |
428cc588 | 555 | stream = s->streams[i]; |
9200514a | 556 | if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) |
e4529df9 | 557 | astream = stream; |
9200514a | 558 | else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) |
e4529df9 | 559 | vstream = stream; |
428cc588 AH |
560 | } |
561 | ||
e4529df9 DB |
562 | // parse the second object (we want a mixed array) |
563 | if (amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0) | |
428cc588 AH |
564 | return -1; |
565 | ||
566 | return 0; | |
567 | } | |
568 | ||
6e9651d1 | 569 | static int flv_read_header(AVFormatContext *s) |
d4f5d74a | 570 | { |
09ae7b81 | 571 | int offset; |
d4f5d74a | 572 | |
45a8a02a | 573 | avio_skip(s->pb, 4); |
09ae7b81 | 574 | avio_r8(s->pb); // flags |
d4f5d74a | 575 | |
ee0dadc1 | 576 | s->ctx_flags |= AVFMTCTX_NOHEADER; |
b41497e9 | 577 | |
b7effd4e | 578 | offset = avio_rb32(s->pb); |
6b4aa5da | 579 | avio_seek(s->pb, offset, SEEK_SET); |
45a8a02a | 580 | avio_skip(s->pb, 4); |
d4f5d74a | 581 | |
aeb20f7f N |
582 | s->start_time = 0; |
583 | ||
d4f5d74a GM |
584 | return 0; |
585 | } | |
586 | ||
251f320f MS |
587 | static int flv_read_close(AVFormatContext *s) |
588 | { | |
589 | FLVContext *flv = s->priv_data; | |
590 | av_freep(&flv->new_extradata[0]); | |
591 | av_freep(&flv->new_extradata[1]); | |
592 | return 0; | |
593 | } | |
594 | ||
04fd3e81 BC |
595 | static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size) |
596 | { | |
9200514a AK |
597 | av_free(st->codecpar->extradata); |
598 | st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); | |
599 | if (!st->codecpar->extradata) | |
04fd3e81 | 600 | return AVERROR(ENOMEM); |
9200514a AK |
601 | st->codecpar->extradata_size = size; |
602 | avio_read(s->pb, st->codecpar->extradata, st->codecpar->extradata_size); | |
04fd3e81 BC |
603 | return 0; |
604 | } | |
605 | ||
251f320f MS |
606 | static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream, |
607 | int size) | |
608 | { | |
609 | av_free(flv->new_extradata[stream]); | |
e4529df9 | 610 | flv->new_extradata[stream] = av_mallocz(size + |
059a9348 | 611 | AV_INPUT_BUFFER_PADDING_SIZE); |
251f320f MS |
612 | if (!flv->new_extradata[stream]) |
613 | return AVERROR(ENOMEM); | |
614 | flv->new_extradata_size[stream] = size; | |
615 | avio_read(pb, flv->new_extradata[stream], size); | |
616 | return 0; | |
617 | } | |
618 | ||
7e297a46 MS |
619 | static void clear_index_entries(AVFormatContext *s, int64_t pos) |
620 | { | |
621 | int i, j, out; | |
e4529df9 DB |
622 | av_log(s, AV_LOG_WARNING, |
623 | "Found invalid index entries, clearing the index.\n"); | |
7e297a46 MS |
624 | for (i = 0; i < s->nb_streams; i++) { |
625 | AVStream *st = s->streams[i]; | |
626 | /* Remove all index entries that point to >= pos */ | |
627 | out = 0; | |
e4529df9 | 628 | for (j = 0; j < st->nb_index_entries; j++) |
7e297a46 MS |
629 | if (st->index_entries[j].pos < pos) |
630 | st->index_entries[out++] = st->index_entries[j]; | |
7e297a46 MS |
631 | st->nb_index_entries = out; |
632 | } | |
633 | } | |
634 | ||
c951e4b4 LB |
635 | static int amf_skip_tag(AVIOContext *pb, AMFDataType type) |
636 | { | |
637 | int nb = -1, ret, parse_name = 1; | |
638 | ||
639 | switch (type) { | |
640 | case AMF_DATA_TYPE_NUMBER: | |
641 | avio_skip(pb, 8); | |
642 | break; | |
643 | case AMF_DATA_TYPE_BOOL: | |
644 | avio_skip(pb, 1); | |
645 | break; | |
646 | case AMF_DATA_TYPE_STRING: | |
647 | avio_skip(pb, avio_rb16(pb)); | |
648 | break; | |
649 | case AMF_DATA_TYPE_ARRAY: | |
650 | parse_name = 0; | |
651 | case AMF_DATA_TYPE_MIXEDARRAY: | |
652 | nb = avio_rb32(pb); | |
653 | case AMF_DATA_TYPE_OBJECT: | |
654 | while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) { | |
655 | if (parse_name) { | |
656 | int size = avio_rb16(pb); | |
657 | if (!size) { | |
658 | avio_skip(pb, 1); | |
659 | break; | |
660 | } | |
661 | avio_skip(pb, size); | |
662 | } | |
663 | if ((ret = amf_skip_tag(pb, avio_r8(pb))) < 0) | |
664 | return ret; | |
665 | } | |
666 | break; | |
667 | case AMF_DATA_TYPE_NULL: | |
668 | case AMF_DATA_TYPE_OBJECT_END: | |
669 | break; | |
670 | default: | |
671 | return AVERROR_INVALIDDATA; | |
672 | } | |
673 | return 0; | |
674 | } | |
675 | ||
21e2dc9f LB |
676 | static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, |
677 | int64_t dts, int64_t next) | |
678 | { | |
21e2dc9f | 679 | AVIOContext *pb = s->pb; |
e4529df9 | 680 | AVStream *st = NULL; |
21e2dc9f | 681 | char buf[20]; |
c951e4b4 LB |
682 | int ret = AVERROR_INVALIDDATA; |
683 | int i, length = -1; | |
21e2dc9f | 684 | |
c951e4b4 LB |
685 | switch (avio_r8(pb)) { |
686 | case AMF_DATA_TYPE_MIXEDARRAY: | |
21e2dc9f | 687 | avio_seek(pb, 4, SEEK_CUR); |
c951e4b4 LB |
688 | case AMF_DATA_TYPE_OBJECT: |
689 | break; | |
690 | default: | |
691 | goto skip; | |
692 | } | |
21e2dc9f | 693 | |
c951e4b4 LB |
694 | while ((ret = amf_get_string(pb, buf, sizeof(buf))) > 0) { |
695 | AMFDataType type = avio_r8(pb); | |
696 | if (type == AMF_DATA_TYPE_STRING && !strcmp(buf, "text")) { | |
697 | length = avio_rb16(pb); | |
698 | ret = av_get_packet(pb, pkt, length); | |
699 | if (ret < 0) | |
700 | goto skip; | |
701 | else | |
702 | break; | |
703 | } else { | |
704 | if ((ret = amf_skip_tag(pb, type)) < 0) | |
705 | goto skip; | |
706 | } | |
707 | } | |
21e2dc9f | 708 | |
c951e4b4 LB |
709 | if (length < 0) { |
710 | ret = AVERROR_INVALIDDATA; | |
711 | goto skip; | |
712 | } | |
21e2dc9f LB |
713 | |
714 | for (i = 0; i < s->nb_streams; i++) { | |
715 | st = s->streams[i]; | |
9200514a | 716 | if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) |
21e2dc9f LB |
717 | break; |
718 | } | |
719 | ||
720 | if (i == s->nb_streams) { | |
41f43202 | 721 | st = create_stream(s, AVMEDIA_TYPE_DATA); |
21e2dc9f | 722 | if (!st) |
629b2ed0 | 723 | return AVERROR(ENOMEM); |
9200514a | 724 | st->codecpar->codec_id = AV_CODEC_ID_TEXT; |
21e2dc9f LB |
725 | } |
726 | ||
727 | pkt->dts = dts; | |
728 | pkt->pts = dts; | |
729 | pkt->size = ret; | |
730 | ||
731 | pkt->stream_index = st->index; | |
e4529df9 | 732 | pkt->flags |= AV_PKT_FLAG_KEY; |
21e2dc9f | 733 | |
c951e4b4 | 734 | skip: |
21e2dc9f | 735 | avio_seek(s->pb, next + 4, SEEK_SET); |
e4529df9 | 736 | |
21e2dc9f LB |
737 | return ret; |
738 | } | |
739 | ||
d4f5d74a GM |
740 | static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
741 | { | |
ebd61055 | 742 | FLVContext *flv = s->priv_data; |
a7ac1a7b VG |
743 | int ret, i, size, flags, is_audio; |
744 | enum FlvTagType type; | |
4fe8a452 | 745 | int64_t next, pos; |
ebd61055 | 746 | int64_t dts, pts = AV_NOPTS_VALUE; |
2df73eef | 747 | int sample_rate = 0, channels = 0; |
e4529df9 DB |
748 | AVStream *st = NULL; |
749 | ||
750 | /* pkt size is repeated at end. skip it */ | |
751 | for (;; avio_skip(s->pb, 4)) { | |
752 | pos = avio_tell(s->pb); | |
753 | type = avio_r8(s->pb); | |
754 | size = avio_rb24(s->pb); | |
755 | dts = avio_rb24(s->pb); | |
756 | dts |= avio_r8(s->pb) << 24; | |
1a3eb042 | 757 | av_log(s, AV_LOG_TRACE, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); |
e4529df9 DB |
758 | if (s->pb->eof_reached) |
759 | return AVERROR_EOF; | |
760 | avio_skip(s->pb, 3); /* stream id, always 0 */ | |
761 | flags = 0; | |
762 | ||
763 | if (flv->validate_next < flv->validate_count) { | |
764 | int64_t validate_pos = flv->validate_index[flv->validate_next].pos; | |
765 | if (pos == validate_pos) { | |
766 | if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <= | |
767 | VALIDATE_INDEX_TS_THRESH) { | |
768 | flv->validate_next++; | |
769 | } else { | |
770 | clear_index_entries(s, validate_pos); | |
771 | flv->validate_count = 0; | |
772 | } | |
773 | } else if (pos > validate_pos) { | |
7e297a46 MS |
774 | clear_index_entries(s, validate_pos); |
775 | flv->validate_count = 0; | |
776 | } | |
7e297a46 | 777 | } |
115329f1 | 778 | |
e4529df9 DB |
779 | if (size == 0) |
780 | continue; | |
781 | ||
782 | next = size + avio_tell(s->pb); | |
783 | ||
784 | if (type == FLV_TAG_TYPE_AUDIO) { | |
785 | is_audio = 1; | |
786 | flags = avio_r8(s->pb); | |
787 | size--; | |
788 | } else if (type == FLV_TAG_TYPE_VIDEO) { | |
789 | is_audio = 0; | |
790 | flags = avio_r8(s->pb); | |
791 | size--; | |
792 | if ((flags & 0xf0) == 0x50) /* video info / command frame */ | |
793 | goto skip; | |
794 | } else { | |
795 | if (type == FLV_TAG_TYPE_META && size > 13 + 1 + 4) | |
796 | if (flv_read_metabody(s, next) > 0) { | |
797 | return flv_data_packet(s, pkt, dts, next); | |
798 | } else /* skip packet */ | |
799 | av_log(s, AV_LOG_DEBUG, | |
374fdc8c | 800 | "Skipping flv packet: type %d, size %d, flags %d.\n", |
e4529df9 DB |
801 | type, size, flags); |
802 | ||
803 | skip: | |
585dc1ae MS |
804 | if (avio_seek(s->pb, next, SEEK_SET) != next) { |
805 | // This can happen if flv_read_metabody above read past | |
806 | // next, on a non-seekable input, and the preceding data has | |
807 | // been flushed out from the IO buffer. | |
808 | av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n"); | |
809 | return AVERROR_INVALIDDATA; | |
810 | } | |
e4529df9 DB |
811 | continue; |
812 | } | |
ae58b54b | 813 | |
e4529df9 DB |
814 | /* skip empty data packets */ |
815 | if (!size) | |
816 | continue; | |
817 | ||
818 | /* now find stream */ | |
819 | for (i = 0; i < s->nb_streams; i++) { | |
820 | st = s->streams[i]; | |
9200514a AK |
821 | if (is_audio && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
822 | if (flv_same_audio_codec(st->codecpar, flags)) | |
e4529df9 DB |
823 | break; |
824 | } else if (!is_audio && | |
9200514a AK |
825 | st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { |
826 | if (flv_same_video_codec(st->codecpar, flags)) | |
e4529df9 | 827 | break; |
09a445ce LB |
828 | } |
829 | } | |
629b2ed0 | 830 | if (i == s->nb_streams) { |
e4529df9 DB |
831 | st = create_stream(s, is_audio ? AVMEDIA_TYPE_AUDIO |
832 | : AVMEDIA_TYPE_VIDEO); | |
629b2ed0 VG |
833 | if (!st) |
834 | return AVERROR(ENOMEM); | |
835 | } | |
1a3eb042 | 836 | av_log(s, AV_LOG_TRACE, "%d %X %d \n", is_audio, flags, st->discard); |
fa14804c LB |
837 | |
838 | if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || | |
839 | is_audio) | |
840 | av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME); | |
841 | ||
e4529df9 DB |
842 | if ((st->discard >= AVDISCARD_NONKEY && |
843 | !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio)) || | |
844 | (st->discard >= AVDISCARD_BIDIR && | |
845 | ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio)) || | |
846 | st->discard >= AVDISCARD_ALL) { | |
847 | avio_seek(s->pb, next, SEEK_SET); | |
848 | continue; | |
849 | } | |
e4529df9 | 850 | break; |
d4f5d74a | 851 | } |
068f2a22 | 852 | |
e4529df9 DB |
853 | // if not streamed and no duration from metadata then seek to end to find |
854 | // the duration from the timestamps | |
83548fe8 AK |
855 | if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && |
856 | (!s->duration || s->duration == AV_NOPTS_VALUE) && | |
09f4822e | 857 | !flv->searched_for_end) { |
15f14fc7 | 858 | int size; |
e4529df9 | 859 | const int64_t pos = avio_tell(s->pb); |
40665d27 UK |
860 | // Read the last 4 bytes of the file, this should be the size of the |
861 | // previous FLV tag. Use the timestamp of its payload as duration. | |
e4529df9 DB |
862 | const int64_t fsize = avio_size(s->pb); |
863 | avio_seek(s->pb, fsize - 4, SEEK_SET); | |
864 | size = avio_rb32(s->pb); | |
e4eb13ca MS |
865 | if (size > 0 && size < fsize) { |
866 | // Seek to the start of the last FLV tag at position (fsize - 4 - size) | |
867 | // but skip the byte indicating the type. | |
868 | avio_seek(s->pb, fsize - 3 - size, SEEK_SET); | |
869 | if (size == avio_rb24(s->pb) + 11) { | |
870 | uint32_t ts = avio_rb24(s->pb); | |
871 | ts |= avio_r8(s->pb) << 24; | |
872 | s->duration = ts * (int64_t)AV_TIME_BASE / 1000; | |
873 | } | |
15f14fc7 | 874 | } |
6b4aa5da | 875 | avio_seek(s->pb, pos, SEEK_SET); |
09f4822e | 876 | flv->searched_for_end = 1; |
15f14fc7 MN |
877 | } |
878 | ||
e4529df9 | 879 | if (is_audio) { |
2215c39e | 880 | int bits_per_coded_sample; |
e4529df9 DB |
881 | channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1; |
882 | sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> | |
883 | FLV_AUDIO_SAMPLERATE_OFFSET) >> 3; | |
2215c39e | 884 | bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; |
9200514a AK |
885 | if (!st->codecpar->channels || !st->codecpar->sample_rate || |
886 | !st->codecpar->bits_per_coded_sample) { | |
887 | st->codecpar->channels = channels; | |
888 | st->codecpar->channel_layout = channels == 1 | |
e4529df9 DB |
889 | ? AV_CH_LAYOUT_MONO |
890 | : AV_CH_LAYOUT_STEREO; | |
9200514a AK |
891 | st->codecpar->sample_rate = sample_rate; |
892 | st->codecpar->bits_per_coded_sample = bits_per_coded_sample; | |
2f3d7ea9 | 893 | } |
9200514a AK |
894 | if (!st->codecpar->codec_id) { |
895 | flv_set_audio_codec(s, st, st->codecpar, | |
e4529df9 DB |
896 | flags & FLV_AUDIO_CODECID_MASK); |
897 | flv->last_sample_rate = | |
9200514a | 898 | sample_rate = st->codecpar->sample_rate; |
e4529df9 | 899 | flv->last_channels = |
9200514a | 900 | channels = st->codecpar->channels; |
2215c39e | 901 | } else { |
9200514a AK |
902 | AVCodecParameters *par = avcodec_parameters_alloc(); |
903 | if (!par) { | |
904 | ret = AVERROR(ENOMEM); | |
905 | goto leave; | |
906 | } | |
907 | par->sample_rate = sample_rate; | |
908 | par->bits_per_coded_sample = bits_per_coded_sample; | |
909 | flv_set_audio_codec(s, st, par, flags & FLV_AUDIO_CODECID_MASK); | |
910 | sample_rate = par->sample_rate; | |
911 | avcodec_parameters_free(&par); | |
068f2a22 | 912 | } |
e4529df9 | 913 | } else { |
c91c63b5 | 914 | size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1); |
bb01a3f0 MN |
915 | } |
916 | ||
9200514a AK |
917 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC || |
918 | st->codecpar->codec_id == AV_CODEC_ID_H264) { | |
b7effd4e | 919 | int type = avio_r8(s->pb); |
04fd3e81 | 920 | size--; |
279e3aaa LB |
921 | |
922 | if (size < 0) { | |
923 | ret = AVERROR_INVALIDDATA; | |
924 | goto leave; | |
925 | } | |
926 | ||
9200514a | 927 | if (st->codecpar->codec_id == AV_CODEC_ID_H264) { |
e4529df9 DB |
928 | // sign extension |
929 | int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; | |
ebd61055 | 930 | pts = dts + cts; |
5d983fdb | 931 | if (cts < 0 && !flv->wrong_dts) { // dts might be wrong |
ebd61055 | 932 | flv->wrong_dts = 1; |
e4529df9 | 933 | av_log(s, AV_LOG_WARNING, |
374fdc8c | 934 | "Negative cts, previous timestamps might be wrong.\n"); |
ebd61055 | 935 | } |
04fd3e81 BC |
936 | } |
937 | if (type == 0) { | |
9200514a | 938 | if (st->codecpar->extradata) { |
251f320f MS |
939 | if ((ret = flv_queue_extradata(flv, s->pb, is_audio, size)) < 0) |
940 | return ret; | |
941 | ret = AVERROR(EAGAIN); | |
942 | goto leave; | |
943 | } | |
6298eb81 | 944 | if ((ret = flv_get_extradata(s, st, size)) < 0) |
04fd3e81 | 945 | return ret; |
9200514a | 946 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { |
d2718187 | 947 | MPEG4AudioConfig cfg; |
547f8345 BL |
948 | |
949 | /* Workaround for buggy Omnia A/XE encoder */ | |
950 | AVDictionaryEntry *t = av_dict_get(s->metadata, "Encoder", NULL, 0); | |
951 | if (t && !strcmp(t->value, "Omnia A/XE")) | |
9200514a | 952 | st->codecpar->extradata_size = 2; |
547f8345 | 953 | |
9200514a AK |
954 | avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata, |
955 | st->codecpar->extradata_size * 8, 1); | |
956 | st->codecpar->channels = cfg.channels; | |
957 | st->codecpar->channel_layout = 0; | |
7d6096e4 | 958 | if (cfg.ext_sample_rate) |
9200514a | 959 | st->codecpar->sample_rate = cfg.ext_sample_rate; |
7d6096e4 | 960 | else |
9200514a | 961 | st->codecpar->sample_rate = cfg.sample_rate; |
1a3eb042 | 962 | av_log(s, AV_LOG_TRACE, "mp4a config channels %d sample rate %d\n", |
9200514a | 963 | st->codecpar->channels, st->codecpar->sample_rate); |
d2718187 BC |
964 | } |
965 | ||
527c2e64 HC |
966 | ret = AVERROR(EAGAIN); |
967 | goto leave; | |
04fd3e81 BC |
968 | } |
969 | } | |
970 | ||
fcb4228c | 971 | /* skip empty data packets */ |
527c2e64 HC |
972 | if (!size) { |
973 | ret = AVERROR(EAGAIN); | |
974 | goto leave; | |
975 | } | |
fcb4228c | 976 | |
e4529df9 DB |
977 | ret = av_get_packet(s->pb, pkt, size); |
978 | if (ret < 0) | |
6f3e0b21 | 979 | return AVERROR(EIO); |
d4f5d74a | 980 | /* note: we need to modify the packet size here to handle the last |
e4529df9 DB |
981 | * packet */ |
982 | pkt->size = ret; | |
983 | pkt->dts = dts; | |
984 | pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts; | |
d4f5d74a | 985 | pkt->stream_index = st->index; |
251f320f MS |
986 | if (flv->new_extradata[is_audio]) { |
987 | uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, | |
988 | flv->new_extradata_size[is_audio]); | |
989 | if (side) { | |
990 | memcpy(side, flv->new_extradata[is_audio], | |
991 | flv->new_extradata_size[is_audio]); | |
992 | av_freep(&flv->new_extradata[is_audio]); | |
993 | flv->new_extradata_size[is_audio] = 0; | |
994 | } | |
995 | } | |
2215c39e | 996 | if (is_audio && (sample_rate != flv->last_sample_rate || |
e4529df9 | 997 | channels != flv->last_channels)) { |
2215c39e MS |
998 | flv->last_sample_rate = sample_rate; |
999 | flv->last_channels = channels; | |
1000 | ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0); | |
1001 | } | |
115329f1 | 1002 | |
6cac3a3b | 1003 | if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) |
cc947f04 | 1004 | pkt->flags |= AV_PKT_FLAG_KEY; |
115329f1 | 1005 | |
527c2e64 | 1006 | leave: |
45a8a02a | 1007 | avio_skip(s->pb, 4); |
d4f5d74a GM |
1008 | return ret; |
1009 | } | |
1010 | ||
fc8fa007 | 1011 | static int flv_read_seek(AVFormatContext *s, int stream_index, |
e4529df9 | 1012 | int64_t ts, int flags) |
fc8fa007 | 1013 | { |
7e297a46 MS |
1014 | FLVContext *flv = s->priv_data; |
1015 | flv->validate_count = 0; | |
ff1ec0c3 | 1016 | return avio_seek_time(s->pb, stream_index, ts, flags); |
fc8fa007 HC |
1017 | } |
1018 | ||
5b54a90c LB |
1019 | #define OFFSET(x) offsetof(FLVContext, x) |
1020 | #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | |
1021 | static const AVOption options[] = { | |
f4634ae8 | 1022 | { "flv_metadata", "Allocate streams according to the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD }, |
5b54a90c LB |
1023 | { NULL } |
1024 | }; | |
1025 | ||
1026 | static const AVClass class = { | |
1027 | .class_name = "flvdec", | |
1028 | .item_name = av_default_item_name, | |
1029 | .option = options, | |
1030 | .version = LIBAVUTIL_VERSION_INT, | |
1031 | }; | |
1032 | ||
c6610a21 | 1033 | AVInputFormat ff_flv_demuxer = { |
dfc2c4d9 | 1034 | .name = "flv", |
0177b7d2 | 1035 | .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"), |
dfc2c4d9 AK |
1036 | .priv_data_size = sizeof(FLVContext), |
1037 | .read_probe = flv_probe, | |
1038 | .read_header = flv_read_header, | |
1039 | .read_packet = flv_read_packet, | |
20234a4b | 1040 | .read_seek = flv_read_seek, |
20234a4b MS |
1041 | .read_close = flv_read_close, |
1042 | .extensions = "flv", | |
5b54a90c | 1043 | .priv_class = &class, |
d4f5d74a | 1044 | }; |