3 * Copyright (c) 2003 The FFmpeg Project
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/dict.h"
24 #include "libavutil/intfloat.h"
25 #include "libavutil/avassert.h"
33 static const AVCodecTag flv_video_codec_ids
[] = {
34 { AV_CODEC_ID_FLV1
, FLV_CODECID_H263
},
35 { AV_CODEC_ID_H263
, FLV_CODECID_REALH263
},
36 { AV_CODEC_ID_MPEG4
, FLV_CODECID_MPEG4
},
37 { AV_CODEC_ID_FLASHSV
, FLV_CODECID_SCREEN
},
38 { AV_CODEC_ID_FLASHSV2
, FLV_CODECID_SCREEN2
},
39 { AV_CODEC_ID_VP6F
, FLV_CODECID_VP6
},
40 { AV_CODEC_ID_VP6
, FLV_CODECID_VP6
},
41 { AV_CODEC_ID_VP6A
, FLV_CODECID_VP6A
},
42 { AV_CODEC_ID_H264
, FLV_CODECID_H264
},
43 { AV_CODEC_ID_NONE
, 0 }
46 static const AVCodecTag flv_audio_codec_ids
[] = {
47 { AV_CODEC_ID_MP3
, FLV_CODECID_MP3
>> FLV_AUDIO_CODECID_OFFSET
},
48 { AV_CODEC_ID_PCM_U8
, FLV_CODECID_PCM
>> FLV_AUDIO_CODECID_OFFSET
},
49 { AV_CODEC_ID_PCM_S16BE
, FLV_CODECID_PCM
>> FLV_AUDIO_CODECID_OFFSET
},
50 { AV_CODEC_ID_PCM_S16LE
, FLV_CODECID_PCM_LE
>> FLV_AUDIO_CODECID_OFFSET
},
51 { AV_CODEC_ID_ADPCM_SWF
, FLV_CODECID_ADPCM
>> FLV_AUDIO_CODECID_OFFSET
},
52 { AV_CODEC_ID_AAC
, FLV_CODECID_AAC
>> FLV_AUDIO_CODECID_OFFSET
},
53 { AV_CODEC_ID_NELLYMOSER
, FLV_CODECID_NELLYMOSER
>> FLV_AUDIO_CODECID_OFFSET
},
54 { AV_CODEC_ID_PCM_MULAW
, FLV_CODECID_PCM_MULAW
>> FLV_AUDIO_CODECID_OFFSET
},
55 { AV_CODEC_ID_PCM_ALAW
, FLV_CODECID_PCM_ALAW
>> FLV_AUDIO_CODECID_OFFSET
},
56 { AV_CODEC_ID_SPEEX
, FLV_CODECID_SPEEX
>> FLV_AUDIO_CODECID_OFFSET
},
57 { AV_CODEC_ID_NONE
, 0 }
60 typedef struct FLVContext
{
62 int64_t duration_offset
;
63 int64_t filesize_offset
;
65 int64_t delay
; ///< first dts delay (needed for AVC & Speex)
68 typedef struct FLVStreamContext
{
69 int64_t last_ts
; ///< last timestamp for each stream
72 static int get_audio_flags(AVFormatContext
*s
, AVCodecContext
*enc
)
74 int flags
= (enc
->bits_per_coded_sample
== 16) ? FLV_SAMPLESSIZE_16BIT
75 : FLV_SAMPLESSIZE_8BIT
;
77 if (enc
->codec_id
== AV_CODEC_ID_AAC
) // specs force these parameters
78 return FLV_CODECID_AAC
| FLV_SAMPLERATE_44100HZ
|
79 FLV_SAMPLESSIZE_16BIT
| FLV_STEREO
;
80 else if (enc
->codec_id
== AV_CODEC_ID_SPEEX
) {
81 if (enc
->sample_rate
!= 16000) {
82 av_log(s
, AV_LOG_ERROR
,
83 "FLV only supports wideband (16kHz) Speex audio\n");
84 return AVERROR(EINVAL
);
86 if (enc
->channels
!= 1) {
87 av_log(s
, AV_LOG_ERROR
, "FLV only supports mono Speex audio\n");
88 return AVERROR(EINVAL
);
90 return FLV_CODECID_SPEEX
| FLV_SAMPLERATE_11025HZ
| FLV_SAMPLESSIZE_16BIT
;
92 switch (enc
->sample_rate
) {
94 flags
|= FLV_SAMPLERATE_44100HZ
;
97 flags
|= FLV_SAMPLERATE_22050HZ
;
100 flags
|= FLV_SAMPLERATE_11025HZ
;
102 case 16000: // nellymoser only
103 case 8000: // nellymoser only
104 case 5512: // not MP3
105 if (enc
->codec_id
!= AV_CODEC_ID_MP3
) {
106 flags
|= FLV_SAMPLERATE_SPECIAL
;
110 av_log(s
, AV_LOG_ERROR
,
111 "FLV does not support sample rate %d, "
112 "choose from (44100, 22050, 11025)\n", enc
->sample_rate
);
113 return AVERROR(EINVAL
);
117 if (enc
->channels
> 1)
120 switch (enc
->codec_id
) {
121 case AV_CODEC_ID_MP3
:
122 flags
|= FLV_CODECID_MP3
| FLV_SAMPLESSIZE_16BIT
;
124 case AV_CODEC_ID_PCM_U8
:
125 flags
|= FLV_CODECID_PCM
| FLV_SAMPLESSIZE_8BIT
;
127 case AV_CODEC_ID_PCM_S16BE
:
128 flags
|= FLV_CODECID_PCM
| FLV_SAMPLESSIZE_16BIT
;
130 case AV_CODEC_ID_PCM_S16LE
:
131 flags
|= FLV_CODECID_PCM_LE
| FLV_SAMPLESSIZE_16BIT
;
133 case AV_CODEC_ID_ADPCM_SWF
:
134 flags
|= FLV_CODECID_ADPCM
| FLV_SAMPLESSIZE_16BIT
;
136 case AV_CODEC_ID_NELLYMOSER
:
137 if (enc
->sample_rate
== 8000)
138 flags
|= FLV_CODECID_NELLYMOSER_8KHZ_MONO
| FLV_SAMPLESSIZE_16BIT
;
139 else if (enc
->sample_rate
== 16000)
140 flags
|= FLV_CODECID_NELLYMOSER_16KHZ_MONO
| FLV_SAMPLESSIZE_16BIT
;
142 flags
|= FLV_CODECID_NELLYMOSER
| FLV_SAMPLESSIZE_16BIT
;
144 case AV_CODEC_ID_PCM_MULAW
:
145 flags
= FLV_CODECID_PCM_MULAW
| FLV_SAMPLERATE_SPECIAL
| FLV_SAMPLESSIZE_16BIT
;
147 case AV_CODEC_ID_PCM_ALAW
:
148 flags
= FLV_CODECID_PCM_ALAW
| FLV_SAMPLERATE_SPECIAL
| FLV_SAMPLESSIZE_16BIT
;
151 flags
|= enc
->codec_tag
<< 4;
154 av_log(s
, AV_LOG_ERROR
, "Audio codec '%s' not compatible with FLV\n",
155 avcodec_get_name(enc
->codec_id
));
156 return AVERROR(EINVAL
);
162 static void put_amf_string(AVIOContext
*pb
, const char *str
)
164 size_t len
= strlen(str
);
166 avio_write(pb
, str
, len
);
169 static void put_avc_eos_tag(AVIOContext
*pb
, unsigned ts
)
171 avio_w8(pb
, FLV_TAG_TYPE_VIDEO
);
172 avio_wb24(pb
, 5); /* Tag Data Size */
173 avio_wb24(pb
, ts
); /* lower 24 bits of timestamp in ms */
174 avio_w8(pb
, (ts
>> 24) & 0x7F); /* MSB of ts in ms */
175 avio_wb24(pb
, 0); /* StreamId = 0 */
176 avio_w8(pb
, 23); /* ub[4] FrameType = 1, ub[4] CodecId = 7 */
177 avio_w8(pb
, 2); /* AVC end of sequence */
178 avio_wb24(pb
, 0); /* Always 0 for AVC EOS. */
179 avio_wb32(pb
, 16); /* Size of FLV tag */
182 static void put_amf_double(AVIOContext
*pb
, double d
)
184 avio_w8(pb
, AMF_DATA_TYPE_NUMBER
);
185 avio_wb64(pb
, av_double2int(d
));
188 static void put_amf_bool(AVIOContext
*pb
, int b
)
190 avio_w8(pb
, AMF_DATA_TYPE_BOOL
);
194 static int flv_write_header(AVFormatContext
*s
)
196 AVIOContext
*pb
= s
->pb
;
197 FLVContext
*flv
= s
->priv_data
;
198 AVCodecContext
*audio_enc
= NULL
, *video_enc
= NULL
, *data_enc
= NULL
;
199 int i
, metadata_count
= 0;
200 double framerate
= 0.0;
201 int64_t metadata_size_pos
, data_size
, metadata_count_pos
;
202 AVDictionaryEntry
*tag
= NULL
;
204 for (i
= 0; i
< s
->nb_streams
; i
++) {
205 AVCodecContext
*enc
= s
->streams
[i
]->codec
;
206 FLVStreamContext
*sc
;
207 switch (enc
->codec_type
) {
208 case AVMEDIA_TYPE_VIDEO
:
209 if (s
->streams
[i
]->avg_frame_rate
.den
&&
210 s
->streams
[i
]->avg_frame_rate
.num
) {
211 framerate
= av_q2d(s
->streams
[i
]->avg_frame_rate
);
214 av_log(s
, AV_LOG_ERROR
,
215 "at most one video stream is supported in flv\n");
216 return AVERROR(EINVAL
);
219 if (enc
->codec_tag
== 0) {
220 av_log(s
, AV_LOG_ERROR
, "Video codec '%s' for stream %d is not compatible with FLV\n",
221 avcodec_get_name(enc
->codec_id
), i
);
222 return AVERROR(EINVAL
);
224 if (enc
->codec_id
== AV_CODEC_ID_MPEG4
||
225 enc
->codec_id
== AV_CODEC_ID_H263
) {
226 int error
= enc
->strict_std_compliance
> FF_COMPLIANCE_UNOFFICIAL
;
227 av_log(s
, error
? AV_LOG_ERROR
: AV_LOG_WARNING
,
228 "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(enc
->codec_id
));
231 av_log(s
, AV_LOG_ERROR
,
232 "use vstrict=-1 / -strict -1 to use it anyway.\n");
233 return AVERROR(EINVAL
);
237 case AVMEDIA_TYPE_AUDIO
:
239 av_log(s
, AV_LOG_ERROR
,
240 "at most one audio stream is supported in flv\n");
241 return AVERROR(EINVAL
);
244 if (get_audio_flags(s
, enc
) < 0)
245 return AVERROR_INVALIDDATA
;
246 if (enc
->codec_id
== AV_CODEC_ID_PCM_S16BE
)
247 av_log(s
, AV_LOG_WARNING
,
248 "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
250 case AVMEDIA_TYPE_DATA
:
251 if (enc
->codec_id
!= AV_CODEC_ID_TEXT
) {
252 av_log(s
, AV_LOG_ERROR
, "Data codec '%s' for stream %d is not compatible with FLV\n",
253 avcodec_get_name(enc
->codec_id
), i
);
254 return AVERROR_INVALIDDATA
;
259 av_log(s
, AV_LOG_ERROR
, "Codec type '%s' for stream %d is not compatible with FLV\n",
260 av_get_media_type_string(enc
->codec_type
), i
);
261 return AVERROR(EINVAL
);
263 avpriv_set_pts_info(s
->streams
[i
], 32, 1, 1000); /* 32 bit pts in ms */
265 sc
= av_mallocz(sizeof(FLVStreamContext
));
267 return AVERROR(ENOMEM
);
268 s
->streams
[i
]->priv_data
= sc
;
272 flv
->delay
= AV_NOPTS_VALUE
;
274 avio_write(pb
, "FLV", 3);
276 avio_w8(pb
, FLV_HEADER_FLAG_HASAUDIO
* !!audio_enc
+
277 FLV_HEADER_FLAG_HASVIDEO
* !!video_enc
);
281 for (i
= 0; i
< s
->nb_streams
; i
++)
282 if (s
->streams
[i
]->codec
->codec_tag
== 5) {
283 avio_w8(pb
, 8); // message type
284 avio_wb24(pb
, 0); // include flags
285 avio_wb24(pb
, 0); // time stamp
286 avio_wb32(pb
, 0); // reserved
287 avio_wb32(pb
, 11); // size
292 avio_w8(pb
, 18); // tag type META
293 metadata_size_pos
= avio_tell(pb
);
294 avio_wb24(pb
, 0); // size of data part (sum of all parts below)
295 avio_wb24(pb
, 0); // timestamp
296 avio_wb32(pb
, 0); // reserved
298 /* now data of data_size size */
300 /* first event name as a string */
301 avio_w8(pb
, AMF_DATA_TYPE_STRING
);
302 put_amf_string(pb
, "onMetaData"); // 12 bytes
304 /* mixed array (hash) with size and string/type/data tuples */
305 avio_w8(pb
, AMF_DATA_TYPE_MIXEDARRAY
);
306 metadata_count_pos
= avio_tell(pb
);
307 metadata_count
= 4 * !!video_enc
+
310 2; // +2 for duration and file size
312 avio_wb32(pb
, metadata_count
);
314 put_amf_string(pb
, "duration");
315 flv
->duration_offset
= avio_tell(pb
);
317 // fill in the guessed duration, it'll be corrected later if incorrect
318 put_amf_double(pb
, s
->duration
/ AV_TIME_BASE
);
321 put_amf_string(pb
, "width");
322 put_amf_double(pb
, video_enc
->width
);
324 put_amf_string(pb
, "height");
325 put_amf_double(pb
, video_enc
->height
);
327 put_amf_string(pb
, "videodatarate");
328 put_amf_double(pb
, video_enc
->bit_rate
/ 1024.0);
330 if (framerate
!= 0.0) {
331 put_amf_string(pb
, "framerate");
332 put_amf_double(pb
, framerate
);
336 put_amf_string(pb
, "videocodecid");
337 put_amf_double(pb
, video_enc
->codec_tag
);
341 put_amf_string(pb
, "audiodatarate");
342 put_amf_double(pb
, audio_enc
->bit_rate
/ 1024.0);
344 put_amf_string(pb
, "audiosamplerate");
345 put_amf_double(pb
, audio_enc
->sample_rate
);
347 put_amf_string(pb
, "audiosamplesize");
348 put_amf_double(pb
, audio_enc
->codec_id
== AV_CODEC_ID_PCM_U8
? 8 : 16);
350 put_amf_string(pb
, "stereo");
351 put_amf_bool(pb
, audio_enc
->channels
== 2);
353 put_amf_string(pb
, "audiocodecid");
354 put_amf_double(pb
, audio_enc
->codec_tag
);
358 put_amf_string(pb
, "datastream");
359 put_amf_double(pb
, 0.0);
362 while ((tag
= av_dict_get(s
->metadata
, "", tag
, AV_DICT_IGNORE_SUFFIX
))) {
363 if( !strcmp(tag
->key
, "width")
364 ||!strcmp(tag
->key
, "height")
365 ||!strcmp(tag
->key
, "videodatarate")
366 ||!strcmp(tag
->key
, "framerate")
367 ||!strcmp(tag
->key
, "videocodecid")
368 ||!strcmp(tag
->key
, "audiodatarate")
369 ||!strcmp(tag
->key
, "audiosamplerate")
370 ||!strcmp(tag
->key
, "audiosamplesize")
371 ||!strcmp(tag
->key
, "stereo")
372 ||!strcmp(tag
->key
, "audiocodecid")
373 ||!strcmp(tag
->key
, "duration")
374 ||!strcmp(tag
->key
, "onMetaData")
376 av_log(s
, AV_LOG_DEBUG
, "Ignoring metadata for %s\n", tag
->key
);
379 put_amf_string(pb
, tag
->key
);
380 avio_w8(pb
, AMF_DATA_TYPE_STRING
);
381 put_amf_string(pb
, tag
->value
);
385 put_amf_string(pb
, "filesize");
386 flv
->filesize_offset
= avio_tell(pb
);
387 put_amf_double(pb
, 0); // delayed write
389 put_amf_string(pb
, "");
390 avio_w8(pb
, AMF_END_OF_OBJECT
);
392 /* write total size of tag */
393 data_size
= avio_tell(pb
) - metadata_size_pos
- 10;
395 avio_seek(pb
, metadata_count_pos
, SEEK_SET
);
396 avio_wb32(pb
, metadata_count
);
398 avio_seek(pb
, metadata_size_pos
, SEEK_SET
);
399 avio_wb24(pb
, data_size
);
400 avio_skip(pb
, data_size
+ 10 - 3);
401 avio_wb32(pb
, data_size
+ 11);
403 for (i
= 0; i
< s
->nb_streams
; i
++) {
404 AVCodecContext
*enc
= s
->streams
[i
]->codec
;
405 if (enc
->codec_id
== AV_CODEC_ID_AAC
|| enc
->codec_id
== AV_CODEC_ID_H264
|| enc
->codec_id
== AV_CODEC_ID_MPEG4
) {
407 avio_w8(pb
, enc
->codec_type
== AVMEDIA_TYPE_VIDEO
?
408 FLV_TAG_TYPE_VIDEO
: FLV_TAG_TYPE_AUDIO
);
409 avio_wb24(pb
, 0); // size patched later
410 avio_wb24(pb
, 0); // ts
411 avio_w8(pb
, 0); // ts ext
412 avio_wb24(pb
, 0); // streamid
414 if (enc
->codec_id
== AV_CODEC_ID_AAC
) {
415 avio_w8(pb
, get_audio_flags(s
, enc
));
416 avio_w8(pb
, 0); // AAC sequence header
417 avio_write(pb
, enc
->extradata
, enc
->extradata_size
);
419 avio_w8(pb
, enc
->codec_tag
| FLV_FRAME_KEY
); // flags
420 avio_w8(pb
, 0); // AVC sequence header
421 avio_wb24(pb
, 0); // composition time
422 ff_isom_write_avcc(pb
, enc
->extradata
, enc
->extradata_size
);
424 data_size
= avio_tell(pb
) - pos
;
425 avio_seek(pb
, -data_size
- 10, SEEK_CUR
);
426 avio_wb24(pb
, data_size
);
427 avio_skip(pb
, data_size
+ 10 - 3);
428 avio_wb32(pb
, data_size
+ 11); // previous tag size
435 static int flv_write_trailer(AVFormatContext
*s
)
439 AVIOContext
*pb
= s
->pb
;
440 FLVContext
*flv
= s
->priv_data
;
444 for (i
= 0; i
< s
->nb_streams
; i
++) {
445 AVCodecContext
*enc
= s
->streams
[i
]->codec
;
446 FLVStreamContext
*sc
= s
->streams
[i
]->priv_data
;
447 if (enc
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
448 (enc
->codec_id
== AV_CODEC_ID_H264
|| enc
->codec_id
== AV_CODEC_ID_MPEG4
))
449 put_avc_eos_tag(pb
, sc
->last_ts
);
452 file_size
= avio_tell(pb
);
454 /* update information */
455 if (avio_seek(pb
, flv
->duration_offset
, SEEK_SET
) < 0)
456 av_log(s
, AV_LOG_WARNING
, "Failed to update header with correct duration.\n");
458 put_amf_double(pb
, flv
->duration
/ (double)1000);
459 if (avio_seek(pb
, flv
->filesize_offset
, SEEK_SET
) < 0)
460 av_log(s
, AV_LOG_WARNING
, "Failed to update header with correct filesize.\n");
462 put_amf_double(pb
, file_size
);
464 avio_seek(pb
, file_size
, SEEK_SET
);
468 static int flv_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
470 AVIOContext
*pb
= s
->pb
;
471 AVCodecContext
*enc
= s
->streams
[pkt
->stream_index
]->codec
;
472 FLVContext
*flv
= s
->priv_data
;
473 FLVStreamContext
*sc
= s
->streams
[pkt
->stream_index
]->priv_data
;
475 int size
= pkt
->size
;
476 uint8_t *data
= NULL
;
477 int flags
= -1, flags_size
, ret
;
479 if (enc
->codec_id
== AV_CODEC_ID_VP6F
|| enc
->codec_id
== AV_CODEC_ID_VP6A
||
480 enc
->codec_id
== AV_CODEC_ID_VP6
|| enc
->codec_id
== AV_CODEC_ID_AAC
)
482 else if (enc
->codec_id
== AV_CODEC_ID_H264
|| enc
->codec_id
== AV_CODEC_ID_MPEG4
)
487 switch (enc
->codec_type
) {
488 case AVMEDIA_TYPE_VIDEO
:
489 avio_w8(pb
, FLV_TAG_TYPE_VIDEO
);
491 flags
= enc
->codec_tag
;
493 av_log(s
, AV_LOG_ERROR
,
494 "Video codec '%s' is not compatible with FLV\n",
495 avcodec_get_name(enc
->codec_id
));
496 return AVERROR(EINVAL
);
499 flags
|= pkt
->flags
& AV_PKT_FLAG_KEY
? FLV_FRAME_KEY
: FLV_FRAME_INTER
;
501 case AVMEDIA_TYPE_AUDIO
:
502 flags
= get_audio_flags(s
, enc
);
506 avio_w8(pb
, FLV_TAG_TYPE_AUDIO
);
508 case AVMEDIA_TYPE_DATA
:
509 avio_w8(pb
, FLV_TAG_TYPE_META
);
512 return AVERROR(EINVAL
);
515 if (enc
->codec_id
== AV_CODEC_ID_H264
|| enc
->codec_id
== AV_CODEC_ID_MPEG4
) {
516 /* check if extradata looks like mp4 formated */
517 if (enc
->extradata_size
> 0 && *(uint8_t*)enc
->extradata
!= 1)
518 if ((ret
= ff_avc_parse_nal_units_buf(pkt
->data
, &data
, &size
)) < 0)
520 } else if (enc
->codec_id
== AV_CODEC_ID_AAC
&& pkt
->size
> 2 &&
521 (AV_RB16(pkt
->data
) & 0xfff0) == 0xfff0) {
522 if (!s
->streams
[pkt
->stream_index
]->nb_frames
) {
523 av_log(s
, AV_LOG_ERROR
, "Malformed AAC bitstream detected: "
524 "use the audio bitstream filter 'aac_adtstoasc' to fix it "
525 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
526 return AVERROR_INVALIDDATA
;
528 av_log(s
, AV_LOG_WARNING
, "aac bitstream error\n");
531 if (flv
->delay
== AV_NOPTS_VALUE
)
532 flv
->delay
= -pkt
->dts
;
534 if (pkt
->dts
< -flv
->delay
) {
535 av_log(s
, AV_LOG_WARNING
,
536 "Packets are not in the proper order with respect to DTS\n");
537 return AVERROR(EINVAL
);
540 ts
= pkt
->dts
+ flv
->delay
; // add delay to force positive dts
542 /* check Speex packet duration */
543 if (enc
->codec_id
== AV_CODEC_ID_SPEEX
&& ts
- sc
->last_ts
> 160)
544 av_log(s
, AV_LOG_WARNING
, "Warning: Speex stream has more than "
545 "8 frames per packet. Adobe Flash "
546 "Player cannot handle this!\n");
548 if (sc
->last_ts
< ts
)
551 avio_wb24(pb
, size
+ flags_size
);
552 avio_wb24(pb
, ts
& 0xFFFFFF);
553 avio_w8(pb
, (ts
>> 24) & 0x7F); // timestamps are 32 bits _signed_
554 avio_wb24(pb
, flv
->reserved
);
556 if (enc
->codec_type
== AVMEDIA_TYPE_DATA
) {
558 int64_t metadata_size_pos
= avio_tell(pb
);
559 avio_w8(pb
, AMF_DATA_TYPE_STRING
);
560 put_amf_string(pb
, "onTextData");
561 avio_w8(pb
, AMF_DATA_TYPE_MIXEDARRAY
);
563 put_amf_string(pb
, "type");
564 avio_w8(pb
, AMF_DATA_TYPE_STRING
);
565 put_amf_string(pb
, "Text");
566 put_amf_string(pb
, "text");
567 avio_w8(pb
, AMF_DATA_TYPE_STRING
);
568 put_amf_string(pb
, pkt
->data
);
569 put_amf_string(pb
, "");
570 avio_w8(pb
, AMF_END_OF_OBJECT
);
571 /* write total size of tag */
572 data_size
= avio_tell(pb
) - metadata_size_pos
;
573 avio_seek(pb
, metadata_size_pos
- 10, SEEK_SET
);
574 avio_wb24(pb
, data_size
);
575 avio_seek(pb
, data_size
+ 10 - 3, SEEK_CUR
);
576 avio_wb32(pb
, data_size
+ 11);
578 av_assert1(flags
>=0);
580 if (enc
->codec_id
== AV_CODEC_ID_VP6
)
582 if (enc
->codec_id
== AV_CODEC_ID_VP6F
|| enc
->codec_id
== AV_CODEC_ID_VP6A
) {
583 if (enc
->extradata_size
)
584 avio_w8(pb
, enc
->extradata
[0]);
586 avio_w8(pb
, ((FFALIGN(enc
->width
, 16) - enc
->width
) << 4) |
587 (FFALIGN(enc
->height
, 16) - enc
->height
));
588 } else if (enc
->codec_id
== AV_CODEC_ID_AAC
)
589 avio_w8(pb
, 1); // AAC raw
590 else if (enc
->codec_id
== AV_CODEC_ID_H264
|| enc
->codec_id
== AV_CODEC_ID_MPEG4
) {
591 avio_w8(pb
, 1); // AVC NALU
592 avio_wb24(pb
, pkt
->pts
- pkt
->dts
);
595 avio_write(pb
, data
? data
: pkt
->data
, size
);
597 avio_wb32(pb
, size
+ flags_size
+ 11); // previous tag size
598 flv
->duration
= FFMAX(flv
->duration
,
599 pkt
->pts
+ flv
->delay
+ pkt
->duration
);
607 AVOutputFormat ff_flv_muxer
= {
609 .long_name
= NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
610 .mime_type
= "video/x-flv",
612 .priv_data_size
= sizeof(FLVContext
),
613 .audio_codec
= CONFIG_LIBMP3LAME
? AV_CODEC_ID_MP3
: AV_CODEC_ID_ADPCM_SWF
,
614 .video_codec
= AV_CODEC_ID_FLV1
,
615 .write_header
= flv_write_header
,
616 .write_packet
= flv_write_packet
,
617 .write_trailer
= flv_write_trailer
,
618 .codec_tag
= (const AVCodecTag
* const []) {
619 flv_video_codec_ids
, flv_audio_codec_ids
, 0
621 .flags
= AVFMT_GLOBALHEADER
| AVFMT_VARIABLE_FPS
|