|  | @@ -178,7 +178,7 @@ static int flv_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | AVIOContext *pb = s->pb; |  |  | AVIOContext *pb = s->pb; | 
														
													
														
															
																|  |  | FLVContext *flv = s->priv_data; |  |  | 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; |  |  | int i, metadata_count = 0; | 
														
													
														
															
																|  |  | double framerate = 0.0; |  |  | double framerate = 0.0; | 
														
													
														
															
																|  |  | int64_t metadata_size_pos, data_size, metadata_count_pos; |  |  | int64_t metadata_size_pos, data_size, metadata_count_pos; | 
														
													
												
													
														
															
																|  | @@ -187,7 +187,8 @@ static int flv_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | for(i=0; i<s->nb_streams; i++){ |  |  | for(i=0; i<s->nb_streams; i++){ | 
														
													
														
															
																|  |  | AVCodecContext *enc = s->streams[i]->codec; |  |  | AVCodecContext *enc = s->streams[i]->codec; | 
														
													
														
															
																|  |  | FLVStreamContext *sc; |  |  | 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) { |  |  | if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) { | 
														
													
														
															
																|  |  | framerate = av_q2d(s->streams[i]->r_frame_rate); |  |  | framerate = av_q2d(s->streams[i]->r_frame_rate); | 
														
													
														
															
																|  |  | } else { |  |  | } else { | 
														
													
												
													
														
															
																|  | @@ -198,10 +199,22 @@ static int flv_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | av_log(s, AV_LOG_ERROR, "video codec not compatible with flv\n"); |  |  | av_log(s, AV_LOG_ERROR, "video codec not compatible with flv\n"); | 
														
													
														
															
																|  |  | return -1; |  |  | return -1; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | } else { |  |  |  | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  |  |  |  | case AVMEDIA_TYPE_AUDIO: | 
														
													
														
															
																|  |  | audio_enc = enc; |  |  | audio_enc = enc; | 
														
													
														
															
																|  |  | if (get_audio_flags(s, enc) < 0) |  |  | 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 */ |  |  | avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
												
													
														
															
																|  | @@ -247,7 +260,11 @@ static int flv_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | /* mixed array (hash) with size and string/type/data tuples */ |  |  | /* mixed array (hash) with size and string/type/data tuples */ | 
														
													
														
															
																|  |  | avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); |  |  | avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); | 
														
													
														
															
																|  |  | metadata_count_pos = avio_tell(pb); |  |  | 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); |  |  | avio_wb32(pb, metadata_count); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | put_amf_string(pb, "duration"); |  |  | put_amf_string(pb, "duration"); | 
														
													
												
													
														
															
																|  | @@ -288,6 +305,11 @@ static int flv_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | put_amf_double(pb, audio_enc->codec_tag); |  |  | 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))) { |  |  | while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { | 
														
													
														
															
																|  |  | put_amf_string(pb, tag->key); |  |  | put_amf_string(pb, tag->key); | 
														
													
														
															
																|  |  | avio_w8(pb, AMF_DATA_TYPE_STRING); |  |  | avio_w8(pb, AMF_DATA_TYPE_STRING); | 
														
													
												
													
														
															
																|  | @@ -396,7 +418,8 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) | 
														
													
														
															
																|  |  | else |  |  | else | 
														
													
														
															
																|  |  | flags_size= 1; |  |  | 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); |  |  | avio_w8(pb, FLV_TAG_TYPE_VIDEO); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | flags = enc->codec_tag; |  |  | flags = enc->codec_tag; | 
														
													
												
													
														
															
																|  | @@ -406,15 +429,21 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; |  |  | flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; | 
														
													
														
															
																|  |  | } else { |  |  |  | 
														
													
														
															
																|  |  | assert(enc->codec_type == AVMEDIA_TYPE_AUDIO); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  |  |  |  | case AVMEDIA_TYPE_AUDIO: | 
														
													
														
															
																|  |  | flags = get_audio_flags(s, enc); |  |  | flags = get_audio_flags(s, enc); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | assert(size); |  |  | assert(size); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | avio_w8(pb, FLV_TAG_TYPE_AUDIO); |  |  | avio_w8(pb, FLV_TAG_TYPE_AUDIO); | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | case AVMEDIA_TYPE_DATA: | 
														
													
														
															
																|  |  |  |  |  | avio_w8(pb, FLV_TAG_TYPE_META); | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  |  |  |  | default: | 
														
													
														
															
																|  |  |  |  |  | return AVERROR(EINVAL); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | if (enc->codec_id == CODEC_ID_H264) { |  |  | if (enc->codec_id == CODEC_ID_H264) { | 
														
													
														
															
																|  |  | /* check if extradata looks like MP4 */ |  |  | /* check if extradata looks like MP4 */ | 
														
													
														
															
																|  |  | if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) { |  |  | if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) { | 
														
													
												
													
														
															
																|  | @@ -446,6 +475,29 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) | 
														
													
														
															
																|  |  | avio_wb24(pb,ts); |  |  | avio_wb24(pb,ts); | 
														
													
														
															
																|  |  | avio_w8(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_ |  |  | avio_w8(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_ | 
														
													
														
															
																|  |  | avio_wb24(pb,flv->reserved); |  |  | avio_wb24(pb,flv->reserved); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | 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); |  |  | avio_w8(pb,flags); | 
														
													
														
															
																|  |  | if (enc->codec_id == CODEC_ID_VP6) |  |  | if (enc->codec_id == CODEC_ID_VP6) | 
														
													
														
															
																|  |  | avio_w8(pb,0); |  |  | avio_w8(pb,0); | 
														
													
												
													
														
															
																|  | @@ -462,7 +514,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | avio_wb32(pb,size+flags_size+11); // previous tag size |  |  | avio_wb32(pb,size+flags_size+11); // previous tag size | 
														
													
														
															
																|  |  | flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration); |  |  | flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration); | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | avio_flush(pb); |  |  | avio_flush(pb); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | av_free(data); |  |  | av_free(data); | 
														
													
												
													
														
															
																|  | 
 |