1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2004-2021 musikcube team 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright notice, 11 // this list of conditions and the following disclaimer. 12 // 13 // * Redistributions in binary form must reproduce the above copyright 14 // notice, this list of conditions and the following disclaimer in the 15 // documentation and/or other materials provided with the distribution. 16 // 17 // * Neither the name of the author nor the names of other contributors may 18 // be used to endorse or promote products derived from this software 19 // without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 // POSSIBILITY OF SUCH DAMAGE. 32 // 33 ////////////////////////////////////////////////////////////////////////////// 34 35 #pragma once 36 37 #ifdef WIN32 38 #define ENABLE_FFMPEG 39 #endif 40 41 #ifdef ENABLE_FFMPEG 42 43 #include <musikcore/sdk/IBlockingEncoder.h> 44 #include <musikcore/sdk/DataBuffer.h> 45 #include <string> 46 47 extern "C" { 48 #pragma warning(push, 0) 49 #include <libavcodec/avcodec.h> 50 #include <libavformat/avio.h> 51 #include <libavformat/avformat.h> 52 #include <libavutil/audio_fifo.h> 53 #include <libswresample/swresample.h> 54 #pragma warning(pop) 55 } 56 57 class FfmpegEncoder : public musik::core::sdk::IBlockingEncoder { 58 using IBuffer = musik::core::sdk::IBuffer; 59 using IDataStream = musik::core::sdk::IDataStream; 60 61 public: 62 FfmpegEncoder(const std::string& format); 63 64 virtual void Release() override; 65 virtual bool Initialize(IDataStream* out, size_t rate, size_t channels, size_t bitrate) override; 66 virtual bool Encode(const IBuffer* pcm) override; 67 virtual void Finalize() override; 68 Stream()69 IDataStream* Stream() { return this->out; } 70 71 private: 72 void Cleanup(); 73 bool OpenOutputCodec(size_t rate, size_t channels, size_t bitrate); 74 bool OpenOutputContext(); 75 bool WriteOutputHeader(); 76 bool WriteOutputTrailer(); 77 bool WriteSamplesToFifo(const IBuffer* pcm); 78 bool ReadFromFifoAndWriteToOutput(bool drain); 79 void FlushResampler(); 80 AVFrame* ReallocFrame(AVFrame* original, AVSampleFormat format, int samplesPerChannel, int sampleRate); 81 int SendReceiveAndWriteFrame(AVFrame* frame); 82 83 bool isValid; 84 IDataStream* out; 85 int readBufferSize; 86 AVAudioFifo* outputFifo; 87 AVCodec* outputCodec; 88 AVCodecContext* outputContext; 89 AVFormatContext* outputFormatContext; 90 AVIOContext* ioContext; 91 void* ioContextOutputBuffer; 92 AVFrame* outputFrame; 93 AVFrame* resampledFrame; 94 SwrContext* resampler; 95 int64_t globalTimestamp; 96 std::string format; 97 int inputChannelCount; 98 int inputSampleRate; 99 }; 100 101 #endif // ENABLE_FFMPEG