diff --git a/.gitignore b/.gitignore index 6466313..ca32786 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,7 @@ -################################################################################ -# This .gitignore file was automatically created by Microsoft(R) Visual Studio. -################################################################################ - -/source/ffmpeg-cpp/.vs/ffmpeg-cpp/v15 -/source/ffmpeg-cpp/ffmpeg-cpp/obj -/source/ffmpeg-cpp/demo/obj -/source/ffmpeg-cpp/x64/Debug -/source/ffmpeg-cpp/obj/Debug -/source/ffmpeg-cpp/demo/samples/out.mp4 -/ffmpeg/include +/ffmpeg/include /ffmpeg/lib /ffmpeg/bin /bin /lib - -/source/ffmpeg-cpp/decode_audio/obj -/source/ffmpeg-cpp/encode_audio/obj -/source/ffmpeg-cpp/encode_video/obj -/source/ffmpeg-cpp/decode_video/obj -/source/ffmpeg-cpp/filtering_video/obj -/include - -/source/ffmpeg-cpp/remuxing/obj +/.vs +/.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..77be6f6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.5) + +project(ffmpegcpp VERSION 1.0.0) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +file(GLOB_RECURSE ffmpegcpp_files "include/ffmpegcpp/*.h" "src/*.cpp") +file(GLOB_RECURSE header_files "include/ffmpegcpp/*.h") + +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${ffmpegcpp_files}) + +add_library(ffmpegcpp STATIC ${ffmpegcpp_files}) + +set_target_properties(ffmpegcpp PROPERTIES + VERSION ${PROJECT_VERSION} + PUBLIC_HEADER ${header_files} + CXX_STANDARD 17 +) + +set_target_properties(ffmpegcpp PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib +) + +target_include_directories(ffmpegcpp PRIVATE + include/ffmpegcpp + ffmpeg/include +) + +target_link_libraries(ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/avcodec.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/avdevice.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/avfilter.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/avformat.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/avutil.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/postproc.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/swresample.lib + ${PROJECT_SOURCE_DIR}/ffmpeg/lib/swscale.lib +) + +install(TARGETS ffmpegcpp + ARCHIVE DESTINATION ${CMAKE_BINARY_DIR}/lib + LIBRARY DESTINATION ${CMAKE_BINARY_DIR}/lib + PUBLIC_HEADER DESTINATION ${CMAKE_BINARY_DIR}/lib/include +) + +install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/ffmpeg/bin/ DESTINATION ${CMAKE_BINARY_DIR}/bin/Release FILES_MATCHING PATTERN "*.dll") +install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/samples/ DESTINATION ${CMAKE_BINARY_DIR}/bin/Release/samples) + +add_subdirectory(examples) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..738c5c3 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(decode_audio) +add_subdirectory(decode_video) +add_subdirectory(demo) +add_subdirectory(encode_audio) +add_subdirectory(encode_video) +add_subdirectory(filtering_video) +add_subdirectory(remuxing) diff --git a/examples/decode_audio/CMakeLists.txt b/examples/decode_audio/CMakeLists.txt new file mode 100644 index 0000000..45606a9 --- /dev/null +++ b/examples/decode_audio/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_executable(decode_audio + decode_audio.cpp +) + +set_target_properties(decode_audio PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(decode_audio PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(decode_audio ffmpegcpp) + +set_target_properties(decode_audio PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/decode_audio/decode_audio.cpp b/examples/decode_audio/decode_audio.cpp similarity index 63% rename from source/ffmpeg-cpp/decode_audio/decode_audio.cpp rename to examples/decode_audio/decode_audio.cpp index fc11027..9eb51cc 100644 --- a/source/ffmpeg-cpp/decode_audio/decode_audio.cpp +++ b/examples/decode_audio/decode_audio.cpp @@ -1,21 +1,19 @@ #include +#include #include "ffmpegcpp.h" -using namespace std; -using namespace ffmpegcpp; - -class RawAudioFileSink : public AudioFrameSink +class RawAudioFileSink : public ffmpegcpp::AudioFrameSink { public: - RawAudioFileSink(const char* fileName) + RawAudioFileSink(const std::string & fileName) { - file = fopen(fileName, "wb"); + file = fopen(fileName.c_str(), "wb"); } - virtual void WriteFrame(AVFrame* frame, AVRational* timeBase) + void WriteFrame(AVFrame* frame, AVRational* timeBase) override { // Just write out the samples channel by channel to a file. int data_size = av_get_bytes_per_sample((AVSampleFormat)frame->format); @@ -28,12 +26,12 @@ class RawAudioFileSink : public AudioFrameSink } } - virtual void Close() + void Close() override { fclose(file); } - virtual bool IsPrimed() + bool IsPrimed() const override { // Return whether we have all information we need to start writing out data. // Since we don't really need any data in this use case, we are always ready. @@ -52,36 +50,33 @@ int main() try { // Load this container file so we can extract audio from it. - Demuxer* demuxer = new Demuxer("samples/big_buck_bunny.mp4"); + ffmpegcpp::Demuxer demuxer("samples/big_buck_bunny.mp4"); // Create a file sink that will just output the raw audio data. - RawAudioFileSink* fileSink = new RawAudioFileSink("rawaudio"); + auto fileSink = std::make_unique("rawaudio"); // tie the file sink to the best audio stream in the input container. - demuxer->DecodeBestAudioStream(fileSink); + demuxer.DecodeBestAudioStream(fileSink.get()); // Prepare the output pipeline. This will push a small amount of frames to the file sink until it IsPrimed returns true. - demuxer->PreparePipeline(); + demuxer.PreparePipeline(); // Push all the remaining frames through. - while (!demuxer->IsDone()) + while (!demuxer.IsDone()) { - demuxer->Step(); + demuxer.Step(); } - // done - delete demuxer; - delete fileSink; } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << "Exception caught!" << endl; - cerr << e.what() << endl; + std::cerr << "Exception caught!" << '\n'; + std::cerr << e.what() << '\n'; throw e; } - cout << "Decoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Decoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); } diff --git a/examples/decode_video/CMakeLists.txt b/examples/decode_video/CMakeLists.txt new file mode 100644 index 0000000..9e57c11 --- /dev/null +++ b/examples/decode_video/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_executable(decode_video + decode_video.cpp +) + +set_target_properties(decode_video PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(decode_video PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(decode_video ffmpegcpp) + +set_target_properties(decode_video PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/decode_video/decode_video.cpp b/examples/decode_video/decode_video.cpp similarity index 72% rename from source/ffmpeg-cpp/decode_video/decode_video.cpp rename to examples/decode_video/decode_video.cpp index 03e45af..a63132b 100644 --- a/source/ffmpeg-cpp/decode_video/decode_video.cpp +++ b/examples/decode_video/decode_video.cpp @@ -1,12 +1,10 @@ #include +#include #include "ffmpegcpp.h" -using namespace std; -using namespace ffmpegcpp; - -class PGMFileSink : public VideoFrameSink +class PGMFileSink : public ffmpegcpp::VideoFrameSink { public: @@ -14,7 +12,7 @@ class PGMFileSink : public VideoFrameSink { } - virtual void WriteFrame(AVFrame* frame, AVRational* timeBase) + void WriteFrame(AVFrame* frame, AVRational* timeBase) override { ++frameNumber; printf("saving frame %3d\n", frameNumber); @@ -41,12 +39,12 @@ class PGMFileSink : public VideoFrameSink fclose(f); } - virtual void Close() + void Close() override { // nothing to do here. } - virtual bool IsPrimed() + bool IsPrimed() const override { // Return whether we have all information we need to start writing out data. // Since we don't really need any data in this use case, we are always ready. @@ -67,36 +65,32 @@ int main() try { // Load this container file so we can extract video from it. - Demuxer* demuxer = new Demuxer("samples/big_buck_bunny.mp4"); + ffmpegcpp::Demuxer demuxer("samples/big_buck_bunny.mp4"); // Create a file sink that will just output the raw frame data in one PGM file per frame. - PGMFileSink* fileSink = new PGMFileSink(); + auto fileSink = std::make_unique(); // tie the file sink to the best video stream in the input container. - demuxer->DecodeBestVideoStream(fileSink); + demuxer.DecodeBestVideoStream(fileSink.get()); // Prepare the output pipeline. This will push a small amount of frames to the file sink until it IsPrimed returns true. - demuxer->PreparePipeline(); + demuxer.PreparePipeline(); // Push all the remaining frames through. - while (!demuxer->IsDone()) + while (!demuxer.IsDone()) { - demuxer->Step(); + demuxer.Step(); } - - // done - delete demuxer; - delete fileSink; } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << "Exception caught!" << endl; - cerr << e.what() << endl; + std::cerr << "Exception caught!" << '\n'; + std::cerr << e.what() << '\n'; throw e; } - cout << "Decoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Decoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); } diff --git a/examples/demo/CMakeLists.txt b/examples/demo/CMakeLists.txt new file mode 100644 index 0000000..68ab5f3 --- /dev/null +++ b/examples/demo/CMakeLists.txt @@ -0,0 +1,19 @@ + +add_executable(demo + demo.cpp + GeneratedAudioSource.cpp + GeneratedVideoSource.cpp +) + +set_target_properties(demo PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(demo PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(demo ffmpegcpp) + +set_target_properties(demo PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/demo/GeneratedAudioSource.cpp b/examples/demo/GeneratedAudioSource.cpp similarity index 78% rename from source/ffmpeg-cpp/demo/GeneratedAudioSource.cpp rename to examples/demo/GeneratedAudioSource.cpp index b1e04df..fe19250 100644 --- a/source/ffmpeg-cpp/demo/GeneratedAudioSource.cpp +++ b/examples/demo/GeneratedAudioSource.cpp @@ -1,6 +1,6 @@ #include "GeneratedAudioSource.h" -GeneratedAudioSource::GeneratedAudioSource(AudioFrameSink* frameSink) +GeneratedAudioSource::GeneratedAudioSource(ffmpegcpp::AudioFrameSink* frameSink) { this->sampleRate = 44100; this->channels = 2; @@ -8,7 +8,7 @@ GeneratedAudioSource::GeneratedAudioSource(AudioFrameSink* frameSink) // generate a raw video source that will convert the raw format to any other format and pass it on to the encoder // or any other sink (might be a filter as well). - output = new RawAudioDataSource(format, this->sampleRate, this->channels, frameSink); + output = std::make_unique(format, this->sampleRate, this->channels, frameSink); samples = new uint16_t[channels * 2 * sampleCount]; @@ -16,7 +16,6 @@ GeneratedAudioSource::GeneratedAudioSource(AudioFrameSink* frameSink) GeneratedAudioSource::~GeneratedAudioSource() { - delete output; delete samples; } @@ -28,7 +27,7 @@ void GeneratedAudioSource::PreparePipeline() } } -bool GeneratedAudioSource::IsDone() +bool GeneratedAudioSource::IsDone() const { return frameNumber >= 120; } @@ -37,7 +36,7 @@ void GeneratedAudioSource::Step() { /* encode a single tone sound */ float t = 0.0f; - float tincr = 2 * M_PI * 440.0 / sampleRate; + float tincr = (float)(2.0 * M_PI * 440.0) / (float)sampleRate; for (int i = 0; i < 120; i++) { /* make sure the frame is writable -- makes a copy if the encoder diff --git a/examples/demo/GeneratedAudioSource.h b/examples/demo/GeneratedAudioSource.h new file mode 100644 index 0000000..779ae0f --- /dev/null +++ b/examples/demo/GeneratedAudioSource.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "ffmpegcpp.h" + +class GeneratedAudioSource : public ffmpegcpp::InputSource +{ +public: + + GeneratedAudioSource(ffmpegcpp::AudioFrameSink* frameSink); + ~GeneratedAudioSource() override; + + void PreparePipeline() override; + bool IsDone() const override; + void Step() override; + +private: + + int sampleRate; + int channels; + AVSampleFormat format; + + std::unique_ptr output; + + int sampleCount = 735; + + uint16_t* samples; + + int frameNumber = 0; +}; + diff --git a/source/ffmpeg-cpp/demo/GeneratedVideoSource.cpp b/examples/demo/GeneratedVideoSource.cpp similarity index 90% rename from source/ffmpeg-cpp/demo/GeneratedVideoSource.cpp rename to examples/demo/GeneratedVideoSource.cpp index 54cb44a..6b5036c 100644 --- a/source/ffmpeg-cpp/demo/GeneratedVideoSource.cpp +++ b/examples/demo/GeneratedVideoSource.cpp @@ -1,15 +1,14 @@ #include "GeneratedVideoSource.h" -GeneratedVideoSource::GeneratedVideoSource(int width, int height, VideoFrameSink* frameSink) +GeneratedVideoSource::GeneratedVideoSource(int width, int height, ffmpegcpp::VideoFrameSink* frameSink) { // generate a raw video source that will convert the raw format to any other format and pass it on to the encoder // or any other sink (might be a filter as well). - output = new RawVideoDataSource(width, height, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA, 30, frameSink); + output = std::make_unique(width, height, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA, 30, frameSink); } GeneratedVideoSource::~GeneratedVideoSource() { - delete output; delete rgb; } @@ -35,7 +34,7 @@ void GeneratedVideoSource::Step() } } -bool GeneratedVideoSource::IsDone() +bool GeneratedVideoSource::IsDone() const { return frameNumber >= 100; } diff --git a/examples/demo/GeneratedVideoSource.h b/examples/demo/GeneratedVideoSource.h new file mode 100644 index 0000000..ac53339 --- /dev/null +++ b/examples/demo/GeneratedVideoSource.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "ffmpegcpp.h" + +class GeneratedVideoSource : public ffmpegcpp::InputSource +{ +public: + + GeneratedVideoSource(int width, int height, ffmpegcpp::VideoFrameSink* frameSink); + ~GeneratedVideoSource() override; + + void PreparePipeline() override; + bool IsDone() const override; + void Step() override; + +private: + + std::unique_ptr output; + + int frameNumber = 0; + + uint8_t *rgb = nullptr; +}; + diff --git a/source/ffmpeg-cpp/demo/demo.cpp b/examples/demo/demo.cpp similarity index 50% rename from source/ffmpeg-cpp/demo/demo.cpp rename to examples/demo/demo.cpp index 2d652c6..6e82aaf 100644 --- a/source/ffmpeg-cpp/demo/demo.cpp +++ b/examples/demo/demo.cpp @@ -1,14 +1,12 @@ #include +#include #include "GeneratedVideoSource.h" #include "GeneratedAudioSource.h" #include -using namespace ffmpegcpp; -using namespace std; - // This example demonstrates different combinations and usages for ffmpeg-cpp. // Configure it by changing the values below. // The list of supported codecs is not limited to the ones mentioned below, @@ -19,37 +17,40 @@ void PlayDemo(int argc, char** argv) { // These are example video and audio sources used below. - const char* rawVideoFile = "samples/carphone_qcif.y4m"; - int rawVideoWidth = 176; int rawVideoHeight = 162; - const char* rawAudioFile = "samples/Vivaldi_s16le_2_channels_samplerate_11025.dat"; - const char* rawAudioFormat = "s16le"; int rawAudioSampleRate = 11025; int rawAudioChannels = 2; + std::string rawVideoFile = "samples/carphone_qcif.y4m"; + int rawVideoWidth = 176; + int rawVideoHeight = 162; + std::string rawAudioFile = "samples/Vivaldi_s16le_2_channels_samplerate_11025.dat"; + std::string rawAudioFormat = "s16le"; + int rawAudioSampleRate = 11025; + int rawAudioChannels = 2; - const char* encodedVideoFile = "samples/carphone.h264"; - const char* encodedAudioFile = "samples/Vivaldi_Sonata_eminor_.mp3"; + std::string encodedVideoFile = "samples/carphone.h264"; + std::string encodedAudioFile = "samples/Vivaldi_Sonata_eminor_.mp3"; - const char* containerWithVideoAndAudioFile = "samples/big_buck_bunny.mp4"; - const char* containerWithAudioFile = "samples/DesiJourney.wav"; + std::string containerWithVideoAndAudioFile = "samples/big_buck_bunny.mp4"; + std::string containerWithAudioFile = "samples/DesiJourney.wav"; // hard-code the settings here, but let them be overridden by the arguments - string inputAudioSource = "CONTAINER"; // options are RAW, ENCODED, CONTAINER, GENERATED - string inputVideoSource = "ENCODED"; // options are RAW, ENCODED, CONTAINER, GENERATED - string outputAudioCodec = "AAC"; // options are MP2, AAC, NONE - string outputVideoCodec = "H264"; // options are H264, H265, VP9, NONE (H264 and H265 only work on Nvidia hardware) - string outputContainerName = "out.mp4"; // container format is deduced from extension so use a known one + std::string inputAudioSource = "CONTAINER"; // options are RAW, ENCODED, CONTAINER, GENERATED + std::string inputVideoSource = "ENCODED"; // options are RAW, ENCODED, CONTAINER, GENERATED + std::string outputAudioCodec = "AAC"; // options are MP2, AAC, NONE + std::string outputVideoCodec = "H264"; // options are H264, H265, VP9, NONE (H264 and H265 only work on Nvidia hardware) + std::string outputContainerName = "out.mp4"; // container format is deduced from extension so use a known one // you can use any filter string that you can use in the ffmpeg command-line here // set the filter to NULL to disable filtering. // See https://trac.ffmpeg.org/wiki/FilteringGuide for more info // This example rotates the entire video and then puts a vignette on top of it. - const char* videoFilterConfig = NULL;//"transpose=cclock[middle];[middle]vignette" + const char* videoFilterConfig = nullptr;//"transpose=cclock[middle];[middle]vignette" // if command line is specified, we overwrite our hard-coded settings if (argc >= 6) { - inputAudioSource = string(argv[1]); - inputVideoSource = string(argv[2]); - outputAudioCodec = string(argv[3]); - outputVideoCodec = string(argv[4]); + inputAudioSource = std::string(argv[1]); + inputVideoSource = std::string(argv[2]); + outputAudioCodec = std::string(argv[3]); + outputVideoCodec = std::string(argv[4]); videoFilterConfig = argv[5]; } @@ -63,24 +64,24 @@ void PlayDemo(int argc, char** argv) */ // create the output muxer - we'll be adding encoders to it later - Muxer* muxer = new Muxer(outputContainerName.c_str()); + auto muxer = std::make_unique(outputContainerName.c_str()); /** * CONFIGURE AUDIO OUTPUT */ // create the output encoder based on our setting above - AudioCodec* audioCodec = nullptr; + std::unique_ptr audioCodec; if (outputAudioCodec == "MP2") { - printf("Encoding audio as MP2...\n"); - audioCodec = new AudioCodec(AV_CODEC_ID_MP2); + std::cout << "Encoding audio as MP2...\n"; + audioCodec = std::make_unique(AV_CODEC_ID_MP2); } else if (outputAudioCodec == "AAC") { - printf("Encoding audio as AAC...\n"); - audioCodec = new AudioCodec(AV_CODEC_ID_AAC); + std::cout << "Encoding audio as AAC...\n"; + audioCodec = std::make_unique(AV_CODEC_ID_AAC); } else if (outputAudioCodec == "NONE") @@ -90,10 +91,10 @@ void PlayDemo(int argc, char** argv) // create an encoder - this encoder will receive raw data from any source (filter, file, container, memory, etc), // encode it and send it to the muxer (the output container). - AudioEncoder* audioEncoder = nullptr; + std::unique_ptr audioEncoder; if (audioCodec != nullptr) { - audioEncoder = new AudioEncoder(audioCodec, muxer); + audioEncoder = std::make_unique(audioCodec.get(), muxer.get()); } /** @@ -101,27 +102,27 @@ void PlayDemo(int argc, char** argv) */ // create the output encoder based on our setting above - VideoCodec* videoCodec = nullptr; + std::unique_ptr videoCodec; if (outputVideoCodec == "H264") { - printf("Encoding video as H264 on Nvidia GPU...\n"); - H264NVEncCodec* h264Codec = new H264NVEncCodec(); + std::cout << "Encoding video as H264 on Nvidia GPU...\n"; + auto h264Codec = std::make_unique(); h264Codec->SetPreset("hq"); - videoCodec = h264Codec; + videoCodec = std::move(h264Codec); } else if (outputVideoCodec == "H265") { - printf("Encoding video as H265 on Nvidia GPU...\n"); - H265NVEncCodec* h265Codec = new H265NVEncCodec(); + std::cout << "Encoding video as H265 on Nvidia GPU...\n"; + auto h265Codec = std::make_unique(); h265Codec->SetPreset("hq"); - videoCodec = h265Codec; + videoCodec = std::move(h265Codec); } else if (outputVideoCodec == "VP9") { - printf("Encoding video as VP9...\n"); - VP9Codec* vp9Codec = new VP9Codec(); + std::cout << "Encoding video as VP9...\n"; + auto vp9Codec = std::make_unique(); vp9Codec->SetLossless(true); - videoCodec = vp9Codec; + videoCodec = std::move(vp9Codec); } else if (outputVideoCodec == "NONE") { @@ -130,10 +131,10 @@ void PlayDemo(int argc, char** argv) // create an encoder for the codec and tie it to the muxer // this encoder will receive data from an input source (file, raw, filter, etc), encode it and send it to the output container (muxer) - VideoEncoder* videoEncoder = nullptr; + std::unique_ptr videoEncoder; if (videoCodec != nullptr) { - videoEncoder = new VideoEncoder(videoCodec, muxer); + videoEncoder = std::make_unique(videoCodec.get(), muxer.get()); } /** @@ -141,31 +142,31 @@ void PlayDemo(int argc, char** argv) */ // only do this when there is an output - otherwise there is no point in reading audio - InputSource* audioInputSource = nullptr; + std::unique_ptr audioInputSource; if (audioEncoder != nullptr) { if (inputAudioSource == "RAW") { - printf("Pulling audio from %s...\n", rawAudioFile); - audioInputSource = new RawAudioFileSource(rawAudioFile, rawAudioFormat, rawAudioSampleRate, rawAudioChannels, audioEncoder); + std::cout << "Pulling audio from " << rawAudioFile << "...\n"; + audioInputSource = std::make_unique(rawAudioFile, rawAudioFormat, rawAudioSampleRate, rawAudioChannels, audioEncoder.get()); } else if (inputAudioSource == "ENCODED") { - printf("Pulling audio from %s...\n", encodedAudioFile); - audioInputSource = new EncodedFileSource(encodedAudioFile, AV_CODEC_ID_MP3, audioEncoder); + std::cout << "Pulling audio from " << encodedAudioFile << "...\n"; + audioInputSource = std::make_unique(encodedAudioFile, AV_CODEC_ID_MP3, audioEncoder.get()); } else if (inputAudioSource == "CONTAINER") { // if the input comes from a container, we use the demuxer class - it is just an input source like any other - printf("Pulling audio from %s...\n", containerWithAudioFile); - Demuxer* demuxer = new Demuxer(containerWithAudioFile); - demuxer->DecodeBestAudioStream(audioEncoder); - audioInputSource = demuxer; + std::cout << "Pulling audio from " << containerWithAudioFile << "...\n"; + auto demuxer = std::make_unique(containerWithAudioFile); + demuxer->DecodeBestAudioStream(audioEncoder.get()); + audioInputSource = std::move(demuxer); } else if (inputAudioSource == "GENERATED") { - printf("Generating 440Hz audio tone...\n"); - audioInputSource = new GeneratedAudioSource(audioEncoder); + std::cout << "Generating 440Hz audio tone...\n"; + audioInputSource = std::make_unique(audioEncoder.get()); } } @@ -173,17 +174,14 @@ void PlayDemo(int argc, char** argv) * CONFIGURE VIDEO FILTER IF IT IS USED */ - VideoFrameSink* videoFrameSink = videoEncoder; - // If a video filter was specified, we inject it into the pipeline here. // Instead of feeding the video source directly to the encoder, we feed it to // the video filter instead, which will pass it on to the encoder. - VideoFilter* videoFilter = nullptr; - if (videoFilterConfig != NULL && videoEncoder != nullptr) + std::unique_ptr videoFilter; + if (videoFilterConfig != nullptr && videoEncoder != nullptr) { - printf("Applying filter %s to video...\n", videoFilterConfig); - videoFilter = new VideoFilter(videoFilterConfig, videoEncoder); - videoFrameSink = videoFilter; // used to feed the source below + std::cout << "Applying filter " << videoFilterConfig << " to video...\n"; + videoFilter = std::make_unique(videoFilterConfig, videoEncoder.get()); } /** @@ -191,30 +189,30 @@ void PlayDemo(int argc, char** argv) */ // only do this when there is video output - InputSource* videoInputSource = nullptr; + std::unique_ptr videoInputSource; if (videoEncoder != nullptr) { if (inputVideoSource == "RAW") { - printf("Pulling video from %s...\n", rawVideoFile); - videoInputSource = new RawVideoFileSource(rawVideoFile, videoFrameSink); + std::cout << "Pulling video from " << rawVideoFile << "...\n"; + videoInputSource = std::make_unique(rawVideoFile, videoFilter.get()); } else if (inputVideoSource == "ENCODED") { - printf("Pulling video from %s...\n", encodedVideoFile); - videoInputSource = new RawVideoFileSource(encodedVideoFile, videoFrameSink); + std::cout << "Pulling video from " << encodedVideoFile << "...\n"; + videoInputSource = std::make_unique(encodedVideoFile, videoFilter.get()); } else if (inputVideoSource == "CONTAINER") { - printf("Pulling video from %s...\n", containerWithVideoAndAudioFile); - Demuxer* demuxer = new Demuxer(containerWithVideoAndAudioFile); - demuxer->DecodeBestVideoStream(videoFrameSink); - videoInputSource = demuxer; + std::cout << "Pulling video from " << containerWithVideoAndAudioFile << "...\n"; + auto demuxer = std::make_unique(containerWithVideoAndAudioFile); + demuxer->DecodeBestVideoStream(videoFilter.get()); + videoInputSource = std::move(demuxer); } else if (inputVideoSource == "GENERATED") { - printf("Generating checkerboard video pattern...\n"); - videoInputSource = new GeneratedVideoSource(640, 480, videoFrameSink); + std::cout << "Generating checkerboard video pattern...\n"; + videoInputSource = std::make_unique(640, 480, videoFilter.get()); } } @@ -249,35 +247,10 @@ void PlayDemo(int argc, char** argv) // close the muxer and save the file to disk muxer->Close(); - // all done - if (audioCodec != nullptr) - { - delete audioCodec; - delete audioEncoder; - } - if (videoCodec != nullptr) - { - delete videoCodec; - delete videoEncoder; - if (videoFilter != nullptr) delete videoFilter; - } - - if (audioInputSource != nullptr) - { - delete audioInputSource; - } - - if (videoInputSource != nullptr) - { - delete videoInputSource; - } - - - delete muxer; } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << e.what() << endl; + std::cerr << e.what() << '\n'; throw e; } } @@ -286,8 +259,8 @@ int main(int argc, char **argv) { PlayDemo(argc, argv); - cout << "Encoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Encoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); diff --git a/examples/encode_audio/CMakeLists.txt b/examples/encode_audio/CMakeLists.txt new file mode 100644 index 0000000..5caddf5 --- /dev/null +++ b/examples/encode_audio/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_executable(encode_audio + encode_audio.cpp +) + +set_target_properties(encode_audio PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(encode_audio PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(encode_audio ffmpegcpp) + +set_target_properties(encode_audio PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/encode_audio/encode_audio.cpp b/examples/encode_audio/encode_audio.cpp similarity index 56% rename from source/ffmpeg-cpp/encode_audio/encode_audio.cpp rename to examples/encode_audio/encode_audio.cpp index 13652e2..f5cb0a4 100644 --- a/source/ffmpeg-cpp/encode_audio/encode_audio.cpp +++ b/examples/encode_audio/encode_audio.cpp @@ -1,32 +1,33 @@ #include +#include +#include #include "ffmpegcpp.h" -using namespace std; -using namespace ffmpegcpp; - int main() { // This example will take a raw audio file and encode it into as MP3. try { // Create a muxer that will output as MP3. - Muxer* muxer = new Muxer("output.mp3"); + auto muxer = std::make_unique("output.mp3"); // Create a MP3 codec that will encode the raw data. - AudioCodec* codec = new AudioCodec(AV_CODEC_ID_MP3); + auto codec = std::make_unique(AV_CODEC_ID_MP3); // Create an encoder that will encode the raw audio data as MP3. // Tie it to the muxer so it will be written to the file. - AudioEncoder* encoder = new AudioEncoder(codec, muxer); + auto encoder = std::make_unique(codec.get(), muxer.get()); // Load the raw audio file so we can process it. // We need to provide some info because we can't derive it from the raw format. // Hand it the encoder so it will pass on its raw data to the encoder, which will in turn pass it on to the muxer. - const char* rawAudioFile = "samples/Vivaldi_s16le_2_channels_samplerate_11025.dat"; - const char* rawAudioFormat = "s16le"; int rawAudioSampleRate = 11025; int rawAudioChannels = 2; - RawAudioFileSource* audioFile = new RawAudioFileSource(rawAudioFile, rawAudioFormat, rawAudioSampleRate, rawAudioChannels, encoder); + std::string rawAudioFile = "samples/Vivaldi_s16le_2_channels_samplerate_11025.dat"; + std::string rawAudioFormat = "s16le"; + int rawAudioSampleRate = 11025; + int rawAudioChannels = 2; + auto audioFile = std::make_unique(rawAudioFile, rawAudioFormat, rawAudioSampleRate, rawAudioChannels, encoder.get()); // Prepare the output pipeline. This will push a small amount of frames to the file sink until it IsPrimed returns true. audioFile->PreparePipeline(); @@ -40,15 +41,15 @@ int main() // Save everything to disk by closing the muxer. muxer->Close(); } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << "Exception caught!" << endl; - cerr << e.what() << endl; + std::cerr << "Exception caught!" << '\n'; + std::cerr << e.what() << '\n'; throw e; } - cout << "Encoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Encoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); } diff --git a/examples/encode_video/CMakeLists.txt b/examples/encode_video/CMakeLists.txt new file mode 100644 index 0000000..f58f7e0 --- /dev/null +++ b/examples/encode_video/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_executable(encode_video + encode_video.cpp +) + +set_target_properties(encode_video PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(encode_video PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(encode_video ffmpegcpp) + +set_target_properties(encode_video PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/encode_video/encode_video.cpp b/examples/encode_video/encode_video.cpp similarity index 67% rename from source/ffmpeg-cpp/encode_video/encode_video.cpp rename to examples/encode_video/encode_video.cpp index 1fc4e98..3a6529b 100644 --- a/source/ffmpeg-cpp/encode_video/encode_video.cpp +++ b/examples/encode_video/encode_video.cpp @@ -1,21 +1,19 @@ #include +#include #include "ffmpegcpp.h" -using namespace std; -using namespace ffmpegcpp; - int main() { // This example will take a raw audio file and encode it into as MP3. try { // Create a muxer that will output the video as MKV. - Muxer* muxer = new Muxer("output.mpg"); + auto muxer = std::make_unique("output.mpg"); // Create a MPEG2 codec that will encode the raw data. - VideoCodec* codec = new VideoCodec("mpeg2video"); + auto codec = std::make_unique("mpeg2video"); // Set the global quality of the video encoding. This maps to the command line // parameter -qscale and must be within range [0,31]. @@ -23,13 +21,13 @@ int main() // Create an encoder that will encode the raw audio data as MP3. // Tie it to the muxer so it will be written to the file. - VideoEncoder* encoder = new VideoEncoder(codec, muxer); + auto encoder = std::make_unique(codec.get(), muxer.get()); // Load the raw video file so we can process it. // FFmpeg is very good at deducing the file format, even from raw video files, // but if we have something weird, we can specify the properties of the format // in the constructor as commented out below. - RawVideoFileSource* videoFile = new RawVideoFileSource("samples/carphone_qcif.y4m", encoder); + auto videoFile = std::make_unique("samples/carphone_qcif.y4m", encoder.get()); // Prepare the output pipeline. This will push a small amount of frames to the file sink until it IsPrimed returns true. videoFile->PreparePipeline(); @@ -43,15 +41,15 @@ int main() // Save everything to disk by closing the muxer. muxer->Close(); } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << "Exception caught!" << endl; - cerr << e.what() << endl; + std::cerr << "Exception caught!" << '\n'; + std::cerr << e.what() << '\n'; throw e; } - cout << "Encoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Encoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); } diff --git a/examples/filtering_video/CMakeLists.txt b/examples/filtering_video/CMakeLists.txt new file mode 100644 index 0000000..ab86583 --- /dev/null +++ b/examples/filtering_video/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_executable(filtering_video + filtering_video.cpp +) + +set_target_properties(filtering_video PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(filtering_video PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(filtering_video ffmpegcpp) + +set_target_properties(filtering_video PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/filtering_video/filtering_video.cpp b/examples/filtering_video/filtering_video.cpp similarity index 59% rename from source/ffmpeg-cpp/filtering_video/filtering_video.cpp rename to examples/filtering_video/filtering_video.cpp index 07936b9..aa3f1d6 100644 --- a/source/ffmpeg-cpp/filtering_video/filtering_video.cpp +++ b/examples/filtering_video/filtering_video.cpp @@ -1,21 +1,19 @@ #include +#include #include "ffmpegcpp.h" -using namespace std; -using namespace ffmpegcpp; - int main() { // This example will apply some filters to a video and write it back. try { // Create a muxer that will output the video as MKV. - Muxer* muxer = new Muxer("filtered_video.mp4"); + auto muxer = std::make_unique("filtered_video.mp4"); // Create a MPEG2 codec that will encode the raw data. - VideoCodec* codec = new VideoCodec(AV_CODEC_ID_MPEG2VIDEO); + auto codec = std::make_unique(AV_CODEC_ID_MPEG2VIDEO); // Set the global quality of the video encoding. This maps to the command line // parameter -qscale and must be within range [0,31]. @@ -23,14 +21,14 @@ int main() // Create an encoder that will encode the raw audio data as MP3. // Tie it to the muxer so it will be written to the file. - VideoEncoder* encoder = new VideoEncoder(codec, muxer); + auto encoder = std::make_unique(codec.get(), muxer.get()); // Create a video filter and do some funny stuff with the video data. - VideoFilter* filter = new VideoFilter("scale=640:150,transpose=cclock,vignette", encoder); + auto filter = std::make_unique("scale=640:150,transpose=cclock,vignette", encoder.get()); // Load a video from a container and send it to the filter first. - Demuxer* demuxer = new Demuxer("samples/big_buck_bunny.mp4"); - demuxer->DecodeBestVideoStream(filter); + auto demuxer = std::make_unique("samples/big_buck_bunny.mp4"); + demuxer->DecodeBestVideoStream(filter.get()); // Prepare the output pipeline. This will push a small amount of frames to the file sink until it IsPrimed returns true. demuxer->PreparePipeline(); @@ -44,15 +42,15 @@ int main() // Save everything to disk by closing the muxer. muxer->Close(); } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << "Exception caught!" << endl; - cerr << e.what() << endl; + std::cerr << "Exception caught!" << '\n'; + std::cerr << e.what() << '\n'; throw e; } - cout << "Encoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Encoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); } diff --git a/examples/remuxing/CMakeLists.txt b/examples/remuxing/CMakeLists.txt new file mode 100644 index 0000000..3f0f4d6 --- /dev/null +++ b/examples/remuxing/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_executable(remuxing + remuxing.cpp +) + +set_target_properties(remuxing PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_include_directories(remuxing PUBLIC + ${PROJECT_SOURCE_DIR}/include/ffmpegcpp + ${PROJECT_SOURCE_DIR}/ffmpeg/include +) + +target_link_libraries(remuxing ffmpegcpp) + +set_target_properties(remuxing PROPERTIES FOLDER examples) diff --git a/source/ffmpeg-cpp/remuxing/remuxing.cpp b/examples/remuxing/remuxing.cpp similarity index 59% rename from source/ffmpeg-cpp/remuxing/remuxing.cpp rename to examples/remuxing/remuxing.cpp index 668c556..73b8c84 100644 --- a/source/ffmpeg-cpp/remuxing/remuxing.cpp +++ b/examples/remuxing/remuxing.cpp @@ -1,22 +1,19 @@ #include +#include #include "ffmpegcpp.h" -using namespace std; -using namespace ffmpegcpp; - - int main() { // This example will take a raw audio file and encode it into as MP3. try { // Create a muxer that will output the video as MKV. - Muxer* muxer = new Muxer("output.mkv"); + auto muxer = std::make_unique("output.mkv"); // Create a codec that will encode video as VP9 - VP9Codec* videoCodec = new VP9Codec(); + auto videoCodec = std::make_unique(); // Configure the codec to not do compression, to use multiple CPU's and to go as fast as possible. videoCodec->SetLossless(true); @@ -24,19 +21,19 @@ int main() videoCodec->SetDeadline("realtime"); // Create a codec that will encode audio as AAC - AudioCodec* audioCodec = new AudioCodec(AV_CODEC_ID_AAC); + auto audioCodec = std::make_unique(AV_CODEC_ID_AAC); // Create encoders for both - VideoEncoder* videoEncoder = new VideoEncoder(videoCodec, muxer); - AudioEncoder* audioEncoder = new AudioEncoder(audioCodec, muxer); + auto videoEncoder = std::make_unique(videoCodec.get(), muxer.get()); + auto audioEncoder = std::make_unique(audioCodec.get(), muxer.get()); // Load both audio and video from a container - Demuxer* videoContainer = new Demuxer("samples/big_buck_bunny.mp4"); - Demuxer* audioContainer = new Demuxer("samples/DesiJourney.wav"); + auto videoContainer = std::make_unique("samples/big_buck_bunny.mp4"); + auto audioContainer = std::make_unique("samples/DesiJourney.wav"); // Tie the best stream from each container to the output - videoContainer->DecodeBestVideoStream(videoEncoder); - audioContainer->DecodeBestAudioStream(audioEncoder); + videoContainer->DecodeBestVideoStream(videoEncoder.get()); + audioContainer->DecodeBestAudioStream(audioEncoder.get()); // Prepare the pipeline. We want to call this before the rest of the loop // to ensure that the muxer will be fully ready to receive data from @@ -56,15 +53,15 @@ int main() // Save everything to disk by closing the muxer. muxer->Close(); } - catch (FFmpegException e) + catch (ffmpegcpp::FFmpegException e) { - cerr << "Exception caught!" << endl; - cerr << e.what() << endl; + std::cerr << "Exception caught!" << '\n'; + std::cerr << e.what() << '\n'; throw e; } - cout << "Encoding complete!" << endl; - cout << "Press any key to continue..." << endl; + std::cout << "Encoding complete!" << '\n'; + std::cout << "Press any key to continue..." << '\n'; getchar(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/AudioFormatConverter.h b/include/ffmpegcpp/AudioFormatConverter.h similarity index 67% rename from source/ffmpeg-cpp/ffmpeg-cpp/AudioFormatConverter.h rename to include/ffmpegcpp/AudioFormatConverter.h index 8891b53..78946dc 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/AudioFormatConverter.h +++ b/include/ffmpegcpp/AudioFormatConverter.h @@ -1,25 +1,26 @@ #pragma once -#include "ffmpeg.h" -#include "ConvertedAudioProcessor.h" + +#include "FFmpegResource.h" + +struct AVCodecContext; +struct AVFrame; +struct AVAudioFifo; namespace ffmpegcpp { + class ConvertedAudioProcessor; + class AudioFormatConverter { public: AudioFormatConverter(ConvertedAudioProcessor* output, AVCodecContext* codecContext); - ~AudioFormatConverter(); void ProcessFrame(AVFrame* frame); - - private: - void CleanUp(); - void InitDelayed(AVFrame* frame); void AddToFifo(AVFrame* frame); @@ -33,10 +34,10 @@ namespace ffmpegcpp bool initialized = false; - AVAudioFifo* fifo = nullptr; - AVFrame* tmp_frame = nullptr; - AVFrame* converted_frame = nullptr; - struct SwrContext* swr_ctx = nullptr; + FFmpegResource fifo; + FFmpegResource tmp_frame; + FFmpegResource converted_frame; + FFmpegResource swr_ctx; int in_sample_rate, out_sample_rate; diff --git a/include/ffmpegcpp/CodecDeducer.h b/include/ffmpegcpp/CodecDeducer.h new file mode 100644 index 0000000..3771d52 --- /dev/null +++ b/include/ffmpegcpp/CodecDeducer.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +enum AVCodecID; +struct AVCodec; + +namespace ffmpegcpp +{ + class CodecDeducer + { + public: + + static AVCodec* DeduceEncoderFromFilename(const std::string & fileName); + + static AVCodec* DeduceEncoder(AVCodecID codecId); + static AVCodec* DeduceEncoder(const std::string & codecName); + + static AVCodec* DeduceDecoder(AVCodecID codecId); + static AVCodec* DeduceDecoder(const std::string & codecName); + }; + +} diff --git a/include/ffmpegcpp/Codecs/AudioCodec.h b/include/ffmpegcpp/Codecs/AudioCodec.h new file mode 100644 index 0000000..b3073aa --- /dev/null +++ b/include/ffmpegcpp/Codecs/AudioCodec.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Codecs/Codec.h" + +#include + +enum AVCodecID; +enum AVSampleFormat; + +namespace ffmpegcpp +{ + class OpenCodec; + + class AudioCodec : public Codec + { + public: + + AudioCodec(const std::string & codecName); + AudioCodec(AVCodecID codecId); + + std::unique_ptr Open(int bitRate, AVSampleFormat format, int sampleRate); + + bool IsFormatSupported(AVSampleFormat format) const; + bool IsChannelsSupported(int channels) const; + bool IsSampleRateSupported(int sampleRate) const; + + AVSampleFormat GetDefaultSampleFormat() const; + int GetDefaultSampleRate() const; + + }; + + +} \ No newline at end of file diff --git a/include/ffmpegcpp/Codecs/Codec.h b/include/ffmpegcpp/Codecs/Codec.h new file mode 100644 index 0000000..1633900 --- /dev/null +++ b/include/ffmpegcpp/Codecs/Codec.h @@ -0,0 +1,38 @@ +#pragma once + +#include "FFmpegResource.h" + +#include +#include + +enum AVCodecID; +struct AVCodecContext; + +namespace ffmpegcpp +{ + class OpenCodec; + + class Codec + { + public: + + Codec(const std::string & codecName); + Codec(AVCodecID codecId); + + void SetOption(const std::string & name, const std::string & value); + void SetOption(const std::string & name, int value); + void SetOption(const std::string & name, double value); + + void SetGlobalContainerHeader(); // used by the Muxer for configuration purposes + + protected: + + FFmpegResource codecContext; + + std::unique_ptr Open(); + + private: + + bool opened = false; + }; +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H264NVEncCodec.h b/include/ffmpegcpp/Codecs/H264NVEncCodec.h similarity index 69% rename from source/ffmpeg-cpp/ffmpeg-cpp/codecs/H264NVEncCodec.h rename to include/ffmpegcpp/Codecs/H264NVEncCodec.h index 2d99be5..1ad40d7 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H264NVEncCodec.h +++ b/include/ffmpegcpp/Codecs/H264NVEncCodec.h @@ -1,6 +1,8 @@ #pragma once #include "VideoCodec.h" +#include + namespace ffmpegcpp { @@ -11,7 +13,7 @@ namespace ffmpegcpp H264NVEncCodec(); - void SetPreset(const char* preset); + void SetPreset(const std::string & preset); }; diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H265NVEncCodec.h b/include/ffmpegcpp/Codecs/H265NVEncCodec.h similarity index 69% rename from source/ffmpeg-cpp/ffmpeg-cpp/codecs/H265NVEncCodec.h rename to include/ffmpegcpp/Codecs/H265NVEncCodec.h index 58099b0..2374fa7 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H265NVEncCodec.h +++ b/include/ffmpegcpp/Codecs/H265NVEncCodec.h @@ -1,6 +1,8 @@ #pragma once #include "VideoCodec.h" +#include + namespace ffmpegcpp { @@ -11,7 +13,7 @@ namespace ffmpegcpp H265NVEncCodec(); - void SetPreset(const char* preset); + void SetPreset(const std::string & preset); }; diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/JPGCodec.h b/include/ffmpegcpp/Codecs/JPGCodec.h similarity index 100% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/JPGCodec.h rename to include/ffmpegcpp/Codecs/JPGCodec.h diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/PNGCodec.h b/include/ffmpegcpp/Codecs/PNGCodec.h similarity index 100% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/PNGCodec.h rename to include/ffmpegcpp/Codecs/PNGCodec.h diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VP9Codec.h b/include/ffmpegcpp/Codecs/VP9Codec.h similarity index 76% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VP9Codec.h rename to include/ffmpegcpp/Codecs/VP9Codec.h index c49b215..3bb00b3 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VP9Codec.h +++ b/include/ffmpegcpp/Codecs/VP9Codec.h @@ -1,6 +1,8 @@ #pragma once #include "VideoCodec.h" +#include + namespace ffmpegcpp { @@ -11,12 +13,11 @@ namespace ffmpegcpp VP9Codec(); - void SetDeadline(const char* deadline); + void SetDeadline(const std::string & deadline); void SetCpuUsed(int cpuUsed); void SetLossless(bool lossless); void SetCrf(int crf); }; - } \ No newline at end of file diff --git a/include/ffmpegcpp/Codecs/VideoCodec.h b/include/ffmpegcpp/Codecs/VideoCodec.h new file mode 100644 index 0000000..bf3d165 --- /dev/null +++ b/include/ffmpegcpp/Codecs/VideoCodec.h @@ -0,0 +1,37 @@ +#pragma once + +#include "Codec.h" + +#include + +enum AVCodecID; +enum AVSampleFormat; +struct AVRational; + +namespace ffmpegcpp +{ + class OpenCodec; + + class VideoCodec : public Codec + { + public: + + VideoCodec(const std::string & codecName); + VideoCodec(AVCodecID codecId); + virtual ~VideoCodec(); + + std::unique_ptr Open(int width, int height, AVRational* frameRate, AVPixelFormat format); + + // This maps to the qscale parameter so should be in the range [0,31]. + void SetQualityScale(int qscale); + + bool IsPixelFormatSupported(AVPixelFormat format) const; + bool IsFrameRateSupported(AVRational* frameRate) const; + + AVPixelFormat GetDefaultPixelFormat() const; + AVRational GetClosestSupportedFrameRate(AVRational frameRate) const; + + }; + + +} \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/ConvertedAudioProcessor.h b/include/ffmpegcpp/ConvertedAudioProcessor.h similarity index 100% rename from source/ffmpeg-cpp/ffmpeg-cpp/ConvertedAudioProcessor.h rename to include/ffmpegcpp/ConvertedAudioProcessor.h diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/AudioInputStream.h b/include/ffmpegcpp/Demuxing/AudioInputStream.h similarity index 62% rename from source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/AudioInputStream.h rename to include/ffmpegcpp/Demuxing/AudioInputStream.h index bfdee63..374d9c5 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/AudioInputStream.h +++ b/include/ffmpegcpp/Demuxing/AudioInputStream.h @@ -1,11 +1,13 @@ #pragma once -#include "ffmpeg.h" -#include "InputStream.h" -#include "Frame Sinks/AudioFrameSink.h" +#include "Demuxing/InputStream.h" + +struct AVStream; namespace ffmpegcpp { + class AudioFrameSink; + class AudioInputStream : public InputStream { @@ -16,6 +18,6 @@ namespace ffmpegcpp protected: - virtual void ConfigureCodecContext(); + void ConfigureCodecContext() override; }; } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/InputStream.h b/include/ffmpegcpp/Demuxing/InputStream.h similarity index 61% rename from source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/InputStream.h rename to include/ffmpegcpp/Demuxing/InputStream.h index f55fabc..816bff2 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/InputStream.h +++ b/include/ffmpegcpp/Demuxing/InputStream.h @@ -1,29 +1,34 @@ #pragma once -#include "ffmpeg.h" -#include "std.h" -#include "Frame Sinks/FrameSink.h" +#include "FFmpegResource.h" + +struct AVCodecContext; +struct AVFrame; +struct AVPacket; +struct AVRational; +struct AVStream; namespace ffmpegcpp { + class FrameSink; + class InputStream { public: InputStream(AVStream* stream); - ~InputStream(); void Open(); virtual void DecodePacket(AVPacket* pkt); void Close(); - bool IsPrimed(); + bool IsPrimed() const; protected: - AVCodecContext* codecContext = nullptr; + FFmpegResource codecContext; void SetFrameSink(FrameSink* frameSink); @@ -37,9 +42,7 @@ namespace ffmpegcpp FrameSink* output; - AVFrame* frame; - - void CleanUp(); + FFmpegResource frame; }; diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/VideoInputStream.h b/include/ffmpegcpp/Demuxing/VideoInputStream.h similarity index 55% rename from source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/VideoInputStream.h rename to include/ffmpegcpp/Demuxing/VideoInputStream.h index 1436f4f..3c6fb25 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/VideoInputStream.h +++ b/include/ffmpegcpp/Demuxing/VideoInputStream.h @@ -1,22 +1,23 @@ #pragma once -#include "ffmpeg.h" -#include "InputStream.h" -#include "Frame Sinks/VideoFrameSink.h" +#include "Demuxing/InputStream.h" + +struct AVStream; namespace ffmpegcpp { + class VideoFrameSink; + class VideoInputStream : public InputStream { public: VideoInputStream(VideoFrameSink* frameSink, AVStream* stream); - ~VideoInputStream(); protected: - virtual void ConfigureCodecContext(); + void ConfigureCodecContext() override; }; } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/FFmpegException.h b/include/ffmpegcpp/FFmpegException.h similarity index 53% rename from source/ffmpeg-cpp/ffmpeg-cpp/FFmpegException.h rename to include/ffmpegcpp/FFmpegException.h index d3da0dd..7b0671d 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/FFmpegException.h +++ b/include/ffmpegcpp/FFmpegException.h @@ -2,7 +2,8 @@ #include "ffmpeg.h" -#include "std.h" +#include +#include namespace ffmpegcpp { @@ -11,16 +12,15 @@ namespace ffmpegcpp public: - FFmpegException(std::string error); + FFmpegException(const std::string & error); - FFmpegException(std::string error, int returnValue); + FFmpegException(const std::string & error, int returnValue); - virtual char const* what() const + char const* what() const override { return std::exception::what(); } - private: char error[AV_ERROR_MAX_STRING_SIZE]; diff --git a/include/ffmpegcpp/FFmpegResource.h b/include/ffmpegcpp/FFmpegResource.h new file mode 100644 index 0000000..841263f --- /dev/null +++ b/include/ffmpegcpp/FFmpegResource.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include "ffmpeg.h" + +namespace ffmpegcpp +{ + + template struct Deleter {}; + + template <> + struct Deleter { + void operator()(AVCodecContext * ptr) { avcodec_free_context(&ptr); } + }; + + template <> + struct Deleter { + void operator()(AVPacket * ptr) { av_packet_free(&ptr); } + }; + + template <> + struct Deleter { + void operator()(AVFrame * ptr) { av_frame_free(&ptr); } + }; + + template <> + struct Deleter { + void operator()(AVFilterGraph * ptr) { avfilter_graph_free(&ptr); } + }; + + template <> + struct Deleter { + void operator()(AVAudioFifo * ptr) { av_audio_fifo_free(ptr); } + }; + + template <> + struct Deleter { + void operator()(AVCodecParserContext * ptr) { av_parser_close(ptr); } + }; + + template <> + struct Deleter { + void operator()(AVFormatContext * ptr) { avformat_close_input(&ptr); } + }; + + template <> + struct Deleter { + void operator()(struct SwsContext * ptr) { sws_freeContext(ptr); } + }; + + template <> + struct Deleter { + void operator()(struct SwrContext * ptr) { swr_free(&ptr); } + }; + + template + class FFmpegResource : public std::unique_ptr> + { + public: + FFmpegResource() : std::unique_ptr>() {} + FFmpegResource(value_type * ptr) : std::unique_ptr>(ptr) {} + }; + + template + FFmpegResource MakeFFmpegResource(value_type * ptr) + { + return FFmpegResource(ptr); + } +} diff --git a/include/ffmpegcpp/FrameSinks/AudioEncoder.h b/include/ffmpegcpp/FrameSinks/AudioEncoder.h new file mode 100644 index 0000000..a99bf35 --- /dev/null +++ b/include/ffmpegcpp/FrameSinks/AudioEncoder.h @@ -0,0 +1,53 @@ +#pragma once + +#include "FFmpegResource.h" +#include "FrameSinks/AudioFrameSink.h" +#include "ConvertedAudioProcessor.h" + +#include + +struct AVFrame; +struct AVPacket; +struct AVRational; + +namespace ffmpegcpp +{ + class AudioCodec; + class AudioFormatConverter; + class Muxer; + class OpenCodec; + class OutputStream; + + class AudioEncoder : public AudioFrameSink, public ConvertedAudioProcessor + { + public: + AudioEncoder(AudioCodec* codec, Muxer* muxer); + AudioEncoder(AudioCodec* codec, Muxer* muxer, int bitRate); + + void WriteFrame(AVFrame* frame, AVRational* timeBase) override; + void Close() override; + + void WriteConvertedFrame(AVFrame* frame) override; + + bool IsPrimed() const override; + + private: + + void OpenLazily(AVFrame* frame, AVRational* timeBase); + + void PollCodecForPackets(); + + std::unique_ptr output; + + AudioCodec* closedCodec; + + std::unique_ptr formatConverter; + std::unique_ptr codec; + FFmpegResource pkt; + + int frameNumber = 0; + + int finalBitRate = -1; + }; +} + diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioFrameSink.h b/include/ffmpegcpp/FrameSinks/AudioFrameSink.h similarity index 57% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioFrameSink.h rename to include/ffmpegcpp/FrameSinks/AudioFrameSink.h index 13d7fa7..5de043c 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioFrameSink.h +++ b/include/ffmpegcpp/FrameSinks/AudioFrameSink.h @@ -1,6 +1,6 @@ #pragma once -#include "FrameSink.h" +#include "FrameSinks/FrameSink.h" namespace ffmpegcpp { @@ -8,8 +8,6 @@ namespace ffmpegcpp { public: - virtual void WriteFrame(AVFrame* frame, AVRational* timeBase) = 0; - virtual ~AudioFrameSink() {} }; } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/FrameSink.h b/include/ffmpegcpp/FrameSinks/FrameSink.h similarity index 85% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/FrameSink.h rename to include/ffmpegcpp/FrameSinks/FrameSink.h index 8690078..48b7640 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/FrameSink.h +++ b/include/ffmpegcpp/FrameSinks/FrameSink.h @@ -12,7 +12,7 @@ namespace ffmpegcpp virtual void Close() = 0; - virtual bool IsPrimed() = 0; + virtual bool IsPrimed() const = 0; virtual ~FrameSink() {} }; diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoEncoder.h b/include/ffmpegcpp/FrameSinks/VideoEncoder.h similarity index 54% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoEncoder.h rename to include/ffmpegcpp/FrameSinks/VideoEncoder.h index daec115..d69f0b3 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoEncoder.h +++ b/include/ffmpegcpp/FrameSinks/VideoEncoder.h @@ -1,14 +1,24 @@ #pragma once -#include "ffmpeg.h" +#include "FFmpegResource.h" +#include "FrameSinks/VideoFrameSink.h" -#include "Frame Sinks/VideoFrameSink.h" -#include "Codecs/VideoCodec.h" -#include "VideoFormatConverter.h" -#include "Muxing/Muxer.h" +#include + +enum AVPixelFormat; +struct AVRational; +struct AVFrame; +struct AVPacket; namespace ffmpegcpp { + class VideoCodec; + class Muxer; + class OutputStream; + class VideoFormatConverter; + class OpenCodec; + + class VideoEncoder : public VideoFrameSink { public: @@ -16,12 +26,11 @@ namespace ffmpegcpp VideoEncoder(VideoCodec* codec, Muxer* muxer, AVPixelFormat format); VideoEncoder(VideoCodec* codec, Muxer* muxer, AVRational frameRate); VideoEncoder(VideoCodec* codec, Muxer* muxer, AVRational frameRate, AVPixelFormat format); - virtual ~VideoEncoder(); - void WriteFrame(AVFrame* frame, AVRational* timeBase); - void Close(); + void WriteFrame(AVFrame* frame, AVRational* timeBase) override; + void Close() override; - bool IsPrimed(); + bool IsPrimed() const override; private: @@ -29,16 +38,14 @@ namespace ffmpegcpp void PollCodecForPackets(); VideoCodec* closedCodec; - OutputStream* output; + std::unique_ptr output; - VideoFormatConverter* formatConverter = nullptr; - OpenCodec* codec = nullptr; - AVPacket* pkt = nullptr; + std::unique_ptr formatConverter; + std::unique_ptr codec; + FFmpegResource pkt; int frameNumber = 0; - void CleanUp(); - AVPixelFormat finalPixelFormat = AV_PIX_FMT_NONE; AVRational finalFrameRate; diff --git a/include/ffmpegcpp/FrameSinks/VideoFilter.h b/include/ffmpegcpp/FrameSinks/VideoFilter.h new file mode 100644 index 0000000..0060ba8 --- /dev/null +++ b/include/ffmpegcpp/FrameSinks/VideoFilter.h @@ -0,0 +1,49 @@ +#pragma once + +#include "FrameSinks/VideoFrameSink.h" +#include "FFmpegResource.h" + +#include + +struct AVFilterContext; +struct AVFilterGraph; +struct AVFrame; +struct AVFrame; +struct AVRational; + +namespace ffmpegcpp +{ + class VideoFilter : public VideoFrameSink + { + + public: + + VideoFilter(const std::string & filterString, VideoFrameSink* target); + + void WriteFrame(AVFrame* frame, AVRational* timeBase) override; + void Close() override; + + bool IsPrimed() const override; + + private: + + void InitDelayed(AVFrame* frame, AVRational* timeBase); + void PollFilterGraphForFrames(); + + VideoFrameSink* target; + + std::string filterString; + AVPixelFormat outputFormat; + + FFmpegResource filter_graph; + AVFilterContext *buffersink_ctx = nullptr; + AVFilterContext *buffersrc_ctx = nullptr; + FFmpegResource filt_frame; + + bool initialized = false; + + AVRational* timeBase; + }; + + +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFrameSink.h b/include/ffmpegcpp/FrameSinks/VideoFrameSink.h similarity index 57% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFrameSink.h rename to include/ffmpegcpp/FrameSinks/VideoFrameSink.h index ece64aa..6ce74c1 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFrameSink.h +++ b/include/ffmpegcpp/FrameSinks/VideoFrameSink.h @@ -1,6 +1,6 @@ #pragma once -#include "FrameSink.h" +#include "FrameSinks/FrameSink.h" namespace ffmpegcpp { @@ -8,8 +8,6 @@ namespace ffmpegcpp { public: - virtual void WriteFrame(AVFrame* frame, AVRational* timeBase) = 0; - virtual ~VideoFrameSink() {} }; } diff --git a/include/ffmpegcpp/Muxing/AudioOutputStream.h b/include/ffmpegcpp/Muxing/AudioOutputStream.h new file mode 100644 index 0000000..9720288 --- /dev/null +++ b/include/ffmpegcpp/Muxing/AudioOutputStream.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Muxing/OutputStream.h" + +struct AVPacket; +struct AVRational; +struct AVStream; + +namespace ffmpegcpp +{ + class Codec; + class Muxer; + class OpenCodec; + + class AudioOutputStream : public OutputStream + { + public: + + AudioOutputStream(Muxer* muxer, Codec* codec); + + void OpenStream(AVStream* stream, int containerFlags) override; + + void WritePacket(AVPacket* pkt, OpenCodec* openCodec) override; + + bool IsPrimed() const override; + + protected: + + void PreparePacketForMuxer(AVPacket* pkt) override; + + private: + + void LazilyInitialize(OpenCodec* openCodec); + + AVStream* stream; + + bool initialized = false; + + AVRational codecTimeBase; + }; +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/Muxer.h b/include/ffmpegcpp/Muxing/Muxer.h similarity index 61% rename from source/ffmpeg-cpp/ffmpeg-cpp/Muxing/Muxer.h rename to include/ffmpegcpp/Muxing/Muxer.h index 46b29f6..031846d 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/Muxer.h +++ b/include/ffmpegcpp/Muxing/Muxer.h @@ -1,8 +1,13 @@ #pragma once -#include "ffmpeg.h" -#include "std.h" +#include "FFmpegResource.h" +#include +#include + +struct AVFormatContext; +struct AVOutputFormat; +struct AVPacket; namespace ffmpegcpp { @@ -12,7 +17,7 @@ namespace ffmpegcpp { { public: - Muxer(const char* fileName); + Muxer(const std::string & fileName); ~Muxer(); void AddOutputStream(OutputStream* stream); @@ -21,7 +26,7 @@ namespace ffmpegcpp { void Close(); - bool IsPrimed(); + bool IsPrimed(); // ToDo: this should be const... private: @@ -29,7 +34,7 @@ namespace ffmpegcpp { void Open(); std::vector outputStreams; - std::vector packetQueue; + std::vector> packetQueue; AVOutputFormat* containerFormat; diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/OutputStream.h b/include/ffmpegcpp/Muxing/OutputStream.h similarity index 67% rename from source/ffmpeg-cpp/ffmpeg-cpp/Muxing/OutputStream.h rename to include/ffmpegcpp/Muxing/OutputStream.h index 9164497..a001f11 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/OutputStream.h +++ b/include/ffmpegcpp/Muxing/OutputStream.h @@ -1,11 +1,18 @@ #pragma once -#include "ffmpeg.h" -#include "Codecs/Codec.h" -#include "Muxer.h" +#include "FFmpegResource.h" + +#include + +struct AVPacket; +struct AVStream; namespace ffmpegcpp { + class Codec; + class Muxer; + class OpenCodec; + class OutputStream { public: @@ -16,7 +23,7 @@ namespace ffmpegcpp virtual void WritePacket(AVPacket* pkt, OpenCodec* openCodec) = 0; - virtual bool IsPrimed() = 0; + virtual bool IsPrimed() const = 0; void DrainPacketQueue(); @@ -26,10 +33,9 @@ namespace ffmpegcpp void SendPacketToMuxer(AVPacket* packet); - Codec* codec; - std::vector packetQueue; + std::vector> packetQueue; private: diff --git a/include/ffmpegcpp/Muxing/VideoOutputStream.h b/include/ffmpegcpp/Muxing/VideoOutputStream.h new file mode 100644 index 0000000..a722319 --- /dev/null +++ b/include/ffmpegcpp/Muxing/VideoOutputStream.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Muxing/OutputStream.h" + +struct AVPacket; +struct AVStream; + +namespace ffmpegcpp +{ + class Codec; + class Muxer; + class OpenCodec; + + class VideoOutputStream : public OutputStream + { + public: + + VideoOutputStream(Muxer* muxer, Codec* codec); + + void OpenStream(AVStream* stream, int containerFlags) override; + + void WritePacket(AVPacket* pkt, OpenCodec* openCodec) override; + + bool IsPrimed() const override; + + protected: + + void PreparePacketForMuxer(AVPacket* pkt) override; + + private: + + void LazilyInitialize(OpenCodec* openCodec); + + AVStream* stream; + + bool initialized = false; + + AVRational codecTimeBase; + }; +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/OpenCodec.h b/include/ffmpegcpp/OpenCodec.h similarity index 74% rename from source/ffmpeg-cpp/ffmpeg-cpp/OpenCodec.h rename to include/ffmpegcpp/OpenCodec.h index dbe9301..cc770f5 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/OpenCodec.h +++ b/include/ffmpegcpp/OpenCodec.h @@ -1,6 +1,6 @@ #pragma once -#include "ffmpeg.h" +struct AVCodecContext; namespace ffmpegcpp { @@ -11,7 +11,7 @@ namespace ffmpegcpp OpenCodec(AVCodecContext* openCodecContext); ~OpenCodec(); - AVCodecContext* GetContext(); + AVCodecContext* GetContext() const; private: diff --git a/include/ffmpegcpp/Sources/Demuxer.h b/include/ffmpegcpp/Sources/Demuxer.h new file mode 100644 index 0000000..5a7eac0 --- /dev/null +++ b/include/ffmpegcpp/Sources/Demuxer.h @@ -0,0 +1,65 @@ +#pragma once + +#include "Sources/InputSource.h" +#include "FFmpegResource.h" + +#include +#include + +enum AVMediaType; +struct AVCodec; +struct AVDictionary; +struct AVFormatContext; +struct AVInputFormat; +struct AVPacket; +struct AVStream; + +namespace ffmpegcpp +{ + class AudioFrameSink; + class InputStream; + class VideoFrameSink; + + struct StreamInfo + { + unsigned int streamId; + AVCodec* codec; + AVStream* stream; + }; + + class Demuxer : public InputSource + { + public: + + Demuxer(const std::string & fileName, AVInputFormat* inputFormat = nullptr, AVDictionary *inputFormatOptions = nullptr); + + void DecodeBestAudioStream(AudioFrameSink* frameSink); + void DecodeBestVideoStream(VideoFrameSink* frameSink); + + void DecodeAudioStream(int streamId, AudioFrameSink* frameSink); + void DecodeVideoStream(int streamId, VideoFrameSink* frameSink); + + std::vector GetAudioStreamInfo() const; + std::vector GetVideoStreamInfo() const; + + void PreparePipeline() override; + bool IsDone() const override; + void Step() override; + + private: + + std::vector GetStreamInfo(AVMediaType mediaType) const; + + void DecodePacket(); + + bool done = false; + + std::string fileName; + + std::vector> inputStreams; + + FFmpegResource containerContext; + FFmpegResource pkt; + + }; +} diff --git a/include/ffmpegcpp/Sources/EncodedFileSource.h b/include/ffmpegcpp/Sources/EncodedFileSource.h new file mode 100644 index 0000000..c3a0609 --- /dev/null +++ b/include/ffmpegcpp/Sources/EncodedFileSource.h @@ -0,0 +1,60 @@ +#pragma once + +#include "Sources/InputSource.h" +#include "FFmpegResource.h" + +#include + +enum AVCodecID; +struct AVCodec; +struct AVCodecContext; +struct AVCodecParserContext; +struct AVFrame; +struct AVPacket; +struct AVRational; + +namespace ffmpegcpp +{ + class FrameSink; + + // EncodedFileSource takes a file that is already encoded but not in a container (ie .mp3, .h264) + // and feeds it to the system. + class EncodedFileSource : public InputSource + { + + public: + EncodedFileSource(const std::string & inFileName, AVCodecID codecId, FrameSink* output); + EncodedFileSource(const std::string & inFileName, const std::string & codecName, FrameSink* output); + virtual ~EncodedFileSource(); + + void PreparePipeline() override; + bool IsDone() const override; + void Step() override; + + private: + + void CleanUp(); + + bool done = false; + + FrameSink* output; + + FFmpegResource parser; + + FFmpegResource codecContext; + + int bufferSize; + + FFmpegResource decoded_frame; + FFmpegResource pkt; + uint8_t* buffer = nullptr; + + FILE* file; + + void Init(const std::string & inFileName, AVCodec* codec, FrameSink* output); + + void Decode(AVPacket *packet, AVFrame* targetFrame); + + AVRational timeBaseCorrectedByTicksPerFrame; + }; +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/InputSource.h b/include/ffmpegcpp/Sources/InputSource.h similarity index 70% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/InputSource.h rename to include/ffmpegcpp/Sources/InputSource.h index c89dd13..fddb1ac 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/InputSource.h +++ b/include/ffmpegcpp/Sources/InputSource.h @@ -6,13 +6,9 @@ namespace ffmpegcpp { public: - virtual ~InputSource() {} - virtual void PreparePipeline() = 0; - virtual bool IsDone() = 0; + virtual bool IsDone() const = 0; virtual void Step() = 0; }; } - - diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioDataSource.h b/include/ffmpegcpp/Sources/RawAudioDataSource.h similarity index 79% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioDataSource.h rename to include/ffmpegcpp/Sources/RawAudioDataSource.h index 418f032..e982802 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioDataSource.h +++ b/include/ffmpegcpp/Sources/RawAudioDataSource.h @@ -1,10 +1,14 @@ #pragma once -#include "ffmpeg.h" -#include "Frame Sinks/AudioFrameSink.h" +#include "FFmpegResource.h" + +enum AVSampleFormat; +struct AVFrame; namespace ffmpegcpp { + class AudioFrameSink; + // RawVideoDataSource is used to feed raw memory to the system and process it. // You can use this if the video data comes from another source than the file system (ie rendering). class RawAudioDataSource @@ -14,19 +18,16 @@ namespace ffmpegcpp RawAudioDataSource(AVSampleFormat sampleFormat, int sampleRate, int channels, AudioFrameSink* output); RawAudioDataSource(AVSampleFormat sampleFormat, int sampleRate, int channels, int64_t channelLayout, AudioFrameSink* output); - virtual ~RawAudioDataSource(); void WriteData(void* data, int sampleCount); void Close(); - bool IsPrimed(); + bool IsPrimed() const; private: - void CleanUp(); - AudioFrameSink* output; - AVFrame* frame = nullptr; + FFmpegResource frame; }; } diff --git a/include/ffmpegcpp/Sources/RawAudioFileSource.h b/include/ffmpegcpp/Sources/RawAudioFileSource.h new file mode 100644 index 0000000..f553d3a --- /dev/null +++ b/include/ffmpegcpp/Sources/RawAudioFileSource.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Sources/InputSource.h" + +#include +#include + +namespace ffmpegcpp +{ + class AudioFrameSink; + class Demuxer; + + class RawAudioFileSource : public InputSource + { + public: + + RawAudioFileSource(const std::string & fileName, const std::string & inputFormat, int sampleRate, int channels, AudioFrameSink* frameSink); + + void PreparePipeline() override; + bool IsDone() const override; + void Step() override; + + private: + + std::unique_ptr demuxer; + }; + + +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoDataSource.h b/include/ffmpegcpp/Sources/RawVideoDataSource.h similarity index 76% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoDataSource.h rename to include/ffmpegcpp/Sources/RawVideoDataSource.h index d131b05..1817208 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoDataSource.h +++ b/include/ffmpegcpp/Sources/RawVideoDataSource.h @@ -1,10 +1,15 @@ #pragma once -#include "ffmpeg.h" -#include "Frame Sinks/VideoFrameSink.h" +#include "FFmpegResource.h" + +enum AVPixelFormat; +struct AVFrame; +struct AVRational; namespace ffmpegcpp { + class VideoFrameSink; + // RawVideoDataSource is used to feed raw memory to the system and process it. // You can use this if the video data comes from another source than the file system (ie rendering). class RawVideoDataSource @@ -14,27 +19,25 @@ namespace ffmpegcpp RawVideoDataSource(int width, int height, AVPixelFormat pixelFormat, int framesPerSecond, VideoFrameSink* output); RawVideoDataSource(int width, int height, AVPixelFormat sourcePixelFormat, AVPixelFormat targetPixelFormat, int framesPerSecond, VideoFrameSink* output); - virtual ~RawVideoDataSource(); void WriteFrame(void* data, int bytesPerRow); void Close(); - int GetWidth(); - int GetHeight(); + int GetWidth() const; + int GetHeight() const; - bool IsPrimed(); + bool IsPrimed() const; private: void Init(int width, int height, AVPixelFormat sourcePixelFormat, AVPixelFormat targetPixelFormat, int framesPerSecond, VideoFrameSink* output); - void CleanUp(); AVPixelFormat sourcePixelFormat; AVRational timeBase; VideoFrameSink* output; - AVFrame* frame = nullptr; - struct SwsContext* swsContext = nullptr; + FFmpegResource frame; + FFmpegResource swsContext; }; } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoFileSource.h b/include/ffmpegcpp/Sources/RawVideoFileSource.h similarity index 58% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoFileSource.h rename to include/ffmpegcpp/Sources/RawVideoFileSource.h index 4d45222..1b0e024 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoFileSource.h +++ b/include/ffmpegcpp/Sources/RawVideoFileSource.h @@ -1,33 +1,32 @@ #pragma once -#include "ffmpeg.h" - -#include "InputSource.h" -#include "Demuxer.h" +#include "Sources/InputSource.h" +#include +#include namespace ffmpegcpp { + class Demuxer; + class VideoFrameSink; + class RawVideoFileSource : public InputSource { public: - RawVideoFileSource(const char* fileName, VideoFrameSink* frameSink); + RawVideoFileSource(const std::string & fileName, VideoFrameSink* frameSink); // I couldn't get this to work. The thing is that it also crashes weirdly when I run ffmpeg directly, // so I think it's more an issue of ffmpeg than one of my library. //RawVideoFileSource(const char* fileName, int width, int height, const char* frameRate, AVPixelFormat format, VideoFrameSink* frameSink); - virtual ~RawVideoFileSource(); - virtual void PreparePipeline(); - virtual bool IsDone(); - virtual void Step(); + void PreparePipeline() override; + bool IsDone() const override; + void Step() override; private: - void CleanUp(); - - Demuxer* demuxer = nullptr; + std::unique_ptr demuxer; }; diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/VideoFormatConverter.h b/include/ffmpegcpp/VideoFormatConverter.h similarity index 61% rename from source/ffmpeg-cpp/ffmpeg-cpp/VideoFormatConverter.h rename to include/ffmpegcpp/VideoFormatConverter.h index 6d252e4..d0b881c 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/VideoFormatConverter.h +++ b/include/ffmpegcpp/VideoFormatConverter.h @@ -1,7 +1,9 @@ #pragma once -#include "ffmpeg.h" -#include "ConvertedAudioProcessor.h" +#include "FFmpegResource.h" + +struct AVCodecContext; +struct AVFrame; namespace ffmpegcpp { @@ -10,26 +12,19 @@ namespace ffmpegcpp public: VideoFormatConverter(AVCodecContext* codecContext); - ~VideoFormatConverter(); AVFrame* ConvertFrame(AVFrame* frame); - - private: - void CleanUp(); - void InitDelayed(AVFrame* frame); - AVCodecContext* codecContext; bool initialized = false; - AVFrame* converted_frame = nullptr; - struct SwsContext* swsContext = nullptr; + FFmpegResource converted_frame; + FFmpegResource swsContext; }; - } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg.h b/include/ffmpegcpp/ffmpeg.h similarity index 100% rename from source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg.h rename to include/ffmpegcpp/ffmpeg.h diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpegcpp.h b/include/ffmpegcpp/ffmpegcpp.h similarity index 76% rename from source/ffmpeg-cpp/ffmpeg-cpp/ffmpegcpp.h rename to include/ffmpegcpp/ffmpegcpp.h index 6b1f519..4fb65ea 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpegcpp.h +++ b/include/ffmpegcpp/ffmpegcpp.h @@ -11,9 +11,9 @@ #include "Sources/RawVideoDataSource.h" #include "Sources/EncodedFileSource.h" -#include "Frame Sinks/VideoEncoder.h" -#include "Frame Sinks/AudioEncoder.h" -#include "Frame Sinks/VideoFilter.h" +#include "FrameSinks/VideoEncoder.h" +#include "FrameSinks/AudioEncoder.h" +#include "FrameSinks/VideoFilter.h" #include "Codecs/AudioCodec.h" @@ -24,5 +24,8 @@ #include "Codecs/JPGCodec.h" #include "Codecs/Codec.h" +#include "Demuxing/InputStream.h" #include "FFmpegException.h" +#include "FFmpegResource.h" + diff --git a/source/ffmpeg-cpp/FFmpegLibraryLocationProperty.props b/source/ffmpeg-cpp/FFmpegLibraryLocationProperty.props deleted file mode 100644 index b2dffa9..0000000 --- a/source/ffmpeg-cpp/FFmpegLibraryLocationProperty.props +++ /dev/null @@ -1,20 +0,0 @@ - - - - - $(ProjectDir)..\..\..\ffmpeg\ - $(ProjectDir)..\..\..\samples - - - - - - $(FFmpegLibraryDir) - true - - - $(SamplesDir) - true - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj b/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj deleted file mode 100644 index e0fb0d2..0000000 --- a/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj +++ /dev/null @@ -1,199 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {C6101E18-D73B-430C-A79C-084E1236EA94} - Win32Proj - decodeaudio - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib;%(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib;%(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib;%(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib;%(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj.filters b/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj.filters deleted file mode 100644 index 88e5ec5..0000000 --- a/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj.user b/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj.user deleted file mode 100644 index 6c84d89..0000000 --- a/source/ffmpeg-cpp/decode_audio/decode_audio.vcxproj.user +++ /dev/null @@ -1,19 +0,0 @@ - - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/decode_video/decode_video.vcxproj b/source/ffmpeg-cpp/decode_video/decode_video.vcxproj deleted file mode 100644 index fccf89e..0000000 --- a/source/ffmpeg-cpp/decode_video/decode_video.vcxproj +++ /dev/null @@ -1,200 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233} - Win32Proj - decodeaudio - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/decode_video/decode_video.vcxproj.filters b/source/ffmpeg-cpp/decode_video/decode_video.vcxproj.filters deleted file mode 100644 index dbaf137..0000000 --- a/source/ffmpeg-cpp/decode_video/decode_video.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/decode_video/decode_video.vcxproj.user b/source/ffmpeg-cpp/decode_video/decode_video.vcxproj.user deleted file mode 100644 index 6c84d89..0000000 --- a/source/ffmpeg-cpp/decode_video/decode_video.vcxproj.user +++ /dev/null @@ -1,19 +0,0 @@ - - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/demo/GeneratedAudioSource.h b/source/ffmpeg-cpp/demo/GeneratedAudioSource.h deleted file mode 100644 index b8acdb6..0000000 --- a/source/ffmpeg-cpp/demo/GeneratedAudioSource.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "ffmpegcpp.h" - -using namespace ffmpegcpp; - -class GeneratedAudioSource : public InputSource -{ -public: - - GeneratedAudioSource(AudioFrameSink* frameSink); - ~GeneratedAudioSource(); - - virtual void PreparePipeline(); - virtual bool IsDone(); - virtual void Step(); - -private: - - int sampleRate; - int channels; - AVSampleFormat format; - - RawAudioDataSource* output; - - int sampleCount = 735; - - uint16_t* samples; - - int frameNumber = 0; -}; - diff --git a/source/ffmpeg-cpp/demo/GeneratedVideoSource.h b/source/ffmpeg-cpp/demo/GeneratedVideoSource.h deleted file mode 100644 index 2c9e5b0..0000000 --- a/source/ffmpeg-cpp/demo/GeneratedVideoSource.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "ffmpegcpp.h" - -using namespace ffmpegcpp; - -class GeneratedVideoSource : public InputSource -{ -public: - - GeneratedVideoSource(int width, int height, VideoFrameSink* frameSink); - ~GeneratedVideoSource(); - - virtual void PreparePipeline(); - virtual bool IsDone(); - virtual void Step(); - -private: - - RawVideoDataSource* output; - - int frameNumber = 0; - - uint8_t *rgb = NULL; -}; - diff --git a/source/ffmpeg-cpp/demo/demo.vcxproj b/source/ffmpeg-cpp/demo/demo.vcxproj deleted file mode 100644 index 35e0da7..0000000 --- a/source/ffmpeg-cpp/demo/demo.vcxproj +++ /dev/null @@ -1,207 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2} - Win32Proj - demo - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - false - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - true - obj\$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - obj\$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - - - false - obj\$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/demo/demo.vcxproj.filters b/source/ffmpeg-cpp/demo/demo.vcxproj.filters deleted file mode 100644 index ff353b2..0000000 --- a/source/ffmpeg-cpp/demo/demo.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/demo/demo.vcxproj.user b/source/ffmpeg-cpp/demo/demo.vcxproj.user deleted file mode 100644 index 6c84d89..0000000 --- a/source/ffmpeg-cpp/demo/demo.vcxproj.user +++ /dev/null @@ -1,19 +0,0 @@ - - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj b/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj deleted file mode 100644 index 434460a..0000000 --- a/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj +++ /dev/null @@ -1,201 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6} - Win32Proj - decodeaudio - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj.filters b/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj.filters deleted file mode 100644 index ae624bc..0000000 --- a/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj.user b/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj.user deleted file mode 100644 index 6c84d89..0000000 --- a/source/ffmpeg-cpp/encode_audio/encode_audio.vcxproj.user +++ /dev/null @@ -1,19 +0,0 @@ - - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/encode_video/encode_video.vcxproj b/source/ffmpeg-cpp/encode_video/encode_video.vcxproj deleted file mode 100644 index e9c6d00..0000000 --- a/source/ffmpeg-cpp/encode_video/encode_video.vcxproj +++ /dev/null @@ -1,200 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3} - Win32Proj - decodeaudio - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/encode_video/encode_video.vcxproj.filters b/source/ffmpeg-cpp/encode_video/encode_video.vcxproj.filters deleted file mode 100644 index c863a03..0000000 --- a/source/ffmpeg-cpp/encode_video/encode_video.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/encode_video/encode_video.vcxproj.user b/source/ffmpeg-cpp/encode_video/encode_video.vcxproj.user deleted file mode 100644 index 6c84d89..0000000 --- a/source/ffmpeg-cpp/encode_video/encode_video.vcxproj.user +++ /dev/null @@ -1,19 +0,0 @@ - - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp.sln b/source/ffmpeg-cpp/ffmpeg-cpp.sln deleted file mode 100644 index 99292a3..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp.sln +++ /dev/null @@ -1,281 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.106 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "demo\demo.vcxproj", "{D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ffmpeg-cpp", "ffmpeg-cpp\ffmpeg-cpp.vcxproj", "{BABFD64D-9BF1-4328-B977-24BF81800620}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{3B1FE419-D7D2-4406-9C24-5A6F6ED63E73}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decode_audio", "decode_audio\decode_audio.vcxproj", "{C6101E18-D73B-430C-A79C-084E1236EA94}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decode_video", "decode_video\decode_video.vcxproj", "{AAD3AB93-F831-4339-8AAD-DC956B9B9233}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encode_audio", "encode_audio\encode_audio.vcxproj", "{9D936BE4-46AA-489F-82E7-D2CFEB157FB6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encode_video", "encode_video\encode_video.vcxproj", "{597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "remuxing", "remuxing\remuxing.vcxproj", "{B337D322-355B-4348-A2A8-270471BE2C95}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "filtering_video", "filtering_video\filtering_video.vcxproj", "{80579A29-8073-46A0-B328-661155E0887B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - DebugDLL|x64 = DebugDLL|x64 - DebugDLL|x86 = DebugDLL|x86 - DebugDLLStaticDeps|x64 = DebugDLLStaticDeps|x64 - DebugDLLStaticDeps|x86 = DebugDLLStaticDeps|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - ReleaseDLL|x64 = ReleaseDLL|x64 - ReleaseDLL|x86 = ReleaseDLL|x86 - ReleaseDLLStaticDeps|x64 = ReleaseDLLStaticDeps|x64 - ReleaseDLLStaticDeps|x86 = ReleaseDLLStaticDeps|x86 - ReleaseLTO|x64 = ReleaseLTO|x64 - ReleaseLTO|x86 = ReleaseLTO|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Debug|x64.ActiveCfg = Debug|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Debug|x64.Build.0 = Debug|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Debug|x86.ActiveCfg = Debug|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Debug|x86.Build.0 = Debug|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLL|x64.ActiveCfg = Debug|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLL|x64.Build.0 = Debug|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLL|x86.Build.0 = Debug|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Release|x64.ActiveCfg = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Release|x64.Build.0 = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Release|x86.ActiveCfg = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.Release|x86.Build.0 = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLL|x64.Build.0 = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLL|x86.Build.0 = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseLTO|x64.Build.0 = Release|x64 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {D8377B20-EEFC-4ABC-95F0-24BC86B7E3F2}.ReleaseLTO|x86.Build.0 = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Debug|x64.ActiveCfg = Debug|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Debug|x64.Build.0 = Debug|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Debug|x86.ActiveCfg = Debug|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Debug|x86.Build.0 = Debug|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLL|x64.ActiveCfg = Debug|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLL|x64.Build.0 = Debug|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLL|x86.Build.0 = Debug|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Release|x64.ActiveCfg = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Release|x64.Build.0 = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Release|x86.ActiveCfg = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.Release|x86.Build.0 = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLL|x64.Build.0 = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLL|x86.Build.0 = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseLTO|x64.Build.0 = Release|x64 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {BABFD64D-9BF1-4328-B977-24BF81800620}.ReleaseLTO|x86.Build.0 = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Debug|x64.ActiveCfg = Debug|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Debug|x64.Build.0 = Debug|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Debug|x86.ActiveCfg = Debug|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Debug|x86.Build.0 = Debug|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLL|x64.ActiveCfg = Debug|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLL|x64.Build.0 = Debug|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLL|x86.Build.0 = Debug|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Release|x64.ActiveCfg = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Release|x64.Build.0 = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Release|x86.ActiveCfg = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.Release|x86.Build.0 = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLL|x64.Build.0 = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLL|x86.Build.0 = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseLTO|x64.Build.0 = Release|x64 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {C6101E18-D73B-430C-A79C-084E1236EA94}.ReleaseLTO|x86.Build.0 = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Debug|x64.ActiveCfg = Debug|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Debug|x64.Build.0 = Debug|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Debug|x86.ActiveCfg = Debug|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Debug|x86.Build.0 = Debug|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLL|x64.ActiveCfg = Debug|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLL|x64.Build.0 = Debug|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLL|x86.Build.0 = Debug|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Release|x64.ActiveCfg = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Release|x64.Build.0 = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Release|x86.ActiveCfg = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.Release|x86.Build.0 = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLL|x64.Build.0 = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLL|x86.Build.0 = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseLTO|x64.Build.0 = Release|x64 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {AAD3AB93-F831-4339-8AAD-DC956B9B9233}.ReleaseLTO|x86.Build.0 = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Debug|x64.ActiveCfg = Debug|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Debug|x64.Build.0 = Debug|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Debug|x86.ActiveCfg = Debug|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Debug|x86.Build.0 = Debug|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLL|x64.ActiveCfg = Debug|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLL|x64.Build.0 = Debug|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLL|x86.Build.0 = Debug|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Release|x64.ActiveCfg = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Release|x64.Build.0 = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Release|x86.ActiveCfg = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.Release|x86.Build.0 = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLL|x64.Build.0 = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLL|x86.Build.0 = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseLTO|x64.Build.0 = Release|x64 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6}.ReleaseLTO|x86.Build.0 = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Debug|x64.ActiveCfg = Debug|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Debug|x64.Build.0 = Debug|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Debug|x86.ActiveCfg = Debug|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Debug|x86.Build.0 = Debug|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLL|x64.ActiveCfg = Debug|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLL|x64.Build.0 = Debug|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLL|x86.Build.0 = Debug|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Release|x64.ActiveCfg = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Release|x64.Build.0 = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Release|x86.ActiveCfg = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.Release|x86.Build.0 = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLL|x64.Build.0 = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLL|x86.Build.0 = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseLTO|x64.Build.0 = Release|x64 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3}.ReleaseLTO|x86.Build.0 = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.Debug|x64.ActiveCfg = Debug|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.Debug|x64.Build.0 = Debug|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.Debug|x86.ActiveCfg = Debug|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.Debug|x86.Build.0 = Debug|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLL|x64.ActiveCfg = Debug|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLL|x64.Build.0 = Debug|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLL|x86.Build.0 = Debug|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.Release|x64.ActiveCfg = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.Release|x64.Build.0 = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.Release|x86.ActiveCfg = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.Release|x86.Build.0 = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLL|x64.Build.0 = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLL|x86.Build.0 = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseLTO|x64.Build.0 = Release|x64 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {B337D322-355B-4348-A2A8-270471BE2C95}.ReleaseLTO|x86.Build.0 = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.Debug|x64.ActiveCfg = Debug|x64 - {80579A29-8073-46A0-B328-661155E0887B}.Debug|x64.Build.0 = Debug|x64 - {80579A29-8073-46A0-B328-661155E0887B}.Debug|x86.ActiveCfg = Debug|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.Debug|x86.Build.0 = Debug|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLL|x64.ActiveCfg = Debug|x64 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLL|x64.Build.0 = Debug|x64 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLL|x86.ActiveCfg = Debug|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLL|x86.Build.0 = Debug|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.Release|x64.ActiveCfg = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.Release|x64.Build.0 = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.Release|x86.ActiveCfg = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.Release|x86.Build.0 = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLL|x64.ActiveCfg = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLL|x64.Build.0 = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLL|x86.ActiveCfg = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLL|x86.Build.0 = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseLTO|x64.ActiveCfg = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseLTO|x64.Build.0 = Release|x64 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseLTO|x86.ActiveCfg = Release|Win32 - {80579A29-8073-46A0-B328-661155E0887B}.ReleaseLTO|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {C6101E18-D73B-430C-A79C-084E1236EA94} = {3B1FE419-D7D2-4406-9C24-5A6F6ED63E73} - {AAD3AB93-F831-4339-8AAD-DC956B9B9233} = {3B1FE419-D7D2-4406-9C24-5A6F6ED63E73} - {9D936BE4-46AA-489F-82E7-D2CFEB157FB6} = {3B1FE419-D7D2-4406-9C24-5A6F6ED63E73} - {597D5EF8-04DB-48F9-A8F3-4B593B81C7C3} = {3B1FE419-D7D2-4406-9C24-5A6F6ED63E73} - {B337D322-355B-4348-A2A8-270471BE2C95} = {3B1FE419-D7D2-4406-9C24-5A6F6ED63E73} - {80579A29-8073-46A0-B328-661155E0887B} = {3B1FE419-D7D2-4406-9C24-5A6F6ED63E73} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {1838F09B-B929-4D1E-ABB6-FA2A94F4A4BE} - EndGlobalSection -EndGlobal diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/CodecDeducer.h b/source/ffmpeg-cpp/ffmpeg-cpp/CodecDeducer.h deleted file mode 100644 index c3cc536..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/CodecDeducer.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "ffmpeg.h" - -namespace ffmpegcpp -{ - class CodecDeducer - { - public: - - static AVCodec* DeduceEncoderFromFilename(const char* fileName); - - static AVCodec* DeduceEncoder(AVCodecID codecId); - static AVCodec* DeduceEncoder(const char* codecName); - - static AVCodec* DeduceDecoder(AVCodecID codecId); - static AVCodec* DeduceDecoder(const char* codecName); - }; - -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/AudioCodec.h b/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/AudioCodec.h deleted file mode 100644 index ec605cd..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/AudioCodec.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "Codec.h" -#include "OpenCodec.h" - -namespace ffmpegcpp -{ - - class AudioCodec : public Codec - { - public: - - AudioCodec(const char* codecName); - AudioCodec(AVCodecID codecId); - virtual ~AudioCodec(); - - OpenCodec* Open(int bitRate, AVSampleFormat format, int sampleRate); - - bool IsFormatSupported(AVSampleFormat format); - bool IsChannelsSupported(int channels); - bool IsSampleRateSupported(int sampleRate); - - AVSampleFormat GetDefaultSampleFormat(); - int GetDefaultSampleRate(); - - }; - - -} \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/Codec.cpp b/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/Codec.cpp deleted file mode 100644 index 8b44c97..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/Codec.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "Codec.h" -#include "FFmpegException.h" -#include "CodecDeducer.h" - -using namespace std; - -namespace ffmpegcpp -{ - Codec::Codec(const char* codecName) - { - - AVCodec* codec = CodecDeducer::DeduceEncoder(codecName); - codecContext = LoadContext(codec); - } - - - Codec::Codec(AVCodecID codecId) - { - AVCodec* codec = CodecDeducer::DeduceEncoder(codecId); - codecContext = LoadContext(codec); - } - - void Codec::SetOption(const char* name, const char* value) - { - av_opt_set(codecContext->priv_data, name, value, 0); - } - - void Codec::SetOption(const char* name, int value) - { - av_opt_set_int(codecContext->priv_data, name, value, 0); - } - - void Codec::SetOption(const char* name, double value) - { - av_opt_set_double(codecContext->priv_data, name, value, 0); - } - - AVCodecContext* Codec::LoadContext(AVCodec* codec) - { - AVCodecContext* codecContext = avcodec_alloc_context3(codec); - if (!codecContext) - { - CleanUp(); - throw FFmpegException("Could not allocate video codec context for codec " + string(codec->name)); - } - - // copy the type - codecContext->codec_type = codec->type; - - return codecContext; - } - - void Codec::CleanUp() - { - if (codecContext != nullptr && !opened) - { - avcodec_free_context(&codecContext); - } - } - - OpenCodec* Codec::Open() - { - if (opened) - { - throw FFmpegException("You can only open a codec once"); - } - - int ret = avcodec_open2(codecContext, codecContext->codec, NULL); - if (ret < 0) - { - throw FFmpegException("Could not open codecContext for codec", ret); - } - - opened = true; - - return new OpenCodec(codecContext); - } - - Codec::~Codec() - { - CleanUp(); - } - - void Codec::SetGlobalContainerHeader() - { - if (opened) throw FFmpegException("This flag should be set before opening the codec"); - codecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - } -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/Codec.h b/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/Codec.h deleted file mode 100644 index 8d4d717..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/Codec.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "ffmpeg.h" -#include "std.h" - -#include "OpenCodec.h" - -namespace ffmpegcpp -{ - - class Codec - { - public: - - Codec(const char* codecName); - Codec(AVCodecID codecId); - virtual ~Codec(); - - void SetOption(const char* name, const char* value); - void SetOption(const char* name, int value); - void SetOption(const char* name, double value); - - void SetGlobalContainerHeader(); // used by the Muxer for configuration purposes - - protected: - - AVCodecContext* codecContext = nullptr; - - OpenCodec* Open(); - - private: - - void CleanUp(); - - AVCodecContext* LoadContext(AVCodec* codec); - - bool opened = false; - }; -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VideoCodec.h b/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VideoCodec.h deleted file mode 100644 index e67be18..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VideoCodec.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "Codec.h" -#include "OpenCodec.h" - -namespace ffmpegcpp -{ - - class VideoCodec : public Codec - { - public: - - VideoCodec(const char* codecName); - VideoCodec(AVCodecID codecId); - virtual ~VideoCodec(); - - OpenCodec* Open(int width, int height, AVRational* frameRate, AVPixelFormat format); - - // This maps to the qscale parameter so should be in the range [0,31]. - void SetQualityScale(int qscale); - - bool IsPixelFormatSupported(AVPixelFormat format); - bool IsFrameRateSupported(AVRational* frameRate); - - AVPixelFormat GetDefaultPixelFormat(); - AVRational GetClosestSupportedFrameRate(AVRational frameRate); - - }; - - -} \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioEncoder.h b/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioEncoder.h deleted file mode 100644 index f60effa..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioEncoder.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "ffmpeg.h" -#include "std.h" - -#include "Frame Sinks/AudioFrameSink.h" -#include "Codecs/AudioCodec.h" -#include "ConvertedAudioProcessor.h" -#include "AudioFormatConverter.h" -#include "Muxing/Muxer.h" -#include "Muxing/OutputStream.h" - -namespace ffmpegcpp -{ - class AudioEncoder : public AudioFrameSink, public ConvertedAudioProcessor - { - public: - AudioEncoder(AudioCodec* codec, Muxer* muxer); - AudioEncoder(AudioCodec* codec, Muxer* muxer, int bitRate); - virtual ~AudioEncoder(); - - void WriteFrame(AVFrame* frame, AVRational* timeBase); - void Close(); - - virtual void WriteConvertedFrame(AVFrame* frame); - - bool IsPrimed(); - - private: - - void OpenLazily(AVFrame* frame, AVRational* timeBase); - - void CleanUp(); - - void PollCodecForPackets(); - - OutputStream* output; - - AudioCodec* closedCodec; - - AudioFormatConverter *formatConverter = nullptr; - OpenCodec* codec = nullptr; - AVPacket* pkt = nullptr; - - int frameNumber = 0; - - int finalBitRate = -1; - }; -} - diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFilter.h b/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFilter.h deleted file mode 100644 index 1afe66e..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFilter.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "ffmpeg.h" - -#include "VideoFrameSink.h" - -namespace ffmpegcpp -{ - class VideoFilter : public VideoFrameSink - { - - public: - - VideoFilter(const char* filterString, VideoFrameSink* target); - virtual ~VideoFilter(); - - void WriteFrame(AVFrame* frame, AVRational* timeBase); - void Close(); - - bool IsPrimed(); - - private: - - void InitDelayed(AVFrame* frame, AVRational* timeBase); - void PollFilterGraphForFrames(); - - VideoFrameSink* target; - - const char* filterString; - AVPixelFormat outputFormat; - - AVFilterGraph *filter_graph = nullptr; - AVFilterContext *buffersink_ctx = nullptr; - AVFilterContext *buffersrc_ctx = nullptr; - AVFrame* filt_frame = nullptr; - - bool initialized = false; - - AVRational* timeBase; - - void CleanUp(); - }; - - -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/AudioOutputStream.h b/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/AudioOutputStream.h deleted file mode 100644 index 0181295..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/AudioOutputStream.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "ffmpeg.h" -#include "Codecs/Codec.h" -#include "OutputStream.h" -#include "Muxer.h" - -namespace ffmpegcpp -{ - class AudioOutputStream : public OutputStream - { - public: - - AudioOutputStream(Muxer* muxer, Codec* codec); - - virtual void OpenStream(AVStream* stream, int containerFlags); - - virtual void WritePacket(AVPacket* pkt, OpenCodec* openCodec); - - virtual bool IsPrimed(); - - protected: - - virtual void PreparePacketForMuxer(AVPacket* pkt); - - private: - - void LazilyInitialize(OpenCodec* openCodec); - - AVStream* stream; - - bool initialized = false; - - AVRational codecTimeBase; - }; -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.h b/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.h deleted file mode 100644 index fe4fc6d..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "ffmpeg.h" -#include "Codecs/Codec.h" -#include "OutputStream.h" -#include "Muxer.h" - -namespace ffmpegcpp -{ - class VideoOutputStream : public OutputStream - { - public: - - VideoOutputStream(Muxer* muxer, Codec* codec); - - virtual void OpenStream(AVStream* stream, int containerFlags); - - virtual void WritePacket(AVPacket* pkt, OpenCodec* openCodec); - - virtual bool IsPrimed(); - - protected: - - virtual void PreparePacketForMuxer(AVPacket* pkt); - - private: - - void LazilyInitialize(OpenCodec* openCodec); - - AVStream* stream; - - bool initialized = false; - - AVRational codecTimeBase; - }; -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/Demuxer.cpp b/source/ffmpeg-cpp/ffmpeg-cpp/Sources/Demuxer.cpp deleted file mode 100644 index 8f157eb..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/Demuxer.cpp +++ /dev/null @@ -1,260 +0,0 @@ -#include "Demuxer.h" -#include "FFmpegException.h" -#include "CodecDeducer.h" - -#include - -using namespace std; - -namespace ffmpegcpp -{ - - Demuxer::Demuxer(const char* fileName) - : Demuxer(fileName, NULL, NULL) - { - } - - Demuxer::Demuxer(const char* fileName, AVInputFormat* inputFormat, AVDictionary *format_opts) - { - this->fileName = fileName; - - // open input file, and allocate format context - int ret; - if ((ret = avformat_open_input(&containerContext, fileName, inputFormat, &format_opts)) < 0) - { - CleanUp(); - throw FFmpegException("Failed to open input container " + string(fileName), ret); - } - - // retrieve stream information - if (ret = (avformat_find_stream_info(containerContext, NULL)) < 0) - { - CleanUp(); - throw FFmpegException("Failed to read streams from " + string(fileName), ret); - } - - inputStreams = new InputStream*[containerContext->nb_streams]; - for (int i = 0; i < containerContext->nb_streams; ++i) - { - inputStreams[i] = nullptr; - } - - // initialize packet, set data to NULL, let the demuxer fill it - pkt = av_packet_alloc(); - if (!pkt) - { - CleanUp(); - throw FFmpegException("Failed to create packet for input stream"); - } - av_init_packet(pkt); - pkt->data = NULL; - pkt->size = 0; - } - - Demuxer::~Demuxer() - { - CleanUp(); - } - - void Demuxer::CleanUp() - { - if (inputStreams != nullptr) - { - for (int i = 0; i < containerContext->nb_streams; ++i) - { - if (inputStreams[i] != nullptr) - { - delete inputStreams[i]; - } - } - delete inputStreams; - inputStreams = nullptr; - } - if (containerContext != nullptr) - { - avformat_close_input(&containerContext); - containerContext = nullptr; - } - if (pkt != nullptr) - { - av_packet_free(&pkt); - pkt = nullptr; - } - } - - vector Demuxer::GetAudioStreamInfo() - { - return GetStreamInfo(AVMEDIA_TYPE_AUDIO); - } - - vector Demuxer::GetVideoStreamInfo() - { - return GetStreamInfo(AVMEDIA_TYPE_VIDEO); - } - - vector Demuxer::GetStreamInfo(AVMediaType mediaType) - { - vector streamInfo; - for (int i = 0; i < containerContext->nb_streams; ++i) - { - AVStream* stream = containerContext->streams[i]; - - /* find decoder for the stream */ - AVCodec* codec = CodecDeducer::DeduceDecoder(stream->codecpar->codec_id); - if (!codec) - { - throw FFmpegException(string("Failed to deduce codec for stream ") + std::to_string(i) + " in container"); - } - - if (codec->type == mediaType) - { - streamInfo.push_back(CreateInfo(i, stream, codec)); - } - } - return streamInfo; - } - - StreamInfo Demuxer::CreateInfo(int streamIndex, AVStream* stream, AVCodec* codec) - { - StreamInfo info; - info.streamId = streamIndex; - info.stream = stream; - info.codec = codec; - return info; - } - - void Demuxer::DecodeBestAudioStream(AudioFrameSink* frameSink) - { - int ret = av_find_best_stream(containerContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); - if (ret < 0) - { - throw FFmpegException("Could not find " + string(av_get_media_type_string(AVMEDIA_TYPE_AUDIO)) + " stream in input file " + fileName, ret); - } - int streamIndex = ret; - return DecodeAudioStream(streamIndex, frameSink); - } - - void Demuxer::DecodeBestVideoStream(VideoFrameSink* frameSink) - { - int ret = av_find_best_stream(containerContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); - if (ret < 0) - { - throw FFmpegException("Could not find " + string(av_get_media_type_string(AVMEDIA_TYPE_VIDEO)) + " stream in input file " + fileName, ret); - } - int streamIndex = ret; - return DecodeVideoStream(streamIndex, frameSink); - } - - void Demuxer::DecodeAudioStream(int streamIndex, AudioFrameSink* frameSink) - { - // each input stream can only be used once - if (inputStreams[streamIndex] != nullptr) - { - throw FFmpegException("That stream is already tied to a frame sink, you cannot process the same stream multiple times"); - } - - // create the stream - AVStream* stream = containerContext->streams[streamIndex]; - AudioInputStream* inputStream = new AudioInputStream(frameSink, stream); - inputStream->Open(); - - // remember and return - inputStreams[streamIndex] = inputStream; - } - - void Demuxer::DecodeVideoStream(int streamIndex, VideoFrameSink* frameSink) - { - // each input stream can only be used once - if (inputStreams[streamIndex] != nullptr) - { - throw FFmpegException("That stream is already tied to a frame sink, you cannot process the same stream multiple times"); - } - - // create the stream - AVStream* stream = containerContext->streams[streamIndex]; - VideoInputStream* inputStream = new VideoInputStream(frameSink, stream); - inputStream->Open(); - - // remember and return - inputStreams[streamIndex] = inputStream; - } - - void Demuxer::PreparePipeline() - { - bool allPrimed = false; - do - { - Step(); - - // see if all input streams are primed - allPrimed = true; - for (int i = 0; i < containerContext->nb_streams; ++i) - { - InputStream* stream = inputStreams[i]; - if (stream != nullptr) - { - if (!stream->IsPrimed()) allPrimed = false; - } - } - - } while (!allPrimed && !IsDone()); - } - - bool Demuxer::IsDone() - { - return done; - } - - void Demuxer::Step() - { - // read frames from the file - int ret = av_read_frame(containerContext, pkt); - - // EOF - if (ret == AVERROR_EOF) - { - pkt->data = NULL; - pkt->size = 0; - for (int i = 0; i < containerContext->nb_streams; ++i) - { - InputStream* stream = inputStreams[i]; - if (stream != nullptr) - { - pkt->stream_index = i; - DecodePacket(); - stream->Close(); - } - } - - done = true; - return; - } - - // not ready yet - if (ret == AVERROR(EAGAIN)) return; - - // error - if (ret < 0) - { - throw FFmpegException("Error during demuxing", ret); - } - - // decode the finished packet - DecodePacket(); - } - - void Demuxer::DecodePacket() - { - int streamIndex = pkt->stream_index; - InputStream* inputStream = inputStreams[streamIndex]; - - if (inputStream != nullptr) - { - inputStream->DecodePacket(pkt); - } - - // We need to unref the packet here because packets might pass by here - // that don't have a stream attached to them. We want to dismiss them! - av_packet_unref(pkt); - } -} \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/Demuxer.h b/source/ffmpeg-cpp/ffmpeg-cpp/Sources/Demuxer.h deleted file mode 100644 index 7af3531..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/Demuxer.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "ffmpeg.h" -#include "std.h" - -#include "Demuxing/AudioInputStream.h" -#include "Demuxing/VideoInputStream.h" -#include "Demuxing/InputStream.h" -#include "Sources/InputSource.h" - -namespace ffmpegcpp -{ - struct StreamInfo - { - int streamId; - AVCodec* codec; - AVStream* stream; - }; - - class Demuxer : public InputSource - { - public: - - Demuxer(const char* fileName); - Demuxer(const char* fileName, AVInputFormat* inputFormat, AVDictionary *inputFormatOptions); - ~Demuxer(); - - void DecodeBestAudioStream(AudioFrameSink* frameSink); - void DecodeBestVideoStream(VideoFrameSink* frameSink); - - void DecodeAudioStream(int streamId, AudioFrameSink* frameSink); - void DecodeVideoStream(int streamId, VideoFrameSink* frameSink); - - std::vector GetAudioStreamInfo(); - std::vector GetVideoStreamInfo(); - - virtual void PreparePipeline(); - virtual bool IsDone(); - virtual void Step(); - - private: - - bool done = false; - - const char* fileName; - - std::vector GetStreamInfo(AVMediaType mediaType); - StreamInfo CreateInfo(int streamIndex, AVStream* stream, AVCodec* codec); - - InputStream** inputStreams = nullptr; - - AVFormatContext* containerContext = nullptr; - AVPacket* pkt = nullptr; - - void DecodePacket(); - - void CleanUp(); - }; -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/EncodedFileSource.h b/source/ffmpeg-cpp/ffmpeg-cpp/Sources/EncodedFileSource.h deleted file mode 100644 index 8637d03..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/EncodedFileSource.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "ffmpeg.h" -#include "Frame Sinks/FrameSink.h" -#include "InputSource.h" - -namespace ffmpegcpp -{ - // EncodedFileSource takes a file that is already encoded but not in a container (ie .mp3, .h264) - // and feeds it to the system. - class EncodedFileSource : public InputSource - { - - public: - EncodedFileSource(const char* inFileName, AVCodecID codecId, FrameSink* output); - EncodedFileSource(const char* inFileName, const char* codecName, FrameSink* output); - virtual ~EncodedFileSource(); - - virtual void PreparePipeline(); - virtual bool IsDone(); - virtual void Step(); - - private: - - void CleanUp(); - - bool done = false; - - FrameSink* output; - - AVCodecParserContext* parser = nullptr; - - AVCodec* codec; - AVCodecContext* codecContext = nullptr; - - int bufferSize; - - AVFrame* decoded_frame = nullptr; - AVPacket* pkt = nullptr; - uint8_t* buffer = nullptr; - - FILE* file; - - void Init(const char* inFileName, AVCodec* codec, FrameSink* output); - - void Decode(AVPacket *packet, AVFrame* targetFrame); - - AVRational timeBaseCorrectedByTicksPerFrame; - }; -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioFileSource.cpp b/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioFileSource.cpp deleted file mode 100644 index 6b55509..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioFileSource.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "RawAudioFileSource.h" -#include "FFmpegException.h" -#include "std.h" - -using namespace std; - -namespace ffmpegcpp -{ - RawAudioFileSource::RawAudioFileSource(const char* fileName, const char* inputFormat, int sampleRate, int channels, AudioFrameSink* frameSink) - { - - // try to deduce the input format from the input format name - AVInputFormat *file_iformat; - if (!(file_iformat = av_find_input_format(inputFormat))) - { - CleanUp(); - throw FFmpegException("Unknown input format: " + string(inputFormat)); - } - - AVDictionary* format_opts = NULL; - - av_dict_set_int(&format_opts, "sample_rate", sampleRate, 0); - av_dict_set_int(&format_opts, "channels", channels, 0); - - // create the demuxer - try - { - demuxer = new Demuxer(fileName, file_iformat, format_opts); - demuxer->DecodeBestAudioStream(frameSink); - } - catch (FFmpegException e) - { - CleanUp(); - throw e; - } - } - - - RawAudioFileSource::~RawAudioFileSource() - { - CleanUp(); - } - - void RawAudioFileSource::CleanUp() - { - if (demuxer != nullptr) - { - delete demuxer; - demuxer = nullptr; - } - } - - void RawAudioFileSource::PreparePipeline() - { - demuxer->PreparePipeline(); - } - - bool RawAudioFileSource::IsDone() - { - return demuxer->IsDone(); - } - - void RawAudioFileSource::Step() - { - demuxer->Step(); - } -} - diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioFileSource.h b/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioFileSource.h deleted file mode 100644 index 23270a5..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioFileSource.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "ffmpeg.h" - -#include "InputSource.h" -#include "Demuxer.h" - - -namespace ffmpegcpp -{ - class RawAudioFileSource : public InputSource - { - public: - - RawAudioFileSource(const char* fileName, const char* inputFormat, int sampleRate, int channels, AudioFrameSink* frameSink); - virtual ~RawAudioFileSource(); - - virtual void PreparePipeline(); - virtual bool IsDone(); - virtual void Step(); - - private: - - void CleanUp(); - - Demuxer* demuxer = nullptr; - }; - - -} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj b/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj deleted file mode 100644 index fed6ac2..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj +++ /dev/null @@ -1,267 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {BABFD64D-9BF1-4328-B977-24BF81800620} - Win32Proj - ffmpegcpp - 10.0.17763.0 - - - - StaticLibrary - true - v141 - Unicode - - - StaticLibrary - false - v141 - true - Unicode - - - StaticLibrary - true - v141 - Unicode - false - - - StaticLibrary - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - true - $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(FFmpegLibraryDir)lib - $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(FFmpegLibraryDir)lib - $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\lib\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_LIB;%(PreprocessorDefinitions) - true - $(FFmpegLibraryDir)include;$(ProjectDir);%(AdditionalIncludeDirectories) - - - Windows - true - - - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib - - - xcopy $(ProjectDir)*.h $(ProjectDir)..\..\..\include /y /s /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - $(FFmpegLibraryDir)include;$(ProjectDir);%(AdditionalIncludeDirectories) - - - Windows - true - - - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib - - - xcopy $(ProjectDir)*.h $(ProjectDir)..\..\..\include /y /s - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - $(FFmpegLibraryDir)include;$(ProjectDir);%(AdditionalIncludeDirectories) - - - Windows - true - true - true - - - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib - - - xcopy $(ProjectDir)*.h $(ProjectDir)..\..\..\include /y /s - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_LIB;%(PreprocessorDefinitions) - true - $(FFmpegLibraryDir)include;$(ProjectDir);%(AdditionalIncludeDirectories) - - - Windows - true - true - true - - - $(FFmpegLibraryDir)lib\avcodec.lib;$(FFmpegLibraryDir)lib\avfilter.lib;$(FFmpegLibraryDir)lib\avformat.lib;$(FFmpegLibraryDir)lib\avutil.lib;$(FFmpegLibraryDir)lib\swresample.lib;$(FFmpegLibraryDir)lib\swscale.lib - - - xcopy $(ProjectDir)*.h $(ProjectDir)..\..\..\include /y /s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj.filters b/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj.filters deleted file mode 100644 index e88632f..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj.filters +++ /dev/null @@ -1,219 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj.user b/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj.user deleted file mode 100644 index 0b0f24d..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/ffmpeg-cpp.vcxproj.user +++ /dev/null @@ -1,6 +0,0 @@ - - - - true - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/std.h b/source/ffmpeg-cpp/ffmpeg-cpp/std.h deleted file mode 100644 index 97f7e65..0000000 --- a/source/ffmpeg-cpp/ffmpeg-cpp/std.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include -#include -#include diff --git a/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj b/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj deleted file mode 100644 index 4362b9a..0000000 --- a/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj +++ /dev/null @@ -1,200 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {80579A29-8073-46A0-B328-661155E0887B} - Win32Proj - decodeaudio - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj.filters b/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj.filters deleted file mode 100644 index b1ed7c9..0000000 --- a/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj.user b/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj.user deleted file mode 100644 index 6c84d89..0000000 --- a/source/ffmpeg-cpp/filtering_video/filtering_video.vcxproj.user +++ /dev/null @@ -1,19 +0,0 @@ - - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - - $(OutDir) - WindowsLocalDebugger - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/remuxing/remuxing.vcxproj b/source/ffmpeg-cpp/remuxing/remuxing.vcxproj deleted file mode 100644 index c45c067..0000000 --- a/source/ffmpeg-cpp/remuxing/remuxing.vcxproj +++ /dev/null @@ -1,200 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {B337D322-355B-4348-A2A8-270471BE2C95} - Win32Proj - decodeaudio - 10.0.17763.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)..\..\..\bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - false - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - pch.h - $(FFmpegLibraryDir)include;..\ffmpeg-cpp;%(AdditionalIncludeDirectories) - - - Console - true - true - true - %(AdditionalDependencies) - - - xcopy $(SamplesDir) $(OutDir)samples /s /y /i -xcopy $(FFmpegLibraryDir)bin $(OutDir) /s /y /i - - - - - {babfd64d-9bf1-4328-b977-24bf81800620} - - - - - - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/remuxing/remuxing.vcxproj.filters b/source/ffmpeg-cpp/remuxing/remuxing.vcxproj.filters deleted file mode 100644 index de7d8a5..0000000 --- a/source/ffmpeg-cpp/remuxing/remuxing.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/remuxing/remuxing.vcxproj.user b/source/ffmpeg-cpp/remuxing/remuxing.vcxproj.user deleted file mode 100644 index be25078..0000000 --- a/source/ffmpeg-cpp/remuxing/remuxing.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/AudioFormatConverter.cpp b/src/AudioFormatConverter.cpp similarity index 68% rename from source/ffmpeg-cpp/ffmpeg-cpp/AudioFormatConverter.cpp rename to src/AudioFormatConverter.cpp index 61e43db..688dfcb 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/AudioFormatConverter.cpp +++ b/src/AudioFormatConverter.cpp @@ -1,4 +1,7 @@ #include "AudioFormatConverter.h" + +#include "ConvertedAudioProcessor.h" +#include "ffmpeg.h" #include "FFmpegException.h" namespace ffmpegcpp @@ -8,11 +11,10 @@ namespace ffmpegcpp this->output = writer; this->codecContext = codecContext; - converted_frame = av_frame_alloc(); + converted_frame = MakeFFmpegResource(av_frame_alloc()); int ret; if (!converted_frame) { - CleanUp(); throw FFmpegException("Error allocating an audio frame"); } @@ -30,20 +32,18 @@ namespace ffmpegcpp converted_frame->nb_samples = nb_samples; if (nb_samples) { - ret = av_frame_get_buffer(converted_frame, 0); + ret = av_frame_get_buffer(converted_frame.get(), 0); if (ret < 0) { - CleanUp(); throw FFmpegException("Error allocating an audio buffer", ret); } } // create the temporary frame that will hold parts of the converted data // this data will later be assembled in a complete converted_frame. - tmp_frame = av_frame_alloc(); + tmp_frame = MakeFFmpegResource(av_frame_alloc()); if (!tmp_frame) { - CleanUp(); throw FFmpegException("Error allocating an audio frame"); } tmp_frame->format = codecContext->sample_fmt; @@ -52,43 +52,13 @@ namespace ffmpegcpp tmp_frame->nb_samples = 0; // Create the FIFO buffer based on the specified output sample format - fifo = av_audio_fifo_alloc(codecContext->sample_fmt, codecContext->channels, nb_samples); + fifo = MakeFFmpegResource(av_audio_fifo_alloc(codecContext->sample_fmt, codecContext->channels, nb_samples)); if (!fifo) { - CleanUp(); throw FFmpegException("Failed to create FIFO queue for audio format converter"); } } - AudioFormatConverter::~AudioFormatConverter() - { - CleanUp(); - } - - void AudioFormatConverter::CleanUp() - { - if (converted_frame != nullptr) - { - av_frame_free(&converted_frame); - converted_frame = nullptr; - } - if (tmp_frame != nullptr) - { - av_frame_free(&tmp_frame); - tmp_frame = nullptr; - } - if (swr_ctx != nullptr) - { - swr_free(&swr_ctx); - swr_ctx = nullptr; - } - if (fifo != nullptr) - { - av_audio_fifo_free(fifo); - fifo = nullptr; - } - } - void AudioFormatConverter::InitDelayed(AVFrame* frame) { swr_ctx = swr_alloc(); @@ -100,16 +70,16 @@ namespace ffmpegcpp // set options in_sample_rate = frame->sample_rate; out_sample_rate = codecContext->sample_rate; - av_opt_set_int(swr_ctx, "in_channel_count", frame->channels, 0); - av_opt_set_int(swr_ctx, "in_sample_rate", frame->sample_rate, 0); - av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", (AVSampleFormat)frame->format, 0); - av_opt_set_int(swr_ctx, "out_channel_count", codecContext->channels, 0); - av_opt_set_int(swr_ctx, "out_sample_rate", codecContext->sample_rate, 0); - av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", codecContext->sample_fmt, 0); + av_opt_set_int(swr_ctx.get(), "in_channel_count", frame->channels, 0); + av_opt_set_int(swr_ctx.get(), "in_sample_rate", frame->sample_rate, 0); + av_opt_set_sample_fmt(swr_ctx.get(), "in_sample_fmt", (AVSampleFormat)frame->format, 0); + av_opt_set_int(swr_ctx.get(), "out_channel_count", codecContext->channels, 0); + av_opt_set_int(swr_ctx.get(), "out_sample_rate", codecContext->sample_rate, 0); + av_opt_set_sample_fmt(swr_ctx.get(), "out_sample_fmt", codecContext->sample_fmt, 0); // initialize the resampling context int ret; - if ((ret = swr_init(swr_ctx)) < 0) + if ((ret = swr_init(swr_ctx.get())) < 0) { throw FFmpegException("Failed to initialize the resampling context", ret); } @@ -126,7 +96,7 @@ namespace ffmpegcpp } int ret; - ret = swr_convert_frame(swr_ctx, tmp_frame, frame); + ret = swr_convert_frame(swr_ctx.get(), tmp_frame.get(), frame); if (ret < 0) { throw FFmpegException("Error while converting audio frame to destination format", ret); @@ -134,8 +104,8 @@ namespace ffmpegcpp while (tmp_frame->nb_samples > 0) { - AddToFifo(tmp_frame); - ret = swr_convert_frame(swr_ctx, tmp_frame, NULL); + AddToFifo(tmp_frame.get()); + ret = swr_convert_frame(swr_ctx.get(), tmp_frame.get(), nullptr); if (ret < 0) { throw FFmpegException("Error while converting audio frame to destination format", ret); @@ -145,15 +115,15 @@ namespace ffmpegcpp /* If we have enough samples for the encoder, we encode them. * At the end of the file, we pass the remaining samples to * the encoder. */ - bool finished = (frame == NULL); - int fifoSize = av_audio_fifo_size(fifo); + bool finished = (frame == nullptr); + int fifoSize = av_audio_fifo_size(fifo.get()); while (fifoSize >= converted_frame->nb_samples || (finished && fifoSize > 0)) { // Take one frame worth of audio samples from the FIFO buffer, // encode it and write it to the output file. PullConvertedFrameFromFifo(); - fifoSize = av_audio_fifo_size(fifo); + fifoSize = av_audio_fifo_size(fifo.get()); } } @@ -161,13 +131,13 @@ namespace ffmpegcpp { // Make the FIFO as large as it needs to be to hold both, the old and the new samples. int ret; - if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame->nb_samples)) < 0) + if ((ret = av_audio_fifo_realloc(fifo.get(), av_audio_fifo_size(fifo.get()) + frame->nb_samples)) < 0) { throw FFmpegException("Could not reallocate FIFO", ret); } /* Store the new samples in the FIFO buffer. */ - if (av_audio_fifo_write(fifo, (void **)frame->extended_data, frame->nb_samples) < frame->nb_samples) + if (av_audio_fifo_write(fifo.get(), (void **)frame->extended_data, frame->nb_samples) < frame->nb_samples) { throw FFmpegException("Could not write data to FIFO"); } @@ -178,14 +148,13 @@ namespace ffmpegcpp /* Use the maximum number of possible samples per frame. * If there is less than the maximum possible frame size in the FIFO * buffer use this number. Otherwise, use the maximum possible frame size. */ - const int frame_size = FFMIN(av_audio_fifo_size(fifo), converted_frame->nb_samples); - int data_written; + const int frame_size = FFMIN(av_audio_fifo_size(fifo.get()), converted_frame->nb_samples); converted_frame->nb_samples = frame_size; /* Read as many samples from the FIFO buffer as required to fill the frame. * The samples are stored in the frame temporarily. */ int ret; - if ((ret = av_audio_fifo_read(fifo, (void **)converted_frame->data, frame_size)) < frame_size) + if ((ret = av_audio_fifo_read(fifo.get(), (void **)converted_frame->data, frame_size)) < frame_size) { throw FFmpegException("Could not read data from FIFO", ret); } @@ -203,10 +172,10 @@ namespace ffmpegcpp converted_frame->pts = av_rescale_q(samples_count, inv_sample_rate, codecContext->time_base); samples_count += converted_frame->nb_samples; - output->WriteConvertedFrame(converted_frame); + output->WriteConvertedFrame(converted_frame.get()); samplesInCurrentFrame = 0; - int ret = av_frame_make_writable(converted_frame); + int ret = av_frame_make_writable(converted_frame.get()); if (ret < 0) { throw FFmpegException("Failed to make audio frame writable", ret); diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/CodecDeducer.cpp b/src/CodecDeducer.cpp similarity index 69% rename from source/ffmpeg-cpp/ffmpeg-cpp/CodecDeducer.cpp rename to src/CodecDeducer.cpp index ba61b88..7821dde 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/CodecDeducer.cpp +++ b/src/CodecDeducer.cpp @@ -1,13 +1,15 @@ #include "CodecDeducer.h" + +#include "ffmpeg.h" #include "FFmpegException.h" using namespace std; namespace ffmpegcpp { - AVCodec* CodecDeducer::DeduceEncoder(const char* codecName) + AVCodec* CodecDeducer::DeduceEncoder(const std::string & codecName) { - AVCodec* codec = avcodec_find_encoder_by_name(codecName); + AVCodec* codec = avcodec_find_encoder_by_name(codecName.c_str()); if (!codec) { throw FFmpegException("Codec " + string(codecName) + " not found"); @@ -25,9 +27,9 @@ namespace ffmpegcpp return codec; } - AVCodec* CodecDeducer::DeduceDecoder(const char* codecName) + AVCodec* CodecDeducer::DeduceDecoder(const std::string & codecName) { - AVCodec* codec = avcodec_find_decoder_by_name(codecName); + AVCodec* codec = avcodec_find_decoder_by_name(codecName.c_str()); if (!codec) { throw FFmpegException("Codec " + string(codecName) + " not found"); @@ -45,7 +47,7 @@ namespace ffmpegcpp return codec; } - AVCodec* CodecDeducer::DeduceEncoderFromFilename(const char* fileName) + AVCodec* CodecDeducer::DeduceEncoderFromFilename(const std::string & fileName) { throw FFmpegException("Not implemented yet"); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/AudioCodec.cpp b/src/Codecs/AudioCodec.cpp similarity index 86% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/AudioCodec.cpp rename to src/Codecs/AudioCodec.cpp index 3d18e0c..6904f9a 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/AudioCodec.cpp +++ b/src/Codecs/AudioCodec.cpp @@ -1,11 +1,13 @@ -#include "AudioCodec.h" +#include "Codecs/AudioCodec.h" #include "FFmpegException.h" +#include "ffmpeg.h" +#include "OpenCodec.h" using namespace std; namespace ffmpegcpp { - AudioCodec::AudioCodec(const char* codecName) + AudioCodec::AudioCodec(const std::string & codecName) : Codec(codecName) { } @@ -15,10 +17,6 @@ namespace ffmpegcpp { } - AudioCodec::~AudioCodec() - { - } - /* check that a given sample format is supported by the encoder */ static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt) { @@ -77,7 +75,7 @@ namespace ffmpegcpp return best_ch_layout; } - bool AudioCodec::IsChannelsSupported(int channels) + bool AudioCodec::IsChannelsSupported(int channels) const { int64_t channelLayout = av_get_default_channel_layout(channels); const uint64_t *p = codecContext->codec->channel_layouts; @@ -89,7 +87,7 @@ namespace ffmpegcpp return false; } - bool AudioCodec::IsFormatSupported(AVSampleFormat format) + bool AudioCodec::IsFormatSupported(AVSampleFormat format) const { const enum AVSampleFormat *p = codecContext->codec->sample_fmts; @@ -101,7 +99,7 @@ namespace ffmpegcpp return false; } - bool AudioCodec::IsSampleRateSupported(int sampleRate) + bool AudioCodec::IsSampleRateSupported(int sampleRate) const { const int *p; if (!codecContext->codec->supported_samplerates) return true; // all sample rates are fair game @@ -114,18 +112,18 @@ namespace ffmpegcpp return false; } - AVSampleFormat AudioCodec::GetDefaultSampleFormat() + AVSampleFormat AudioCodec::GetDefaultSampleFormat() const { AVSampleFormat format = (codecContext->codec->sample_fmts ? codecContext->codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP); return format; } - int AudioCodec::GetDefaultSampleRate() + int AudioCodec::GetDefaultSampleRate() const { return select_sample_rate(codecContext->codec); } - OpenCodec* AudioCodec::Open(int bitRate, AVSampleFormat format, int sampleRate) + std::unique_ptr AudioCodec::Open(int bitRate, AVSampleFormat format, int sampleRate) { // do some sanity checks diff --git a/src/Codecs/Codec.cpp b/src/Codecs/Codec.cpp new file mode 100644 index 0000000..8589b99 --- /dev/null +++ b/src/Codecs/Codec.cpp @@ -0,0 +1,82 @@ + +#include "CodecDeducer.h" +#include "Codecs/Codec.h" +#include "ffmpeg.h" +#include "FFmpegException.h" +#include "OpenCodec.h" + +using namespace std; + +namespace +{ + ffmpegcpp::FFmpegResource LoadContext(AVCodec* codec) + { + auto codecContext = ffmpegcpp::MakeFFmpegResource(avcodec_alloc_context3(codec)); + if (!codecContext) + { + throw ffmpegcpp::FFmpegException("Could not allocate video codec context for codec " + string(codec->name)); + } + + // copy the type + codecContext->codec_type = codec->type; + + return codecContext; + } + +} + +namespace ffmpegcpp +{ + Codec::Codec(const std::string & codecName) + { + + AVCodec* codec = CodecDeducer::DeduceEncoder(codecName); + codecContext = LoadContext(codec); + } + + + Codec::Codec(AVCodecID codecId) + { + AVCodec* codec = CodecDeducer::DeduceEncoder(codecId); + codecContext = LoadContext(codec); + } + + void Codec::SetOption(const std::string & name, const std::string & value) + { + av_opt_set(codecContext->priv_data, name.c_str(), value.c_str(), 0); + } + + void Codec::SetOption(const std::string & name, int value) + { + av_opt_set_int(codecContext->priv_data, name.c_str(), value, 0); + } + + void Codec::SetOption(const std::string & name, double value) + { + av_opt_set_double(codecContext->priv_data, name.c_str(), value, 0); + } + + std::unique_ptr Codec::Open() + { + if (opened) + { + throw FFmpegException("You can only open a codec once"); + } + + int ret = avcodec_open2(codecContext.get(), codecContext->codec, nullptr); + if (ret < 0) + { + throw FFmpegException("Could not open codecContext for codec", ret); + } + + opened = true; + + return std::make_unique(codecContext.get()); + } + + void Codec::SetGlobalContainerHeader() + { + if (opened) throw FFmpegException("This flag should be set before opening the codec"); + codecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } +} diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H264NVEncCodec.cpp b/src/Codecs/H264NVEncCodec.cpp similarity index 58% rename from source/ffmpeg-cpp/ffmpeg-cpp/codecs/H264NVEncCodec.cpp rename to src/Codecs/H264NVEncCodec.cpp index 424c6b1..d76c386 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H264NVEncCodec.cpp +++ b/src/Codecs/H264NVEncCodec.cpp @@ -1,4 +1,4 @@ -#include "H264NVEncCodec.h" +#include "Codecs/H264NVEncCodec.h" namespace ffmpegcpp { @@ -9,7 +9,7 @@ namespace ffmpegcpp } - void H264NVEncCodec::SetPreset(const char* preset) + void H264NVEncCodec::SetPreset(const std::string & preset) { SetOption("preset", preset); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H265NVEncCodec.cpp b/src/Codecs/H265NVEncCodec.cpp similarity index 58% rename from source/ffmpeg-cpp/ffmpeg-cpp/codecs/H265NVEncCodec.cpp rename to src/Codecs/H265NVEncCodec.cpp index 31c55f2..745c885 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/codecs/H265NVEncCodec.cpp +++ b/src/Codecs/H265NVEncCodec.cpp @@ -1,4 +1,4 @@ -#include "H265NVEncCodec.h" +#include "Codecs/H265NVEncCodec.h" namespace ffmpegcpp { @@ -9,7 +9,7 @@ namespace ffmpegcpp } - void H265NVEncCodec::SetPreset(const char* preset) + void H265NVEncCodec::SetPreset(const std::string & preset) { SetOption("preset", preset); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/JPGCodec.cpp b/src/Codecs/JPGCodec.cpp similarity index 91% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/JPGCodec.cpp rename to src/Codecs/JPGCodec.cpp index 6431dd5..f695dc1 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/JPGCodec.cpp +++ b/src/Codecs/JPGCodec.cpp @@ -1,4 +1,4 @@ -#include "JPGCodec.h" +#include "Codecs/JPGCodec.h" namespace ffmpegcpp { diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/PNGCodec.cpp b/src/Codecs/PNGCodec.cpp similarity index 91% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/PNGCodec.cpp rename to src/Codecs/PNGCodec.cpp index ff0f522..173c2e1 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/PNGCodec.cpp +++ b/src/Codecs/PNGCodec.cpp @@ -1,4 +1,4 @@ -#include "PNGCodec.h" +#include "Codecs/PNGCodec.h" namespace ffmpegcpp { diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VP9Codec.cpp b/src/Codecs/VP9Codec.cpp similarity index 80% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VP9Codec.cpp rename to src/Codecs/VP9Codec.cpp index 1497525..aa4f3c0 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VP9Codec.cpp +++ b/src/Codecs/VP9Codec.cpp @@ -1,4 +1,4 @@ -#include "VP9Codec.h" +#include "Codecs/VP9Codec.h" namespace ffmpegcpp { @@ -9,7 +9,7 @@ namespace ffmpegcpp } - void VP9Codec::SetDeadline(const char* deadline) + void VP9Codec::SetDeadline(const std::string & deadline) { SetOption("deadline", deadline); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VideoCodec.cpp b/src/Codecs/VideoCodec.cpp similarity index 86% rename from source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VideoCodec.cpp rename to src/Codecs/VideoCodec.cpp index c166957..5b30a49 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Codecs/VideoCodec.cpp +++ b/src/Codecs/VideoCodec.cpp @@ -1,11 +1,13 @@ -#include "VideoCodec.h" +#include "Codecs/VideoCodec.h" #include "FFmpegException.h" +#include "ffmpeg.h" +#include "OpenCodec.h" using namespace std; namespace ffmpegcpp { - VideoCodec::VideoCodec(const char* codecName) + VideoCodec::VideoCodec(const std::string & codecName) : Codec(codecName) { } @@ -26,7 +28,7 @@ namespace ffmpegcpp codecContext->global_quality = FF_QP2LAMBDA * 0; } - bool VideoCodec::IsPixelFormatSupported(AVPixelFormat format) + bool VideoCodec::IsPixelFormatSupported(AVPixelFormat format) const { if (format == AV_PIX_FMT_NONE) return true; // let the codec deal with this const enum AVPixelFormat *p = codecContext->codec->pix_fmts; @@ -38,7 +40,7 @@ namespace ffmpegcpp return false; } - bool VideoCodec::IsFrameRateSupported(AVRational* frameRate) + bool VideoCodec::IsFrameRateSupported(AVRational* frameRate) const { if (!codecContext->codec->supported_framerates) return true; // all frame rates are fair game const AVRational *p = codecContext->codec->supported_framerates; @@ -50,7 +52,7 @@ namespace ffmpegcpp return false; } - OpenCodec* VideoCodec::Open(int width, int height, AVRational* frameRate, AVPixelFormat format) + std::unique_ptr VideoCodec::Open(int width, int height, AVRational* frameRate, AVPixelFormat format) { // sanity checks @@ -78,14 +80,14 @@ namespace ffmpegcpp return Codec::Open(); } - AVPixelFormat VideoCodec::GetDefaultPixelFormat() + AVPixelFormat VideoCodec::GetDefaultPixelFormat() const { const enum AVPixelFormat *p = codecContext->codec->pix_fmts; if (*p == AV_PIX_FMT_NONE) throw FFmpegException("Codec " + string(codecContext->codec->name) + " does not have a default pixel format, you have to specify one"); return *p; } - AVRational VideoCodec::GetClosestSupportedFrameRate(AVRational originalFrameRate) + AVRational VideoCodec::GetClosestSupportedFrameRate(AVRational originalFrameRate) const { if (!codecContext->codec->supported_framerates) { diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/AudioInputStream.cpp b/src/Demuxing/AudioInputStream.cpp similarity index 82% rename from source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/AudioInputStream.cpp rename to src/Demuxing/AudioInputStream.cpp index 0674174..da32466 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/AudioInputStream.cpp +++ b/src/Demuxing/AudioInputStream.cpp @@ -1,4 +1,7 @@ -#include "AudioInputStream.h" +#include "Demuxing/AudioInputStream.h" + +#include "ffmpeg.h" +#include "FrameSinks/AudioFrameSink.h" namespace ffmpegcpp { diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/InputStream.cpp b/src/Demuxing/InputStream.cpp similarity index 80% rename from source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/InputStream.cpp rename to src/Demuxing/InputStream.cpp index 6fbe39c..e99c4be 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/InputStream.cpp +++ b/src/Demuxing/InputStream.cpp @@ -1,6 +1,8 @@ -#include "InputStream.h" +#include "Demuxing/InputStream.h" #include "CodecDeducer.h" +#include "ffmpeg.h" #include "FFmpegException.h" +#include "FrameSinks/FrameSink.h" using namespace std; @@ -14,26 +16,19 @@ namespace ffmpegcpp AVCodec* codec = CodecDeducer::DeduceDecoder(stream->codecpar->codec_id); if (!codec) { - CleanUp(); throw FFmpegException("Failed to find codec for stream " + to_string(stream->index)); } // Allocate a codec context for the decoder - codecContext = avcodec_alloc_context3(codec); + codecContext = MakeFFmpegResource(avcodec_alloc_context3(codec)); if (!codecContext) { - CleanUp(); throw FFmpegException("Failed to allocate the codec context for " + string(codec->name)); } codecContext->framerate = stream->avg_frame_rate; } - InputStream::~InputStream() - { - CleanUp(); - } - void InputStream::ConfigureCodecContext() { // does nothing by default @@ -45,7 +40,7 @@ namespace ffmpegcpp // Copy codec parameters from input stream to output codec context int ret; - if ((ret = avcodec_parameters_to_context(codecContext, stream->codecpar)) < 0) + if ((ret = avcodec_parameters_to_context(codecContext.get(), stream->codecpar)) < 0) { throw FFmpegException("Failed to copy " + string(codec->name) + " codec parameters to decoder context", ret); } @@ -54,7 +49,7 @@ namespace ffmpegcpp ConfigureCodecContext(); // Init the decoders - if ((ret = avcodec_open2(codecContext, codec, NULL)) < 0) + if ((ret = avcodec_open2(codecContext.get(), codec, nullptr)) < 0) { throw FFmpegException("Failed to open codec " + string(codec->name), ret); } @@ -66,27 +61,13 @@ namespace ffmpegcpp timeBaseCorrectedByTicksPerFrame.num *= codecContext->ticks_per_frame; // assign the frame that will be read from the container - frame = av_frame_alloc(); + frame = MakeFFmpegResource(av_frame_alloc()); if (!frame) { throw FFmpegException("Could not allocate frame"); } } - void InputStream::CleanUp() - { - if (codecContext != nullptr) - { - avcodec_free_context(&codecContext); - codecContext = nullptr; - } - if (frame != nullptr) - { - av_frame_free(&frame); - frame = nullptr; - } - } - void InputStream::SetFrameSink(FrameSink* frameSink) { output = frameSink; @@ -99,7 +80,7 @@ namespace ffmpegcpp int ret; /* send the packet with the compressed data to the decoder */ - ret = avcodec_send_packet(codecContext, pkt); + ret = avcodec_send_packet(codecContext.get(), pkt); if (ret < 0) { throw FFmpegException("Error submitting the packet to the decoder", ret); @@ -108,7 +89,7 @@ namespace ffmpegcpp /* read all the output frames (in general there may be any number of them */ while (ret >= 0) { - ret = avcodec_receive_frame(codecContext, frame); + ret = avcodec_receive_frame(codecContext.get(), frame.get()); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return; else if (ret < 0) @@ -131,7 +112,7 @@ namespace ffmpegcpp // push the frame to the next stage. // The time_base is filled in in the codecContext after the first frame is decoded // so we can fetch it from there. - output->WriteFrame(frame, time_base); + output->WriteFrame(frame.get(), time_base); } } @@ -140,7 +121,7 @@ namespace ffmpegcpp output->Close(); } - bool InputStream::IsPrimed() + bool InputStream::IsPrimed() const { return output->IsPrimed(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/VideoInputStream.cpp b/src/Demuxing/VideoInputStream.cpp similarity index 69% rename from source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/VideoInputStream.cpp rename to src/Demuxing/VideoInputStream.cpp index d1facae..5dd598e 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Demuxing/VideoInputStream.cpp +++ b/src/Demuxing/VideoInputStream.cpp @@ -1,4 +1,7 @@ -#include "VideoInputStream.h" +#include "Demuxing/VideoInputStream.h" + +#include "ffmpeg.h" +#include "FrameSinks/VideoFrameSink.h" namespace ffmpegcpp { @@ -8,10 +11,6 @@ namespace ffmpegcpp SetFrameSink(frameSink); } - VideoInputStream::~VideoInputStream() - { - } - void VideoInputStream::ConfigureCodecContext() { diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/FFmpegException.cpp b/src/FFmpegException.cpp similarity index 57% rename from source/ffmpeg-cpp/ffmpeg-cpp/FFmpegException.cpp rename to src/FFmpegException.cpp index 660aa8b..169f90c 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/FFmpegException.cpp +++ b/src/FFmpegException.cpp @@ -4,11 +4,11 @@ using namespace std; namespace ffmpegcpp { - FFmpegException::FFmpegException(string error) : exception(error.c_str()) + FFmpegException::FFmpegException(const string & error) : exception(error.c_str()) { } - FFmpegException::FFmpegException(string error, int returnValue) + FFmpegException::FFmpegException(const string & error, int returnValue) : exception( (error + ": " + av_make_error_string(this->error, AV_ERROR_MAX_STRING_SIZE, returnValue)).c_str() ) diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioEncoder.cpp b/src/FrameSinks/AudioEncoder.cpp similarity index 73% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioEncoder.cpp rename to src/FrameSinks/AudioEncoder.cpp index 4220afb..94633ed 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/AudioEncoder.cpp +++ b/src/FrameSinks/AudioEncoder.cpp @@ -1,7 +1,13 @@ -#include "AudioEncoder.h" -#include "Muxing/AudioOutputStream.h" +#include "FrameSinks/AudioEncoder.h" +#include "AudioFormatConverter.h" +#include "Codecs/AudioCodec.h" +#include "ffmpeg.h" #include "FFmpegException.h" +#include "Muxing/AudioOutputStream.h" +#include "Muxing/Muxer.h" +#include "Muxing/OutputStream.h" +#include "OpenCodec.h" using namespace std; @@ -13,8 +19,8 @@ namespace ffmpegcpp this->closedCodec = codec; // create an output stream - output = new AudioOutputStream(muxer, codec); - muxer->AddOutputStream(output); + output = std::make_unique(muxer, codec); + muxer->AddOutputStream(output.get()); } AudioEncoder::AudioEncoder(AudioCodec* codec, Muxer* muxer, int bitRate) @@ -33,52 +39,22 @@ namespace ffmpegcpp codec = closedCodec->Open(bitRate, format, sampleRate); - pkt = av_packet_alloc(); + pkt = MakeFFmpegResource(av_packet_alloc()); if (!pkt) { - CleanUp(); throw FFmpegException("Failed to allocate packet"); } try { - formatConverter = new AudioFormatConverter(this, codec->GetContext()); + formatConverter = std::make_unique(this, codec->GetContext()); } catch (FFmpegException e) { - CleanUp(); throw e; } } - AudioEncoder::~AudioEncoder() - { - CleanUp(); - } - - void AudioEncoder::CleanUp() - { - if (pkt != nullptr) - { - av_packet_free(&pkt); - } - if (formatConverter != nullptr) - { - delete formatConverter; - formatConverter = nullptr; - } - if (codec != nullptr) - { - delete codec; - codec = nullptr; - } - if (output != nullptr) - { - delete output; - output = nullptr; - } - } - void AudioEncoder::WriteFrame(AVFrame* frame, AVRational* timeBase) { // if we haven't opened the codec yet, we do it now! @@ -116,10 +92,10 @@ namespace ffmpegcpp if (codec == nullptr) return; // can't close if we were never opened // First flush the converter and the FIFO queue in it - formatConverter->ProcessFrame(NULL); + formatConverter->ProcessFrame(nullptr); // then flush our encoder - WriteConvertedFrame(NULL); + WriteConvertedFrame(nullptr); } void AudioEncoder::PollCodecForPackets() @@ -127,7 +103,7 @@ namespace ffmpegcpp int ret = 0; while (ret >= 0) { - ret = avcodec_receive_packet(codec->GetContext(), pkt); + ret = avcodec_receive_packet(codec->GetContext(), pkt.get()); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return; @@ -139,13 +115,13 @@ namespace ffmpegcpp //printf("Write packet %3 (size=%5d)\n", data->pkt->pts, data->pkt->size); //fwrite(data->pkt->data, 1, data->pkt->size, data->f); - output->WritePacket(pkt, codec); + output->WritePacket(pkt.get(), codec.get()); - av_packet_unref(pkt); + av_packet_unref(pkt.get()); } } - bool AudioEncoder::IsPrimed() + bool AudioEncoder::IsPrimed() const { return output->IsPrimed(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoEncoder.cpp b/src/FrameSinks/VideoEncoder.cpp similarity index 80% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoEncoder.cpp rename to src/FrameSinks/VideoEncoder.cpp index 9d52254..6600e20 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoEncoder.cpp +++ b/src/FrameSinks/VideoEncoder.cpp @@ -1,7 +1,13 @@ -#include "VideoEncoder.h" +#include "FrameSinks/VideoEncoder.h" + +#include "Codecs/VideoCodec.h" +#include "ffmpeg.h" #include "FFmpegException.h" +#include "Muxing/Muxer.h" #include "Muxing/VideoOutputStream.h" +#include "VideoFormatConverter.h" +#include "OpenCodec.h" using namespace std; @@ -13,8 +19,8 @@ namespace ffmpegcpp this->closedCodec = codec; // create an output stream - this->output = new VideoOutputStream(muxer, codec); - muxer->AddOutputStream(output); + this->output = std::make_unique(muxer, codec); + muxer->AddOutputStream(output.get()); } VideoEncoder::VideoEncoder(VideoCodec* codec, Muxer* muxer, AVPixelFormat format) @@ -38,34 +44,6 @@ namespace ffmpegcpp finalFrameRateSet = true; } - VideoEncoder::~VideoEncoder() - { - CleanUp(); - } - - void VideoEncoder::CleanUp() - { - if (pkt != nullptr) - { - av_packet_free(&pkt); - } - if (codec != nullptr) - { - delete codec; - codec = nullptr; - } - if (formatConverter != nullptr) - { - delete formatConverter; - formatConverter = nullptr; - } - if (output != nullptr) - { - delete output; - output = nullptr; - } - } - void VideoEncoder::OpenLazily(AVFrame* frame, AVRational* timeBase) { // configure the parameters for the codec based on the frame and our preferences @@ -87,23 +65,21 @@ namespace ffmpegcpp // open the codec codec = closedCodec->Open(width, height, &frameRate, format); - + // allocate the packet we'll be using - pkt = av_packet_alloc(); + pkt = MakeFFmpegResource(av_packet_alloc()); if (!pkt) { - CleanUp(); throw FFmpegException("Failed to allocate packet"); } // set up the format converter try { - formatConverter = new VideoFormatConverter(codec->GetContext()); + formatConverter = std::make_unique(codec->GetContext()); } catch (FFmpegException e) { - CleanUp(); throw e; } } @@ -140,7 +116,7 @@ namespace ffmpegcpp { if (codec == nullptr) return; // can't close if we were never opened - int ret = avcodec_send_frame(codec->GetContext(), NULL); + int ret = avcodec_send_frame(codec->GetContext(), nullptr); if (ret < 0) { throw FFmpegException("Error flushing codec after encoding", ret); @@ -154,7 +130,7 @@ namespace ffmpegcpp int ret = 0; while (ret >= 0) { - ret = avcodec_receive_packet(codec->GetContext(), pkt); + ret = avcodec_receive_packet(codec->GetContext(), pkt.get()); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return; @@ -166,13 +142,13 @@ namespace ffmpegcpp //printf("Write packet %3 (size=%5d)\n", data->pkt->pts, data->pkt->size); //fwrite(data->pkt->data, 1, data->pkt->size, data->f); - output->WritePacket(pkt, codec); + output->WritePacket(pkt.get(), codec.get()); - av_packet_unref(pkt); + av_packet_unref(pkt.get()); } } - bool VideoEncoder::IsPrimed() + bool VideoEncoder::IsPrimed() const { return output->IsPrimed(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFilter.cpp b/src/FrameSinks/VideoFilter.cpp similarity index 82% rename from source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFilter.cpp rename to src/FrameSinks/VideoFilter.cpp index 2a599c8..d420c38 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Frame Sinks/VideoFilter.cpp +++ b/src/FrameSinks/VideoFilter.cpp @@ -1,26 +1,17 @@ -#include "VideoFilter.h" +#include "FrameSinks/VideoFilter.h" + +#include "ffmpeg.h" #include "FFmpegException.h" namespace ffmpegcpp { - VideoFilter::VideoFilter(const char* filterString, VideoFrameSink* target) + VideoFilter::VideoFilter(const std::string & filterString, VideoFrameSink* target) { this->target = target; this->filterString = filterString; } - VideoFilter::~VideoFilter() - { - CleanUp(); - } - - void VideoFilter::CleanUp() - { - avfilter_graph_free(&filter_graph); - av_frame_free(&filt_frame); - } - void VideoFilter::InitDelayed(AVFrame* frame, AVRational* timeBase) { outputFormat = (AVPixelFormat)frame->format; @@ -35,7 +26,7 @@ namespace ffmpegcpp const AVFilter *buffersrc = avfilter_get_by_name("buffer"); const AVFilter *buffersink = avfilter_get_by_name("buffersink"); - filt_frame = av_frame_alloc(); + filt_frame = MakeFFmpegResource(av_frame_alloc()); if (!filt_frame) { throw FFmpegException("Could not allocate intermediate video frame for filter"); @@ -51,7 +42,7 @@ namespace ffmpegcpp enum AVPixelFormat out_pix_fmts[] = { outputFormat, AV_PIX_FMT_NONE }; - filter_graph = avfilter_graph_alloc(); + filter_graph = MakeFFmpegResource(avfilter_graph_alloc()); if (!outputs || !inputs || !filter_graph) { throw FFmpegException("Failed to allocate filter graph"); @@ -67,7 +58,7 @@ namespace ffmpegcpp //codec->codecContext->sample_aspect_ratio.num, codec->codecContext->sample_aspect_ratio.den); ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", - args, NULL, filter_graph); + args, nullptr, filter_graph.get()); if (ret < 0) { throw FFmpegException("Cannot create buffer source", ret); @@ -75,7 +66,7 @@ namespace ffmpegcpp /* buffer video sink: to terminate the filter chain. */ ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", - NULL, NULL, filter_graph); + nullptr, nullptr, filter_graph.get()); if (ret < 0) { throw FFmpegException("Cannot create buffer sink", ret); @@ -102,7 +93,7 @@ namespace ffmpegcpp outputs->name = av_strdup("in"); outputs->filter_ctx = buffersrc_ctx; outputs->pad_idx = 0; - outputs->next = NULL; + outputs->next = nullptr; /* * The buffer sink input must be connected to the output pad of @@ -113,15 +104,15 @@ namespace ffmpegcpp inputs->name = av_strdup("out"); inputs->filter_ctx = buffersink_ctx; inputs->pad_idx = 0; - inputs->next = NULL; + inputs->next = nullptr; - if ((ret = avfilter_graph_parse_ptr(filter_graph, filterString, - &inputs, &outputs, NULL)) < 0) + if ((ret = avfilter_graph_parse_ptr(filter_graph.get(), filterString.c_str(), + &inputs, &outputs, nullptr)) < 0) { throw FFmpegException("Failed to parse and generate filters", ret); } - if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) + if ((ret = avfilter_graph_config(filter_graph.get(), nullptr)) < 0) { throw FFmpegException("Failed to configure filter graph", ret); } @@ -158,7 +149,7 @@ namespace ffmpegcpp { if (!initialized) return; // can't close if we were never opened - int ret = av_buffersrc_add_frame_flags(buffersrc_ctx, NULL, AV_BUFFERSRC_FLAG_KEEP_REF); + int ret = av_buffersrc_add_frame_flags(buffersrc_ctx, nullptr, AV_BUFFERSRC_FLAG_KEEP_REF); PollFilterGraphForFrames(); // close our target as well @@ -171,7 +162,7 @@ namespace ffmpegcpp int ret = 0; while (ret >= 0) { - ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); + ret = av_buffersink_get_frame(buffersink_ctx, filt_frame.get()); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { return; @@ -181,14 +172,14 @@ namespace ffmpegcpp throw FFmpegException("Erorr during filtering", ret); } - target->WriteFrame(filt_frame, timeBase); + target->WriteFrame(filt_frame.get(), timeBase); - av_frame_unref(filt_frame); + av_frame_unref(filt_frame.get()); } } - bool VideoFilter::IsPrimed() + bool VideoFilter::IsPrimed() const { return target->IsPrimed(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/AudioOutputStream.cpp b/src/Muxing/AudioOutputStream.cpp similarity index 93% rename from source/ffmpeg-cpp/ffmpeg-cpp/Muxing/AudioOutputStream.cpp rename to src/Muxing/AudioOutputStream.cpp index b79c564..d914f49 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/AudioOutputStream.cpp +++ b/src/Muxing/AudioOutputStream.cpp @@ -1,5 +1,10 @@ -#include "AudioOutputStream.h" +#include "Muxing/AudioOutputStream.h" + +#include "Codecs/Codec.h" +#include "ffmpeg.h" #include "FFmpegException.h" +#include "Muxing/Muxer.h" +#include "OpenCodec.h" using namespace std; namespace ffmpegcpp @@ -85,7 +90,7 @@ namespace ffmpegcpp } } - bool AudioOutputStream::IsPrimed() + bool AudioOutputStream::IsPrimed() const { return initialized; } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/Muxer.cpp b/src/Muxing/Muxer.cpp similarity index 80% rename from source/ffmpeg-cpp/ffmpeg-cpp/Muxing/Muxer.cpp rename to src/Muxing/Muxer.cpp index 2135608..d5628a6 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/Muxer.cpp +++ b/src/Muxing/Muxer.cpp @@ -1,24 +1,27 @@ -#include "Muxer.h" +#include "Muxing/Muxer.h" + +#include "ffmpeg.h" #include "FFmpegException.h" -#include "OutputStream.h" +#include "Muxing/OutputStream.h" -#include +#include +#include using namespace std; namespace ffmpegcpp { - Muxer::Muxer(const char* fileName) + Muxer::Muxer(const std::string & fileName) { this->fileName = fileName; /* allocate the output media context */ - avformat_alloc_output_context2(&containerContext, NULL, NULL, fileName); + avformat_alloc_output_context2(&containerContext, nullptr, nullptr, fileName.c_str()); if (!containerContext) { printf("WARNING: Could not deduce output format from file extension: using MP4. as default\n"); - avformat_alloc_output_context2(&containerContext, NULL, "mp4", fileName); + avformat_alloc_output_context2(&containerContext, nullptr, "mp4", fileName.c_str()); } if (!containerContext) { @@ -59,13 +62,6 @@ namespace ffmpegcpp avformat_free_context(containerContext); containerContext = nullptr; } - - // clean up the queue - for (int i = 0; i < packetQueue.size(); ++i) - { - AVPacket* tmp_pkt = packetQueue[i]; - av_packet_free(&tmp_pkt); - } } void Muxer::AddOutputStream(OutputStream* outputStream) @@ -73,7 +69,7 @@ namespace ffmpegcpp if (opened) throw FFmpegException("You cannot open a new stream after something was written to the muxer"); // create an internal stream and pass it on - AVStream* stream = avformat_new_stream(containerContext, NULL); + AVStream* stream = avformat_new_stream(containerContext, nullptr); if (!stream) { throw FFmpegException("Could not allocate stream for container " + string(containerContext->oformat->name)); @@ -89,11 +85,10 @@ namespace ffmpegcpp bool Muxer::IsPrimed() { if (opened) return true; // we were already opened before - always primed from now on! - bool allPrimed = true; - for (int i = 0; i < outputStreams.size(); ++i) - { - if (!outputStreams[i]->IsPrimed()) allPrimed = false; - } + + bool allPrimed = std::all_of(cbegin(outputStreams), cend(outputStreams), [](const auto & stream){ + return stream->IsPrimed(); + }); // we are finally primed - open ourselves before we continue. if (allPrimed) @@ -134,36 +129,33 @@ namespace ffmpegcpp { Open(); opened = true; - printf("After %d cached packets, we can finally open the container\n", packetQueue.size()); + std::cout << "After " << packetQueue.size() << " cached packets, we can finally open the container\n"; // flush the queue - for (int i = 0; i < packetQueue.size(); ++i) + std::for_each(begin(packetQueue), end(packetQueue), [this](const auto & tmp_pkt) { - AVPacket* tmp_pkt = packetQueue[i]; - // Write the compressed frame to the media file. - int ret = av_interleaved_write_frame(containerContext, tmp_pkt); + int ret = av_interleaved_write_frame(containerContext, tmp_pkt.get()); if (ret < 0) { throw FFmpegException("Error while writing frame to output container", ret); } - av_packet_unref(tmp_pkt); - av_packet_free(&tmp_pkt); - } + av_packet_unref(tmp_pkt.get()); + }); packetQueue.clear(); } // not ready - buffer the packet else { - AVPacket* tmp_pkt = av_packet_alloc(); + auto tmp_pkt = MakeFFmpegResource(av_packet_alloc()); if (!tmp_pkt) { throw FFmpegException("Failed to allocate packet"); } - av_packet_ref(tmp_pkt, pkt); - packetQueue.push_back(tmp_pkt); + av_packet_ref(tmp_pkt.get(), pkt); + packetQueue.emplace_back(std::move(tmp_pkt)); } } @@ -192,7 +184,7 @@ namespace ffmpegcpp } // Write the stream header, if any. - int ret = avformat_write_header(containerContext, NULL); + int ret = avformat_write_header(containerContext, nullptr); if (ret < 0) { throw FFmpegException("Error when writing header to output file " + fileName, ret); @@ -205,10 +197,9 @@ namespace ffmpegcpp // We must be sure to do this because in an extreme case, one entire stream // might be queueing all its packets before we are opened, so it might not // be draining them at all. - for (int i = 0; i < outputStreams.size(); ++i) - { - outputStreams[i]->DrainPacketQueue(); - } + std::for_each(begin(outputStreams), end(outputStreams), [](auto * stream){ + stream->DrainPacketQueue(); + }); // free the stream CleanUp(); diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/OutputStream.cpp b/src/Muxing/OutputStream.cpp similarity index 54% rename from source/ffmpeg-cpp/ffmpeg-cpp/Muxing/OutputStream.cpp rename to src/Muxing/OutputStream.cpp index 8e1bfa9..40584c8 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/OutputStream.cpp +++ b/src/Muxing/OutputStream.cpp @@ -1,5 +1,12 @@ -#include "OutputStream.h" +#include "Muxing/OutputStream.h" + +#include "Codecs/Codec.h" +#include "ffmpeg.h" #include "FFmpegException.h" +#include "Muxing/Muxer.h" + +#include +#include using namespace std; @@ -27,32 +34,30 @@ namespace ffmpegcpp // otherwise, we queue the packet else { - AVPacket* tmp_pkt = av_packet_alloc(); + auto tmp_pkt = MakeFFmpegResource(av_packet_alloc()); if (!tmp_pkt) { throw FFmpegException("Failed to allocate packet"); } - av_packet_ref(tmp_pkt, pkt); - packetQueue.push_back(tmp_pkt); + av_packet_ref(tmp_pkt.get(), pkt); + packetQueue.emplace_back(std::move(tmp_pkt)); } } void OutputStream::DrainPacketQueue() { - if (packetQueue.size() > 0) printf("Drain %d packets from the packet queue...", packetQueue.size()); - for (int i = 0; i < packetQueue.size(); ++i) - { - AVPacket* tmp_pkt = packetQueue[i]; + if (packetQueue.size() > 0) + std::cout << "Drain " << packetQueue.size() << " packets from the packet queue..."; + std::for_each(begin(packetQueue), end(packetQueue), [this](auto & tmp_pkt) + { // Write the compressed frame to the media file - PreparePacketForMuxer(tmp_pkt); - muxer->WritePacket(tmp_pkt); + PreparePacketForMuxer(tmp_pkt.get()); + muxer->WritePacket(tmp_pkt.get()); // Release the packet - av_packet_unref(tmp_pkt); - av_packet_free(&tmp_pkt); - } - + av_packet_unref(tmp_pkt.get()); + }); packetQueue.clear(); } } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.cpp b/src/Muxing/VideoOutputStream.cpp similarity index 92% rename from source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.cpp rename to src/Muxing/VideoOutputStream.cpp index 5a555a4..09fa10d 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Muxing/VideoOutputStream.cpp +++ b/src/Muxing/VideoOutputStream.cpp @@ -1,5 +1,10 @@ -#include "VideoOutputStream.h" +#include "Muxing/VideoOutputStream.h" + +#include "Codecs/Codec.h" +#include "ffmpeg.h" #include "FFmpegException.h" +#include "Muxing/Muxer.h" +#include "OpenCodec.h" using namespace std; @@ -82,7 +87,7 @@ namespace ffmpegcpp pkt->duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den; } - bool VideoOutputStream::IsPrimed() + bool VideoOutputStream::IsPrimed() const { return initialized; } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/OpenCodec.cpp b/src/OpenCodec.cpp similarity index 86% rename from source/ffmpeg-cpp/ffmpeg-cpp/OpenCodec.cpp rename to src/OpenCodec.cpp index b54c900..7a7e356 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/OpenCodec.cpp +++ b/src/OpenCodec.cpp @@ -1,6 +1,6 @@ -#pragma once - #include "OpenCodec.h" + +#include "ffmpeg.h" #include "FFmpegException.h" using namespace std; @@ -22,7 +22,7 @@ namespace ffmpegcpp avcodec_free_context(&context); } - AVCodecContext* OpenCodec::GetContext() + AVCodecContext* OpenCodec::GetContext() const { return context; } diff --git a/src/Sources/Demuxer.cpp b/src/Sources/Demuxer.cpp new file mode 100644 index 0000000..f91c056 --- /dev/null +++ b/src/Sources/Demuxer.cpp @@ -0,0 +1,200 @@ +#include "Sources/Demuxer.h" + +#include "CodecDeducer.h" +#include "Demuxing/AudioInputStream.h" +#include "Demuxing/InputStream.h" +#include "Demuxing/VideoInputStream.h" +#include "ffmpeg.h" +#include "FFmpegException.h" + +#include +#include + +namespace ffmpegcpp +{ + Demuxer::Demuxer(const std::string & fileName, AVInputFormat* inputFormat, AVDictionary *format_opts) + { + this->fileName = fileName; + + // open input file, and allocate format context + auto container_ctx = containerContext.get(); + if (int ret = avformat_open_input(&container_ctx, fileName.c_str(), inputFormat, &format_opts); ret < 0) + { + throw FFmpegException("Failed to open input container " + fileName, ret); + } + + // retrieve stream information + if (int ret = avformat_find_stream_info(containerContext.get(), nullptr); ret < 0) + { + throw FFmpegException("Failed to read streams from " + fileName, ret); + } + + for (unsigned int i = 0; i < containerContext->nb_streams; ++i) + { + inputStreams.emplace_back(nullptr); + } + + // initialize packet, set data to NULL, let the demuxer fill it + pkt = av_packet_alloc(); + if (!pkt) + { + throw FFmpegException("Failed to create packet for input stream"); + } + av_init_packet(pkt.get()); + pkt->data = nullptr; + pkt->size = 0; + } + + std::vector Demuxer::GetAudioStreamInfo() const + { + return GetStreamInfo(AVMEDIA_TYPE_AUDIO); + } + + std::vector Demuxer::GetVideoStreamInfo() const + { + return GetStreamInfo(AVMEDIA_TYPE_VIDEO); + } + + std::vector Demuxer::GetStreamInfo(AVMediaType mediaType) const + { + std::vector streamInfo; + for (unsigned int i = 0; i < containerContext->nb_streams; ++i) + { + AVStream* stream = containerContext->streams[i]; + + /* find decoder for the stream */ + AVCodec* codec = CodecDeducer::DeduceDecoder(stream->codecpar->codec_id); + if (!codec) + { + throw FFmpegException("Failed to deduce codec for stream " + std::to_string(i) + " in container"); + } + + if (codec->type == mediaType) + { + streamInfo.push_back({ i, codec, stream }); + } + } + return streamInfo; + } + + void Demuxer::DecodeBestAudioStream(AudioFrameSink* frameSink) + { + int streamIndex = av_find_best_stream(containerContext.get(), AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0); + if (streamIndex < 0) + { + throw FFmpegException("Could not find " + std::string(av_get_media_type_string(AVMEDIA_TYPE_AUDIO)) + " stream in input file " + fileName, streamIndex); + } + return DecodeAudioStream(streamIndex, frameSink); + } + + void Demuxer::DecodeBestVideoStream(VideoFrameSink* frameSink) + { + int streamIndex = av_find_best_stream(containerContext.get(), AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0); + if (streamIndex < 0) + { + throw FFmpegException("Could not find " + std::string(av_get_media_type_string(AVMEDIA_TYPE_VIDEO)) + " stream in input file " + fileName, streamIndex); + } + return DecodeVideoStream(streamIndex, frameSink); + } + + void Demuxer::DecodeAudioStream(int streamIndex, AudioFrameSink* frameSink) + { + // each input stream can only be used once + if (inputStreams[streamIndex] != nullptr) + { + throw FFmpegException("That stream is already tied to a frame sink, you cannot process the same stream multiple times"); + } + + // create the stream + auto inputStream = std::make_unique(frameSink, containerContext->streams[streamIndex]); + inputStream->Open(); + inputStreams[streamIndex] = std::move(inputStream); + } + + void Demuxer::DecodeVideoStream(int streamIndex, VideoFrameSink* frameSink) + { + // each input stream can only be used once + if (inputStreams[streamIndex] != nullptr) + { + throw FFmpegException("That stream is already tied to a frame sink, you cannot process the same stream multiple times"); + } + + // create the stream + auto inputStream = std::make_unique(frameSink, containerContext->streams[streamIndex]); + inputStream->Open(); + inputStreams[streamIndex] = std::move(inputStream); + } + + void Demuxer::PreparePipeline() + { + bool allPrimed = false; + do + { + Step(); + + // see if all input streams are primed + allPrimed = std::all_of(cbegin(inputStreams), cend(inputStreams), [](const auto & stream){ + return stream->IsPrimed(); + }); + + } while (!allPrimed && !IsDone()); + } + + bool Demuxer::IsDone() const + { + return done; + } + + void Demuxer::Step() + { + // read frames from the file + int ret = av_read_frame(containerContext.get(), pkt.get()); + + // EOF + if (ret == AVERROR_EOF) + { + pkt->data = nullptr; + pkt->size = 0; + for (unsigned int i = 0; i < containerContext->nb_streams; ++i) + { + auto & stream = inputStreams[i]; + if (stream != nullptr) + { + pkt->stream_index = i; + DecodePacket(); + stream->Close(); + } + } + + done = true; + return; + } + + // not ready yet + if (ret == AVERROR(EAGAIN)) return; + + // error + if (ret < 0) + { + throw FFmpegException("Error during demuxing", ret); + } + + // decode the finished packet + DecodePacket(); + } + + void Demuxer::DecodePacket() + { + int streamIndex = pkt->stream_index; + const auto & inputStream = inputStreams[streamIndex]; + + if (inputStream != nullptr) + { + inputStream->DecodePacket(pkt.get()); + } + + // We need to unref the packet here because packets might pass by here + // that don't have a stream attached to them. We want to dismiss them! + av_packet_unref(pkt.get()); + } +} \ No newline at end of file diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/EncodedFileSource.cpp b/src/Sources/EncodedFileSource.cpp similarity index 75% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/EncodedFileSource.cpp rename to src/Sources/EncodedFileSource.cpp index 88ccd43..4142090 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/EncodedFileSource.cpp +++ b/src/Sources/EncodedFileSource.cpp @@ -1,12 +1,15 @@ -#include "EncodedFileSource.h" -#include "FFmpegException.h" +#include "Sources/EncodedFileSource.h" + #include "CodecDeducer.h" +#include "ffmpeg.h" +#include "FFmpegException.h" +#include "FrameSinks/FrameSink.h" using namespace std; namespace ffmpegcpp { - EncodedFileSource::EncodedFileSource(const char* inFileName, const char* codecName, FrameSink* output) + EncodedFileSource::EncodedFileSource(const std::string & inFileName, const std::string & codecName, FrameSink* output) { try { @@ -20,7 +23,7 @@ namespace ffmpegcpp } } - EncodedFileSource::EncodedFileSource(const char* inFileName, AVCodecID codecId, FrameSink* output) + EncodedFileSource::EncodedFileSource(const std::string & inFileName, AVCodecID codecId, FrameSink* output) { try { @@ -41,39 +44,18 @@ namespace ffmpegcpp void EncodedFileSource::CleanUp() { - if (decoded_frame != nullptr) - { - av_frame_free(&decoded_frame); - decoded_frame = nullptr; - } - if (pkt != nullptr) - { - av_packet_free(&pkt); - pkt = nullptr; - } if (buffer != nullptr) { delete buffer; buffer = nullptr; } - if (codecContext != nullptr) - { - avcodec_free_context(&codecContext); - codecContext = nullptr; - } - if (parser != nullptr) - { - av_parser_close(parser); - parser = nullptr; - } fclose(file); } - void EncodedFileSource::Init(const char* inFileName, AVCodec* codec, FrameSink* output) + void EncodedFileSource::Init(const std::string & inFileName, AVCodec* codec, FrameSink* output) { this->output = output; - this->codec = codec; parser = av_parser_init(codec->id); if (!parser) @@ -81,31 +63,31 @@ namespace ffmpegcpp throw FFmpegException("Parser for codec not found " + string(codec->name)); } - codecContext = avcodec_alloc_context3(codec); + codecContext = MakeFFmpegResource(avcodec_alloc_context3(codec)); if (!codecContext) { throw FFmpegException("Failed to allocate context for codec " + string(codec->name)); } /* open it */ - if (int ret = avcodec_open2(codecContext, codec, NULL) < 0) + if (int ret = avcodec_open2(codecContext.get(), codec, nullptr) < 0) { throw FFmpegException("Failed to open context for codec " + string(codec->name), ret); } - file = fopen(inFileName, "rb"); + file = fopen(inFileName.c_str(), "rb"); if (!file) { throw FFmpegException("Could not open file " + string(inFileName)); } - decoded_frame = av_frame_alloc(); + decoded_frame = MakeFFmpegResource(av_frame_alloc()); if (!decoded_frame) { throw FFmpegException("Could not allocate video frame"); } - pkt = av_packet_alloc(); + pkt = MakeFFmpegResource(av_packet_alloc()); if (!pkt) { throw FFmpegException("Failed to allocate packet"); @@ -142,7 +124,7 @@ namespace ffmpegcpp } } - bool EncodedFileSource::IsDone() + bool EncodedFileSource::IsDone() const { return done; } @@ -163,8 +145,8 @@ namespace ffmpegcpp data = buffer; while (data_size > 0) { - ret = av_parser_parse2(parser, codecContext, &pkt->data, &pkt->size, - data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); + ret = av_parser_parse2(parser.get(), codecContext.get(), &pkt->data, &pkt->size, + data, static_cast(data_size), AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); if (ret < 0) { throw FFmpegException("Error while parsing file", ret); @@ -174,7 +156,7 @@ namespace ffmpegcpp if (pkt->size) { - Decode(pkt, decoded_frame); + Decode(pkt.get(), decoded_frame.get()); } } @@ -183,9 +165,9 @@ namespace ffmpegcpp { /* flush the decoder */ - pkt->data = NULL; + pkt->data = nullptr; pkt->size = 0; - Decode(pkt, decoded_frame); + Decode(pkt.get(), decoded_frame.get()); output->Close(); @@ -198,7 +180,7 @@ namespace ffmpegcpp int ret; /* send the packet with the compressed data to the decoder */ - ret = avcodec_send_packet(codecContext, pkt); + ret = avcodec_send_packet(codecContext.get(), pkt); if (ret < 0) { throw FFmpegException("Error submitting the packet to the decoder", ret); @@ -207,7 +189,7 @@ namespace ffmpegcpp /* read all the output frames (in general there may be any number of them */ while (ret >= 0) { - ret = avcodec_receive_frame(codecContext, frame); + ret = avcodec_receive_frame(codecContext.get(), frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return; else if (ret < 0) diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioDataSource.cpp b/src/Sources/RawAudioDataSource.cpp similarity index 78% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioDataSource.cpp rename to src/Sources/RawAudioDataSource.cpp index 3354795..0432a4d 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawAudioDataSource.cpp +++ b/src/Sources/RawAudioDataSource.cpp @@ -1,5 +1,8 @@ -#include "RawAudioDataSource.h" +#include "Sources/RawAudioDataSource.h" + +#include "ffmpeg.h" #include "FFmpegException.h" +#include "FrameSinks/AudioFrameSink.h" namespace ffmpegcpp { @@ -16,10 +19,9 @@ namespace ffmpegcpp // create the frame int ret; - frame = av_frame_alloc(); + frame = MakeFFmpegResource(av_frame_alloc()); if (!frame) { - CleanUp(); throw FFmpegException("Could not allocate video frame"); } @@ -30,35 +32,20 @@ namespace ffmpegcpp frame->nb_samples = 735; // allocate the buffers for the frame data - ret = av_frame_get_buffer(frame, 0); + ret = av_frame_get_buffer(frame.get(), 0); if (ret < 0) { - CleanUp(); throw FFmpegException("Could not allocate the video frame data", ret); } } - RawAudioDataSource::~RawAudioDataSource() - { - CleanUp(); - } - - void RawAudioDataSource::CleanUp() - { - if (frame != nullptr) - { - av_frame_free(&frame); - frame = nullptr; - } - } - void RawAudioDataSource::WriteData(void* data, int sampleCount) { // resize the frame to the input frame->nb_samples = sampleCount; - int ret = av_frame_make_writable(frame); + int ret = av_frame_make_writable(frame.get()); if (ret < 0) { throw FFmpegException("Failed to make audio frame writable", ret); @@ -70,7 +57,7 @@ namespace ffmpegcpp // pass on to the sink // we don't have a time_base so we pass NULL and hope that it gets handled later... - output->WriteFrame(frame, NULL); + output->WriteFrame(frame.get(), nullptr); } void RawAudioDataSource::Close() @@ -78,7 +65,7 @@ namespace ffmpegcpp output->Close(); } - bool RawAudioDataSource::IsPrimed() + bool RawAudioDataSource::IsPrimed() const { return output->IsPrimed(); } diff --git a/src/Sources/RawAudioFileSource.cpp b/src/Sources/RawAudioFileSource.cpp new file mode 100644 index 0000000..b8484a4 --- /dev/null +++ b/src/Sources/RawAudioFileSource.cpp @@ -0,0 +1,53 @@ +#include "Sources/RawAudioFileSource.h" + +#include "ffmpeg.h" +#include "FFmpegException.h" +#include "Sources/Demuxer.h" + +using namespace std; + +namespace ffmpegcpp +{ + RawAudioFileSource::RawAudioFileSource(const std::string & fileName, const std::string & inputFormat, int sampleRate, int channels, AudioFrameSink* frameSink) + { + + // try to deduce the input format from the input format name + AVInputFormat *file_iformat; + if (!(file_iformat = av_find_input_format(inputFormat.c_str()))) + { + throw FFmpegException("Unknown input format: " + inputFormat); + } + + AVDictionary* format_opts = nullptr; + + av_dict_set_int(&format_opts, "sample_rate", sampleRate, 0); + av_dict_set_int(&format_opts, "channels", channels, 0); + + // create the demuxer + try + { + demuxer = std::make_unique(fileName, file_iformat, format_opts); + demuxer->DecodeBestAudioStream(frameSink); + } + catch (FFmpegException e) + { + throw e; + } + } + + void RawAudioFileSource::PreparePipeline() + { + demuxer->PreparePipeline(); + } + + bool RawAudioFileSource::IsDone() const + { + return demuxer->IsDone(); + } + + void RawAudioFileSource::Step() + { + demuxer->Step(); + } +} + diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoDataSource.cpp b/src/Sources/RawVideoDataSource.cpp similarity index 73% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoDataSource.cpp rename to src/Sources/RawVideoDataSource.cpp index ee199b6..f1d3179 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoDataSource.cpp +++ b/src/Sources/RawVideoDataSource.cpp @@ -1,5 +1,8 @@ -#include "RawVideoDataSource.h" +#include "Sources/RawVideoDataSource.h" + +#include "ffmpeg.h" #include "FFmpegException.h" +#include "FrameSinks/VideoFrameSink.h" namespace ffmpegcpp { @@ -27,10 +30,9 @@ namespace ffmpegcpp // create the frame int ret; - frame = av_frame_alloc(); + frame = MakeFFmpegResource(av_frame_alloc()); if (!frame) { - CleanUp(); throw FFmpegException("Could not allocate video frame"); } @@ -39,37 +41,17 @@ namespace ffmpegcpp frame->height = height; /* allocate the buffers for the frame data */ - ret = av_frame_get_buffer(frame, 32); + ret = av_frame_get_buffer(frame.get(), 32); if (ret < 0) { - CleanUp(); throw FFmpegException("Could not allocate the video frame data", ret); } } - RawVideoDataSource::~RawVideoDataSource() - { - CleanUp(); - } - - void RawVideoDataSource::CleanUp() - { - if (frame != nullptr) - { - av_frame_free(&frame); - frame = nullptr; - } - if (swsContext != nullptr) - { - sws_freeContext(swsContext); - swsContext = nullptr; - } - } - void RawVideoDataSource::WriteFrame(void* data, int bytesPerRow) { // make sure the frame data is writable - int ret = av_frame_make_writable(frame); + int ret = av_frame_make_writable(frame.get()); if (ret < 0) { throw FFmpegException("Error making frame writable", ret); @@ -79,15 +61,15 @@ namespace ffmpegcpp // if the source and target pixel format are the same, we don't do any conversions, we just copy // but we use sws_scale anyway because we need to convert to the internal line_size format of frame - swsContext = sws_getCachedContext(swsContext, + swsContext = sws_getCachedContext(swsContext.get(), frame->width, frame->height, sourcePixelFormat, frame->width, frame->height, (AVPixelFormat)frame->format, - 0, 0, 0, 0); - sws_scale(swsContext, (const uint8_t * const *)&data, in_linesize, 0, + 0, nullptr, nullptr, nullptr); + sws_scale(swsContext.get(), (const uint8_t * const *)&data, in_linesize, 0, frame->height, frame->data, frame->linesize); // send to the output - output->WriteFrame(frame, &this->timeBase); + output->WriteFrame(frame.get(), &this->timeBase); } void RawVideoDataSource::Close() @@ -95,17 +77,17 @@ namespace ffmpegcpp output->Close(); } - int RawVideoDataSource::GetWidth() + int RawVideoDataSource::GetWidth() const { return frame->width; } - int RawVideoDataSource::GetHeight() + int RawVideoDataSource::GetHeight() const { return frame->height; } - bool RawVideoDataSource::IsPrimed() + bool RawVideoDataSource::IsPrimed() const { return output->IsPrimed(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoFileSource.cpp b/src/Sources/RawVideoFileSource.cpp similarity index 79% rename from source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoFileSource.cpp rename to src/Sources/RawVideoFileSource.cpp index 28c0d95..47c8bac 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/Sources/RawVideoFileSource.cpp +++ b/src/Sources/RawVideoFileSource.cpp @@ -1,23 +1,21 @@ -#include "RawVideoFileSource.h" -#include "FFmpegException.h" -#include "std.h" +#include "Sources/RawVideoFileSource.h" -using namespace std; +#include "ffmpeg.h" +#include "FFmpegException.h" +#include "Sources/Demuxer.h" namespace ffmpegcpp { - RawVideoFileSource::RawVideoFileSource(const char* fileName, VideoFrameSink* frameSink) + RawVideoFileSource::RawVideoFileSource(const std::string & fileName, VideoFrameSink* frameSink) { - // create the demuxer - it can handle figuring out the video type on its own apparently try { - demuxer = new Demuxer(fileName, NULL, NULL); + demuxer = std::make_unique(fileName); demuxer->DecodeBestVideoStream(frameSink); } catch (FFmpegException e) { - CleanUp(); throw e; } } @@ -60,27 +58,12 @@ namespace ffmpegcpp } }*/ - - RawVideoFileSource::~RawVideoFileSource() - { - CleanUp(); - } - - void RawVideoFileSource::CleanUp() - { - if (demuxer != nullptr) - { - delete demuxer; - demuxer = nullptr; - } - } - void RawVideoFileSource::PreparePipeline() { demuxer->PreparePipeline(); } - bool RawVideoFileSource::IsDone() + bool RawVideoFileSource::IsDone() const { return demuxer->IsDone(); } diff --git a/source/ffmpeg-cpp/ffmpeg-cpp/VideoFormatConverter.cpp b/src/VideoFormatConverter.cpp similarity index 64% rename from source/ffmpeg-cpp/ffmpeg-cpp/VideoFormatConverter.cpp rename to src/VideoFormatConverter.cpp index 1b2b2c9..aeb722d 100644 --- a/source/ffmpeg-cpp/ffmpeg-cpp/VideoFormatConverter.cpp +++ b/src/VideoFormatConverter.cpp @@ -1,4 +1,7 @@ #include "VideoFormatConverter.h" + +#include "ConvertedAudioProcessor.h" +#include "ffmpeg.h" #include "FFmpegException.h" namespace ffmpegcpp @@ -7,11 +10,10 @@ namespace ffmpegcpp { this->codecContext = codecContext; - converted_frame = av_frame_alloc(); + converted_frame = MakeFFmpegResource(av_frame_alloc()); int ret; if (!converted_frame) { - CleanUp(); throw FFmpegException("Error allocating a video frame"); } @@ -21,40 +23,20 @@ namespace ffmpegcpp converted_frame->height = codecContext->height; /* allocate the buffers for the frame data */ - ret = av_frame_get_buffer(converted_frame, 32); + ret = av_frame_get_buffer(converted_frame.get(), 32); if (ret < 0) { - CleanUp(); throw FFmpegException("Failed to allocate buffer for frame", ret); } } - VideoFormatConverter::~VideoFormatConverter() - { - CleanUp(); - } - - void VideoFormatConverter::CleanUp() - { - if (converted_frame != nullptr) - { - av_frame_free(&converted_frame); - converted_frame = nullptr; - } - if (swsContext != nullptr) - { - sws_freeContext(swsContext); - swsContext = nullptr; - } - } - void VideoFormatConverter::InitDelayed(AVFrame* frame) { // configure the conversion context based in the source and target data - swsContext = sws_getCachedContext(swsContext, + swsContext = sws_getCachedContext(swsContext.get(), frame->width, frame->height, (AVPixelFormat)frame->format, converted_frame->width, converted_frame->height, (AVPixelFormat)converted_frame->format, - 0, 0, 0, 0); + 0, nullptr, nullptr, nullptr); } @@ -68,12 +50,12 @@ namespace ffmpegcpp } // convert the frame - sws_scale(swsContext, frame->data, frame->linesize, 0, + sws_scale(swsContext.get(), frame->data, frame->linesize, 0, frame->height, converted_frame->data, converted_frame->linesize); - av_frame_copy_props(converted_frame, frame); // remember all the other data + av_frame_copy_props(converted_frame.get(), frame); // remember all the other data - return converted_frame; + return converted_frame.get(); } }