mirror of
https://github.com/HappyTanuki/BumbleCee.git
synced 2025-10-26 09:55:14 +00:00
Compare commits
5 Commits
f846dd7195
...
refactor
| Author | SHA1 | Date | |
|---|---|---|---|
| 610074e4ac | |||
| e3b5e92164 | |||
| b123b2ecdb | |||
| e26d20a869 | |||
| f3974bb86f |
8
.clang-format
Normal file
8
.clang-format
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Google C/C++ Code Style Settings
|
||||||
|
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
Standard: c++20
|
||||||
|
IndentWidth: 2
|
||||||
|
UseTab: Never
|
||||||
|
ColumnLimit: 80
|
||||||
10
.idea/.gitignore
generated
vendored
10
.idea/.gitignore
generated
vendored
@@ -1,10 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Environment-dependent path to Maven home directory
|
|
||||||
/mavenHomeManager.xml
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
9
.idea/BumbleCee.iml
generated
9
.idea/BumbleCee.iml
generated
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="JAVA_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$" />
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/BumbleCee.iml" filepath="$PROJECT_DIR$/.idea/BumbleCee.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
19
.vscode/c_cpp_properties.json
vendored
19
.vscode/c_cpp_properties.json
vendored
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Linux",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**",
|
|
||||||
"${workspaceFolder}/include"
|
|
||||||
],
|
|
||||||
"defines": [
|
|
||||||
"DDPP_CORO=on"
|
|
||||||
],
|
|
||||||
"compilerPath": "/usr/bin/gcc",
|
|
||||||
"cStandard": "c17",
|
|
||||||
"cppStandard": "c++20",
|
|
||||||
"intelliSenseMode": "linux-gcc-x64"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 4
|
|
||||||
}
|
|
||||||
13
.vscode/launch.json
vendored
13
.vscode/launch.json
vendored
@@ -1,13 +1,17 @@
|
|||||||
{
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Debug",
|
"name": "(gdb) Launch",
|
||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/build/BumbleCee",
|
"program": "${workspaceFolder}/build/Debug Clang 18.1.3 x86_64-pc-linux-gnu/tests/${fileBasenameNoExtension}",
|
||||||
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${fileDirname}",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
"MIMode": "gdb",
|
"MIMode": "gdb",
|
||||||
@@ -22,8 +26,7 @@
|
|||||||
"text": "-gdb-set disassembly-flavor intel",
|
"text": "-gdb-set disassembly-flavor intel",
|
||||||
"ignoreFailures": true
|
"ignoreFailures": true
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"preLaunchTask": "${defaultBuildTask}"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
57
.vscode/settings.json
vendored
57
.vscode/settings.json
vendored
@@ -1,9 +1,18 @@
|
|||||||
{
|
{
|
||||||
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
"editor.rulers": [
|
||||||
|
{
|
||||||
|
"column": 80
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"editor.renderWhitespace": "boundary",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"cmake.generator": "Ninja",
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"cctype": "cpp",
|
"cctype": "cpp",
|
||||||
"clocale": "cpp",
|
"clocale": "cpp",
|
||||||
"cmath": "cpp",
|
"cmath": "cpp",
|
||||||
|
"csetjmp": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
"cstdarg": "cpp",
|
"cstdarg": "cpp",
|
||||||
"cstddef": "cpp",
|
"cstddef": "cpp",
|
||||||
"cstdio": "cpp",
|
"cstdio": "cpp",
|
||||||
@@ -12,37 +21,53 @@
|
|||||||
"ctime": "cpp",
|
"ctime": "cpp",
|
||||||
"cwchar": "cpp",
|
"cwchar": "cpp",
|
||||||
"cwctype": "cpp",
|
"cwctype": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
"array": "cpp",
|
"array": "cpp",
|
||||||
"atomic": "cpp",
|
"atomic": "cpp",
|
||||||
|
"strstream": "cpp",
|
||||||
|
"barrier": "cpp",
|
||||||
"bit": "cpp",
|
"bit": "cpp",
|
||||||
"bitset": "cpp",
|
"bitset": "cpp",
|
||||||
|
"cfenv": "cpp",
|
||||||
"charconv": "cpp",
|
"charconv": "cpp",
|
||||||
"chrono": "cpp",
|
"chrono": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
"compare": "cpp",
|
"compare": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
"concepts": "cpp",
|
"concepts": "cpp",
|
||||||
"condition_variable": "cpp",
|
"condition_variable": "cpp",
|
||||||
|
"coroutine": "cpp",
|
||||||
"cstdint": "cpp",
|
"cstdint": "cpp",
|
||||||
"deque": "cpp",
|
"deque": "cpp",
|
||||||
"forward_list": "cpp",
|
"forward_list": "cpp",
|
||||||
"list": "cpp",
|
"list": "cpp",
|
||||||
"map": "cpp",
|
"map": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
"string": "cpp",
|
"string": "cpp",
|
||||||
"unordered_map": "cpp",
|
"unordered_map": "cpp",
|
||||||
|
"unordered_set": "cpp",
|
||||||
"vector": "cpp",
|
"vector": "cpp",
|
||||||
"exception": "cpp",
|
"exception": "cpp",
|
||||||
|
"expected": "cpp",
|
||||||
"algorithm": "cpp",
|
"algorithm": "cpp",
|
||||||
"functional": "cpp",
|
"functional": "cpp",
|
||||||
"iterator": "cpp",
|
"iterator": "cpp",
|
||||||
"memory": "cpp",
|
"memory": "cpp",
|
||||||
"memory_resource": "cpp",
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
"optional": "cpp",
|
"optional": "cpp",
|
||||||
"random": "cpp",
|
"random": "cpp",
|
||||||
"ratio": "cpp",
|
"ratio": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"source_location": "cpp",
|
||||||
"string_view": "cpp",
|
"string_view": "cpp",
|
||||||
"system_error": "cpp",
|
"system_error": "cpp",
|
||||||
"tuple": "cpp",
|
"tuple": "cpp",
|
||||||
"type_traits": "cpp",
|
"type_traits": "cpp",
|
||||||
"utility": "cpp",
|
"utility": "cpp",
|
||||||
|
"rope": "cpp",
|
||||||
|
"slist": "cpp",
|
||||||
"format": "cpp",
|
"format": "cpp",
|
||||||
"fstream": "cpp",
|
"fstream": "cpp",
|
||||||
"future": "cpp",
|
"future": "cpp",
|
||||||
@@ -51,20 +76,46 @@
|
|||||||
"iosfwd": "cpp",
|
"iosfwd": "cpp",
|
||||||
"iostream": "cpp",
|
"iostream": "cpp",
|
||||||
"istream": "cpp",
|
"istream": "cpp",
|
||||||
|
"latch": "cpp",
|
||||||
"limits": "cpp",
|
"limits": "cpp",
|
||||||
"mutex": "cpp",
|
"mutex": "cpp",
|
||||||
"new": "cpp",
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
"ostream": "cpp",
|
"ostream": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"scoped_allocator": "cpp",
|
||||||
"semaphore": "cpp",
|
"semaphore": "cpp",
|
||||||
"shared_mutex": "cpp",
|
"shared_mutex": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"spanstream": "cpp",
|
||||||
"sstream": "cpp",
|
"sstream": "cpp",
|
||||||
|
"stacktrace": "cpp",
|
||||||
"stdexcept": "cpp",
|
"stdexcept": "cpp",
|
||||||
|
"stdfloat": "cpp",
|
||||||
"stop_token": "cpp",
|
"stop_token": "cpp",
|
||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
|
"syncstream": "cpp",
|
||||||
"thread": "cpp",
|
"thread": "cpp",
|
||||||
|
"typeindex": "cpp",
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
"variant": "cpp",
|
"variant": "cpp",
|
||||||
"__config": "cpp",
|
"__locale": "cpp",
|
||||||
"rope": "cpp"
|
"ios": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"print": "cpp",
|
||||||
|
"__bit_reference": "cpp",
|
||||||
|
"__hash_table": "cpp",
|
||||||
|
"__node_handle": "cpp",
|
||||||
|
"__split_buffer": "cpp",
|
||||||
|
"__threading_support": "cpp",
|
||||||
|
"__verbose_abort": "cpp",
|
||||||
|
"queue": "cpp"
|
||||||
|
},
|
||||||
|
"files.exclude": {
|
||||||
|
"**/*.rpyc": true,
|
||||||
|
"**/*.rpa": true,
|
||||||
|
"**/*.rpymc": true,
|
||||||
|
"**/cache/": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
37
.vscode/tasks.json
vendored
37
.vscode/tasks.json
vendored
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"type": "cppbuild",
|
|
||||||
"label": "ninja",
|
|
||||||
"command": "ninja",
|
|
||||||
"args": [],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/build/"
|
|
||||||
},
|
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
},
|
|
||||||
"dependsOn": ["cmake"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "shell",
|
|
||||||
"label": "cmake",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"..",
|
|
||||||
"-G",
|
|
||||||
"Ninja"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/build/"
|
|
||||||
},
|
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
115
CMakeLists.txt
115
CMakeLists.txt
@@ -2,23 +2,28 @@ cmake_minimum_required (VERSION 3.16)
|
|||||||
set(BOT_NAME "BumbleCee")
|
set(BOT_NAME "BumbleCee")
|
||||||
project(${BOT_NAME} LANGUAGES CXX)
|
project(${BOT_NAME} LANGUAGES CXX)
|
||||||
|
|
||||||
set(CMAKE_BUILD_TYPE Debug)
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
set(BOOST_EXCLUDE_LIBRARIES nowide)
|
set(BOOST_EXCLUDE_LIBRARIES nowide)
|
||||||
|
set(BUILD_TESTING ON)
|
||||||
|
|
||||||
|
set(DPP_BUILD_TEST OFF)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(OPENSSL_ROOT_DIR "C:/Program Files/OpenSSL-Win64")
|
set(OPENSSL_ROOT_DIR "C:/Program Files/OpenSSL-Win64")
|
||||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
|
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||||
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MDd/libcrypto.lib")
|
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MTd/libcrypto.lib")
|
||||||
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MDd/libssl.lib")
|
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MTd/libssl.lib")
|
||||||
else()
|
else()
|
||||||
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MD/libcrypto.lib")
|
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MT/libcrypto.lib")
|
||||||
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MD/libssl.lib")
|
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MT/libssl.lib")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -26,14 +31,15 @@ find_package(OpenSSL REQUIRED)
|
|||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS})
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
Boost
|
Boost
|
||||||
URL "https://github.com/boostorg/boost/releases/download/boost-1.89.0/boost-1.89.0-cmake.7z"
|
URL "https://github.com/boostorg/boost/releases/download/boost-1.89.0/boost-1.89.0-cmake.7z"
|
||||||
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||||
CMAKE_ARGS
|
EXCLUDE_FROM_ALL
|
||||||
-DBOOST_USE_STATIC_LIBS=OFF # DLL 사용
|
|
||||||
-DBOOST_USE_STATIC_RUNTIME=OFF # /MD, /MDd 사용
|
|
||||||
)
|
)
|
||||||
|
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Do not build SHARED libraries" FORCE)
|
||||||
message(STATUS "Fetching and making available Boost...")
|
message(STATUS "Fetching and making available Boost...")
|
||||||
FetchContent_MakeAvailable(Boost)
|
FetchContent_MakeAvailable(Boost)
|
||||||
|
|
||||||
@@ -42,23 +48,23 @@ FetchContent_Declare(
|
|||||||
GIT_REPOSITORY "https://github.com/brainboxdotcc/DPP.git"
|
GIT_REPOSITORY "https://github.com/brainboxdotcc/DPP.git"
|
||||||
GIT_TAG "v10.1.3"
|
GIT_TAG "v10.1.3"
|
||||||
GIT_SHALLOW ON
|
GIT_SHALLOW ON
|
||||||
CMAKE_ARGS -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON
|
|
||||||
)
|
)
|
||||||
|
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build SHARED libraries" FORCE)
|
||||||
message(STATUS "Fetching and making available dpp...")
|
message(STATUS "Fetching and making available dpp...")
|
||||||
FetchContent_MakeAvailable(dpp)
|
FetchContent_MakeAvailable(dpp)
|
||||||
|
|
||||||
|
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD} CACHE BOOL "Type of libraries to build" FORCE)
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
# 플랫폼별 FFmpeg 바이너리 다운로드 및 링크
|
# 플랫폼별 FFmpeg 바이너리 다운로드 및 링크
|
||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||||
set(FFMPEG_URL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-lgpl-shared.zip")
|
set(FFMPEG_URL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-lgpl-shared.zip")
|
||||||
set(FFMPEG_SHA256HASH "SHA256=c95a9d4e030f694f33c85a7611204383a0bca906514a08d83d3858496b122f76")
|
|
||||||
set(FFMPEG_ARCHIVE_NAME "ffmpeg-windows")
|
set(FFMPEG_ARCHIVE_NAME "ffmpeg-windows")
|
||||||
set(FFMPEG_LIB_DIR "lib")
|
set(FFMPEG_LIB_DIR "lib")
|
||||||
set(FFMPEG_INCLUDE_DIR "include")
|
set(FFMPEG_INCLUDE_DIR "include")
|
||||||
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||||
set(FFMPEG_URL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-lgpl-shared.tar.xz")
|
set(FFMPEG_URL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-lgpl-shared.tar.xz")
|
||||||
set(FFMPEG_SHA256HASH "SHA256=ebf6b197ffe52d798504895b4c2b84114ad5d2b406ac76e18374b44d1184ade3")
|
|
||||||
set(FFMPEG_ARCHIVE_NAME "ffmpeg-linux")
|
set(FFMPEG_ARCHIVE_NAME "ffmpeg-linux")
|
||||||
set(FFMPEG_LIB_DIR "lib")
|
set(FFMPEG_LIB_DIR "lib")
|
||||||
set(FFMPEG_INCLUDE_DIR "include")
|
set(FFMPEG_INCLUDE_DIR "include")
|
||||||
@@ -69,7 +75,6 @@ endif()
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
ffmpeg
|
ffmpeg
|
||||||
URL ${FFMPEG_URL}
|
URL ${FFMPEG_URL}
|
||||||
URL_HASH ${FFMPEG_SHA256HASH}
|
|
||||||
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||||
SOURCE_DIR ${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}
|
SOURCE_DIR ${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}
|
||||||
)
|
)
|
||||||
@@ -87,41 +92,42 @@ find_library(AVUTIL_LIBRARY NAMES avutil PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT
|
|||||||
message(STATUS "AVUTIL_LIBRARY = ${AVUTIL_LIBRARY}")
|
message(STATUS "AVUTIL_LIBRARY = ${AVUTIL_LIBRARY}")
|
||||||
find_library(SWSCALE_LIBRARY NAMES swscale PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT_PATH)
|
find_library(SWSCALE_LIBRARY NAMES swscale PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT_PATH)
|
||||||
message(STATUS "SWSCALE_LIBRARY = ${SWSCALE_LIBRARY}")
|
message(STATUS "SWSCALE_LIBRARY = ${SWSCALE_LIBRARY}")
|
||||||
|
find_library(SWRESAMPLE_LIBRARY NAMES swresample PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT_PATH)
|
||||||
|
message(STATUS "SWRESAMPLE_LIBRARY = ${SWRESAMPLE_LIBRARY}")
|
||||||
|
|
||||||
if(NOT AVCODEC_LIBRARY OR NOT AVFORMAT_LIBRARY OR NOT AVUTIL_LIBRARY)
|
if(NOT AVCODEC_LIBRARY OR NOT AVFORMAT_LIBRARY OR NOT AVUTIL_LIBRARY OR NOT SWRESAMPLE_LIBRARY)
|
||||||
message(FATAL_ERROR "FFmpeg 라이브러리를 찾을 수 없습니다. 다운로드 경로를 확인해주세요.")
|
message(FATAL_ERROR "FFmpeg 라이브러리를 찾을 수 없습니다. 다운로드 경로를 확인해주세요.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB_RECURSE CORES "src/*.cpp" "src/*.cxx" "src/*.cc")
|
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.cxx" "src/*.cc")
|
||||||
|
|
||||||
set(ALL_SOURCE_FILES
|
add_library(${BOT_NAME}_lib ${SOURCES})
|
||||||
${CORES}
|
|
||||||
${AUDIO_SOURCES}
|
|
||||||
${COMMANDS_SOURCES}
|
|
||||||
${QUEUE_SOURCES}
|
|
||||||
${SETTINGS_SOURCES}
|
|
||||||
${UTILS_SOURCES}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(${BOT_NAME} ${ALL_SOURCE_FILES})
|
target_include_directories(${BOT_NAME}_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE dpp)
|
target_include_directories(${BOT_NAME}_lib PUBLIC ${OpenSSL_INCLUDE_DIRS})
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE Boost::filesystem)
|
target_include_directories(${BOT_NAME}_lib PUBLIC ${FFMPEG_INCLUDE_PATH})
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE Boost::process)
|
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE Boost::log)
|
target_precompile_headers(${BOT_NAME}_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/precomp.h")
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE Boost::beast)
|
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE OpenSSL::Crypto)
|
target_link_libraries(${BOT_NAME}_lib PUBLIC dpp)
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE OpenSSL::SSL)
|
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::filesystem)
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE ${AVUTIL_LIBRARY})
|
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::process)
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE ${AVCODEC_LIBRARY})
|
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::log)
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE ${AVFORMAT_LIBRARY})
|
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::beast)
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE ${SWSCALE_LIBRARY})
|
target_link_libraries(${BOT_NAME}_lib PUBLIC OpenSSL::Crypto)
|
||||||
|
target_link_libraries(${BOT_NAME}_lib PUBLIC OpenSSL::SSL)
|
||||||
|
target_link_libraries(${BOT_NAME}_lib PUBLIC ${AVUTIL_LIBRARY})
|
||||||
|
target_link_libraries(${BOT_NAME}_lib PUBLIC ${AVCODEC_LIBRARY})
|
||||||
|
target_link_libraries(${BOT_NAME}_lib PUBLIC ${AVFORMAT_LIBRARY})
|
||||||
|
target_link_libraries(${BOT_NAME}_lib PUBLIC ${SWSCALE_LIBRARY})
|
||||||
|
target_link_libraries(${BOT_NAME}_lib PUBLIC ${SWRESAMPLE_LIBRARY})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(${BOT_NAME} PRIVATE ws2_32)
|
target_link_libraries(${BOT_NAME}_lib PUBLIC ws2_32)
|
||||||
endif()
|
endif()
|
||||||
if(UNIX AND NOT APPLE AND CMAKE_BUILD_TYPE STREQUAL "Release")
|
if(UNIX AND NOT APPLE)
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${BOT_NAME}_lib PROPERTIES
|
||||||
BUILD_WITH_INSTALL_RPATH TRUE
|
BUILD_WITH_INSTALL_RPATH TRUE
|
||||||
INSTALL_RPATH "$ORIGIN"
|
INSTALL_RPATH "$ORIGIN"
|
||||||
SKIP_BUILD_RPATH FALSE
|
SKIP_BUILD_RPATH FALSE
|
||||||
@@ -129,30 +135,29 @@ if(UNIX AND NOT APPLE AND CMAKE_BUILD_TYPE STREQUAL "Release")
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(${BOT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
add_executable(${BOT_NAME} ${SOURCES})
|
||||||
|
|
||||||
target_include_directories(${BOT_NAME} PRIVATE ${OpenSSL_INCLUDE_DIRS})
|
target_link_libraries(${BOT_NAME} PUBLIC ${BOT_NAME}_lib)
|
||||||
target_include_directories(${BOT_NAME} PRIVATE ${FFMPEG_INCLUDE_PATH})
|
|
||||||
|
|
||||||
target_precompile_headers(${BOT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/precomp.h")
|
file(GLOB FFMPEG_SHARED
|
||||||
|
"${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}/bin/*.dll" # Windows
|
||||||
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
|
"${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}/lib/*.so*" # Linux
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
||||||
"$<TARGET_FILE_DIR:Boost::filesystem>"
|
|
||||||
"$<TARGET_FILE_DIR:${BOT_NAME}>"
|
|
||||||
COMMENT "Copying Boost.Filesystem DLL/so files to output directory"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
|
foreach(ffmpeg_shared ${FFMPEG_SHARED})
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
|
||||||
"$<TARGET_FILE_DIR:Boost::process>"
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${ffmpeg_shared}"
|
||||||
"$<TARGET_FILE_DIR:${BOT_NAME}>"
|
"$<TARGET_FILE_DIR:${BOT_NAME}>"
|
||||||
COMMENT "Copying Boost.Process DLL/so files to output directory"
|
COMMENT "Copying ${ffmpeg_shared} to output directory"
|
||||||
)
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
|
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
"${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}/bin"
|
"$<TARGET_FILE:dpp>"
|
||||||
"$<TARGET_FILE_DIR:${BOT_NAME}>"
|
"$<TARGET_FILE_DIR:${BOT_NAME}>"
|
||||||
COMMENT "Copying FFMpeg_AVCODEC DLL/so files to output directory"
|
COMMENT "Copying dpp DLL/so files to output directory"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_subdirectory(tests)
|
||||||
19
include/core/bumblebee.h
Normal file
19
include/core/bumblebee.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef BUMBLEBEE_INCLUDE_CORE_BUMBLEBEE_H_
|
||||||
|
#define BUMBLEBEE_INCLUDE_CORE_BUMBLEBEE_H_
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
namespace bumblebee {
|
||||||
|
|
||||||
|
class BumbleBee {
|
||||||
|
public:
|
||||||
|
BumbleBee();
|
||||||
|
~BumbleBee();
|
||||||
|
|
||||||
|
private:
|
||||||
|
dpp::cluster cluster;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace bumblebee
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <dpp/dpp.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
@@ -14,6 +16,7 @@
|
|||||||
#include "boost/process.hpp"
|
#include "boost/process.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#include "libavcodec/avcodec.h"
|
||||||
#include "libavformat/avformat.h"
|
#include "libavformat/avformat.h"
|
||||||
#include "libavutil/avutil.h"
|
#include "libavutil/avutil.h"
|
||||||
#include "libswresample/swresample.h"
|
#include "libswresample/swresample.h"
|
||||||
|
|||||||
@@ -7,32 +7,35 @@ namespace utils {
|
|||||||
// @brief 명령어가 실행 가능한지 체크합니다
|
// @brief 명령어가 실행 가능한지 체크합니다
|
||||||
// @param cmd 실행할 명령
|
// @param cmd 실행할 명령
|
||||||
// @return int error_code
|
// @return int error_code
|
||||||
int ValidateCommand(std::string cmd);
|
int ValidateCommand(
|
||||||
|
boost::asio::io_context& ctx, std::string cmd,
|
||||||
|
const std::vector<std::string>& args = std::vector<std::string>());
|
||||||
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
|
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
|
||||||
// @param cmd 실행할 명령
|
// @param cmd 실행할 명령
|
||||||
// @param args 아규먼트
|
// @param args 아규먼트
|
||||||
// @return int error_code
|
// @return int error_code
|
||||||
int ExecuteCommand(
|
int ExecuteCommand(
|
||||||
const std::string& cmd,
|
boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
const std::vector<std::string>& args = std::vector<std::string>());
|
const std::vector<std::string>& args = std::vector<std::string>());
|
||||||
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
|
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
|
||||||
// @param cmd 실행할 명령
|
// @param cmd 실행할 명령
|
||||||
// @param result 실행결과
|
// @param result 실행결과
|
||||||
// @return int error_code
|
// @return int error_code
|
||||||
int ExecuteCommand(const std::string& cmd, std::string& result);
|
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
|
std::string& result);
|
||||||
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
|
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
|
||||||
// @param cmd 실행할 명령
|
// @param cmd 실행할 명령
|
||||||
// @param args 아규먼트
|
// @param args 아규먼트
|
||||||
// @param result 실행결과
|
// @param result 실행결과
|
||||||
// @return int error_code
|
// @return int error_code
|
||||||
int ExecuteCommand(const std::string& cmd, const std::vector<std::string>& args,
|
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
std::string& result);
|
const std::vector<std::string>& args, std::string& result);
|
||||||
// @brief 명령어를 쉘에서 실행하고 결과를 파이프로 연결하여 반환합니다
|
// @brief 명령어를 쉘에서 실행하고 결과를 파이프로 연결하여 반환합니다
|
||||||
// @param cmd 실행할 명령
|
// @param cmd 실행할 명령
|
||||||
// @param args 아규먼트
|
// @param args 아규먼트
|
||||||
// @return boost::process::popen
|
// @return boost::process::popen
|
||||||
boost::process::popen OpenPipe(
|
boost::process::popen OpenPipe(
|
||||||
const std::string& cmd,
|
boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
const std::vector<std::string>& args = std::vector<std::string>());
|
const std::vector<std::string>& args = std::vector<std::string>());
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
#endif
|
#endif
|
||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
int InstallYtdlp();
|
int InstallYtdlp(boost::asio::io_context& ctx);
|
||||||
|
|
||||||
int CheckUpdate();
|
int CheckUpdate(boost::asio::io_context& ctx);
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
|
|||||||
29
src/main.cc
29
src/main.cc
@@ -3,33 +3,8 @@
|
|||||||
#include "utils/update_checker.h"
|
#include "utils/update_checker.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
boost::system::error_code ec;
|
boost::asio::io_context ctx;
|
||||||
char buf[16384];
|
utils::CheckUpdate(ctx);
|
||||||
std::string output;
|
|
||||||
|
|
||||||
utils::CheckUpdate();
|
|
||||||
|
|
||||||
// utils::ExecuteCommand("yt-dlp", {"-U"}, output);
|
|
||||||
// std::cout << output;
|
|
||||||
|
|
||||||
// auto ytdlp_pipe = utils::OpenPipe(
|
|
||||||
// "yt-dlp", {"-o", "-", "--quiet", "--ignore-errors", "-f", "bestaudio",
|
|
||||||
// "https://youtu.be/9_bTl2vvYQg?si=IVhvpDhnpPvziwQR"});
|
|
||||||
|
|
||||||
// while (true) {
|
|
||||||
// boost::system::error_code read_ec;
|
|
||||||
// size_t bytes_read =
|
|
||||||
// boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf, 16384),
|
|
||||||
// read_ec);
|
|
||||||
|
|
||||||
// if (bytes_read > 0) {
|
|
||||||
// std::cout.write(buf, bytes_read);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (read_ec == boost::asio::error::eof || read_ec) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4,50 +4,50 @@
|
|||||||
|
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
int ValidateCommand(std::string cmd) {
|
int ValidateCommand(boost::asio::io_context& ctx, std::string cmd,
|
||||||
|
const std::vector<std::string>& args) {
|
||||||
try {
|
try {
|
||||||
ExecuteCommand(cmd);
|
ExecuteCommand(ctx, cmd, args);
|
||||||
} catch (const boost::process::system_error& e) {
|
} catch (const boost::process::system_error& e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExecuteCommand(const std::string& cmd,
|
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
const std::vector<std::string>& args) {
|
const std::vector<std::string>& args) {
|
||||||
std::string ignored;
|
std::string ignored;
|
||||||
return ExecuteCommand(cmd, args, ignored);
|
return ExecuteCommand(ctx, cmd, args, ignored);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExecuteCommand(const std::string& cmd, std::string& result) {
|
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
std::vector<std::string> ignored;
|
|
||||||
return ExecuteCommand(cmd, ignored, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExecuteCommand(const std::string& cmd, const std::vector<std::string>& args,
|
|
||||||
std::string& result) {
|
std::string& result) {
|
||||||
|
std::vector<std::string> ignored;
|
||||||
|
return ExecuteCommand(ctx, cmd, ignored, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
|
||||||
|
const std::vector<std::string>& args, std::string& result) {
|
||||||
|
try {
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
boost::asio::io_context ctx;
|
|
||||||
boost::process::popen proc(
|
boost::process::popen proc(
|
||||||
ctx, cmd, args, boost::process::process_stdio{{}, nullptr, nullptr});
|
ctx, cmd, args, boost::process::process_stdio{{}, nullptr, nullptr});
|
||||||
|
|
||||||
boost::asio::read(proc, boost::asio::dynamic_buffer(result), ec);
|
boost::asio::read(proc, boost::asio::dynamic_buffer(result), ec);
|
||||||
|
|
||||||
if (ec != boost::asio::error::eof) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
proc.wait();
|
proc.wait();
|
||||||
|
|
||||||
return proc.exit_code();
|
return proc.exit_code();
|
||||||
|
} catch (const boost::process::system_error& e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::process::popen OpenPipe(const std::string& cmd,
|
boost::process::popen OpenPipe(boost::asio::io_context& ctx,
|
||||||
|
const std::string& cmd,
|
||||||
const std::vector<std::string>& args) {
|
const std::vector<std::string>& args) {
|
||||||
boost::asio::io_context ctx;
|
return boost::process::popen(
|
||||||
boost::process::popen proc(
|
ctx, cmd, args, boost::process::process_stdio{nullptr, nullptr, nullptr});
|
||||||
ctx, cmd, args, boost::process::process_stdio{{}, nullptr, nullptr});
|
|
||||||
return proc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
@@ -55,8 +55,18 @@ void DownloadFileFromHTTPS(std::string url, std::string filename) {
|
|||||||
boost::beast::http::write(stream, req);
|
boost::beast::http::write(stream, req);
|
||||||
|
|
||||||
boost::beast::flat_buffer buffer;
|
boost::beast::flat_buffer buffer;
|
||||||
boost::beast::http::response<boost::beast::http::dynamic_body> res;
|
|
||||||
boost::beast::http::read(stream, buffer, res);
|
// 응답 파서 만들기
|
||||||
|
boost::beast::http::response_parser<boost::beast::http::dynamic_body>
|
||||||
|
parser;
|
||||||
|
|
||||||
|
// body 제한 해제 (무제한)
|
||||||
|
parser.body_limit((std::numeric_limits<std::uint64_t>::max)());
|
||||||
|
|
||||||
|
// 응답 읽기
|
||||||
|
boost::beast::http::read(stream, buffer, parser);
|
||||||
|
|
||||||
|
auto res = parser.release();
|
||||||
|
|
||||||
int status = res.result_int();
|
int status = res.result_int();
|
||||||
if (status / 100 == 3) {
|
if (status / 100 == 3) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
int InstallYtdlp() {
|
int InstallYtdlp(boost::asio::io_context& ctx) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << "ytdlp is unavailable. downloading ytdlp...";
|
BOOST_LOG_TRIVIAL(warning) << "ytdlp is unavailable. downloading ytdlp...";
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
DownloadFileFromHTTPS(
|
DownloadFileFromHTTPS(
|
||||||
@@ -16,34 +16,54 @@ int InstallYtdlp() {
|
|||||||
DownloadFileFromHTTPS(
|
DownloadFileFromHTTPS(
|
||||||
"https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp",
|
"https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp",
|
||||||
"yt-dlp");
|
"yt-dlp");
|
||||||
ExecuteCommand(boost::process::environment::find_executable("chmod").c_str(),
|
ExecuteCommand(ctx,
|
||||||
|
boost::process::environment::find_executable("chmod").string(),
|
||||||
{"+x", "yt-dlp"});
|
{"+x", "yt-dlp"});
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CheckUpdate() {
|
static int FindNewLinePos(std::string& string, int start_pos) {
|
||||||
char buf[16384];
|
int newline_pos = start_pos;
|
||||||
|
while (newline_pos < string.size()) {
|
||||||
if (ValidateCommand("yt-dlp") != 0) {
|
if (string[newline_pos] == '\n') {
|
||||||
InstallYtdlp();
|
return newline_pos;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
newline_pos++;
|
||||||
auto ytdlp_pipe = utils::OpenPipe("yt-dlp", {"-U"});
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
boost::system::error_code read_ec;
|
|
||||||
size_t bytes_read =
|
|
||||||
boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf, 16384), read_ec);
|
|
||||||
|
|
||||||
if (bytes_read > 0) {
|
|
||||||
BOOST_LOG_TRIVIAL(info) << buf;
|
|
||||||
}
|
}
|
||||||
|
return newline_pos;
|
||||||
|
}
|
||||||
|
|
||||||
if (read_ec == boost::asio::error::eof || read_ec) {
|
int CheckUpdate(boost::asio::io_context& ctx) {
|
||||||
break;
|
std::string output = "";
|
||||||
|
int old_newline_pos = 0;
|
||||||
|
int newline_pos = 0;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
if (ExecuteCommand(ctx, "yt-dlp.exe", {"--version", "--newline"}, output) !=
|
||||||
|
0) {
|
||||||
|
InstallYtdlp(ctx);
|
||||||
|
ExecuteCommand(ctx, "yt-dlp.exe", {"--version", "--newline"}, output);
|
||||||
}
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "yt-dlp version: "
|
||||||
|
<< output.substr(0, output.size() - 1);
|
||||||
|
output = "";
|
||||||
|
ExecuteCommand(ctx, "yt-dlp.exe", {"-U", "--newline"}, output);
|
||||||
|
#else
|
||||||
|
if (ExecuteCommand(ctx, "yt-dlp", {"--version", "--newline"}, output) != 0) {
|
||||||
|
InstallYtdlp(ctx);
|
||||||
|
ExecuteCommand(ctx, "yt-dlp", {"--version", "--newline"}, output);
|
||||||
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "yt-dlp version: "
|
||||||
|
<< output.substr(0, output.size() - 1);
|
||||||
|
output = "";
|
||||||
|
ExecuteCommand(ctx, "yt-dlp", {"-U", "--newline"}, output);
|
||||||
|
#endif
|
||||||
|
while (newline_pos < output.size()) {
|
||||||
|
old_newline_pos = newline_pos;
|
||||||
|
newline_pos = FindNewLinePos(output, newline_pos);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << output.substr(old_newline_pos, newline_pos - 1);
|
||||||
|
newline_pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
8
tests/CMakeLists.txt
Normal file
8
tests/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
file(GLOB_RECURSE TEST_SOURCES "*.cpp" "*.cxx" "*.cc")
|
||||||
|
|
||||||
|
foreach(test_src ${TEST_SOURCES})
|
||||||
|
get_filename_component(test_name ${test_src} NAME_WE)
|
||||||
|
add_executable(${test_name} ${test_src})
|
||||||
|
target_link_libraries(${test_name} PRIVATE ${BOT_NAME}_lib)
|
||||||
|
add_test(NAME ${test_name} COMMAND ${test_name})
|
||||||
|
endforeach()
|
||||||
52
tests/basic_yt_dlp_download.cc
Normal file
52
tests/basic_yt_dlp_download.cc
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "precomp.h"
|
||||||
|
#include "utils/console.h"
|
||||||
|
#include "utils/update_checker.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
boost::asio::io_context ctx;
|
||||||
|
boost::system::error_code ec;
|
||||||
|
|
||||||
|
// utils::CheckUpdate(ctx);
|
||||||
|
|
||||||
|
char buf[8192];
|
||||||
|
#ifdef WIN32
|
||||||
|
/*try {
|
||||||
|
auto ytdlp_pipe = utils::OpenPipe(ctx,
|
||||||
|
"yt-dlp.exe", { "-o", "-", "--quiet", "--ignore-errors", "-f",
|
||||||
|
"bestaudio", "https://youtu.be/9_bTl2vvYQg?si=IVhvpDhnpPvziwQR" });
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
boost::system::error_code read_ec;
|
||||||
|
size_t bytes_read =
|
||||||
|
boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf,
|
||||||
|
8192), read_ec); if (bytes_read > 0) { std::cout.write(buf, bytes_read);
|
||||||
|
}
|
||||||
|
if (read_ec == boost::asio::error::eof || read_ec) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const boost::process::system_error& e) {
|
||||||
|
std::string error = e.what();
|
||||||
|
return -1;
|
||||||
|
}*/
|
||||||
|
#else
|
||||||
|
auto ytdlp_pipe = utils::OpenPipe(
|
||||||
|
ctx, "yt-dlp",
|
||||||
|
{"-o", "-", "--quiet", "--ignore-errors", "-f", "bestaudio",
|
||||||
|
"https://youtu.be/9_bTl2vvYQg?si=IVhvpDhnpPvziwQR"});
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
boost::system::error_code read_ec;
|
||||||
|
size_t bytes_read =
|
||||||
|
boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf, 8192), read_ec);
|
||||||
|
if (bytes_read > 0) {
|
||||||
|
std::cout.write(buf, bytes_read);
|
||||||
|
}
|
||||||
|
if (read_ec == boost::asio::error::eof || read_ec) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
232
tests/ffmpeg_any_to_opus.cc
Normal file
232
tests/ffmpeg_any_to_opus.cc
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
#define OPUS_FRAME_SIZE 960 // 20ms @ 48kHz
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
const char* input_filename = "golden.webm";
|
||||||
|
const char* output_filename = "output.opus";
|
||||||
|
|
||||||
|
AVFormatContext* fmt_ctx = NULL;
|
||||||
|
AVCodecContext* dec_ctx = NULL;
|
||||||
|
AVCodecContext* enc_ctx = NULL;
|
||||||
|
const AVCodec* decoder = NULL;
|
||||||
|
const AVCodec* encoder = NULL;
|
||||||
|
AVPacket* packet = NULL;
|
||||||
|
AVFrame* frame = NULL;
|
||||||
|
AVFrame* enc_frame = NULL;
|
||||||
|
SwrContext* swr_ctx = NULL;
|
||||||
|
FILE* outfile = NULL;
|
||||||
|
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
|
||||||
|
if (avformat_open_input(&fmt_ctx, input_filename, NULL, NULL) < 0) {
|
||||||
|
fprintf(stderr, "Could not open input file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
|
||||||
|
fprintf(stderr, "Could not find stream info\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stream_index = -1;
|
||||||
|
for (unsigned i = 0; i < fmt_ctx->nb_streams; i++) {
|
||||||
|
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
|
stream_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stream_index == -1) {
|
||||||
|
fprintf(stderr, "No audio stream found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder =
|
||||||
|
avcodec_find_decoder(fmt_ctx->streams[stream_index]->codecpar->codec_id);
|
||||||
|
if (!decoder) {
|
||||||
|
fprintf(stderr, "Decoder not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dec_ctx = avcodec_alloc_context3(decoder);
|
||||||
|
avcodec_parameters_to_context(dec_ctx,
|
||||||
|
fmt_ctx->streams[stream_index]->codecpar);
|
||||||
|
avcodec_open2(dec_ctx, decoder, NULL);
|
||||||
|
|
||||||
|
encoder = avcodec_find_encoder(AV_CODEC_ID_OPUS);
|
||||||
|
if (!encoder) {
|
||||||
|
fprintf(stderr, "Opus encoder not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
enc_ctx = avcodec_alloc_context3(encoder);
|
||||||
|
|
||||||
|
AVChannelLayout enc_layout;
|
||||||
|
av_channel_layout_default(&enc_layout, 2); // 스테레오
|
||||||
|
av_channel_layout_copy(&enc_ctx->ch_layout, &enc_layout);
|
||||||
|
|
||||||
|
enc_ctx->sample_rate = 48000;
|
||||||
|
enc_ctx->sample_fmt = AV_SAMPLE_FMT_FLT;
|
||||||
|
enc_ctx->bit_rate = 128000;
|
||||||
|
|
||||||
|
avcodec_open2(enc_ctx, encoder, NULL);
|
||||||
|
|
||||||
|
swr_ctx = NULL;
|
||||||
|
if (swr_alloc_set_opts2(&swr_ctx, &enc_ctx->ch_layout, enc_ctx->sample_fmt,
|
||||||
|
enc_ctx->sample_rate, &dec_ctx->ch_layout,
|
||||||
|
dec_ctx->sample_fmt, dec_ctx->sample_rate, 0,
|
||||||
|
NULL) < 0) {
|
||||||
|
fprintf(stderr, "Failed to allocate SwrContext\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
swr_init(swr_ctx);
|
||||||
|
|
||||||
|
packet = av_packet_alloc();
|
||||||
|
frame = av_frame_alloc();
|
||||||
|
enc_frame = av_frame_alloc();
|
||||||
|
|
||||||
|
outfile = fopen(output_filename, "wb");
|
||||||
|
if (!outfile) {
|
||||||
|
fprintf(stderr, "Could not open output file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 임시 PCM 버퍼 (float, 스테레오)
|
||||||
|
float* pcm_buffer = (float*)malloc(sizeof(float) * 2 * OPUS_FRAME_SIZE *
|
||||||
|
4); // 충분히 큰 버퍼
|
||||||
|
int buffered_samples = 0;
|
||||||
|
|
||||||
|
while (av_read_frame(fmt_ctx, packet) >= 0) {
|
||||||
|
if (packet->stream_index != stream_index) {
|
||||||
|
av_packet_unref(packet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
avcodec_send_packet(dec_ctx, packet);
|
||||||
|
while (avcodec_receive_frame(dec_ctx, frame) == 0) {
|
||||||
|
int max_out = av_rescale_rnd(
|
||||||
|
swr_get_delay(swr_ctx, dec_ctx->sample_rate) + frame->nb_samples,
|
||||||
|
enc_ctx->sample_rate, dec_ctx->sample_rate, AV_ROUND_UP);
|
||||||
|
|
||||||
|
uint8_t** out_data = NULL;
|
||||||
|
int out_linesize = 0;
|
||||||
|
av_samples_alloc_array_and_samples(&out_data, &out_linesize, 2, max_out,
|
||||||
|
enc_ctx->sample_fmt, 0);
|
||||||
|
|
||||||
|
int converted =
|
||||||
|
swr_convert(swr_ctx, out_data, max_out, (const uint8_t**)frame->data,
|
||||||
|
frame->nb_samples);
|
||||||
|
|
||||||
|
// float PCM으로 임시 버퍼에 추가
|
||||||
|
memcpy(pcm_buffer + buffered_samples * 2, out_data[0],
|
||||||
|
converted * 2 * sizeof(float));
|
||||||
|
buffered_samples += converted;
|
||||||
|
|
||||||
|
av_freep(&out_data[0]);
|
||||||
|
free(out_data);
|
||||||
|
|
||||||
|
// OPUS_FRAME_SIZE 단위로 인코딩
|
||||||
|
while (buffered_samples >= OPUS_FRAME_SIZE) {
|
||||||
|
enc_frame->nb_samples = OPUS_FRAME_SIZE;
|
||||||
|
enc_frame->format = enc_ctx->sample_fmt;
|
||||||
|
enc_frame->sample_rate = enc_ctx->sample_rate;
|
||||||
|
av_channel_layout_copy(&enc_frame->ch_layout, &enc_ctx->ch_layout);
|
||||||
|
enc_frame->data[0] = (uint8_t*)pcm_buffer;
|
||||||
|
|
||||||
|
AVPacket* out_pkt = av_packet_alloc();
|
||||||
|
avcodec_send_frame(enc_ctx, enc_frame);
|
||||||
|
while (avcodec_receive_packet(enc_ctx, out_pkt) == 0) {
|
||||||
|
fwrite(out_pkt->data, 1, out_pkt->size, outfile);
|
||||||
|
av_packet_unref(out_pkt);
|
||||||
|
}
|
||||||
|
av_packet_free(&out_pkt);
|
||||||
|
|
||||||
|
// 버퍼 이동
|
||||||
|
memmove(pcm_buffer, pcm_buffer + OPUS_FRAME_SIZE * 2,
|
||||||
|
(buffered_samples - OPUS_FRAME_SIZE) * 2 * sizeof(float));
|
||||||
|
buffered_samples -= OPUS_FRAME_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av_packet_unref(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 디코더 플러시
|
||||||
|
avcodec_send_packet(dec_ctx, NULL);
|
||||||
|
while (avcodec_receive_frame(dec_ctx, frame) == 0) {
|
||||||
|
int max_out = av_rescale_rnd(
|
||||||
|
swr_get_delay(swr_ctx, dec_ctx->sample_rate) + frame->nb_samples,
|
||||||
|
enc_ctx->sample_rate, dec_ctx->sample_rate, AV_ROUND_UP);
|
||||||
|
|
||||||
|
uint8_t** out_data = NULL;
|
||||||
|
int out_linesize = 0;
|
||||||
|
av_samples_alloc_array_and_samples(&out_data, &out_linesize, 2, max_out,
|
||||||
|
enc_ctx->sample_fmt, 0);
|
||||||
|
|
||||||
|
int converted =
|
||||||
|
swr_convert(swr_ctx, out_data, max_out, (const uint8_t**)frame->data,
|
||||||
|
frame->nb_samples);
|
||||||
|
|
||||||
|
memcpy(pcm_buffer + buffered_samples * 2, out_data[0],
|
||||||
|
converted * 2 * sizeof(float));
|
||||||
|
buffered_samples += converted;
|
||||||
|
|
||||||
|
av_freep(&out_data[0]);
|
||||||
|
free(out_data);
|
||||||
|
|
||||||
|
while (buffered_samples >= OPUS_FRAME_SIZE) {
|
||||||
|
enc_frame->nb_samples = OPUS_FRAME_SIZE;
|
||||||
|
enc_frame->format = enc_ctx->sample_fmt;
|
||||||
|
enc_frame->sample_rate = enc_ctx->sample_rate;
|
||||||
|
av_channel_layout_copy(&enc_frame->ch_layout, &enc_ctx->ch_layout);
|
||||||
|
enc_frame->data[0] = (uint8_t*)pcm_buffer;
|
||||||
|
|
||||||
|
AVPacket* out_pkt = av_packet_alloc();
|
||||||
|
avcodec_send_frame(enc_ctx, enc_frame);
|
||||||
|
while (avcodec_receive_packet(enc_ctx, out_pkt) == 0) {
|
||||||
|
fwrite(out_pkt->data, 1, out_pkt->size, outfile);
|
||||||
|
av_packet_unref(out_pkt);
|
||||||
|
}
|
||||||
|
av_packet_free(&out_pkt);
|
||||||
|
|
||||||
|
memmove(pcm_buffer, pcm_buffer + OPUS_FRAME_SIZE * 2,
|
||||||
|
(buffered_samples - OPUS_FRAME_SIZE) * 2 * sizeof(float));
|
||||||
|
buffered_samples -= OPUS_FRAME_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 마지막 남은 샘플 인코딩
|
||||||
|
if (buffered_samples > 0) {
|
||||||
|
enc_frame->nb_samples = buffered_samples;
|
||||||
|
enc_frame->format = enc_ctx->sample_fmt;
|
||||||
|
enc_frame->sample_rate = enc_ctx->sample_rate;
|
||||||
|
av_channel_layout_copy(&enc_frame->ch_layout, &enc_ctx->ch_layout);
|
||||||
|
enc_frame->data[0] = (uint8_t*)pcm_buffer;
|
||||||
|
|
||||||
|
AVPacket* out_pkt = av_packet_alloc();
|
||||||
|
avcodec_send_frame(enc_ctx, enc_frame);
|
||||||
|
while (avcodec_receive_packet(enc_ctx, out_pkt) == 0) {
|
||||||
|
fwrite(out_pkt->data, 1, out_pkt->size, outfile);
|
||||||
|
av_packet_unref(out_pkt);
|
||||||
|
}
|
||||||
|
av_packet_free(&out_pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 인코더 플러시
|
||||||
|
avcodec_send_frame(enc_ctx, NULL);
|
||||||
|
AVPacket* out_pkt = av_packet_alloc();
|
||||||
|
while (avcodec_receive_packet(enc_ctx, out_pkt) == 0) {
|
||||||
|
fwrite(out_pkt->data, 1, out_pkt->size, outfile);
|
||||||
|
av_packet_unref(out_pkt);
|
||||||
|
}
|
||||||
|
av_packet_free(&out_pkt);
|
||||||
|
|
||||||
|
fclose(outfile);
|
||||||
|
free(pcm_buffer);
|
||||||
|
swr_free(&swr_ctx);
|
||||||
|
av_frame_free(&frame);
|
||||||
|
av_frame_free(&enc_frame);
|
||||||
|
av_packet_free(&packet);
|
||||||
|
avcodec_free_context(&dec_ctx);
|
||||||
|
avcodec_free_context(&enc_ctx);
|
||||||
|
avformat_close_input(&fmt_ctx);
|
||||||
|
|
||||||
|
printf("Encoding finished: %s\n", output_filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
155
tests/ffmpeg_decode_audio.cc
Normal file
155
tests/ffmpeg_decode_audio.cc
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "ffmpeg/libavcodec.h"
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
const char* input_filename = "golden.webm";
|
||||||
|
const char* output_filename = "output.pcm";
|
||||||
|
|
||||||
|
AVFormatContext* fmt_ctx = NULL;
|
||||||
|
AVCodecContext* codec_ctx = NULL;
|
||||||
|
const AVCodec* codec = NULL;
|
||||||
|
AVPacket* packet = NULL;
|
||||||
|
AVFrame* frame = NULL;
|
||||||
|
SwrContext* swr_ctx = NULL;
|
||||||
|
FILE* outfile = NULL;
|
||||||
|
|
||||||
|
if (avformat_open_input(&fmt_ctx, input_filename, NULL, NULL) < 0) {
|
||||||
|
fprintf(stderr, "Could not open input file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
|
||||||
|
fprintf(stderr, "Could not find stream info\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stream_index = -1;
|
||||||
|
for (unsigned i = 0; i < fmt_ctx->nb_streams; i++) {
|
||||||
|
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
|
stream_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stream_index == -1) {
|
||||||
|
fprintf(stderr, "Could not find audio stream\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
codec =
|
||||||
|
avcodec_find_decoder(fmt_ctx->streams[stream_index]->codecpar->codec_id);
|
||||||
|
if (!codec) {
|
||||||
|
fprintf(stderr, "Could not find decoder\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
codec_ctx = avcodec_alloc_context3(codec);
|
||||||
|
if (!codec_ctx) {
|
||||||
|
fprintf(stderr, "Could not allocate codec context\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avcodec_parameters_to_context(
|
||||||
|
codec_ctx, fmt_ctx->streams[stream_index]->codecpar) < 0) {
|
||||||
|
fprintf(stderr, "Failed to copy codec parameters\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
|
||||||
|
fprintf(stderr, "Could not open codec\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet = av_packet_alloc();
|
||||||
|
frame = av_frame_alloc();
|
||||||
|
if (!packet || !frame) {
|
||||||
|
fprintf(stderr, "Could not allocate packet or frame\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
outfile = fopen(output_filename, "wb");
|
||||||
|
if (!outfile) {
|
||||||
|
fprintf(stderr, "Could not open output file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AVChannelLayout 초기화
|
||||||
|
AVChannelLayout in_layout, out_layout;
|
||||||
|
if (av_channel_layout_copy(&in_layout, &codec_ctx->ch_layout) < 0) {
|
||||||
|
fprintf(stderr, "Failed to copy channel layout\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
av_channel_layout_default(&out_layout, 2); // 스테레오
|
||||||
|
|
||||||
|
swr_ctx = NULL; // 먼저 NULL로 선언
|
||||||
|
if (swr_alloc_set_opts2(&swr_ctx, &out_layout, AV_SAMPLE_FMT_S16, 48000,
|
||||||
|
&in_layout, codec_ctx->sample_fmt,
|
||||||
|
codec_ctx->sample_rate, 0, NULL) < 0) {
|
||||||
|
fprintf(stderr, "Failed to allocate and set SwrContext\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swr_init(swr_ctx) < 0) {
|
||||||
|
fprintf(stderr, "Failed to initialize SwrContext\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (av_read_frame(fmt_ctx, packet) >= 0) {
|
||||||
|
if (packet->stream_index == stream_index) {
|
||||||
|
if (avcodec_send_packet(codec_ctx, packet) == 0) {
|
||||||
|
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
|
||||||
|
int out_samples =
|
||||||
|
av_rescale_rnd(swr_get_delay(swr_ctx, codec_ctx->sample_rate) +
|
||||||
|
frame->nb_samples,
|
||||||
|
48000, codec_ctx->sample_rate, AV_ROUND_UP);
|
||||||
|
|
||||||
|
uint8_t** out_buf = NULL;
|
||||||
|
int out_linesize = 0;
|
||||||
|
av_samples_alloc_array_and_samples(&out_buf, &out_linesize, 2,
|
||||||
|
out_samples, AV_SAMPLE_FMT_S16, 0);
|
||||||
|
|
||||||
|
int converted_samples =
|
||||||
|
swr_convert(swr_ctx, out_buf, out_samples,
|
||||||
|
(const uint8_t**)frame->data, frame->nb_samples);
|
||||||
|
|
||||||
|
fwrite(out_buf[0], 1, converted_samples * 2 * 2, outfile);
|
||||||
|
av_freep(&out_buf[0]);
|
||||||
|
free(out_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av_packet_unref(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 디코더 플러시
|
||||||
|
avcodec_send_packet(codec_ctx, NULL);
|
||||||
|
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
|
||||||
|
int out_samples = av_rescale_rnd(
|
||||||
|
swr_get_delay(swr_ctx, codec_ctx->sample_rate) + frame->nb_samples,
|
||||||
|
48000, codec_ctx->sample_rate, AV_ROUND_UP);
|
||||||
|
|
||||||
|
uint8_t** out_buf = NULL;
|
||||||
|
int out_linesize = 0;
|
||||||
|
av_samples_alloc_array_and_samples(&out_buf, &out_linesize, 2, out_samples,
|
||||||
|
AV_SAMPLE_FMT_S16, 0);
|
||||||
|
|
||||||
|
int converted_samples =
|
||||||
|
swr_convert(swr_ctx, out_buf, out_samples, (const uint8_t**)frame->data,
|
||||||
|
frame->nb_samples);
|
||||||
|
|
||||||
|
fwrite(out_buf[0], 1, converted_samples * 2 * 2, outfile);
|
||||||
|
av_freep(&out_buf[0]);
|
||||||
|
free(out_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(outfile);
|
||||||
|
swr_free(&swr_ctx);
|
||||||
|
av_frame_free(&frame);
|
||||||
|
av_packet_free(&packet);
|
||||||
|
avcodec_free_context(&codec_ctx);
|
||||||
|
avformat_close_input(&fmt_ctx);
|
||||||
|
|
||||||
|
printf("Decoding finished, output saved to %s\n", output_filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8
tests/update.cc
Normal file
8
tests/update.cc
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "precomp.h"
|
||||||
|
#include "utils/update_checker.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
boost::asio::io_context ctx;
|
||||||
|
utils::CheckUpdate(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user