From 0c88502b09310b905aa697a44fe4003946fb9ed5 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Mon, 6 Jun 2016 19:29:27 +0300 Subject: [PATCH 1/3] Set the global header flag if the container format requires it Some containers, e.g. Matroska, requires the headers be written in the global headers section, not in each packet. The encoder should be notified, if that is the case. --- src/AvTranscoder/file/OutputFile.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index ff4944a0..fcb38d07 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -42,6 +42,16 @@ IOutputStream& OutputFile::addVideoStream(const VideoCodec& videoDesc) stream.codec->level = videoDesc.getAVCodecContext().level; stream.codec->field_order = videoDesc.getAVCodecContext().field_order; + if (_formatContext.getAVOutputFormat().flags & AVFMT_GLOBALHEADER) { + stream.codec->flags = CODEC_FLAG_GLOBAL_HEADER; + } + + // if the codec is experimental, allow it + if(videoDesc.getAVCodec().capabilities & CODEC_CAP_EXPERIMENTAL) { + LOG_WARN("This codec is considered experimental by libav/ffmpeg:" << videoDesc.getCodecName()); + stream.codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + } + // some codecs need/can use extradata to decode uint8_t* srcExtradata = videoDesc.getAVCodecContext().extradata; const int srcExtradataSize = videoDesc.getAVCodecContext().extradata_size; From b40674d85eb6dc84547f66011b2e8862f0ec3e15 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 21 Jun 2016 17:30:04 +0200 Subject: [PATCH 2/3] OutputFile: updated how to set the codec 'flags' when addVideoStream Because the flags attribute could have a value before this assignement. --- src/AvTranscoder/file/OutputFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index fcb38d07..9e404b4e 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -43,7 +43,7 @@ IOutputStream& OutputFile::addVideoStream(const VideoCodec& videoDesc) stream.codec->field_order = videoDesc.getAVCodecContext().field_order; if (_formatContext.getAVOutputFormat().flags & AVFMT_GLOBALHEADER) { - stream.codec->flags = CODEC_FLAG_GLOBAL_HEADER; + stream.codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } // if the codec is experimental, allow it From e96c7b644ff35f96658001b940b981ddba1d2552 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Wed, 22 Jun 2016 16:45:20 +0200 Subject: [PATCH 3/3] OutputFile: added private method setOutputStream * This method is called for each video/audio output streams. * It sets general parameters of the stream, depending on the format/codec. --- src/AvTranscoder/file/OutputFile.cpp | 43 +++++++++++++++++----------- src/AvTranscoder/file/OutputFile.hpp | 7 +++++ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 9e404b4e..5a415050 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -42,23 +42,7 @@ IOutputStream& OutputFile::addVideoStream(const VideoCodec& videoDesc) stream.codec->level = videoDesc.getAVCodecContext().level; stream.codec->field_order = videoDesc.getAVCodecContext().field_order; - if (_formatContext.getAVOutputFormat().flags & AVFMT_GLOBALHEADER) { - stream.codec->flags |= CODEC_FLAG_GLOBAL_HEADER; - } - - // if the codec is experimental, allow it - if(videoDesc.getAVCodec().capabilities & CODEC_CAP_EXPERIMENTAL) { - LOG_WARN("This codec is considered experimental by libav/ffmpeg:" << videoDesc.getCodecName()); - stream.codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; - } - - // some codecs need/can use extradata to decode - uint8_t* srcExtradata = videoDesc.getAVCodecContext().extradata; - const int srcExtradataSize = videoDesc.getAVCodecContext().extradata_size; - stream.codec->extradata = (uint8_t*)av_malloc(srcExtradataSize + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(stream.codec->extradata, srcExtradata, srcExtradataSize); - memset(((uint8_t*)stream.codec->extradata) + srcExtradataSize, 0, FF_INPUT_BUFFER_PADDING_SIZE); - stream.codec->extradata_size = videoDesc.getAVCodecContext().extradata_size; + setOutputStream(stream, videoDesc); // need to set the time_base on the AVCodecContext and the AVStream // compensating the frame rate with the ticks_per_frame and keeping @@ -85,6 +69,8 @@ IOutputStream& OutputFile::addAudioStream(const AudioCodec& audioDesc) stream.codec->sample_fmt = audioDesc.getAVCodecContext().sample_fmt; stream.codec->frame_size = audioDesc.getAVCodecContext().frame_size; + setOutputStream(stream, audioDesc); + // need to set the time_base on the AVCodecContext of the AVStream av_reduce(&stream.codec->time_base.num, &stream.codec->time_base.den, audioDesc.getAVCodecContext().time_base.num, audioDesc.getAVCodecContext().time_base.den, INT_MAX); @@ -329,4 +315,27 @@ void OutputFile::setupRemainingWrappingOptions() } } } + +void OutputFile::setOutputStream(AVStream& avStream, const ICodec& codec) +{ + // depending on the format, place global headers in extradata instead of every keyframe + if (_formatContext.getAVOutputFormat().flags & AVFMT_GLOBALHEADER) { + avStream.codec->flags |= CODEC_FLAG_GLOBAL_HEADER; + } + + // if the codec is experimental, allow it + if(codec.getAVCodec().capabilities & CODEC_CAP_EXPERIMENTAL) { + LOG_WARN("This codec is considered experimental by libav/ffmpeg:" << codec.getCodecName()); + avStream.codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + } + + // some codecs need/can use extradata to decode + uint8_t* srcExtradata = codec.getAVCodecContext().extradata; + const int srcExtradataSize = codec.getAVCodecContext().extradata_size; + avStream.codec->extradata = (uint8_t*)av_malloc(srcExtradataSize + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(avStream.codec->extradata, srcExtradata, srcExtradataSize); + memset(((uint8_t*)avStream.codec->extradata) + srcExtradataSize, 0, FF_INPUT_BUFFER_PADDING_SIZE); + avStream.codec->extradata_size = codec.getAVCodecContext().extradata_size; +} + } diff --git a/src/AvTranscoder/file/OutputFile.hpp b/src/AvTranscoder/file/OutputFile.hpp index c460c6b5..f9e7731f 100644 --- a/src/AvTranscoder/file/OutputFile.hpp +++ b/src/AvTranscoder/file/OutputFile.hpp @@ -98,6 +98,13 @@ class AvExport OutputFile : public IOutputFile void setupRemainingWrappingOptions(); //@} + /** + * @brief Depending on the format/codec, set general parameters of the stream. + * @param avStream: the stream to set. + * @param codec; the description of the codec used in the stream. + */ + void setOutputStream(AVStream& avStream, const ICodec& codec); + private: FormatContext _formatContext; std::vector _outputStreams; ///< Has ownership