X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fflvenc.c;h=3f24c7e19245ceec12e1a07184a804175a348557;hb=9e13df3776da3a101e895e2840f6f23f5a6f74a0;hp=e4863f1fc73cf1e596080b5e207f702b35a59564;hpb=1b98bfb932ad36667ea7f18e24c54978623f6654;p=ffmpeg diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index e4863f1fc73..3f24c7e1924 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -580,7 +580,7 @@ static int shift_data(AVFormatContext *s) int n = 0; int64_t metadata_size = 0; FLVContext *flv = s->priv_data; - int64_t pos, pos_end = avio_tell(s->pb); + int64_t pos, pos_end = avio_tell(s->pb); /* Save the pre-shift size. */ uint8_t *buf, *read_buf[2]; int read_buf_id = 0; int read_size[2]; @@ -608,7 +608,6 @@ static int shift_data(AVFormatContext *s) avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET); avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size); - avio_seek(s->pb, pos_end, SEEK_SET); /* Shift the data: the AVIO context of the output can only be used for * writing, so we re-open the same output, but for reading. It also avoids @@ -621,9 +620,7 @@ static int shift_data(AVFormatContext *s) goto end; } - /* mark the end of the shift to up to the last data we wrote, and get ready - * for writing */ - pos_end = avio_tell(s->pb); + /* Get ready for writing. */ avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET); /* start reading at where the keyframe index information will be placed */ @@ -653,11 +650,9 @@ end: return ret; } - -static int flv_write_header(AVFormatContext *s) +static int flv_init(struct AVFormatContext *s) { int i; - AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; for (i = 0; i < s->nb_streams; i++) { @@ -736,6 +731,15 @@ static int flv_write_header(AVFormatContext *s) flv->delay = AV_NOPTS_VALUE; + return 0; +} + +static int flv_write_header(AVFormatContext *s) +{ + int i; + AVIOContext *pb = s->pb; + FLVContext *flv = s->priv_data; + avio_write(pb, "FLV", 3); avio_w8(pb, 1); avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_par + @@ -880,7 +884,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) unsigned ts; int size = pkt->size; uint8_t *data = NULL; - int flags = -1, flags_size, ret; + int flags = -1, flags_size, ret = 0; int64_t cur_offset = avio_tell(pb); if (par->codec_type == AVMEDIA_TYPE_AUDIO && !pkt->size) { @@ -898,17 +902,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { - int side_size = 0; + size_t side_size; uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { - av_free(par->extradata); - par->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!par->extradata) { - par->extradata_size = 0; - return AVERROR(ENOMEM); - } + ret = ff_alloc_extradata(par, side_size); + if (ret < 0) + return ret; memcpy(par->extradata, side, side_size); - par->extradata_size = side_size; flv_write_codec_header(s, par, pkt->dts); } } @@ -921,6 +921,12 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) "Packets are not in the proper order with respect to DTS\n"); return AVERROR(EINVAL); } + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { + if (pkt->pts == AV_NOPTS_VALUE) { + av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n"); + return AVERROR(EINVAL); + } + } ts = pkt->dts; @@ -963,10 +969,10 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { - av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " - "use the audio bitstream filter 'aac_adtstoasc' to fix it " - "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); - return AVERROR_INVALIDDATA; + av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " + "use the audio bitstream filter 'aac_adtstoasc' to fix it " + "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); + return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); } @@ -983,7 +989,8 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (size + flags_size >= 1<<24) { av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n", size + flags_size, 1<<24); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } avio_wb24(pb, size + flags_size); @@ -1048,15 +1055,17 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) case AVMEDIA_TYPE_VIDEO: flv->videosize += (avio_tell(pb) - cur_offset); flv->lasttimestamp = flv->acurframeindex / flv->framerate; + flv->acurframeindex++; if (pkt->flags & AV_PKT_FLAG_KEY) { - double ts = flv->acurframeindex / flv->framerate; + double ts = flv->lasttimestamp; int64_t pos = cur_offset; - flv->lastkeyframetimestamp = flv->acurframeindex / flv->framerate; + flv->lastkeyframetimestamp = ts; flv->lastkeyframelocation = pos; - flv_append_keyframe_info(s, flv, ts, pos); + ret = flv_append_keyframe_info(s, flv, ts, pos); + if (ret < 0) + goto fail; } - flv->acurframeindex++; break; case AVMEDIA_TYPE_AUDIO: @@ -1068,10 +1077,22 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) break; } } - +fail: av_free(data); - return pb->error; + return ret; +} + +static int flv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +{ + int ret = 1; + AVStream *st = s->streams[pkt->stream_index]; + + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) + ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); + } + return ret; } static const AVOption options[] = { @@ -1091,7 +1112,7 @@ static const AVClass flv_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -AVOutputFormat ff_flv_muxer = { +const AVOutputFormat ff_flv_muxer = { .name = "flv", .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"), .mime_type = "video/x-flv", @@ -1099,9 +1120,11 @@ AVOutputFormat ff_flv_muxer = { .priv_data_size = sizeof(FLVContext), .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF, .video_codec = AV_CODEC_ID_FLV1, + .init = flv_init, .write_header = flv_write_header, .write_packet = flv_write_packet, .write_trailer = flv_write_trailer, + .check_bitstream= flv_check_bitstream, .codec_tag = (const AVCodecTag* const []) { flv_video_codec_ids, flv_audio_codec_ids, 0 },