From 6b1682c2657d06e155348d1e29dfb7e6148d0f0e Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Fri, 21 Nov 2014 17:34:41 +0100 Subject: [PATCH 1/6] Wrapping: return wrapping process status --- src/AvTranscoder/codedStream/AvOutputStream.cpp | 2 +- src/AvTranscoder/codedStream/AvOutputStream.hpp | 2 +- src/AvTranscoder/codedStream/IOutputStream.hpp | 13 ++++++++++++- src/AvTranscoder/file/OutputFile.cpp | 8 ++++---- src/AvTranscoder/file/OutputFile.hpp | 2 +- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/AvTranscoder/codedStream/AvOutputStream.cpp b/src/AvTranscoder/codedStream/AvOutputStream.cpp index f4503006..67933274 100644 --- a/src/AvTranscoder/codedStream/AvOutputStream.cpp +++ b/src/AvTranscoder/codedStream/AvOutputStream.cpp @@ -14,7 +14,7 @@ AvOutputStream::AvOutputStream( OutputFile& outputFile, const size_t streamIndex { } -bool AvOutputStream::wrap( const CodedData& data ) +IOutputStream::EWrappingStatus AvOutputStream::wrap( const CodedData& data ) { assert( _outputFile != NULL ); return _outputFile->wrap( data, _streamIndex ); diff --git a/src/AvTranscoder/codedStream/AvOutputStream.hpp b/src/AvTranscoder/codedStream/AvOutputStream.hpp index 499c50ba..2b23ea83 100644 --- a/src/AvTranscoder/codedStream/AvOutputStream.hpp +++ b/src/AvTranscoder/codedStream/AvOutputStream.hpp @@ -15,7 +15,7 @@ class AvExport AvOutputStream : public IOutputStream size_t getStreamIndex() const { return _streamIndex; } - bool wrap( const CodedData& data ); + IOutputStream::EWrappingStatus wrap( const CodedData& data ); private: OutputFile* _outputFile; diff --git a/src/AvTranscoder/codedStream/IOutputStream.hpp b/src/AvTranscoder/codedStream/IOutputStream.hpp index 3919d5f2..33093152 100644 --- a/src/AvTranscoder/codedStream/IOutputStream.hpp +++ b/src/AvTranscoder/codedStream/IOutputStream.hpp @@ -11,11 +11,22 @@ namespace avtranscoder class IOutputStream { public: + + /** + * @brief define wrapping result status + **/ + enum EWrappingStatus + { + eWrappingSuccess = 0, + eWrappingWaitingForData, + eWrappingError, + }; + virtual ~IOutputStream() {}; virtual size_t getStreamIndex() const = 0; - virtual bool wrap( const CodedData& data ) = 0; + virtual EWrappingStatus wrap( const CodedData& data ) = 0; }; } diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 40c33e3b..a5e8de2e 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -145,10 +145,10 @@ bool OutputFile::beginWrap( ) return true; } -bool OutputFile::wrap( const CodedData& data, const size_t streamId ) +IOutputStream::EWrappingStatus OutputFile::wrap( const CodedData& data, const size_t streamId ) { if( ! data.getSize() ) - return true; + return IOutputStream::eWrappingSuccess; if( _verbose ) std::cout << "wrap on stream " << streamId << " (" << data.getSize() << " bytes for frame " << _frameCount.at( streamId ) << ")" << std::endl; AVPacket packet; @@ -174,14 +174,14 @@ bool OutputFile::wrap( const CodedData& data, const size_t streamId ) msg += err; // throw std::runtime_error( msg ); std::cout << msg << std::endl; - return false; + return IOutputStream::eWrappingError; } av_free_packet( &packet ); _packetCount++; _frameCount.at( streamId )++; - return true; + return IOutputStream::eWrappingSuccess; } bool OutputFile::endWrap( ) diff --git a/src/AvTranscoder/file/OutputFile.hpp b/src/AvTranscoder/file/OutputFile.hpp index fb49717c..40b7e7e8 100644 --- a/src/AvTranscoder/file/OutputFile.hpp +++ b/src/AvTranscoder/file/OutputFile.hpp @@ -86,7 +86,7 @@ class AvExport OutputFile * @param data coded packet information for the current stream * @param streamId refers to the stream in output ressource **/ - virtual bool wrap( const CodedData& data, const size_t streamId ); + virtual IOutputStream::EWrappingStatus wrap( const CodedData& data, const size_t streamId ); /** * @brief Finalize the end of the wrapping From df3ad6508defd0f2022f5b030a0b50bfc58ed87f Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Fri, 21 Nov 2014 17:47:23 +0100 Subject: [PATCH 2/6] Wrapping: fix packets writting when input/output packet size asymmetry (comparing streams durations) --- src/AvTranscoder/file/OutputFile.cpp | 14 ++++++++++++++ src/AvTranscoder/file/OutputFile.hpp | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index a5e8de2e..9b6c3174 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -20,6 +20,7 @@ OutputFile::OutputFile( const std::string& filename ) , _stream ( NULL ) , _filename ( filename ) , _packetCount ( 0 ) + , _previousProcessedStreamDuration( 0.0 ) , _verbose ( false ) { if( ( _formatContext = avformat_alloc_context() ) == NULL ) @@ -179,6 +180,19 @@ IOutputStream::EWrappingStatus OutputFile::wrap( const CodedData& data, const si av_free_packet( &packet ); + // get the current streams + AVStream* currentStream = _formatContext->streams[ streamId ]; + // compute its duration + double currentStreamDuration = (double)currentStream->cur_dts * currentStream->time_base.num / currentStream->time_base.den; + + if( currentStreamDuration < _previousProcessedStreamDuration ) + { + // if the current stream is strictly shorter than the previous, wait for more data + return IOutputStream::eWrappingWaitingForData; + } + + _previousProcessedStreamDuration = currentStreamDuration; + _packetCount++; _frameCount.at( streamId )++; return IOutputStream::eWrappingSuccess; diff --git a/src/AvTranscoder/file/OutputFile.hpp b/src/AvTranscoder/file/OutputFile.hpp index 40b7e7e8..99cfd6f8 100644 --- a/src/AvTranscoder/file/OutputFile.hpp +++ b/src/AvTranscoder/file/OutputFile.hpp @@ -123,6 +123,8 @@ class AvExport OutputFile std::string _filename; size_t _packetCount; + + double _previousProcessedStreamDuration; bool _verbose; }; From 54a6e3e05096445dafef817779a9ba4f6fea699e Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Fri, 21 Nov 2014 17:49:41 +0100 Subject: [PATCH 3/6] Wrapping: feed the wrapper when waiting for data (from the same stream) to complete wrapping --- .../transcoder/StreamTranscoder.cpp | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 35455665..63c427db 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -303,7 +303,19 @@ bool StreamTranscoder::processRewrap() if( ! _inputStream->readNextPacket( data ) ) return false; - _outputStream->wrap( data ); + IOutputStream::EWrappingStatus wrappingStatus = _outputStream->wrap( data ); + + switch( wrappingStatus ) + { + case IOutputStream::eWrappingSuccess: + return true; + case IOutputStream::eWrappingWaitingForData: + // the wrapper needs more data to write the current packet + return processRewrap(); + case IOutputStream::eWrappingError: + return false; + } + return true; } @@ -355,7 +367,20 @@ bool StreamTranscoder::processTranscode() if( _verbose ) std::cout << "wrap (" << data.getSize() << ")" << std::endl; - _outputStream->wrap( data ); + + IOutputStream::EWrappingStatus wrappingStatus = _outputStream->wrap( data ); + + switch( wrappingStatus ) + { + case IOutputStream::eWrappingSuccess: + return true; + case IOutputStream::eWrappingWaitingForData: + // the wrapper needs more data to write the current packet + return processTranscode(); + case IOutputStream::eWrappingError: + return false; + } + return true; } @@ -406,7 +431,20 @@ bool StreamTranscoder::processTranscode( const int subStreamIndex ) } if( _verbose ) std::cout << "wrap (" << data.getSize() << ")" << std::endl; - _outputStream->wrap( data ); + + IOutputStream::EWrappingStatus wrappingStatus = _outputStream->wrap( data ); + + switch( wrappingStatus ) + { + case IOutputStream::eWrappingSuccess: + return true; + case IOutputStream::eWrappingWaitingForData: + // the wrapper needs more data to write the current packet + return processTranscode( subStreamIndex ); + case IOutputStream::eWrappingError: + return false; + } + return true; } From c1caf536c88d9acfe313372dafd269702decfcb6 Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Fri, 21 Nov 2014 17:55:01 +0100 Subject: [PATCH 4/6] Wrapping: fix double ticks_per_frame compensation into video codec --- src/AvTranscoder/file/OutputFile.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 9b6c3174..617c1867 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -67,12 +67,13 @@ IOutputStream& OutputFile::addVideoStream( const VideoCodec& videoDesc ) _stream->codec->width = videoDesc.getAVCodecContext()->width; _stream->codec->height = videoDesc.getAVCodecContext()->height; _stream->codec->bit_rate = videoDesc.getAVCodecContext()->bit_rate; - _stream->codec->ticks_per_frame = videoDesc.getAVCodecContext()->ticks_per_frame; _stream->codec->pix_fmt = videoDesc.getAVCodecContext()->pix_fmt; _stream->codec->profile = videoDesc.getAVCodecContext()->profile; _stream->codec->level = videoDesc.getAVCodecContext()->level; - // need to set the time_base on the AVCodecContext and the AVStream... + // need to set the time_base on the AVCodecContext and the AVStream + // compensating the frame rate with the ticks_per_frame and keeping + // a coherent reading speed. av_reduce( &_stream->codec->time_base.num, &_stream->codec->time_base.den, From 96bf6fe49d724a2b8dcd9094aa4c3da9329b1f14 Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Fri, 21 Nov 2014 18:04:01 +0100 Subject: [PATCH 5/6] Transcoding: fix the audio output frame size problem when variable audio frame size in input --- src/AvTranscoder/transform/AudioTransform.cpp | 15 +++++++++++++++ src/AvTranscoder/transform/AudioTransform.hpp | 3 +++ 2 files changed, 18 insertions(+) diff --git a/src/AvTranscoder/transform/AudioTransform.cpp b/src/AvTranscoder/transform/AudioTransform.cpp index 5c68a776..285109c6 100644 --- a/src/AvTranscoder/transform/AudioTransform.cpp +++ b/src/AvTranscoder/transform/AudioTransform.cpp @@ -32,6 +32,7 @@ namespace avtranscoder AudioTransform::AudioTransform() : _audioConvertContext( NULL ) + , _previousProcessedAudioFrameSize( 0 ) , _isInit ( false ) { } @@ -64,11 +65,24 @@ bool AudioTransform::init( const Frame& srcFrame, const Frame& dstFrame ) return true; } +bool AudioTransform::initFrames( const Frame& srcFrame, Frame& dstFrame ) +{ + const AudioFrame& src = static_cast( srcFrame ); + const AudioFrame& dst = static_cast( dstFrame ); + + int dstSampleSize = av_get_bytes_per_sample( dst.desc().getAVSampleFormat() ); + dstFrame.getBuffer().resize( src.getNbSamples() * dstSampleSize ); + return true; +} + void AudioTransform::convert( const Frame& srcFrame, Frame& dstFrame ) { if( ! _isInit ) _isInit = init( srcFrame, dstFrame ); + if( srcFrame.getSize() != _previousProcessedAudioFrameSize ) + initFrames( srcFrame, dstFrame ); + const unsigned char* srcData = srcFrame.getPtr(); unsigned char* dstData = dstFrame.getPtr(); @@ -89,6 +103,7 @@ void AudioTransform::convert( const Frame& srcFrame, Frame& dstFrame ) if( dstFrame.getSize() != nbOutputSamples ) dstFrame.getBuffer().resize( nbOutputSamples, 0 ); static_cast( dstFrame ).setNbSamples( static_cast( srcFrame ).getNbSamples() ); + _previousProcessedAudioFrameSize = srcFrame.getSize(); } } diff --git a/src/AvTranscoder/transform/AudioTransform.hpp b/src/AvTranscoder/transform/AudioTransform.hpp index c33665cd..a2d1d1a4 100644 --- a/src/AvTranscoder/transform/AudioTransform.hpp +++ b/src/AvTranscoder/transform/AudioTransform.hpp @@ -26,8 +26,11 @@ class AvExport AudioTransform : public ITransform private: bool init( const Frame& srcFrame, const Frame& dstFrame ); + bool initFrames( const Frame& srcFrame, Frame& dstFrame ); ResampleContext* _audioConvertContext; + + size_t _previousProcessedAudioFrameSize; bool _isInit; }; From 59755cca4b9f083ca8e8db9a0cf7d2630f865e7e Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Fri, 21 Nov 2014 18:17:35 +0100 Subject: [PATCH 6/6] Transcoding: in AudioTransform, reset previous processed audio frame size attribute only when the current frame size is re-initialized --- src/AvTranscoder/transform/AudioTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/transform/AudioTransform.cpp b/src/AvTranscoder/transform/AudioTransform.cpp index 285109c6..ebc6c5bd 100644 --- a/src/AvTranscoder/transform/AudioTransform.cpp +++ b/src/AvTranscoder/transform/AudioTransform.cpp @@ -72,6 +72,7 @@ bool AudioTransform::initFrames( const Frame& srcFrame, Frame& dstFrame ) int dstSampleSize = av_get_bytes_per_sample( dst.desc().getAVSampleFormat() ); dstFrame.getBuffer().resize( src.getNbSamples() * dstSampleSize ); + _previousProcessedAudioFrameSize = srcFrame.getSize(); return true; } @@ -103,7 +104,6 @@ void AudioTransform::convert( const Frame& srcFrame, Frame& dstFrame ) if( dstFrame.getSize() != nbOutputSamples ) dstFrame.getBuffer().resize( nbOutputSamples, 0 ); static_cast( dstFrame ).setNbSamples( static_cast( srcFrame ).getNbSamples() ); - _previousProcessedAudioFrameSize = srcFrame.getSize(); } }