From e3b5e92164727d8482dfef2e4034024f0f0eae49 Mon Sep 17 00:00:00 2001 From: HappyTanuki Date: Thu, 4 Sep 2025 18:03:58 +0900 Subject: [PATCH] =?UTF-8?q?ffmpeg=EC=98=88=EC=A0=9C=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=20=EC=A4=91..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 48 ++++----- .vscode/settings.json | 2 + include/core/bumblebee.h | 19 ++++ include/precomp.h | 2 + tests/ffmpeg_any_to_opus.cc | 193 ++++++++++++++++++++++++++++++++++++ 5 files changed, 240 insertions(+), 24 deletions(-) create mode 100644 include/core/bumblebee.h create mode 100644 tests/ffmpeg_any_to_opus.cc diff --git a/.vscode/launch.json b/.vscode/launch.json index 4317700..0049455 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,29 +4,29 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "name": "(gdb) Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/Debug Clang 18.1.3 x86_64-pc-linux-gnu/tests/${fileBasenameNoExtension}", - "args": [], - "stopAtEntry": false, - "cwd": "${fileDirname}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Set Disassembly Flavor to Intel", - "text": "-gdb-set disassembly-flavor intel", - "ignoreFailures": true - } - ] - } + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/Debug Clang 18.1.3 x86_64-pc-linux-gnu/tests/${fileBasenameNoExtension}", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 388d3b0..c366c4b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,8 @@ "column": 80 } ], + "editor.renderWhitespace": "boundary", + "editor.formatOnSave": true, "cmake.generator": "Ninja", "files.associations": { "cctype": "cpp", diff --git a/include/core/bumblebee.h b/include/core/bumblebee.h new file mode 100644 index 0000000..260a2bd --- /dev/null +++ b/include/core/bumblebee.h @@ -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 \ No newline at end of file diff --git a/include/precomp.h b/include/precomp.h index ba89611..e994123 100644 --- a/include/precomp.h +++ b/include/precomp.h @@ -4,6 +4,8 @@ #include #endif +#include + #include #include diff --git a/tests/ffmpeg_any_to_opus.cc b/tests/ffmpeg_any_to_opus.cc new file mode 100644 index 0000000..e91ba7b --- /dev/null +++ b/tests/ffmpeg_any_to_opus.cc @@ -0,0 +1,193 @@ +#include "precomp.h" +/* check that a given sample format is supported by the encoder */ +static int check_sample_fmt(const AVCodec *codec, + enum AVSampleFormat sample_fmt) { + const enum AVSampleFormat *p = codec->sample_fmts; + + while (*p != AV_SAMPLE_FMT_NONE) { + if (*p == sample_fmt) return 1; + p++; + } + return 0; +} + +/* just pick the highest supported samplerate */ +static int select_sample_rate(const AVCodec *codec) { + const int *p; + int best_samplerate = 0; + + if (!codec->supported_samplerates) return 44100; + + p = codec->supported_samplerates; + while (*p) { + if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate)) + best_samplerate = *p; + p++; + } + return best_samplerate; +} + +/* select layout with the highest channel count */ +static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst) { + const AVChannelLayout *p, *best_ch_layout; + int best_nb_channels = 0; + + if (!codec->ch_layouts) + return av_channel_layout_copy(dst, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); + + p = codec->ch_layouts; + while (p->nb_channels) { + int nb_channels = p->nb_channels; + + if (nb_channels > best_nb_channels) { + best_ch_layout = p; + best_nb_channels = nb_channels; + } + p++; + } + return av_channel_layout_copy(dst, best_ch_layout); +} + +static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, + FILE *output) { + int ret; + + /* send the frame for encoding */ + ret = avcodec_send_frame(ctx, frame); + if (ret < 0) { + fprintf(stderr, "Error sending the frame to the encoder\n"); + exit(1); + } + + /* read all the available output packets (in general there may be any + * number of them */ + while (ret >= 0) { + ret = avcodec_receive_packet(ctx, pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return; + else if (ret < 0) { + fprintf(stderr, "Error encoding audio frame\n"); + exit(1); + } + + fwrite(pkt->data, 1, pkt->size, output); + av_packet_unref(pkt); + } +} + +int main(int argc, char **argv) { + const char *filename; + const AVCodec *codec; + AVCodecContext *c = NULL; + AVFrame *frame; + AVPacket *pkt; + int i, j, k, ret; + FILE *f; + uint16_t *samples; + float t, tincr; + + if (argc <= 1) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 0; + } + filename = argv[1]; + + /* find the MP2 encoder */ + codec = avcodec_find_encoder(AV_CODEC_ID_MP2); + if (!codec) { + fprintf(stderr, "Codec not found\n"); + exit(1); + } + + c = avcodec_alloc_context3(codec); + if (!c) { + fprintf(stderr, "Could not allocate audio codec context\n"); + exit(1); + } + + /* put sample parameters */ + c->bit_rate = 64000; + + /* check that the encoder supports s16 pcm input */ + c->sample_fmt = AV_SAMPLE_FMT_S16; + if (!check_sample_fmt(codec, c->sample_fmt)) { + fprintf(stderr, "Encoder does not support sample format %s", + av_get_sample_fmt_name(c->sample_fmt)); + exit(1); + } + + /* select other audio parameters supported by the encoder */ + c->sample_rate = select_sample_rate(codec); + ret = select_channel_layout(codec, &c->ch_layout); + if (ret < 0) exit(1); + + /* open it */ + if (avcodec_open2(c, codec, NULL) < 0) { + fprintf(stderr, "Could not open codec\n"); + exit(1); + } + + f = fopen(filename, "wb"); + if (!f) { + fprintf(stderr, "Could not open %s\n", filename); + exit(1); + } + + /* packet for holding encoded output */ + pkt = av_packet_alloc(); + if (!pkt) { + fprintf(stderr, "could not allocate the packet\n"); + exit(1); + } + + /* frame containing input raw audio */ + frame = av_frame_alloc(); + if (!frame) { + fprintf(stderr, "Could not allocate audio frame\n"); + exit(1); + } + + frame->nb_samples = c->frame_size; + frame->format = c->sample_fmt; + ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); + if (ret < 0) exit(1); + + /* allocate the data buffers */ + ret = av_frame_get_buffer(frame, 0); + if (ret < 0) { + fprintf(stderr, "Could not allocate audio data buffers\n"); + exit(1); + } + + /* encode a single tone sound */ + t = 0; + tincr = 2 * M_PI * 440.0 / c->sample_rate; + for (i = 0; i < 200; i++) { + /* make sure the frame is writable -- makes a copy if the encoder + * kept a reference internally */ + ret = av_frame_make_writable(frame); + if (ret < 0) exit(1); + samples = (uint16_t *)frame->data[0]; + + for (j = 0; j < c->frame_size; j++) { + samples[2 * j] = (int)(sin(t) * 10000); + + for (k = 1; k < c->ch_layout.nb_channels; k++) + samples[2 * j + k] = samples[2 * j]; + t += tincr; + } + encode(c, frame, pkt, f); + } + + /* flush the encoder */ + encode(c, NULL, pkt, f); + + fclose(f); + + av_frame_free(&frame); + av_packet_free(&pkt); + avcodec_free_context(&c); + + return 0; +}