diff --git a/CMakeLists.txt b/CMakeLists.txt index a727c89..12bb5f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.21) project(ffmini VERSION 0.0.1) set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Group CMake targets inside a folder set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Generate compile_commands.json for language servers +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(FetchContent) FetchContent_Declare( @@ -24,6 +25,8 @@ FetchContent_Declare( list(APPEND FETCH_CONTENTS miniaudio) FetchContent_MakeAvailable(${FETCH_CONTENTS}) +find_package(FFmpeg REQUIRED) + # Group dependencies in Visual Studio and Xcode if (CMAKE_GENERATOR MATCHES "Visual Studio" OR CMAKE_GENERATOR MATCHES "Xcode") set_target_properties(fmt PROPERTIES FOLDER deps) @@ -94,7 +97,7 @@ add_executable(ffmini ${HEADER_FILES} ${SOURCE_FILES}) target_include_directories(ffmini PRIVATE ${PROJECT_SOURCE_DIR} - ${PROJECT_SOURCE_DIR}/dsp + ${FFMPEG_INCLUDE_DIR} ) target_compile_definitions(ffmini PRIVATE ${BASE_DEFINITIONS}) target_compile_features(ffmini PRIVATE cxx_std_20) @@ -103,6 +106,19 @@ target_link_libraries(ffmini PRIVATE asio::asio fmt + miniaudio::miniaudio + ${FFMPEG_AVCODEC_LIBRARY} + ${FFMPEG_AVDEVICE_LIBRARY} + ${FFMPEG_AVFILTER_LIBRARY} + ${FFMPEG_AVFORMAT_LIBRARY} + ${FFMPEG_AVUTIL_LIBRARY} ) source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${SOURCE_FILES}) +#add_custom_command( +# TARGET ffmini # Change this to your actual target name +# POST_BUILD +# COMMAND ${CMAKE_COMMAND} -E copy_directory +# ${FFMPEG_AVCODEC_LIBRARY} +# $ # Copy to the output directory of MyExecutable +#) diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake index 8b13789..a3b5481 100644 --- a/cmake/FindFFmpeg.cmake +++ b/cmake/FindFFmpeg.cmake @@ -1 +1,70 @@ +find_path(FFMPEG_INCLUDE_DIR + NAMES + libavcodec + libavdevice + libavfilter + libavformat + libavutil + libpostproc + libswresample + libswscale +) + +find_library(FFMPEG_AVCODEC_LIBRARY avcodec) +find_library(FFMPEG_AVDEVICE_LIBRARY avdevice) +find_library(FFMPEG_AVFILTER_LIBRARY avfilter) +find_library(FFMPEG_AVFORMAT_LIBRARY avformat) +find_library(FFMPEG_AVUTIL_LIBRARY avutil) +find_library(FFMPEG_POSTPROC_LIBRARY postproc) +find_library(FFMPEG_SWRESAMPLE_LIBRARY swresample) +find_library(FFMPEG_SWSCALE_LIBRARY swscale) + +#find_library(FFMPEG_AVCODEC_LIBRARY NAMES "avcodec.lib" "libavcodec.a") +#find_library(FFMPEG_AVDEVICE_LIBRARY NAMES "avdevice.lib" "libavdevice.a") +#find_library(FFMPEG_AVFILTER_LIBRARY NAMES "avfilter.lib" "libavfilter.a") +#find_library(FFMPEG_AVFORMAT_LIBRARY NAMES "avformat.lib" "libavformat.a") +#find_library(FFMPEG_AVUTIL_LIBRARY NAMES "avutil.lib" "libavutil.a") +#find_library(FFMPEG_POSTPROC_LIBRARY NAMES "postproc.lib" "libpostproc.a") +#find_library(FFMPEG_SWRESAMPLE_LIBRARY NAMES "swresample.lib" "libswresample.a") +#find_library(FFMPEG_SWSCALE_LIBRARY NAMES "swscale.lib" "libswscale.a") + +if (FFMPEG_INCLUDE_DIR AND + FFMPEG_AVCODEC_LIBRARY AND + FFMPEG_AVDEVICE_LIBRARY AND + FFMPEG_AVFILTER_LIBRARY AND + FFMPEG_AVFORMAT_LIBRARY AND + FFMPEG_AVUTIL_LIBRARY AND + FFMPEG_POSTPROC_LIBRARY AND + FFMPEG_SWRESAMPLE_LIBRARY AND + FFMPEG_SWSCALE_LIBRARY) + set(FFMPEG_FOUND TRUE) +else() + set(FFMPEG_FOUND FALSE) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(FFmpeg + REQUIRED_VARS + FFMPEG_INCLUDE_DIR + FFMPEG_AVCODEC_LIBRARY + FFMPEG_AVDEVICE_LIBRARY + FFMPEG_AVFILTER_LIBRARY + FFMPEG_AVFORMAT_LIBRARY + FFMPEG_AVUTIL_LIBRARY + FFMPEG_POSTPROC_LIBRARY + FFMPEG_SWRESAMPLE_LIBRARY + FFMPEG_SWSCALE_LIBRARY +) + +mark_as_advanced( + FFMPEG_INCLUDE_DIR + FFMPEG_AVCODEC_LIBRARY + FFMPEG_AVDEVICE_LIBRARY + FFMPEG_AVFILTER_LIBRARY + FFMPEG_AVFORMAT_LIBRARY + FFMPEG_AVUTIL_LIBRARY + FFMPEG_POSTPROC_LIBRARY + FFMPEG_SWRESAMPLE_LIBRARY + FFMPEG_SWSCALE_LIBRARY +) diff --git a/ffmini.cpp b/ffmini.cpp index 14592b9..1374fee 100644 --- a/ffmini.cpp +++ b/ffmini.cpp @@ -1,7 +1,70 @@ #include "fmt/format.h" +#include "miniaudio.h" + +extern "C" { +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +#include "libavcodec/avcodec.h" +} + +auto callback([[maybe_unused]]ma_device* device, [[maybe_unused]]void* output, [[maybe_unused]]void const* input, [[maybe_unused]]ma_uint32 frame_count) -> void { +} auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int { - fmt::print("Hello, World!\n"); + AVFormatContext* format_context = avformat_alloc_context(); + if (!format_context) { + fmt::print(stderr, "Failed to create AVFormatContext\n"); + return 1; + } + + auto const filename = "C:/Users/miku/Downloads/Porter Robinson - Trying to Feel Alive (Official Audio).webm"; + if (avformat_open_input(&format_context, filename, nullptr, nullptr) != 0) { + fmt::print(stderr, "Failed to open file {}\n", filename); + return 1; + } + + if (avformat_find_stream_info(format_context, nullptr) < 0) { + fmt::print(stderr, "Error loading stream info\n"); + return 1; + } + + std::int64_t stream_index = -1; + AVCodec const* codec = nullptr; + for (std::uint32_t i = 0; i < format_context->nb_streams; ++i) { + auto* params = format_context->streams[i]->codecpar; + codec = avcodec_find_decoder(params->codec_id); + if (!codec) continue; + if (params->codec_type == AVMEDIA_TYPE_AUDIO) { + stream_index = static_cast(i); + } + } + + if (stream_index == -1) { + fmt::print(stderr, "Couldn't find valid audio track inside file: {}\n", filename); + return 1; + } + + ma_device device; + auto device_config = ma_device_config_init(ma_device_type_playback); + device_config.playback.format = ma_format_f32; + device_config.playback.channels = 2; + device_config.sampleRate = 48000; + device_config.dataCallback = callback; + device_config.pUserData = nullptr; + + if (ma_device_init(nullptr, &device_config, &device) != MA_SUCCESS) { + fmt::print(stderr, "Failed to open playback device\n"); + return 1; + } + + if (ma_device_start(&device) != MA_SUCCESS) { + fmt::print(stderr, "Failed to start playback device.\n"); + return 1; + } + + ma_device_uninit(&device); + avformat_close_input(&format_context); + avformat_free_context(format_context); return 0; }