Skip to content

Commit f9a8e38

Browse files
committed
fix: fix switch build
if the socket variant really works is questionable, but it compiles at least
1 parent d9a1fbf commit f9a8e38

File tree

2 files changed

+64
-15
lines changed

2 files changed

+64
-15
lines changed

platforms/build-3ds.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,7 @@ if [ "$COMPILE_TYPE" == "complete_rebuild" ] || [ ! -e "$BUILD_DIR" ]; then
255255
"--wipe" \
256256
--cross-file "$CROSS_FILE" \
257257
"-Dbuildtype=$BUILDTYPE" \
258-
-Ddefault_library=static \
259-
-Duse_embedded_ffmpeg=disabled
258+
-Ddefault_library=static
260259

261260
fi
262261

src/graphics/video_renderer_embedded.cpp

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,23 @@ extern "C" {
2626
#include <sys/wait.h>
2727
#include <unistd.h>
2828

29+
#if defined(__NINTENDO_CONSOLE__) && defined(__SWITCH__)
30+
#include <arpa/inet.h>
31+
#include <netinet/in.h>
32+
#include <netinet/tcp.h>
33+
#include <sys/socket.h>
34+
#include <sys/types.h>
35+
#include <unistd.h>
36+
37+
#ifndef INADDR_LOOPBACK
38+
// 127.0.0.1
39+
#define INADDR_LOOPBACK (static_cast<in_addr_t>(0x7f000001))
40+
#endif
41+
42+
#endif
43+
2944
struct Decoder {
30-
int pipe;
45+
int input_fd;
3146
std::future<std::optional<std::string>> encoding_thread;
3247
std::atomic<bool> should_cancel;
3348
};
@@ -65,7 +80,7 @@ namespace {
6580
u32 fps,
6681
shapes::UPoint size,
6782
const std::filesystem::path& destination_path,
68-
int input_fd,
83+
const std::string& input_url,
6984
const std::unique_ptr<Decoder>& decoder
7085
) {
7186

@@ -104,10 +119,8 @@ namespace {
104119
// "-r {framerate}"
105120
av_dict_set(&input_options, "framerate", framerate.c_str(), 0);
106121

107-
// see: https://ffmpeg.org/ffmpeg-protocols.html
108-
std::string input_url = fmt::format("pipe:{}", input_fd);
109122

110-
// "-i pipe:{fd}"
123+
// "-i {input_url}"
111124
auto av_input_ret = avformat_open_input(&input_format_ctx, input_url.c_str(), input_fmt, &input_options);
112125
if (av_input_ret != 0) {
113126
return fmt::format("Could not open input file stdin: {}", av_error_to_string(av_input_ret));
@@ -333,7 +346,7 @@ namespace {
333346
while (true) {
334347
// check atomic bool, if we are cancelled
335348
// NOTE: the video is garbage after this, since we don't close it correctly (which isn't the intention of this)
336-
if (decoder->should_cancel) {
349+
if (decoder && decoder->should_cancel) {
337350
return std::nullopt;
338351
}
339352

@@ -443,19 +456,38 @@ void VideoRendererBackend::is_supported_async(const std::function<void(bool)>& c
443456

444457

445458
std::optional<std::string> VideoRendererBackend::setup(u32 fps, shapes::UPoint size) {
459+
460+
// see: https://ffmpeg.org/ffmpeg-protocols.html
461+
#if defined(__NINTENDO_CONSOLE__) && defined(__SWITCH__)
462+
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
463+
if (socket_fd < 0) {
464+
return fmt::format("Could not create a UNIX socket: {}", strerror(errno));
465+
}
466+
467+
u16 port = 1045;
468+
std::string input_url = fmt::format("tcp://localhost:{}?listen=1", port);
469+
int close_fd = -1;
470+
471+
#else
446472
std::array<int, 2> pipefd = { 0, 0 };
447473

448474
if (pipe(pipefd.data()) < 0) {
449475
return fmt::format("Could not create a pipe: {}", strerror(errno));
450476
}
477+
int close_fd = pipefd[READ_END];
478+
int input_fd = pipefd[WRITE_END];
479+
std::string input_url = fmt::format("pipe:{}", close_fd);
480+
#endif
451481

452482
std::future<std::optional<std::string>> encoding_thread =
453-
std::async(std::launch::async, [pipefd, fps, size, this] -> std::optional<std::string> {
483+
std::async(std::launch::async, [close_fd, input_url, fps, size, this] -> std::optional<std::string> {
454484
utils::set_thread_name("ffmpeg encoder");
455-
auto result = start_encoding(fps, size, this->m_destination_path, pipefd[READ_END], this->m_decoder);
485+
auto result = start_encoding(fps, size, this->m_destination_path, input_url, this->m_decoder);
456486

457-
if (close(pipefd[READ_END]) < 0) {
458-
spdlog::warn("could not close read end of the pipe: {}", strerror(errno));
487+
if (close_fd >= 0) {
488+
if (close(close_fd) < 0) {
489+
spdlog::warn("could not close read end of the pipe: {}", strerror(errno));
490+
}
459491
}
460492

461493
if (result.has_value()) {
@@ -465,16 +497,34 @@ std::optional<std::string> VideoRendererBackend::setup(u32 fps, shapes::UPoint s
465497
return std::nullopt;
466498
});
467499

500+
#if defined(__NINTENDO_CONSOLE__) && defined(__SWITCH__)
501+
struct sockaddr_in addr;
502+
memset(&addr, 0, sizeof(addr));
503+
504+
addr.sin_family = AF_INET;
505+
addr.sin_port = htons(port);
506+
507+
// localhost
508+
addr.sin_addr.s_addr = INADDR_LOOPBACK;
509+
510+
int input_fd = connect(socket_fd, reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr));
511+
if (input_fd < 0) {
512+
return fmt::format("Could not connect to a TCP socket: {}", strerror(errno));
513+
}
514+
#endif
515+
516+
m_decoder = std::make_unique<Decoder>(input_fd, std::move(encoding_thread), false);
468517

469-
m_decoder = std::make_unique<Decoder>(pipefd[WRITE_END], std::move(encoding_thread), false);
470518
return std::nullopt;
471519
}
472520

473521
bool VideoRendererBackend::add_frame(SDL_Surface* surface) {
474-
if (write(m_decoder->pipe, surface->pixels, static_cast<size_t>(surface->h) * surface->pitch) < 0) {
522+
523+
if (write(m_decoder->input_fd, surface->pixels, static_cast<size_t>(surface->h) * surface->pitch) < 0) {
475524
spdlog::error("failed to write into ffmpeg pipe: {}", strerror(errno));
476525
return false;
477526
}
527+
478528
return true;
479529
}
480530

@@ -484,7 +534,7 @@ bool VideoRendererBackend::finish(bool cancel) {
484534
m_decoder->should_cancel = true;
485535
}
486536

487-
if (close(m_decoder->pipe) < 0) {
537+
if (close(m_decoder->input_fd) < 0) {
488538
spdlog::warn("could not close write end of the pipe: {}", strerror(errno));
489539
}
490540

0 commit comments

Comments
 (0)