blob: 899b07ea7bef8575347c757e7a3de1459ef5437b
1 | /* |
2 | * FLV muxer |
3 | * Copyright (c) 2003 The FFmpeg Project |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "libavutil/intreadwrite.h" |
23 | #include "libavutil/dict.h" |
24 | #include "libavutil/intfloat.h" |
25 | #include "libavutil/avassert.h" |
26 | #include "libavutil/mathematics.h" |
27 | #include "avio_internal.h" |
28 | #include "avio.h" |
29 | #include "avc.h" |
30 | #include "avformat.h" |
31 | #include "flv.h" |
32 | #include "internal.h" |
33 | #include "metadata.h" |
34 | #include "libavutil/opt.h" |
35 | #include "libavcodec/put_bits.h" |
36 | #include "libavcodec/aacenctab.h" |
37 | |
38 | |
39 | static const AVCodecTag flv_video_codec_ids[] = { |
40 | { AV_CODEC_ID_FLV1, FLV_CODECID_H263 }, |
41 | { AV_CODEC_ID_H263, FLV_CODECID_REALH263 }, |
42 | { AV_CODEC_ID_MPEG4, FLV_CODECID_MPEG4 }, |
43 | { AV_CODEC_ID_FLASHSV, FLV_CODECID_SCREEN }, |
44 | { AV_CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2 }, |
45 | { AV_CODEC_ID_VP6F, FLV_CODECID_VP6 }, |
46 | { AV_CODEC_ID_VP6, FLV_CODECID_VP6 }, |
47 | { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A }, |
48 | { AV_CODEC_ID_H264, FLV_CODECID_H264 }, |
49 | { AV_CODEC_ID_NONE, 0 } |
50 | }; |
51 | |
52 | static const AVCodecTag flv_audio_codec_ids[] = { |
53 | { AV_CODEC_ID_MP3, FLV_CODECID_MP3 >> FLV_AUDIO_CODECID_OFFSET }, |
54 | { AV_CODEC_ID_PCM_U8, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET }, |
55 | { AV_CODEC_ID_PCM_S16BE, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET }, |
56 | { AV_CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET }, |
57 | { AV_CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM >> FLV_AUDIO_CODECID_OFFSET }, |
58 | { AV_CODEC_ID_AAC, FLV_CODECID_AAC >> FLV_AUDIO_CODECID_OFFSET }, |
59 | { AV_CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET }, |
60 | { AV_CODEC_ID_PCM_MULAW, FLV_CODECID_PCM_MULAW >> FLV_AUDIO_CODECID_OFFSET }, |
61 | { AV_CODEC_ID_PCM_ALAW, FLV_CODECID_PCM_ALAW >> FLV_AUDIO_CODECID_OFFSET }, |
62 | { AV_CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET }, |
63 | { AV_CODEC_ID_NONE, 0 } |
64 | }; |
65 | |
66 | typedef enum { |
67 | FLV_AAC_SEQ_HEADER_DETECT = (1 << 0), |
68 | FLV_NO_SEQUENCE_END = (1 << 1), |
69 | FLV_ADD_KEYFRAME_INDEX = (1 << 2), |
70 | FLV_NO_METADATA = (1 << 3), |
71 | FLV_NO_DURATION_FILESIZE = (1 << 4), |
72 | } FLVFlags; |
73 | |
74 | typedef struct FLVFileposition { |
75 | int64_t keyframe_position; |
76 | double keyframe_timestamp; |
77 | struct FLVFileposition *next; |
78 | } FLVFileposition; |
79 | |
80 | typedef struct FLVContext { |
81 | AVClass *av_class; |
82 | int reserved; |
83 | int64_t duration_offset; |
84 | int64_t filesize_offset; |
85 | int64_t duration; |
86 | int64_t delay; ///< first dts delay (needed for AVC & Speex) |
87 | |
88 | int64_t datastart_offset; |
89 | int64_t datasize_offset; |
90 | int64_t datasize; |
91 | int64_t videosize_offset; |
92 | int64_t videosize; |
93 | int64_t audiosize_offset; |
94 | int64_t audiosize; |
95 | |
96 | int64_t metadata_size_pos; |
97 | int64_t metadata_totalsize_pos; |
98 | int64_t metadata_totalsize; |
99 | int64_t keyframe_index_size; |
100 | |
101 | int64_t lasttimestamp_offset; |
102 | double lasttimestamp; |
103 | int64_t lastkeyframetimestamp_offset; |
104 | double lastkeyframetimestamp; |
105 | int64_t lastkeyframelocation_offset; |
106 | int64_t lastkeyframelocation; |
107 | |
108 | int acurframeindex; |
109 | int64_t keyframes_info_offset; |
110 | |
111 | int64_t filepositions_count; |
112 | FLVFileposition *filepositions; |
113 | FLVFileposition *head_filepositions; |
114 | |
115 | AVCodecParameters *audio_par; |
116 | AVCodecParameters *video_par; |
117 | double framerate; |
118 | AVCodecParameters *data_par; |
119 | |
120 | int flags; |
121 | } FLVContext; |
122 | |
123 | typedef struct FLVStreamContext { |
124 | int64_t last_ts; ///< last timestamp for each stream |
125 | } FLVStreamContext; |
126 | |
127 | static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) |
128 | { |
129 | int flags = (par->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT |
130 | : FLV_SAMPLESSIZE_8BIT; |
131 | |
132 | if (par->codec_id == AV_CODEC_ID_AAC) // specs force these parameters |
133 | return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | |
134 | FLV_SAMPLESSIZE_16BIT | FLV_STEREO; |
135 | else if (par->codec_id == AV_CODEC_ID_SPEEX) { |
136 | if (par->sample_rate != 16000) { |
137 | av_log(s, AV_LOG_ERROR, |
138 | "FLV only supports wideband (16kHz) Speex audio\n"); |
139 | return AVERROR(EINVAL); |
140 | } |
141 | if (par->channels != 1) { |
142 | av_log(s, AV_LOG_ERROR, "FLV only supports mono Speex audio\n"); |
143 | return AVERROR(EINVAL); |
144 | } |
145 | return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT; |
146 | } else { |
147 | switch (par->sample_rate) { |
148 | case 48000: |
149 | // 48khz mp3 is stored with 44k1 samplerate identifer |
150 | if (par->codec_id == AV_CODEC_ID_MP3) { |
151 | flags |= FLV_SAMPLERATE_44100HZ; |
152 | break; |
153 | } else { |
154 | goto error; |
155 | } |
156 | case 44100: |
157 | flags |= FLV_SAMPLERATE_44100HZ; |
158 | break; |
159 | case 22050: |
160 | flags |= FLV_SAMPLERATE_22050HZ; |
161 | break; |
162 | case 11025: |
163 | flags |= FLV_SAMPLERATE_11025HZ; |
164 | break; |
165 | case 16000: // nellymoser only |
166 | case 8000: // nellymoser only |
167 | case 5512: // not MP3 |
168 | if (par->codec_id != AV_CODEC_ID_MP3) { |
169 | flags |= FLV_SAMPLERATE_SPECIAL; |
170 | break; |
171 | } |
172 | default: |
173 | error: |
174 | av_log(s, AV_LOG_ERROR, |
175 | "FLV does not support sample rate %d, " |
176 | "choose from (44100, 22050, 11025)\n", par->sample_rate); |
177 | return AVERROR(EINVAL); |
178 | } |
179 | } |
180 | |
181 | if (par->channels > 1) |
182 | flags |= FLV_STEREO; |
183 | |
184 | switch (par->codec_id) { |
185 | case AV_CODEC_ID_MP3: |
186 | flags |= FLV_CODECID_MP3 | FLV_SAMPLESSIZE_16BIT; |
187 | break; |
188 | case AV_CODEC_ID_PCM_U8: |
189 | flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_8BIT; |
190 | break; |
191 | case AV_CODEC_ID_PCM_S16BE: |
192 | flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_16BIT; |
193 | break; |
194 | case AV_CODEC_ID_PCM_S16LE: |
195 | flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT; |
196 | break; |
197 | case AV_CODEC_ID_ADPCM_SWF: |
198 | flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT; |
199 | break; |
200 | case AV_CODEC_ID_NELLYMOSER: |
201 | if (par->sample_rate == 8000) |
202 | flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT; |
203 | else if (par->sample_rate == 16000) |
204 | flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT; |
205 | else |
206 | flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT; |
207 | break; |
208 | case AV_CODEC_ID_PCM_MULAW: |
209 | flags = FLV_CODECID_PCM_MULAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT; |
210 | break; |
211 | case AV_CODEC_ID_PCM_ALAW: |
212 | flags = FLV_CODECID_PCM_ALAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT; |
213 | break; |
214 | case 0: |
215 | flags |= par->codec_tag << 4; |
216 | break; |
217 | default: |
218 | av_log(s, AV_LOG_ERROR, "Audio codec '%s' not compatible with FLV\n", |
219 | avcodec_get_name(par->codec_id)); |
220 | return AVERROR(EINVAL); |
221 | } |
222 | |
223 | return flags; |
224 | } |
225 | |
226 | static void put_amf_string(AVIOContext *pb, const char *str) |
227 | { |
228 | size_t len = strlen(str); |
229 | avio_wb16(pb, len); |
230 | avio_write(pb, str, len); |
231 | } |
232 | |
233 | static void put_avc_eos_tag(AVIOContext *pb, unsigned ts) |
234 | { |
235 | avio_w8(pb, FLV_TAG_TYPE_VIDEO); |
236 | avio_wb24(pb, 5); /* Tag Data Size */ |
237 | avio_wb24(pb, ts); /* lower 24 bits of timestamp in ms */ |
238 | avio_w8(pb, (ts >> 24) & 0x7F); /* MSB of ts in ms */ |
239 | avio_wb24(pb, 0); /* StreamId = 0 */ |
240 | avio_w8(pb, 23); /* ub[4] FrameType = 1, ub[4] CodecId = 7 */ |
241 | avio_w8(pb, 2); /* AVC end of sequence */ |
242 | avio_wb24(pb, 0); /* Always 0 for AVC EOS. */ |
243 | avio_wb32(pb, 16); /* Size of FLV tag */ |
244 | } |
245 | |
246 | static void put_amf_double(AVIOContext *pb, double d) |
247 | { |
248 | avio_w8(pb, AMF_DATA_TYPE_NUMBER); |
249 | avio_wb64(pb, av_double2int(d)); |
250 | } |
251 | |
252 | static void put_amf_byte(AVIOContext *pb, unsigned char abyte) |
253 | { |
254 | avio_w8(pb, abyte); |
255 | } |
256 | |
257 | static void put_amf_dword_array(AVIOContext *pb, uint32_t dw) |
258 | { |
259 | avio_w8(pb, AMF_DATA_TYPE_ARRAY); |
260 | avio_wb32(pb, dw); |
261 | } |
262 | |
263 | static void put_amf_bool(AVIOContext *pb, int b) |
264 | { |
265 | avio_w8(pb, AMF_DATA_TYPE_BOOL); |
266 | avio_w8(pb, !!b); |
267 | } |
268 | |
269 | static void write_metadata(AVFormatContext *s, unsigned int ts) |
270 | { |
271 | AVIOContext *pb = s->pb; |
272 | FLVContext *flv = s->priv_data; |
273 | int write_duration_filesize = !(flv->flags & FLV_NO_DURATION_FILESIZE); |
274 | int metadata_count = 0; |
275 | int64_t metadata_count_pos; |
276 | AVDictionaryEntry *tag = NULL; |
277 | |
278 | /* write meta_tag */ |
279 | avio_w8(pb, FLV_TAG_TYPE_META); // tag type META |
280 | flv->metadata_size_pos = avio_tell(pb); |
281 | avio_wb24(pb, 0); // size of data part (sum of all parts below) |
282 | avio_wb24(pb, ts); // timestamp |
283 | avio_wb32(pb, 0); // reserved |
284 | |
285 | /* now data of data_size size */ |
286 | |
287 | /* first event name as a string */ |
288 | avio_w8(pb, AMF_DATA_TYPE_STRING); |
289 | put_amf_string(pb, "onMetaData"); // 12 bytes |
290 | |
291 | /* mixed array (hash) with size and string/type/data tuples */ |
292 | avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); |
293 | metadata_count_pos = avio_tell(pb); |
294 | metadata_count = 4 * !!flv->video_par + |
295 | 5 * !!flv->audio_par + |
296 | 1 * !!flv->data_par; |
297 | if (write_duration_filesize) { |
298 | metadata_count += 2; // +2 for duration and file size |
299 | } |
300 | avio_wb32(pb, metadata_count); |
301 | |
302 | if (write_duration_filesize) { |
303 | put_amf_string(pb, "duration"); |
304 | flv->duration_offset = avio_tell(pb); |
305 | // fill in the guessed duration, it'll be corrected later if incorrect |
306 | put_amf_double(pb, s->duration / AV_TIME_BASE); |
307 | } |
308 | |
309 | if (flv->video_par) { |
310 | put_amf_string(pb, "width"); |
311 | put_amf_double(pb, flv->video_par->width); |
312 | |
313 | put_amf_string(pb, "height"); |
314 | put_amf_double(pb, flv->video_par->height); |
315 | |
316 | put_amf_string(pb, "videodatarate"); |
317 | put_amf_double(pb, flv->video_par->bit_rate / 1024.0); |
318 | |
319 | if (flv->framerate != 0.0) { |
320 | put_amf_string(pb, "framerate"); |
321 | put_amf_double(pb, flv->framerate); |
322 | metadata_count++; |
323 | } |
324 | |
325 | put_amf_string(pb, "videocodecid"); |
326 | put_amf_double(pb, flv->video_par->codec_tag); |
327 | } |
328 | |
329 | if (flv->audio_par) { |
330 | put_amf_string(pb, "audiodatarate"); |
331 | put_amf_double(pb, flv->audio_par->bit_rate / 1024.0); |
332 | |
333 | put_amf_string(pb, "audiosamplerate"); |
334 | put_amf_double(pb, flv->audio_par->sample_rate); |
335 | |
336 | put_amf_string(pb, "audiosamplesize"); |
337 | put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); |
338 | |
339 | put_amf_string(pb, "stereo"); |
340 | put_amf_bool(pb, flv->audio_par->channels == 2); |
341 | |
342 | put_amf_string(pb, "audiocodecid"); |
343 | put_amf_double(pb, flv->audio_par->codec_tag); |
344 | } |
345 | |
346 | if (flv->data_par) { |
347 | put_amf_string(pb, "datastream"); |
348 | put_amf_double(pb, 0.0); |
349 | } |
350 | |
351 | ff_standardize_creation_time(s); |
352 | while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { |
353 | if( !strcmp(tag->key, "width") |
354 | ||!strcmp(tag->key, "height") |
355 | ||!strcmp(tag->key, "videodatarate") |
356 | ||!strcmp(tag->key, "framerate") |
357 | ||!strcmp(tag->key, "videocodecid") |
358 | ||!strcmp(tag->key, "audiodatarate") |
359 | ||!strcmp(tag->key, "audiosamplerate") |
360 | ||!strcmp(tag->key, "audiosamplesize") |
361 | ||!strcmp(tag->key, "stereo") |
362 | ||!strcmp(tag->key, "audiocodecid") |
363 | ||!strcmp(tag->key, "duration") |
364 | ||!strcmp(tag->key, "onMetaData") |
365 | ||!strcmp(tag->key, "datasize") |
366 | ||!strcmp(tag->key, "lasttimestamp") |
367 | ||!strcmp(tag->key, "totalframes") |
368 | ||!strcmp(tag->key, "hasAudio") |
369 | ||!strcmp(tag->key, "hasVideo") |
370 | ||!strcmp(tag->key, "hasCuePoints") |
371 | ||!strcmp(tag->key, "hasMetadata") |
372 | ||!strcmp(tag->key, "hasKeyframes") |
373 | ){ |
374 | av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key); |
375 | continue; |
376 | } |
377 | put_amf_string(pb, tag->key); |
378 | avio_w8(pb, AMF_DATA_TYPE_STRING); |
379 | put_amf_string(pb, tag->value); |
380 | metadata_count++; |
381 | } |
382 | |
383 | if (write_duration_filesize) { |
384 | put_amf_string(pb, "filesize"); |
385 | flv->filesize_offset = avio_tell(pb); |
386 | put_amf_double(pb, 0); // delayed write |
387 | } |
388 | |
389 | if (flv->flags & FLV_ADD_KEYFRAME_INDEX) { |
390 | flv->acurframeindex = 0; |
391 | flv->keyframe_index_size = 0; |
392 | |
393 | put_amf_string(pb, "hasVideo"); |
394 | put_amf_bool(pb, !!flv->video_par); |
395 | metadata_count++; |
396 | |
397 | put_amf_string(pb, "hasKeyframes"); |
398 | put_amf_bool(pb, 1); |
399 | metadata_count++; |
400 | |
401 | put_amf_string(pb, "hasAudio"); |
402 | put_amf_bool(pb, !!flv->audio_par); |
403 | metadata_count++; |
404 | |
405 | put_amf_string(pb, "hasMetadata"); |
406 | put_amf_bool(pb, 1); |
407 | metadata_count++; |
408 | |
409 | put_amf_string(pb, "canSeekToEnd"); |
410 | put_amf_bool(pb, 1); |
411 | metadata_count++; |
412 | |
413 | put_amf_string(pb, "datasize"); |
414 | flv->datasize_offset = avio_tell(pb); |
415 | flv->datasize = 0; |
416 | put_amf_double(pb, flv->datasize); |
417 | metadata_count++; |
418 | |
419 | put_amf_string(pb, "videosize"); |
420 | flv->videosize_offset = avio_tell(pb); |
421 | flv->videosize = 0; |
422 | put_amf_double(pb, flv->videosize); |
423 | metadata_count++; |
424 | |
425 | put_amf_string(pb, "audiosize"); |
426 | flv->audiosize_offset = avio_tell(pb); |
427 | flv->audiosize = 0; |
428 | put_amf_double(pb, flv->audiosize); |
429 | metadata_count++; |
430 | |
431 | put_amf_string(pb, "lasttimestamp"); |
432 | flv->lasttimestamp_offset = avio_tell(pb); |
433 | flv->lasttimestamp = 0; |
434 | put_amf_double(pb, 0); |
435 | metadata_count++; |
436 | |
437 | put_amf_string(pb, "lastkeyframetimestamp"); |
438 | flv->lastkeyframetimestamp_offset = avio_tell(pb); |
439 | flv->lastkeyframetimestamp = 0; |
440 | put_amf_double(pb, 0); |
441 | metadata_count++; |
442 | |
443 | put_amf_string(pb, "lastkeyframelocation"); |
444 | flv->lastkeyframelocation_offset = avio_tell(pb); |
445 | flv->lastkeyframelocation = 0; |
446 | put_amf_double(pb, 0); |
447 | metadata_count++; |
448 | |
449 | put_amf_string(pb, "keyframes"); |
450 | put_amf_byte(pb, AMF_DATA_TYPE_OBJECT); |
451 | metadata_count++; |
452 | |
453 | flv->keyframes_info_offset = avio_tell(pb); |
454 | } |
455 | |
456 | put_amf_string(pb, ""); |
457 | avio_w8(pb, AMF_END_OF_OBJECT); |
458 | |
459 | /* write total size of tag */ |
460 | flv->metadata_totalsize = avio_tell(pb) - flv->metadata_size_pos - 10; |
461 | |
462 | avio_seek(pb, metadata_count_pos, SEEK_SET); |
463 | avio_wb32(pb, metadata_count); |
464 | |
465 | avio_seek(pb, flv->metadata_size_pos, SEEK_SET); |
466 | avio_wb24(pb, flv->metadata_totalsize); |
467 | avio_skip(pb, flv->metadata_totalsize + 10 - 3); |
468 | flv->metadata_totalsize_pos = avio_tell(pb); |
469 | avio_wb32(pb, flv->metadata_totalsize + 11); |
470 | } |
471 | |
472 | static int unsupported_codec(AVFormatContext *s, |
473 | const char* type, int codec_id) |
474 | { |
475 | const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); |
476 | av_log(s, AV_LOG_ERROR, |
477 | "%s codec %s not compatible with flv\n", |
478 | type, |
479 | desc ? desc->name : "unknown"); |
480 | return AVERROR(ENOSYS); |
481 | } |
482 | |
483 | static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par) { |
484 | int64_t data_size; |
485 | AVIOContext *pb = s->pb; |
486 | FLVContext *flv = s->priv_data; |
487 | |
488 | if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 |
489 | || par->codec_id == AV_CODEC_ID_MPEG4) { |
490 | int64_t pos; |
491 | avio_w8(pb, |
492 | par->codec_type == AVMEDIA_TYPE_VIDEO ? |
493 | FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO); |
494 | avio_wb24(pb, 0); // size patched later |
495 | avio_wb24(pb, 0); // ts |
496 | avio_w8(pb, 0); // ts ext |
497 | avio_wb24(pb, 0); // streamid |
498 | pos = avio_tell(pb); |
499 | if (par->codec_id == AV_CODEC_ID_AAC) { |
500 | avio_w8(pb, get_audio_flags(s, par)); |
501 | avio_w8(pb, 0); // AAC sequence header |
502 | |
503 | if (!par->extradata_size && (flv->flags & FLV_AAC_SEQ_HEADER_DETECT)) { |
504 | PutBitContext pbc; |
505 | int samplerate_index; |
506 | int channels = flv->audio_par->channels |
507 | - (flv->audio_par->channels == 8 ? 1 : 0); |
508 | uint8_t data[2]; |
509 | |
510 | for (samplerate_index = 0; samplerate_index < 16; |
511 | samplerate_index++) |
512 | if (flv->audio_par->sample_rate |
513 | == mpeg4audio_sample_rates[samplerate_index]) |
514 | break; |
515 | |
516 | init_put_bits(&pbc, data, sizeof(data)); |
517 | put_bits(&pbc, 5, flv->audio_par->profile + 1); //profile |
518 | put_bits(&pbc, 4, samplerate_index); //sample rate index |
519 | put_bits(&pbc, 4, channels); |
520 | put_bits(&pbc, 1, 0); //frame length - 1024 samples |
521 | put_bits(&pbc, 1, 0); //does not depend on core coder |
522 | put_bits(&pbc, 1, 0); //is not extension |
523 | flush_put_bits(&pbc); |
524 | |
525 | avio_w8(pb, data[0]); |
526 | avio_w8(pb, data[1]); |
527 | |
528 | av_log(s, AV_LOG_WARNING, "AAC sequence header: %02x %02x.\n", |
529 | data[0], data[1]); |
530 | } |
531 | avio_write(pb, par->extradata, par->extradata_size); |
532 | } else { |
533 | avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags |
534 | avio_w8(pb, 0); // AVC sequence header |
535 | avio_wb24(pb, 0); // composition time |
536 | ff_isom_write_avcc(pb, par->extradata, par->extradata_size); |
537 | } |
538 | data_size = avio_tell(pb) - pos; |
539 | avio_seek(pb, -data_size - 10, SEEK_CUR); |
540 | avio_wb24(pb, data_size); |
541 | avio_skip(pb, data_size + 10 - 3); |
542 | avio_wb32(pb, data_size + 11); // previous tag size |
543 | } |
544 | } |
545 | |
546 | static int flv_append_keyframe_info(AVFormatContext *s, FLVContext *flv, double ts, int64_t pos) |
547 | { |
548 | FLVFileposition *position = av_malloc(sizeof(FLVFileposition)); |
549 | |
550 | if (!position) { |
551 | av_log(s, AV_LOG_WARNING, "no mem for add keyframe index!\n"); |
552 | return AVERROR(ENOMEM); |
553 | } |
554 | |
555 | position->keyframe_timestamp = ts; |
556 | position->keyframe_position = pos; |
557 | |
558 | if (!flv->filepositions_count) { |
559 | flv->filepositions = position; |
560 | flv->head_filepositions = flv->filepositions; |
561 | position->next = NULL; |
562 | } else { |
563 | flv->filepositions->next = position; |
564 | position->next = NULL; |
565 | flv->filepositions = flv->filepositions->next; |
566 | } |
567 | |
568 | flv->filepositions_count++; |
569 | |
570 | return 0; |
571 | } |
572 | |
573 | static int shift_data(AVFormatContext *s) |
574 | { |
575 | int ret = 0; |
576 | int n = 0; |
577 | int64_t metadata_size = 0; |
578 | FLVContext *flv = s->priv_data; |
579 | int64_t pos, pos_end = avio_tell(s->pb); |
580 | uint8_t *buf, *read_buf[2]; |
581 | int read_buf_id = 0; |
582 | int read_size[2]; |
583 | AVIOContext *read_pb; |
584 | |
585 | metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */ |
586 | metadata_size += 2 + 13; /* filepositions String */ |
587 | metadata_size += 2 + 5; /* times String */ |
588 | metadata_size += 3; /* Object end */ |
589 | |
590 | flv->keyframe_index_size = metadata_size; |
591 | |
592 | if (metadata_size < 0) |
593 | return metadata_size; |
594 | |
595 | buf = av_malloc_array(metadata_size, 2); |
596 | if (!buf) { |
597 | return AVERROR(ENOMEM); |
598 | } |
599 | read_buf[0] = buf; |
600 | read_buf[1] = buf + metadata_size; |
601 | |
602 | avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET); |
603 | avio_wb24(s->pb, flv->metadata_totalsize + metadata_size); |
604 | |
605 | avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET); |
606 | avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size); |
607 | avio_seek(s->pb, pos_end, SEEK_SET); |
608 | |
609 | /* Shift the data: the AVIO context of the output can only be used for |
610 | * writing, so we re-open the same output, but for reading. It also avoids |
611 | * a read/seek/write/seek back and forth. */ |
612 | avio_flush(s->pb); |
613 | ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL); |
614 | if (ret < 0) { |
615 | av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " |
616 | "the second pass (add_keyframe_index)\n", s->filename); |
617 | goto end; |
618 | } |
619 | |
620 | /* mark the end of the shift to up to the last data we wrote, and get ready |
621 | * for writing */ |
622 | pos_end = avio_tell(s->pb); |
623 | avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET); |
624 | |
625 | /* start reading at where the keyframe index information will be placed */ |
626 | avio_seek(read_pb, flv->keyframes_info_offset, SEEK_SET); |
627 | pos = avio_tell(read_pb); |
628 | |
629 | #define READ_BLOCK do { \ |
630 | read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size); \ |
631 | read_buf_id ^= 1; \ |
632 | } while (0) |
633 | |
634 | /* shift data by chunk of at most keyframe *filepositions* and *times* size */ |
635 | READ_BLOCK; |
636 | do { |
637 | READ_BLOCK; |
638 | n = read_size[read_buf_id]; |
639 | if (n < 0) |
640 | break; |
641 | avio_write(s->pb, read_buf[read_buf_id], n); |
642 | pos += n; |
643 | } while (pos <= pos_end); |
644 | |
645 | ff_format_io_close(s, &read_pb); |
646 | |
647 | end: |
648 | av_free(buf); |
649 | return ret; |
650 | } |
651 | |
652 | |
653 | static int flv_write_header(AVFormatContext *s) |
654 | { |
655 | int i; |
656 | AVIOContext *pb = s->pb; |
657 | FLVContext *flv = s->priv_data; |
658 | |
659 | for (i = 0; i < s->nb_streams; i++) { |
660 | AVCodecParameters *par = s->streams[i]->codecpar; |
661 | FLVStreamContext *sc; |
662 | switch (par->codec_type) { |
663 | case AVMEDIA_TYPE_VIDEO: |
664 | if (s->streams[i]->avg_frame_rate.den && |
665 | s->streams[i]->avg_frame_rate.num) { |
666 | flv->framerate = av_q2d(s->streams[i]->avg_frame_rate); |
667 | } |
668 | if (flv->video_par) { |
669 | av_log(s, AV_LOG_ERROR, |
670 | "at most one video stream is supported in flv\n"); |
671 | return AVERROR(EINVAL); |
672 | } |
673 | flv->video_par = par; |
674 | if (!ff_codec_get_tag(flv_video_codec_ids, par->codec_id)) |
675 | return unsupported_codec(s, "Video", par->codec_id); |
676 | |
677 | if (par->codec_id == AV_CODEC_ID_MPEG4 || |
678 | par->codec_id == AV_CODEC_ID_H263) { |
679 | int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL; |
680 | av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING, |
681 | "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(par->codec_id)); |
682 | |
683 | if (error) { |
684 | av_log(s, AV_LOG_ERROR, |
685 | "use vstrict=-1 / -strict -1 to use it anyway.\n"); |
686 | return AVERROR(EINVAL); |
687 | } |
688 | } else if (par->codec_id == AV_CODEC_ID_VP6) { |
689 | av_log(s, AV_LOG_WARNING, |
690 | "Muxing VP6 in flv will produce flipped video on playback.\n"); |
691 | } |
692 | break; |
693 | case AVMEDIA_TYPE_AUDIO: |
694 | if (flv->audio_par) { |
695 | av_log(s, AV_LOG_ERROR, |
696 | "at most one audio stream is supported in flv\n"); |
697 | return AVERROR(EINVAL); |
698 | } |
699 | flv->audio_par = par; |
700 | if (get_audio_flags(s, par) < 0) |
701 | return unsupported_codec(s, "Audio", par->codec_id); |
702 | if (par->codec_id == AV_CODEC_ID_PCM_S16BE) |
703 | av_log(s, AV_LOG_WARNING, |
704 | "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n"); |
705 | break; |
706 | case AVMEDIA_TYPE_DATA: |
707 | if (par->codec_id != AV_CODEC_ID_TEXT && par->codec_id != AV_CODEC_ID_NONE) |
708 | return unsupported_codec(s, "Data", par->codec_id); |
709 | flv->data_par = par; |
710 | break; |
711 | case AVMEDIA_TYPE_SUBTITLE: |
712 | if (par->codec_id != AV_CODEC_ID_TEXT) { |
713 | av_log(s, AV_LOG_ERROR, "Subtitle codec '%s' for stream %d is not compatible with FLV\n", |
714 | avcodec_get_name(par->codec_id), i); |
715 | return AVERROR_INVALIDDATA; |
716 | } |
717 | flv->data_par = par; |
718 | break; |
719 | default: |
720 | av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n", |
721 | av_get_media_type_string(par->codec_type), i); |
722 | return AVERROR(EINVAL); |
723 | } |
724 | avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ |
725 | |
726 | sc = av_mallocz(sizeof(FLVStreamContext)); |
727 | if (!sc) |
728 | return AVERROR(ENOMEM); |
729 | s->streams[i]->priv_data = sc; |
730 | sc->last_ts = -1; |
731 | } |
732 | |
733 | flv->delay = AV_NOPTS_VALUE; |
734 | |
735 | avio_write(pb, "FLV", 3); |
736 | avio_w8(pb, 1); |
737 | avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_par + |
738 | FLV_HEADER_FLAG_HASVIDEO * !!flv->video_par); |
739 | avio_wb32(pb, 9); |
740 | avio_wb32(pb, 0); |
741 | |
742 | for (i = 0; i < s->nb_streams; i++) |
743 | if (s->streams[i]->codecpar->codec_tag == 5) { |
744 | avio_w8(pb, 8); // message type |
745 | avio_wb24(pb, 0); // include flags |
746 | avio_wb24(pb, 0); // time stamp |
747 | avio_wb32(pb, 0); // reserved |
748 | avio_wb32(pb, 11); // size |
749 | flv->reserved = 5; |
750 | } |
751 | |
752 | if (flv->flags & FLV_NO_METADATA) { |
753 | pb->seekable = 0; |
754 | } else { |
755 | write_metadata(s, 0); |
756 | } |
757 | |
758 | for (i = 0; i < s->nb_streams; i++) { |
759 | flv_write_codec_header(s, s->streams[i]->codecpar); |
760 | } |
761 | |
762 | flv->datastart_offset = avio_tell(pb); |
763 | return 0; |
764 | } |
765 | |
766 | static int flv_write_trailer(AVFormatContext *s) |
767 | { |
768 | int64_t file_size; |
769 | AVIOContext *pb = s->pb; |
770 | FLVContext *flv = s->priv_data; |
771 | int build_keyframes_idx = flv->flags & FLV_ADD_KEYFRAME_INDEX; |
772 | int i, res; |
773 | int64_t cur_pos = avio_tell(s->pb); |
774 | |
775 | if (build_keyframes_idx) { |
776 | FLVFileposition *newflv_posinfo, *p; |
777 | |
778 | avio_seek(pb, flv->videosize_offset, SEEK_SET); |
779 | put_amf_double(pb, flv->videosize); |
780 | |
781 | avio_seek(pb, flv->audiosize_offset, SEEK_SET); |
782 | put_amf_double(pb, flv->audiosize); |
783 | |
784 | avio_seek(pb, flv->lasttimestamp_offset, SEEK_SET); |
785 | put_amf_double(pb, flv->lasttimestamp); |
786 | |
787 | avio_seek(pb, flv->lastkeyframetimestamp_offset, SEEK_SET); |
788 | put_amf_double(pb, flv->lastkeyframetimestamp); |
789 | |
790 | avio_seek(pb, flv->lastkeyframelocation_offset, SEEK_SET); |
791 | put_amf_double(pb, flv->lastkeyframelocation + flv->keyframe_index_size); |
792 | avio_seek(pb, cur_pos, SEEK_SET); |
793 | |
794 | res = shift_data(s); |
795 | if (res < 0) { |
796 | goto end; |
797 | } |
798 | avio_seek(pb, flv->keyframes_info_offset, SEEK_SET); |
799 | put_amf_string(pb, "filepositions"); |
800 | put_amf_dword_array(pb, flv->filepositions_count); |
801 | for (newflv_posinfo = flv->head_filepositions; newflv_posinfo; newflv_posinfo = newflv_posinfo->next) { |
802 | put_amf_double(pb, newflv_posinfo->keyframe_position + flv->keyframe_index_size); |
803 | } |
804 | |
805 | put_amf_string(pb, "times"); |
806 | put_amf_dword_array(pb, flv->filepositions_count); |
807 | for (newflv_posinfo = flv->head_filepositions; newflv_posinfo; newflv_posinfo = newflv_posinfo->next) { |
808 | put_amf_double(pb, newflv_posinfo->keyframe_timestamp); |
809 | } |
810 | |
811 | newflv_posinfo = flv->head_filepositions; |
812 | while (newflv_posinfo) { |
813 | p = newflv_posinfo->next; |
814 | if (p) { |
815 | newflv_posinfo->next = p->next; |
816 | av_free(p); |
817 | p = NULL; |
818 | } else { |
819 | av_free(newflv_posinfo); |
820 | newflv_posinfo = NULL; |
821 | } |
822 | } |
823 | |
824 | put_amf_string(pb, ""); |
825 | avio_w8(pb, AMF_END_OF_OBJECT); |
826 | |
827 | avio_seek(pb, cur_pos + flv->keyframe_index_size, SEEK_SET); |
828 | } |
829 | |
830 | end: |
831 | if (flv->flags & FLV_NO_SEQUENCE_END) { |
832 | av_log(s, AV_LOG_DEBUG, "FLV no sequence end mode open\n"); |
833 | } else { |
834 | /* Add EOS tag */ |
835 | for (i = 0; i < s->nb_streams; i++) { |
836 | AVCodecParameters *par = s->streams[i]->codecpar; |
837 | FLVStreamContext *sc = s->streams[i]->priv_data; |
838 | if (par->codec_type == AVMEDIA_TYPE_VIDEO && |
839 | (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)) |
840 | put_avc_eos_tag(pb, sc->last_ts); |
841 | } |
842 | } |
843 | |
844 | file_size = avio_tell(pb); |
845 | |
846 | if (build_keyframes_idx) { |
847 | flv->datasize = file_size - flv->datastart_offset; |
848 | avio_seek(pb, flv->datasize_offset, SEEK_SET); |
849 | put_amf_double(pb, flv->datasize); |
850 | } |
851 | if (!(flv->flags & FLV_NO_METADATA)) { |
852 | if (!(flv->flags & FLV_NO_DURATION_FILESIZE)) { |
853 | /* update information */ |
854 | if (avio_seek(pb, flv->duration_offset, SEEK_SET) < 0) { |
855 | av_log(s, AV_LOG_WARNING, "Failed to update header with correct duration.\n"); |
856 | } else { |
857 | put_amf_double(pb, flv->duration / (double)1000); |
858 | } |
859 | if (avio_seek(pb, flv->filesize_offset, SEEK_SET) < 0) { |
860 | av_log(s, AV_LOG_WARNING, "Failed to update header with correct filesize.\n"); |
861 | } else { |
862 | put_amf_double(pb, file_size); |
863 | } |
864 | } |
865 | } |
866 | |
867 | return 0; |
868 | } |
869 | |
870 | static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) |
871 | { |
872 | AVIOContext *pb = s->pb; |
873 | AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; |
874 | FLVContext *flv = s->priv_data; |
875 | FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data; |
876 | unsigned ts; |
877 | int size = pkt->size; |
878 | uint8_t *data = NULL; |
879 | int flags = -1, flags_size, ret; |
880 | int64_t cur_offset = avio_tell(pb); |
881 | |
882 | if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A || |
883 | par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC) |
884 | flags_size = 2; |
885 | else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) |
886 | flags_size = 5; |
887 | else |
888 | flags_size = 1; |
889 | |
890 | if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 |
891 | || par->codec_id == AV_CODEC_ID_MPEG4) { |
892 | int side_size = 0; |
893 | uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); |
894 | if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { |
895 | av_free(par->extradata); |
896 | par->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); |
897 | if (!par->extradata) { |
898 | par->extradata_size = 0; |
899 | return AVERROR(ENOMEM); |
900 | } |
901 | memcpy(par->extradata, side, side_size); |
902 | par->extradata_size = side_size; |
903 | flv_write_codec_header(s, par); |
904 | } |
905 | } |
906 | |
907 | if (flv->delay == AV_NOPTS_VALUE) |
908 | flv->delay = -pkt->dts; |
909 | |
910 | if (pkt->dts < -flv->delay) { |
911 | av_log(s, AV_LOG_WARNING, |
912 | "Packets are not in the proper order with respect to DTS\n"); |
913 | return AVERROR(EINVAL); |
914 | } |
915 | |
916 | ts = pkt->dts; |
917 | |
918 | if (s->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) { |
919 | write_metadata(s, ts); |
920 | s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED; |
921 | } |
922 | |
923 | avio_write_marker(pb, av_rescale(ts, AV_TIME_BASE, 1000), |
924 | pkt->flags & AV_PKT_FLAG_KEY && (flv->video_par ? par->codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT); |
925 | |
926 | switch (par->codec_type) { |
927 | case AVMEDIA_TYPE_VIDEO: |
928 | avio_w8(pb, FLV_TAG_TYPE_VIDEO); |
929 | |
930 | flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id); |
931 | |
932 | flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; |
933 | break; |
934 | case AVMEDIA_TYPE_AUDIO: |
935 | flags = get_audio_flags(s, par); |
936 | |
937 | av_assert0(size); |
938 | |
939 | avio_w8(pb, FLV_TAG_TYPE_AUDIO); |
940 | break; |
941 | case AVMEDIA_TYPE_SUBTITLE: |
942 | case AVMEDIA_TYPE_DATA: |
943 | avio_w8(pb, FLV_TAG_TYPE_META); |
944 | break; |
945 | default: |
946 | return AVERROR(EINVAL); |
947 | } |
948 | |
949 | if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { |
950 | /* check if extradata looks like mp4 formatted */ |
951 | if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) |
952 | if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0) |
953 | return ret; |
954 | } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && |
955 | (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { |
956 | if (!s->streams[pkt->stream_index]->nb_frames) { |
957 | av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " |
958 | "use the audio bitstream filter 'aac_adtstoasc' to fix it " |
959 | "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); |
960 | return AVERROR_INVALIDDATA; |
961 | } |
962 | av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); |
963 | } |
964 | |
965 | /* check Speex packet duration */ |
966 | if (par->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160) |
967 | av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than " |
968 | "8 frames per packet. Adobe Flash " |
969 | "Player cannot handle this!\n"); |
970 | |
971 | if (sc->last_ts < ts) |
972 | sc->last_ts = ts; |
973 | |
974 | if (size + flags_size >= 1<<24) { |
975 | av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n", |
976 | size + flags_size, 1<<24); |
977 | return AVERROR(EINVAL); |
978 | } |
979 | |
980 | avio_wb24(pb, size + flags_size); |
981 | avio_wb24(pb, ts & 0xFFFFFF); |
982 | avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_ |
983 | avio_wb24(pb, flv->reserved); |
984 | |
985 | if (par->codec_type == AVMEDIA_TYPE_DATA || |
986 | par->codec_type == AVMEDIA_TYPE_SUBTITLE ) { |
987 | int data_size; |
988 | int64_t metadata_size_pos = avio_tell(pb); |
989 | if (par->codec_id == AV_CODEC_ID_TEXT) { |
990 | // legacy FFmpeg magic? |
991 | avio_w8(pb, AMF_DATA_TYPE_STRING); |
992 | put_amf_string(pb, "onTextData"); |
993 | avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); |
994 | avio_wb32(pb, 2); |
995 | put_amf_string(pb, "type"); |
996 | avio_w8(pb, AMF_DATA_TYPE_STRING); |
997 | put_amf_string(pb, "Text"); |
998 | put_amf_string(pb, "text"); |
999 | avio_w8(pb, AMF_DATA_TYPE_STRING); |
1000 | put_amf_string(pb, pkt->data); |
1001 | put_amf_string(pb, ""); |
1002 | avio_w8(pb, AMF_END_OF_OBJECT); |
1003 | } else { |
1004 | // just pass the metadata through |
1005 | avio_write(pb, data ? data : pkt->data, size); |
1006 | } |
1007 | /* write total size of tag */ |
1008 | data_size = avio_tell(pb) - metadata_size_pos; |
1009 | avio_seek(pb, metadata_size_pos - 10, SEEK_SET); |
1010 | avio_wb24(pb, data_size); |
1011 | avio_seek(pb, data_size + 10 - 3, SEEK_CUR); |
1012 | avio_wb32(pb, data_size + 11); |
1013 | } else { |
1014 | av_assert1(flags>=0); |
1015 | avio_w8(pb,flags); |
1016 | if (par->codec_id == AV_CODEC_ID_VP6) |
1017 | avio_w8(pb,0); |
1018 | if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) { |
1019 | if (par->extradata_size) |
1020 | avio_w8(pb, par->extradata[0]); |
1021 | else |
1022 | avio_w8(pb, ((FFALIGN(par->width, 16) - par->width) << 4) | |
1023 | (FFALIGN(par->height, 16) - par->height)); |
1024 | } else if (par->codec_id == AV_CODEC_ID_AAC) |
1025 | avio_w8(pb, 1); // AAC raw |
1026 | else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { |
1027 | avio_w8(pb, 1); // AVC NALU |
1028 | avio_wb24(pb, pkt->pts - pkt->dts); |
1029 | } |
1030 | |
1031 | avio_write(pb, data ? data : pkt->data, size); |
1032 | |
1033 | avio_wb32(pb, size + flags_size + 11); // previous tag size |
1034 | flv->duration = FFMAX(flv->duration, |
1035 | pkt->pts + flv->delay + pkt->duration); |
1036 | } |
1037 | |
1038 | if (flv->flags & FLV_ADD_KEYFRAME_INDEX) { |
1039 | switch (par->codec_type) { |
1040 | case AVMEDIA_TYPE_VIDEO: |
1041 | flv->videosize += (avio_tell(pb) - cur_offset); |
1042 | flv->lasttimestamp = flv->acurframeindex / flv->framerate; |
1043 | if (pkt->flags & AV_PKT_FLAG_KEY) { |
1044 | double ts = flv->acurframeindex / flv->framerate; |
1045 | int64_t pos = cur_offset; |
1046 | |
1047 | flv->lastkeyframetimestamp = flv->acurframeindex / flv->framerate; |
1048 | flv->lastkeyframelocation = pos; |
1049 | flv_append_keyframe_info(s, flv, ts, pos); |
1050 | } |
1051 | flv->acurframeindex++; |
1052 | break; |
1053 | |
1054 | case AVMEDIA_TYPE_AUDIO: |
1055 | flv->audiosize += (avio_tell(pb) - cur_offset); |
1056 | break; |
1057 | |
1058 | default: |
1059 | av_log(s, AV_LOG_WARNING, "par->codec_type is type = [%d]\n", par->codec_type); |
1060 | break; |
1061 | } |
1062 | } |
1063 | |
1064 | av_free(data); |
1065 | |
1066 | return pb->error; |
1067 | } |
1068 | |
1069 | static const AVOption options[] = { |
1070 | { "flvflags", "FLV muxer flags", offsetof(FLVContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, |
1071 | { "aac_seq_header_detect", "Put AAC sequence header based on stream data", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_AAC_SEQ_HEADER_DETECT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, |
1072 | { "no_sequence_end", "disable sequence end for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_SEQUENCE_END}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, |
1073 | { "no_metadata", "disable metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_METADATA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, |
1074 | { "no_duration_filesize", "disable duration and filesize zero value metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_DURATION_FILESIZE}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, |
1075 | { "add_keyframe_index", "Add keyframe index metadata", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_ADD_KEYFRAME_INDEX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, |
1076 | { NULL }, |
1077 | }; |
1078 | |
1079 | static const AVClass flv_muxer_class = { |
1080 | .class_name = "flv muxer", |
1081 | .item_name = av_default_item_name, |
1082 | .option = options, |
1083 | .version = LIBAVUTIL_VERSION_INT, |
1084 | }; |
1085 | |
1086 | AVOutputFormat ff_flv_muxer = { |
1087 | .name = "flv", |
1088 | .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"), |
1089 | .mime_type = "video/x-flv", |
1090 | .extensions = "flv", |
1091 | .priv_data_size = sizeof(FLVContext), |
1092 | .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF, |
1093 | .video_codec = AV_CODEC_ID_FLV1, |
1094 | .write_header = flv_write_header, |
1095 | .write_packet = flv_write_packet, |
1096 | .write_trailer = flv_write_trailer, |
1097 | .codec_tag = (const AVCodecTag* const []) { |
1098 | flv_video_codec_ids, flv_audio_codec_ids, 0 |
1099 | }, |
1100 | .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | |
1101 | AVFMT_TS_NONSTRICT, |
1102 | .priv_class = &flv_muxer_class, |
1103 | }; |
1104 |