diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-11-17 12:43:55 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-11-17 12:43:55 +0100 |
commit | bb7be3b763d37c1e869431a76da7a8a2ddf1d9f9 (patch) | |
tree | 572112bf0e75ba083b8a777c379b74abfb25b031 /libavformat/flvenc.c | |
parent | c88ae843da4a9589a6ef1138fb9d9aaa28add2d3 (diff) | |
parent | 4d0cd5f58c892276716f46f4b2702915e5018215 (diff) | |
download | ffmpeg-bb7be3b763d37c1e869431a76da7a8a2ddf1d9f9.tar.gz |
Merge commit '4d0cd5f58c892276716f46f4b2702915e5018215'
* commit '4d0cd5f58c892276716f46f4b2702915e5018215':
flvenc: move metadata updates into a single function
Conflicts:
libavformat/flvenc.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/flvenc.c')
-rw-r--r-- | libavformat/flvenc.c | 229 |
1 files changed, 121 insertions, 108 deletions
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 6266fb085d..db610d986a 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -63,6 +63,11 @@ typedef struct FLVContext { int64_t filesize_offset; int64_t duration; int64_t delay; ///< first dts delay (needed for AVC & Speex) + + AVCodecContext *audio_enc; + AVCodecContext *video_enc; + double framerate; + AVCodecContext *data_enc; } FLVContext; typedef struct FLVStreamContext { @@ -191,103 +196,14 @@ static void put_amf_bool(AVIOContext *pb, int b) avio_w8(pb, !!b); } -static int flv_write_header(AVFormatContext *s) +static void write_metadata(AVFormatContext *s) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; - AVCodecContext *audio_enc = NULL, *video_enc = NULL, *data_enc = NULL; int i, metadata_count = 0; - double framerate = 0.0; int64_t metadata_size_pos, data_size, metadata_count_pos; AVDictionaryEntry *tag = NULL; - for (i = 0; i < s->nb_streams; i++) { - AVCodecContext *enc = s->streams[i]->codec; - FLVStreamContext *sc; - switch (enc->codec_type) { - case AVMEDIA_TYPE_VIDEO: - if (s->streams[i]->avg_frame_rate.den && - s->streams[i]->avg_frame_rate.num) { - framerate = av_q2d(s->streams[i]->avg_frame_rate); - } - if (video_enc) { - av_log(s, AV_LOG_ERROR, - "at most one video stream is supported in flv\n"); - return AVERROR(EINVAL); - } - video_enc = enc; - if (enc->codec_tag == 0) { - av_log(s, AV_LOG_ERROR, "Video codec '%s' for stream %d is not compatible with FLV\n", - avcodec_get_name(enc->codec_id), i); - return AVERROR(EINVAL); - } - if (enc->codec_id == AV_CODEC_ID_MPEG4 || - enc->codec_id == AV_CODEC_ID_H263) { - int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL; - av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING, - "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(enc->codec_id)); - - if (error) { - av_log(s, AV_LOG_ERROR, - "use vstrict=-1 / -strict -1 to use it anyway.\n"); - return AVERROR(EINVAL); - } - } - break; - case AVMEDIA_TYPE_AUDIO: - if (audio_enc) { - av_log(s, AV_LOG_ERROR, - "at most one audio stream is supported in flv\n"); - return AVERROR(EINVAL); - } - audio_enc = enc; - if (get_audio_flags(s, enc) < 0) - return AVERROR_INVALIDDATA; - if (enc->codec_id == AV_CODEC_ID_PCM_S16BE) - av_log(s, AV_LOG_WARNING, - "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n"); - break; - case AVMEDIA_TYPE_DATA: - if (enc->codec_id != AV_CODEC_ID_TEXT && enc->codec_id != AV_CODEC_ID_NONE) { - av_log(s, AV_LOG_ERROR, "Data codec '%s' for stream %d is not compatible with FLV\n", - avcodec_get_name(enc->codec_id), i); - return AVERROR_INVALIDDATA; - } - data_enc = enc; - break; - default: - av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n", - av_get_media_type_string(enc->codec_type), i); - return AVERROR(EINVAL); - } - avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ - - sc = av_mallocz(sizeof(FLVStreamContext)); - if (!sc) - return AVERROR(ENOMEM); - s->streams[i]->priv_data = sc; - sc->last_ts = -1; - } - - flv->delay = AV_NOPTS_VALUE; - - avio_write(pb, "FLV", 3); - avio_w8(pb, 1); - avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc + - FLV_HEADER_FLAG_HASVIDEO * !!video_enc); - avio_wb32(pb, 9); - avio_wb32(pb, 0); - - for (i = 0; i < s->nb_streams; i++) - if (s->streams[i]->codec->codec_tag == 5) { - avio_w8(pb, 8); // message type - avio_wb24(pb, 0); // include flags - avio_wb24(pb, 0); // time stamp - avio_wb32(pb, 0); // reserved - avio_wb32(pb, 11); // size - flv->reserved = 5; - } - /* write meta_tag */ avio_w8(pb, 18); // tag type META metadata_size_pos = avio_tell(pb); @@ -304,57 +220,57 @@ static int flv_write_header(AVFormatContext *s) /* mixed array (hash) with size and string/type/data tuples */ avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); metadata_count_pos = avio_tell(pb); - metadata_count = 4 * !!video_enc + - 5 * !!audio_enc + - 1 * !!data_enc + + metadata_count = 4 * !!flv->video_enc + + 5 * !!flv->audio_enc + + 1 * !!flv->data_enc + 2; // +2 for duration and file size avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); - flv->duration_offset= avio_tell(pb); + flv->duration_offset = avio_tell(pb); // fill in the guessed duration, it'll be corrected later if incorrect put_amf_double(pb, s->duration / AV_TIME_BASE); - if (video_enc) { + if (flv->video_enc) { put_amf_string(pb, "width"); - put_amf_double(pb, video_enc->width); + put_amf_double(pb, flv->video_enc->width); put_amf_string(pb, "height"); - put_amf_double(pb, video_enc->height); + put_amf_double(pb, flv->video_enc->height); put_amf_string(pb, "videodatarate"); - put_amf_double(pb, video_enc->bit_rate / 1024.0); + put_amf_double(pb, flv->video_enc->bit_rate / 1024.0); - if (framerate != 0.0) { + if (flv->framerate != 0.0) { put_amf_string(pb, "framerate"); - put_amf_double(pb, framerate); + put_amf_double(pb, flv->framerate); metadata_count++; } put_amf_string(pb, "videocodecid"); - put_amf_double(pb, video_enc->codec_tag); + put_amf_double(pb, flv->video_enc->codec_tag); } - if (audio_enc) { + if (flv->audio_enc) { put_amf_string(pb, "audiodatarate"); - put_amf_double(pb, audio_enc->bit_rate / 1024.0); + put_amf_double(pb, flv->audio_enc->bit_rate / 1024.0); put_amf_string(pb, "audiosamplerate"); - put_amf_double(pb, audio_enc->sample_rate); + put_amf_double(pb, flv->audio_enc->sample_rate); put_amf_string(pb, "audiosamplesize"); - put_amf_double(pb, audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); + put_amf_double(pb, flv->audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); put_amf_string(pb, "stereo"); - put_amf_bool(pb, audio_enc->channels == 2); + put_amf_bool(pb, flv->audio_enc->channels == 2); put_amf_string(pb, "audiocodecid"); - put_amf_double(pb, audio_enc->codec_tag); + put_amf_double(pb, flv->audio_enc->codec_tag); } - if (data_enc) { + if (flv->data_enc) { put_amf_string(pb, "datastream"); put_amf_double(pb, 0.0); } @@ -399,6 +315,103 @@ static int flv_write_header(AVFormatContext *s) avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); +} + +static int flv_write_header(AVFormatContext *s) +{ + int i; + AVIOContext *pb = s->pb; + FLVContext *flv = s->priv_data; + int64_t data_size; + + for (i = 0; i < s->nb_streams; i++) { + AVCodecContext *enc = s->streams[i]->codec; + FLVStreamContext *sc; + switch (enc->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (s->streams[i]->avg_frame_rate.den && + s->streams[i]->avg_frame_rate.num) { + flv->framerate = av_q2d(s->streams[i]->avg_frame_rate); + } + if (flv->video_enc) { + av_log(s, AV_LOG_ERROR, + "at most one video stream is supported in flv\n"); + return AVERROR(EINVAL); + } + flv->video_enc = enc; + if (enc->codec_tag == 0) { + av_log(s, AV_LOG_ERROR, "Video codec '%s' for stream %d is not compatible with FLV\n", + avcodec_get_name(enc->codec_id), i); + return AVERROR(EINVAL); + } + if (enc->codec_id == AV_CODEC_ID_MPEG4 || + enc->codec_id == AV_CODEC_ID_H263) { + int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL; + av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING, + "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(enc->codec_id)); + + if (error) { + av_log(s, AV_LOG_ERROR, + "use vstrict=-1 / -strict -1 to use it anyway.\n"); + return AVERROR(EINVAL); + } + } + break; + case AVMEDIA_TYPE_AUDIO: + if (flv->audio_enc) { + av_log(s, AV_LOG_ERROR, + "at most one audio stream is supported in flv\n"); + return AVERROR(EINVAL); + } + flv->audio_enc = enc; + if (get_audio_flags(s, enc) < 0) + return AVERROR_INVALIDDATA; + if (enc->codec_id == AV_CODEC_ID_PCM_S16BE) + av_log(s, AV_LOG_WARNING, + "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n"); + break; + case AVMEDIA_TYPE_DATA: + if (enc->codec_id != AV_CODEC_ID_TEXT && enc->codec_id != AV_CODEC_ID_NONE) { + av_log(s, AV_LOG_ERROR, "Data codec '%s' for stream %d is not compatible with FLV\n", + avcodec_get_name(enc->codec_id), i); + return AVERROR_INVALIDDATA; + } + flv->data_enc = enc; + break; + default: + av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n", + av_get_media_type_string(enc->codec_type), i); + return AVERROR(EINVAL); + } + avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ + + sc = av_mallocz(sizeof(FLVStreamContext)); + if (!sc) + return AVERROR(ENOMEM); + s->streams[i]->priv_data = sc; + sc->last_ts = -1; + } + + flv->delay = AV_NOPTS_VALUE; + + avio_write(pb, "FLV", 3); + avio_w8(pb, 1); + avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_enc + + FLV_HEADER_FLAG_HASVIDEO * !!flv->video_enc); + avio_wb32(pb, 9); + avio_wb32(pb, 0); + + for (i = 0; i < s->nb_streams; i++) + if (s->streams[i]->codec->codec_tag == 5) { + avio_w8(pb, 8); // message type + avio_wb24(pb, 0); // include flags + avio_wb24(pb, 0); // time stamp + avio_wb32(pb, 0); // reserved + avio_wb32(pb, 11); // size + flv->reserved = 5; + } + + write_metadata(s); for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; |