00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "libavutil/dict.h"
00024 #include "libavutil/intfloat.h"
00025 #include "libavutil/avassert.h"
00026 #include "avc.h"
00027 #include "avformat.h"
00028 #include "flv.h"
00029 #include "internal.h"
00030 #include "metadata.h"
00031
00032
00033 static const AVCodecTag flv_video_codec_ids[] = {
00034 { AV_CODEC_ID_FLV1, FLV_CODECID_H263 },
00035 { AV_CODEC_ID_H263, FLV_CODECID_REALH263 },
00036 { AV_CODEC_ID_MPEG4, FLV_CODECID_MPEG4 },
00037 { AV_CODEC_ID_FLASHSV, FLV_CODECID_SCREEN },
00038 { AV_CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2 },
00039 { AV_CODEC_ID_VP6F, FLV_CODECID_VP6 },
00040 { AV_CODEC_ID_VP6, FLV_CODECID_VP6 },
00041 { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A },
00042 { AV_CODEC_ID_H264, FLV_CODECID_H264 },
00043 { AV_CODEC_ID_NONE, 0 }
00044 };
00045
00046 static const AVCodecTag flv_audio_codec_ids[] = {
00047 { AV_CODEC_ID_MP3, FLV_CODECID_MP3 >> FLV_AUDIO_CODECID_OFFSET },
00048 { AV_CODEC_ID_PCM_U8, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET },
00049 { AV_CODEC_ID_PCM_S16BE, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET },
00050 { AV_CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET },
00051 { AV_CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM >> FLV_AUDIO_CODECID_OFFSET },
00052 { AV_CODEC_ID_AAC, FLV_CODECID_AAC >> FLV_AUDIO_CODECID_OFFSET },
00053 { AV_CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET },
00054 { AV_CODEC_ID_PCM_MULAW, FLV_CODECID_PCM_MULAW >> FLV_AUDIO_CODECID_OFFSET },
00055 { AV_CODEC_ID_PCM_ALAW, FLV_CODECID_PCM_ALAW >> FLV_AUDIO_CODECID_OFFSET },
00056 { AV_CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET },
00057 { AV_CODEC_ID_NONE, 0 }
00058 };
00059
00060 typedef struct FLVContext {
00061 int reserved;
00062 int64_t duration_offset;
00063 int64_t filesize_offset;
00064 int64_t duration;
00065 int64_t delay;
00066 } FLVContext;
00067
00068 typedef struct FLVStreamContext {
00069 int64_t last_ts;
00070 } FLVStreamContext;
00071
00072 static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
00073 {
00074 int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT
00075 : FLV_SAMPLESSIZE_8BIT;
00076
00077 if (enc->codec_id == AV_CODEC_ID_AAC)
00078 return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ |
00079 FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
00080 else if (enc->codec_id == AV_CODEC_ID_SPEEX) {
00081 if (enc->sample_rate != 16000) {
00082 av_log(s, AV_LOG_ERROR,
00083 "FLV only supports wideband (16kHz) Speex audio\n");
00084 return AVERROR(EINVAL);
00085 }
00086 if (enc->channels != 1) {
00087 av_log(s, AV_LOG_ERROR, "FLV only supports mono Speex audio\n");
00088 return AVERROR(EINVAL);
00089 }
00090 return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT;
00091 } else {
00092 switch (enc->sample_rate) {
00093 case 44100:
00094 flags |= FLV_SAMPLERATE_44100HZ;
00095 break;
00096 case 22050:
00097 flags |= FLV_SAMPLERATE_22050HZ;
00098 break;
00099 case 11025:
00100 flags |= FLV_SAMPLERATE_11025HZ;
00101 break;
00102 case 16000:
00103 case 8000:
00104 case 5512:
00105 if (enc->codec_id != AV_CODEC_ID_MP3) {
00106 flags |= FLV_SAMPLERATE_SPECIAL;
00107 break;
00108 }
00109 default:
00110 av_log(s, AV_LOG_ERROR,
00111 "FLV does not support sample rate %d, "
00112 "choose from (44100, 22050, 11025)\n", enc->sample_rate);
00113 return AVERROR(EINVAL);
00114 }
00115 }
00116
00117 if (enc->channels > 1)
00118 flags |= FLV_STEREO;
00119
00120 switch (enc->codec_id) {
00121 case AV_CODEC_ID_MP3:
00122 flags |= FLV_CODECID_MP3 | FLV_SAMPLESSIZE_16BIT;
00123 break;
00124 case AV_CODEC_ID_PCM_U8:
00125 flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_8BIT;
00126 break;
00127 case AV_CODEC_ID_PCM_S16BE:
00128 flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_16BIT;
00129 break;
00130 case AV_CODEC_ID_PCM_S16LE:
00131 flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT;
00132 break;
00133 case AV_CODEC_ID_ADPCM_SWF:
00134 flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT;
00135 break;
00136 case AV_CODEC_ID_NELLYMOSER:
00137 if (enc->sample_rate == 8000)
00138 flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
00139 else if (enc->sample_rate == 16000)
00140 flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
00141 else
00142 flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT;
00143 break;
00144 case AV_CODEC_ID_PCM_MULAW:
00145 flags = FLV_CODECID_PCM_MULAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
00146 break;
00147 case AV_CODEC_ID_PCM_ALAW:
00148 flags = FLV_CODECID_PCM_ALAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
00149 break;
00150 case 0:
00151 flags |= enc->codec_tag << 4;
00152 break;
00153 default:
00154 av_log(s, AV_LOG_ERROR, "Audio codec '%s' not compatible with FLV\n",
00155 avcodec_get_name(enc->codec_id));
00156 return AVERROR(EINVAL);
00157 }
00158
00159 return flags;
00160 }
00161
00162 static void put_amf_string(AVIOContext *pb, const char *str)
00163 {
00164 size_t len = strlen(str);
00165 avio_wb16(pb, len);
00166 avio_write(pb, str, len);
00167 }
00168
00169 static void put_avc_eos_tag(AVIOContext *pb, unsigned ts)
00170 {
00171 avio_w8(pb, FLV_TAG_TYPE_VIDEO);
00172 avio_wb24(pb, 5);
00173 avio_wb24(pb, ts);
00174 avio_w8(pb, (ts >> 24) & 0x7F);
00175 avio_wb24(pb, 0);
00176 avio_w8(pb, 23);
00177 avio_w8(pb, 2);
00178 avio_wb24(pb, 0);
00179 avio_wb32(pb, 16);
00180 }
00181
00182 static void put_amf_double(AVIOContext *pb, double d)
00183 {
00184 avio_w8(pb, AMF_DATA_TYPE_NUMBER);
00185 avio_wb64(pb, av_double2int(d));
00186 }
00187
00188 static void put_amf_bool(AVIOContext *pb, int b)
00189 {
00190 avio_w8(pb, AMF_DATA_TYPE_BOOL);
00191 avio_w8(pb, !!b);
00192 }
00193
00194 static int flv_write_header(AVFormatContext *s)
00195 {
00196 AVIOContext *pb = s->pb;
00197 FLVContext *flv = s->priv_data;
00198 AVCodecContext *audio_enc = NULL, *video_enc = NULL, *data_enc = NULL;
00199 int i, metadata_count = 0;
00200 double framerate = 0.0;
00201 int64_t metadata_size_pos, data_size, metadata_count_pos;
00202 AVDictionaryEntry *tag = NULL;
00203
00204 for (i = 0; i < s->nb_streams; i++) {
00205 AVCodecContext *enc = s->streams[i]->codec;
00206 FLVStreamContext *sc;
00207 switch (enc->codec_type) {
00208 case AVMEDIA_TYPE_VIDEO:
00209 if (s->streams[i]->avg_frame_rate.den &&
00210 s->streams[i]->avg_frame_rate.num) {
00211 framerate = av_q2d(s->streams[i]->avg_frame_rate);
00212 } else {
00213 framerate = 1 / av_q2d(s->streams[i]->codec->time_base);
00214 }
00215 video_enc = enc;
00216 if (enc->codec_tag == 0) {
00217 av_log(s, AV_LOG_ERROR, "Video codec '%s' for stream %d is not compatible with FLV\n",
00218 avcodec_get_name(enc->codec_id), i);
00219 return AVERROR(EINVAL);
00220 }
00221 break;
00222 case AVMEDIA_TYPE_AUDIO:
00223 audio_enc = enc;
00224 if (get_audio_flags(s, enc) < 0)
00225 return AVERROR_INVALIDDATA;
00226 break;
00227 case AVMEDIA_TYPE_DATA:
00228 if (enc->codec_id != AV_CODEC_ID_TEXT) {
00229 av_log(s, AV_LOG_ERROR, "Data codec '%s' for stream %d is not compatible with FLV\n",
00230 avcodec_get_name(enc->codec_id), i);
00231 return AVERROR_INVALIDDATA;
00232 }
00233 data_enc = enc;
00234 break;
00235 default:
00236 av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n",
00237 av_get_media_type_string(enc->codec_type), i);
00238 return AVERROR(EINVAL);
00239 }
00240 avpriv_set_pts_info(s->streams[i], 32, 1, 1000);
00241
00242 sc = av_mallocz(sizeof(FLVStreamContext));
00243 if (!sc)
00244 return AVERROR(ENOMEM);
00245 s->streams[i]->priv_data = sc;
00246 sc->last_ts = -1;
00247 }
00248
00249 flv->delay = AV_NOPTS_VALUE;
00250
00251 avio_write(pb, "FLV", 3);
00252 avio_w8(pb, 1);
00253 avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc +
00254 FLV_HEADER_FLAG_HASVIDEO * !!video_enc);
00255 avio_wb32(pb, 9);
00256 avio_wb32(pb, 0);
00257
00258 for (i = 0; i < s->nb_streams; i++)
00259 if (s->streams[i]->codec->codec_tag == 5) {
00260 avio_w8(pb, 8);
00261 avio_wb24(pb, 0);
00262 avio_wb24(pb, 0);
00263 avio_wb32(pb, 0);
00264 avio_wb32(pb, 11);
00265 flv->reserved = 5;
00266 }
00267
00268
00269 avio_w8(pb, 18);
00270 metadata_size_pos = avio_tell(pb);
00271 avio_wb24(pb, 0);
00272 avio_wb24(pb, 0);
00273 avio_wb32(pb, 0);
00274
00275
00276
00277
00278 avio_w8(pb, AMF_DATA_TYPE_STRING);
00279 put_amf_string(pb, "onMetaData");
00280
00281
00282 avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
00283 metadata_count_pos = avio_tell(pb);
00284 metadata_count = 5 * !!video_enc +
00285 5 * !!audio_enc +
00286 1 * !!data_enc +
00287 2;
00288
00289 avio_wb32(pb, metadata_count);
00290
00291 put_amf_string(pb, "duration");
00292 flv->duration_offset= avio_tell(pb);
00293
00294
00295 put_amf_double(pb, s->duration / AV_TIME_BASE);
00296
00297 if (video_enc) {
00298 put_amf_string(pb, "width");
00299 put_amf_double(pb, video_enc->width);
00300
00301 put_amf_string(pb, "height");
00302 put_amf_double(pb, video_enc->height);
00303
00304 put_amf_string(pb, "videodatarate");
00305 put_amf_double(pb, video_enc->bit_rate / 1024.0);
00306
00307 put_amf_string(pb, "framerate");
00308 put_amf_double(pb, framerate);
00309
00310 put_amf_string(pb, "videocodecid");
00311 put_amf_double(pb, video_enc->codec_tag);
00312 }
00313
00314 if (audio_enc) {
00315 put_amf_string(pb, "audiodatarate");
00316 put_amf_double(pb, audio_enc->bit_rate / 1024.0);
00317
00318 put_amf_string(pb, "audiosamplerate");
00319 put_amf_double(pb, audio_enc->sample_rate);
00320
00321 put_amf_string(pb, "audiosamplesize");
00322 put_amf_double(pb, audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
00323
00324 put_amf_string(pb, "stereo");
00325 put_amf_bool(pb, audio_enc->channels == 2);
00326
00327 put_amf_string(pb, "audiocodecid");
00328 put_amf_double(pb, audio_enc->codec_tag);
00329 }
00330
00331 if (data_enc) {
00332 put_amf_string(pb, "datastream");
00333 put_amf_double(pb, 0.0);
00334 }
00335
00336 while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
00337 if( !strcmp(tag->key, "width")
00338 ||!strcmp(tag->key, "height")
00339 ||!strcmp(tag->key, "videodatarate")
00340 ||!strcmp(tag->key, "framerate")
00341 ||!strcmp(tag->key, "videocodecid")
00342 ||!strcmp(tag->key, "audiodatarate")
00343 ||!strcmp(tag->key, "audiosamplerate")
00344 ||!strcmp(tag->key, "audiosamplesize")
00345 ||!strcmp(tag->key, "stereo")
00346 ||!strcmp(tag->key, "audiocodecid")
00347 ||!strcmp(tag->key, "duration")
00348 ||!strcmp(tag->key, "onMetaData")
00349 ){
00350 av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key);
00351 continue;
00352 }
00353 put_amf_string(pb, tag->key);
00354 avio_w8(pb, AMF_DATA_TYPE_STRING);
00355 put_amf_string(pb, tag->value);
00356 metadata_count++;
00357 }
00358
00359 put_amf_string(pb, "filesize");
00360 flv->filesize_offset = avio_tell(pb);
00361 put_amf_double(pb, 0);
00362
00363 put_amf_string(pb, "");
00364 avio_w8(pb, AMF_END_OF_OBJECT);
00365
00366
00367 data_size = avio_tell(pb) - metadata_size_pos - 10;
00368
00369 avio_seek(pb, metadata_count_pos, SEEK_SET);
00370 avio_wb32(pb, metadata_count);
00371
00372 avio_seek(pb, metadata_size_pos, SEEK_SET);
00373 avio_wb24(pb, data_size);
00374 avio_skip(pb, data_size + 10 - 3);
00375 avio_wb32(pb, data_size + 11);
00376
00377 for (i = 0; i < s->nb_streams; i++) {
00378 AVCodecContext *enc = s->streams[i]->codec;
00379 if (enc->codec_id == AV_CODEC_ID_AAC || enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) {
00380 int64_t pos;
00381 avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ?
00382 FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
00383 avio_wb24(pb, 0);
00384 avio_wb24(pb, 0);
00385 avio_w8(pb, 0);
00386 avio_wb24(pb, 0);
00387 pos = avio_tell(pb);
00388 if (enc->codec_id == AV_CODEC_ID_AAC) {
00389 avio_w8(pb, get_audio_flags(s, enc));
00390 avio_w8(pb, 0);
00391 avio_write(pb, enc->extradata, enc->extradata_size);
00392 } else {
00393 avio_w8(pb, enc->codec_tag | FLV_FRAME_KEY);
00394 avio_w8(pb, 0);
00395 avio_wb24(pb, 0);
00396 ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size);
00397 }
00398 data_size = avio_tell(pb) - pos;
00399 avio_seek(pb, -data_size - 10, SEEK_CUR);
00400 avio_wb24(pb, data_size);
00401 avio_skip(pb, data_size + 10 - 3);
00402 avio_wb32(pb, data_size + 11);
00403 }
00404 }
00405
00406 return 0;
00407 }
00408
00409 static int flv_write_trailer(AVFormatContext *s)
00410 {
00411 int64_t file_size;
00412
00413 AVIOContext *pb = s->pb;
00414 FLVContext *flv = s->priv_data;
00415 int i;
00416
00417
00418 for (i = 0; i < s->nb_streams; i++) {
00419 AVCodecContext *enc = s->streams[i]->codec;
00420 FLVStreamContext *sc = s->streams[i]->priv_data;
00421 if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&
00422 (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4))
00423 put_avc_eos_tag(pb, sc->last_ts);
00424 }
00425
00426 file_size = avio_tell(pb);
00427
00428
00429 avio_seek(pb, flv->duration_offset, SEEK_SET);
00430 put_amf_double(pb, flv->duration / (double)1000);
00431 avio_seek(pb, flv->filesize_offset, SEEK_SET);
00432 put_amf_double(pb, file_size);
00433
00434 avio_seek(pb, file_size, SEEK_SET);
00435 return 0;
00436 }
00437
00438 static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
00439 {
00440 AVIOContext *pb = s->pb;
00441 AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
00442 FLVContext *flv = s->priv_data;
00443 FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data;
00444 unsigned ts;
00445 int size = pkt->size;
00446 uint8_t *data = NULL;
00447 int flags = -1, flags_size, ret;
00448
00449 av_dlog(s, "type:%s pts:%"PRId64" dts:%"PRId64" size:%d\n",
00450 av_get_media_type_string(enc->codec_type), pkt->pts, pkt->dts, size);
00451
00452 if (enc->codec_id == AV_CODEC_ID_VP6 || enc->codec_id == AV_CODEC_ID_VP6F ||
00453 enc->codec_id == AV_CODEC_ID_VP6A || enc->codec_id == AV_CODEC_ID_AAC)
00454 flags_size = 2;
00455 else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4)
00456 flags_size = 5;
00457 else
00458 flags_size = 1;
00459
00460 switch (enc->codec_type) {
00461 case AVMEDIA_TYPE_VIDEO:
00462 avio_w8(pb, FLV_TAG_TYPE_VIDEO);
00463
00464 flags = enc->codec_tag;
00465 if (flags == 0) {
00466 av_log(s, AV_LOG_ERROR,
00467 "Video codec '%s' is not compatible with FLV\n",
00468 avcodec_get_name(enc->codec_id));
00469 return AVERROR(EINVAL);
00470 }
00471
00472 flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER;
00473 break;
00474 case AVMEDIA_TYPE_AUDIO:
00475 flags = get_audio_flags(s, enc);
00476
00477 av_assert0(size);
00478
00479 avio_w8(pb, FLV_TAG_TYPE_AUDIO);
00480 break;
00481 case AVMEDIA_TYPE_DATA:
00482 avio_w8(pb, FLV_TAG_TYPE_META);
00483 break;
00484 default:
00485 return AVERROR(EINVAL);
00486 }
00487
00488 if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) {
00489
00490 if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1)
00491 if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
00492 return ret;
00493 } else if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
00494 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
00495 av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
00496 "use audio bistream filter 'aac_adtstoasc' to fix it "
00497 "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
00498 return AVERROR_INVALIDDATA;
00499 }
00500
00501 if (flv->delay == AV_NOPTS_VALUE)
00502 flv->delay = -pkt->dts;
00503
00504 if (pkt->dts < -flv->delay) {
00505 av_log(s, AV_LOG_WARNING,
00506 "Packets are not in the proper order with respect to DTS\n");
00507 return AVERROR(EINVAL);
00508 }
00509
00510 ts = pkt->dts + flv->delay;
00511
00512
00513 if (enc->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160)
00514 av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
00515 "8 frames per packet. Adobe Flash "
00516 "Player cannot handle this!\n");
00517
00518 if (sc->last_ts < ts)
00519 sc->last_ts = ts;
00520
00521 avio_wb24(pb, size + flags_size);
00522 avio_wb24(pb, ts);
00523 avio_w8(pb, (ts >> 24) & 0x7F);
00524 avio_wb24(pb, flv->reserved);
00525
00526 if (enc->codec_type == AVMEDIA_TYPE_DATA) {
00527 int data_size;
00528 int metadata_size_pos = avio_tell(pb);
00529 avio_w8(pb, AMF_DATA_TYPE_STRING);
00530 put_amf_string(pb, "onTextData");
00531 avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
00532 avio_wb32(pb, 2);
00533 put_amf_string(pb, "type");
00534 avio_w8(pb, AMF_DATA_TYPE_STRING);
00535 put_amf_string(pb, "Text");
00536 put_amf_string(pb, "text");
00537 avio_w8(pb, AMF_DATA_TYPE_STRING);
00538 put_amf_string(pb, pkt->data);
00539 put_amf_string(pb, "");
00540 avio_w8(pb, AMF_END_OF_OBJECT);
00541
00542 data_size = avio_tell(pb) - metadata_size_pos;
00543 avio_seek(pb, metadata_size_pos - 10, SEEK_SET);
00544 avio_wb24(pb, data_size);
00545 avio_seek(pb, data_size + 10 - 3, SEEK_CUR);
00546 avio_wb32(pb, data_size + 11);
00547 } else {
00548 av_assert1(flags>=0);
00549 avio_w8(pb,flags);
00550 if (enc->codec_id == AV_CODEC_ID_VP6)
00551 avio_w8(pb,0);
00552 if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A)
00553 avio_w8(pb, enc->extradata_size ? enc->extradata[0] : 0);
00554 else if (enc->codec_id == AV_CODEC_ID_AAC)
00555 avio_w8(pb,1);
00556 else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) {
00557 avio_w8(pb,1);
00558 avio_wb24(pb,pkt->pts - pkt->dts);
00559 }
00560
00561 avio_write(pb, data ? data : pkt->data, size);
00562
00563 avio_wb32(pb, size + flags_size + 11);
00564 flv->duration = FFMAX(flv->duration,
00565 pkt->pts + flv->delay + pkt->duration);
00566 }
00567
00568 avio_flush(pb);
00569 av_free(data);
00570
00571 return pb->error;
00572 }
00573
00574 AVOutputFormat ff_flv_muxer = {
00575 .name = "flv",
00576 .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
00577 .mime_type = "video/x-flv",
00578 .extensions = "flv",
00579 .priv_data_size = sizeof(FLVContext),
00580 .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF,
00581 .video_codec = AV_CODEC_ID_FLV1,
00582 .write_header = flv_write_header,
00583 .write_packet = flv_write_packet,
00584 .write_trailer = flv_write_trailer,
00585 .codec_tag = (const AVCodecTag* const []) {
00586 flv_video_codec_ids, flv_audio_codec_ids, 0
00587 },
00588 .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
00589 AVFMT_TS_NONSTRICT,
00590 };