diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-06-04 00:33:42 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-06-04 00:33:42 +0200 |
commit | 7d82020fcb7f81fcbbd30b7546ba62af45f1a33c (patch) | |
tree | 16504cac144fc1a8adf7822c642bb27a4c20c427 /libavformat/flvenc.c | |
parent | e10eac910a2df9a2a37f13a1a0876698b240f334 (diff) | |
parent | 19dfbf1915a0739f1a8b2f5a56aa1d3ff0597d9c (diff) | |
download | ffmpeg-7d82020fcb7f81fcbbd30b7546ba62af45f1a33c.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
librtmp: return AVERROR_UNKNOWN instead of -1.
librtmp: don't abuse a variable for two unrelated things.
librtmp: add rtmp_app and rtmp_playpath private options.
bmv: add stricter checks for invalid decoded length
avpacket: fix duplicating side data.
flv: support stream text data as onTextData
Conflicts:
libavcodec/bmv.c
libavformat/flvdec.c
libavformat/flvenc.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/flvenc.c')
-rw-r--r-- | libavformat/flvenc.c | 77 |
1 files changed, 60 insertions, 17 deletions
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index c6d5408f6d..a562ea9eda 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -182,7 +182,7 @@ static int flv_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; - AVCodecContext *audio_enc = NULL, *video_enc = NULL; + 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; @@ -191,7 +191,8 @@ static int flv_write_header(AVFormatContext *s) for(i=0; i<s->nb_streams; i++){ AVCodecContext *enc = s->streams[i]->codec; FLVStreamContext *sc; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { + switch (enc->codec_type) { + case AVMEDIA_TYPE_VIDEO: if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) { framerate = av_q2d(s->streams[i]->r_frame_rate); } else { @@ -202,10 +203,22 @@ static int flv_write_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "video codec not compatible with flv\n"); return -1; } - } else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { + break; + case AVMEDIA_TYPE_AUDIO: audio_enc = enc; if (get_audio_flags(s, enc) < 0) - return -1; + return AVERROR_INVALIDDATA; + break; + case AVMEDIA_TYPE_DATA: + if (enc->codec_id != CODEC_ID_TEXT) { + av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n"); + return AVERROR_INVALIDDATA; + } + data_enc = enc; + break; + default: + av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n"); + return -1; } avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ @@ -251,7 +264,11 @@ 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 = 5*!!video_enc + 5*!!audio_enc + 2; // +2 for duration and file size + metadata_count = 5 * !!video_enc + + 5 * !!audio_enc + + 1 * !!data_enc + + 2; // +2 for duration and file size + avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); @@ -292,6 +309,11 @@ static int flv_write_header(AVFormatContext *s) put_amf_double(pb, audio_enc->codec_tag); } + if (data_enc) { + put_amf_string(pb, "datastream"); + put_amf_double(pb, 0.0); + } + while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { if( !strcmp(tag->key, "width") ||!strcmp(tag->key, "height") @@ -416,7 +438,8 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) else flags_size= 1; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { + switch (enc->codec_type) { + case AVMEDIA_TYPE_VIDEO: avio_w8(pb, FLV_TAG_TYPE_VIDEO); flags = enc->codec_tag; @@ -426,20 +449,20 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) } flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; - } else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { + break; + case AVMEDIA_TYPE_AUDIO: flags = get_audio_flags(s, enc); assert(size); avio_w8(pb, FLV_TAG_TYPE_AUDIO); - } else { - // In-band flv metadata ("scriptdata") - assert(enc->codec_type == AVMEDIA_TYPE_DATA); + break; + case AVMEDIA_TYPE_DATA: avio_w8(pb, FLV_TAG_TYPE_META); - flags_size = 0; - flags = 0; + break; + default: + return AVERROR(EINVAL); } - if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) { /* check if extradata looks like mp4 formated */ if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) { @@ -476,9 +499,29 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) avio_w8(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_ avio_wb24(pb,flv->reserved); - if(flags_size) - avio_w8(pb,flags); - + if (enc->codec_type == AVMEDIA_TYPE_DATA) { + int data_size; + int metadata_size_pos = avio_tell(pb); + avio_w8(pb, AMF_DATA_TYPE_STRING); + put_amf_string(pb, "onTextData"); + avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); + avio_wb32(pb, 2); + put_amf_string(pb, "type"); + avio_w8(pb, AMF_DATA_TYPE_STRING); + put_amf_string(pb, "Text"); + put_amf_string(pb, "text"); + avio_w8(pb, AMF_DATA_TYPE_STRING); + put_amf_string(pb, pkt->data); + put_amf_string(pb, ""); + avio_w8(pb, AMF_END_OF_OBJECT); + /* write total size of tag */ + data_size = avio_tell(pb) - metadata_size_pos; + avio_seek(pb, metadata_size_pos - 10, SEEK_SET); + avio_wb24(pb, data_size); + avio_seek(pb, data_size + 10 - 3, SEEK_CUR); + avio_wb32(pb, data_size + 11); + } else { + avio_w8(pb,flags); if (enc->codec_id == CODEC_ID_VP6) avio_w8(pb,0); if (enc->codec_id == CODEC_ID_VP6F || enc->codec_id == CODEC_ID_VP6A) @@ -494,7 +537,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) avio_wb32(pb,size+flags_size+11); // previous tag size flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration); - + } avio_flush(pb); av_free(data); |