| OLD | NEW |
| 1 /* | 1 /* |
| 2 * FLV muxer | 2 * FLV muxer |
| 3 * Copyright (c) 2003 The FFmpeg Project | 3 * Copyright (c) 2003 The FFmpeg Project |
| 4 * | 4 * |
| 5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
| 6 * | 6 * |
| 7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 {CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET}, | 47 {CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET}, |
| 48 {CODEC_ID_NONE, 0} | 48 {CODEC_ID_NONE, 0} |
| 49 }; | 49 }; |
| 50 | 50 |
| 51 typedef struct FLVContext { | 51 typedef struct FLVContext { |
| 52 int reserved; | 52 int reserved; |
| 53 int64_t duration_offset; | 53 int64_t duration_offset; |
| 54 int64_t filesize_offset; | 54 int64_t filesize_offset; |
| 55 int64_t duration; | 55 int64_t duration; |
| 56 int delay; ///< first dts delay for AVC | 56 int delay; ///< first dts delay for AVC |
| 57 int64_t last_video_ts; |
| 57 } FLVContext; | 58 } FLVContext; |
| 58 | 59 |
| 59 static int get_audio_flags(AVCodecContext *enc){ | 60 static int get_audio_flags(AVCodecContext *enc){ |
| 60 int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT : FLV
_SAMPLESSIZE_8BIT; | 61 int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT : FLV
_SAMPLESSIZE_8BIT; |
| 61 | 62 |
| 62 if (enc->codec_id == CODEC_ID_AAC) // specs force these parameters | 63 if (enc->codec_id == CODEC_ID_AAC) // specs force these parameters |
| 63 return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT
| FLV_STEREO; | 64 return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT
| FLV_STEREO; |
| 64 else if (enc->codec_id == CODEC_ID_SPEEX) { | 65 else if (enc->codec_id == CODEC_ID_SPEEX) { |
| 65 if (enc->sample_rate != 16000) { | 66 if (enc->sample_rate != 16000) { |
| 66 av_log(enc, AV_LOG_ERROR, "flv only supports wideband (16kHz) Speex
audio\n"); | 67 av_log(enc, AV_LOG_ERROR, "flv only supports wideband (16kHz) Speex
audio\n"); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 return flags; | 138 return flags; |
| 138 } | 139 } |
| 139 | 140 |
| 140 static void put_amf_string(ByteIOContext *pb, const char *str) | 141 static void put_amf_string(ByteIOContext *pb, const char *str) |
| 141 { | 142 { |
| 142 size_t len = strlen(str); | 143 size_t len = strlen(str); |
| 143 put_be16(pb, len); | 144 put_be16(pb, len); |
| 144 put_buffer(pb, str, len); | 145 put_buffer(pb, str, len); |
| 145 } | 146 } |
| 146 | 147 |
| 148 static void put_avc_eos_tag(ByteIOContext *pb, unsigned ts) { |
| 149 put_byte(pb, FLV_TAG_TYPE_VIDEO); |
| 150 put_be24(pb, 5); /* Tag Data Size */ |
| 151 put_be24(pb, ts); /* lower 24 bits of timestamp in ms*/ |
| 152 put_byte(pb, (ts >> 24) & 0x7F); /* MSB of ts in ms*/ |
| 153 put_be24(pb, 0); /* StreamId = 0 */ |
| 154 put_byte(pb, 23); /* ub[4] FrameType = 1, ub[4] CodecId = 7 */ |
| 155 put_byte(pb, 2); /* AVC end of sequence */ |
| 156 put_be24(pb, 0); /* Always 0 for AVC EOS. */ |
| 157 put_be32(pb, 16); /* Size of FLV tag */ |
| 158 } |
| 159 |
| 147 static void put_amf_double(ByteIOContext *pb, double d) | 160 static void put_amf_double(ByteIOContext *pb, double d) |
| 148 { | 161 { |
| 149 put_byte(pb, AMF_DATA_TYPE_NUMBER); | 162 put_byte(pb, AMF_DATA_TYPE_NUMBER); |
| 150 put_be64(pb, av_dbl2int(d)); | 163 put_be64(pb, av_dbl2int(d)); |
| 151 } | 164 } |
| 152 | 165 |
| 153 static void put_amf_bool(ByteIOContext *pb, int b) { | 166 static void put_amf_bool(ByteIOContext *pb, int b) { |
| 154 put_byte(pb, AMF_DATA_TYPE_BOOL); | 167 put_byte(pb, AMF_DATA_TYPE_BOOL); |
| 155 put_byte(pb, !!b); | 168 put_byte(pb, !!b); |
| 156 } | 169 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 if(s->streams[i]->codec->codec_tag == 5){ | 208 if(s->streams[i]->codec->codec_tag == 5){ |
| 196 put_byte(pb,8); // message type | 209 put_byte(pb,8); // message type |
| 197 put_be24(pb,0); // include flags | 210 put_be24(pb,0); // include flags |
| 198 put_be24(pb,0); // time stamp | 211 put_be24(pb,0); // time stamp |
| 199 put_be32(pb,0); // reserved | 212 put_be32(pb,0); // reserved |
| 200 put_be32(pb,11); // size | 213 put_be32(pb,11); // size |
| 201 flv->reserved=5; | 214 flv->reserved=5; |
| 202 } | 215 } |
| 203 } | 216 } |
| 204 | 217 |
| 218 flv->last_video_ts = -1; |
| 219 |
| 205 /* write meta_tag */ | 220 /* write meta_tag */ |
| 206 put_byte(pb, 18); // tag type META | 221 put_byte(pb, 18); // tag type META |
| 207 metadata_size_pos= url_ftell(pb); | 222 metadata_size_pos= url_ftell(pb); |
| 208 put_be24(pb, 0); // size of data part (sum of all parts below) | 223 put_be24(pb, 0); // size of data part (sum of all parts below) |
| 209 put_be24(pb, 0); // time stamp | 224 put_be24(pb, 0); // time stamp |
| 210 put_be32(pb, 0); // reserved | 225 put_be32(pb, 0); // reserved |
| 211 | 226 |
| 212 /* now data of data_size size */ | 227 /* now data of data_size size */ |
| 213 | 228 |
| 214 /* first event name as a string */ | 229 /* first event name as a string */ |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 | 317 |
| 303 return 0; | 318 return 0; |
| 304 } | 319 } |
| 305 | 320 |
| 306 static int flv_write_trailer(AVFormatContext *s) | 321 static int flv_write_trailer(AVFormatContext *s) |
| 307 { | 322 { |
| 308 int64_t file_size; | 323 int64_t file_size; |
| 309 | 324 |
| 310 ByteIOContext *pb = s->pb; | 325 ByteIOContext *pb = s->pb; |
| 311 FLVContext *flv = s->priv_data; | 326 FLVContext *flv = s->priv_data; |
| 327 int i; |
| 328 |
| 329 /* Add EOS tag */ |
| 330 for (i = 0; i < s->nb_streams; i++) { |
| 331 AVCodecContext *enc = s->streams[i]->codec; |
| 332 if (enc->codec_type == CODEC_TYPE_VIDEO && |
| 333 enc->codec_id == CODEC_ID_H264) { |
| 334 put_avc_eos_tag(pb, flv->last_video_ts); |
| 335 } |
| 336 } |
| 312 | 337 |
| 313 file_size = url_ftell(pb); | 338 file_size = url_ftell(pb); |
| 314 | 339 |
| 315 /* update informations */ | 340 /* update informations */ |
| 316 url_fseek(pb, flv->duration_offset, SEEK_SET); | 341 url_fseek(pb, flv->duration_offset, SEEK_SET); |
| 317 put_amf_double(pb, flv->duration / (double)1000); | 342 put_amf_double(pb, flv->duration / (double)1000); |
| 318 url_fseek(pb, flv->filesize_offset, SEEK_SET); | 343 url_fseek(pb, flv->filesize_offset, SEEK_SET); |
| 319 put_amf_double(pb, file_size); | 344 put_amf_double(pb, file_size); |
| 320 | 345 |
| 321 url_fseek(pb, file_size, SEEK_SET); | 346 url_fseek(pb, file_size, SEEK_SET); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 /* check if extradata looks like mp4 formated */ | 390 /* check if extradata looks like mp4 formated */ |
| 366 if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) { | 391 if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) { |
| 367 if (ff_avc_parse_nal_units_buf(pkt->data, &data, &size) < 0) | 392 if (ff_avc_parse_nal_units_buf(pkt->data, &data, &size) < 0) |
| 368 return -1; | 393 return -1; |
| 369 } | 394 } |
| 370 if (!flv->delay && pkt->dts < 0) | 395 if (!flv->delay && pkt->dts < 0) |
| 371 flv->delay = -pkt->dts; | 396 flv->delay = -pkt->dts; |
| 372 } | 397 } |
| 373 | 398 |
| 374 ts = pkt->dts + flv->delay; // add delay to force positive dts | 399 ts = pkt->dts + flv->delay; // add delay to force positive dts |
| 400 if (enc->codec_type == CODEC_TYPE_VIDEO) { |
| 401 if (flv->last_video_ts < ts) |
| 402 flv->last_video_ts = ts; |
| 403 } |
| 375 put_be24(pb,size + flags_size); | 404 put_be24(pb,size + flags_size); |
| 376 put_be24(pb,ts); | 405 put_be24(pb,ts); |
| 377 put_byte(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_ | 406 put_byte(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_ |
| 378 put_be24(pb,flv->reserved); | 407 put_be24(pb,flv->reserved); |
| 379 put_byte(pb,flags); | 408 put_byte(pb,flags); |
| 380 if (enc->codec_id == CODEC_ID_VP6) | 409 if (enc->codec_id == CODEC_ID_VP6) |
| 381 put_byte(pb,0); | 410 put_byte(pb,0); |
| 382 if (enc->codec_id == CODEC_ID_VP6F) | 411 if (enc->codec_id == CODEC_ID_VP6F) |
| 383 put_byte(pb, enc->extradata_size ? enc->extradata[0] : 0); | 412 put_byte(pb, enc->extradata_size ? enc->extradata[0] : 0); |
| 384 else if (enc->codec_id == CODEC_ID_AAC) | 413 else if (enc->codec_id == CODEC_ID_AAC) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 411 #else // CONFIG_LIBMP3LAME | 440 #else // CONFIG_LIBMP3LAME |
| 412 CODEC_ID_ADPCM_SWF, | 441 CODEC_ID_ADPCM_SWF, |
| 413 #endif // CONFIG_LIBMP3LAME | 442 #endif // CONFIG_LIBMP3LAME |
| 414 CODEC_ID_FLV1, | 443 CODEC_ID_FLV1, |
| 415 flv_write_header, | 444 flv_write_header, |
| 416 flv_write_packet, | 445 flv_write_packet, |
| 417 flv_write_trailer, | 446 flv_write_trailer, |
| 418 .codec_tag= (const AVCodecTag* const []){flv_video_codec_ids, flv_audio_code
c_ids, 0}, | 447 .codec_tag= (const AVCodecTag* const []){flv_video_codec_ids, flv_audio_code
c_ids, 0}, |
| 419 .flags= AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, | 448 .flags= AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, |
| 420 }; | 449 }; |
| OLD | NEW |