Compare commits

..

5 Commits

Author SHA1 Message Date
09c8bbfcc6 video src now picks the best <=1080p mode
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Has been cancelled
ContinuousDelivery / windows (push) Has been cancelled
ContinuousDelivery / windows-asan (push) Has been cancelled
ContinuousIntegration / linux (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
2024-10-03 16:42:07 +02:00
14a726ad75 move DVT conversion to connection
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run
2024-10-03 16:05:21 +02:00
7cb4f67f96 use sdl yuv to yuv conversion, and better fallbacks
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run
display intended main screen intervals
actually report min interval in debug view and more
2024-10-03 12:33:52 +02:00
a290bec8f1 add experimental NV12 to IYUV conversion routine
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run
2024-10-02 23:35:33 +02:00
2554229211 sdl camera input source
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run
2024-10-02 18:51:35 +02:00
10 changed files with 288 additions and 149 deletions

View File

@ -116,7 +116,8 @@ target_sources(tomato PUBLIC
./frame_streams/sdl/sdl_audio2_frame_stream2.cpp
./frame_streams/sdl/video.hpp
./frame_streams/sdl/video_push_converter.hpp
./frame_streams/sdl/video_push_converter.cpp
./frame_streams/sdl/sdl_video_frame_stream2.hpp
./frame_streams/sdl/sdl_video_frame_stream2.cpp
./stream_manager_ui.hpp
./stream_manager_ui.cpp

View File

@ -297,7 +297,10 @@ float ChatGui4::render(float time_delta) {
acceptable_sessions.push_back(o);
}
static Components::VoIP::DefaultConfig g_default_connections{};
static Components::VoIP::DefaultConfig g_default_connections{
true, true,
true, false
};
if (ImGui::BeginMenu("default connections")) {
ImGui::MenuItem("incoming audio", nullptr, &g_default_connections.incoming_audio);

View File

@ -10,6 +10,8 @@
#include "./frame_streams/sdl/video.hpp"
#include "./frame_streams/frame_stream2.hpp"
#include "./frame_streams/locked_frame_stream.hpp"
#include "./frame_streams/sdl/video_push_converter.hpp"
#include <string>
#include <memory>
@ -27,40 +29,6 @@ namespace Message {
uint64_t getTimeMS(void);
}
// threadsafe queue frame stream
// protected by a simple mutex lock
template<typename FrameType>
struct LockedFrameStream2 : public FrameStream2I<FrameType> {
std::mutex _lock;
std::deque<FrameType> _frames;
~LockedFrameStream2(void) {}
int32_t size(void) { return -1; }
std::optional<FrameType> pop(void) {
std::lock_guard lg{_lock};
if (_frames.empty()) {
return std::nullopt;
}
FrameType new_frame = std::move(_frames.front());
_frames.pop_front();
return std::move(new_frame);
}
bool push(const FrameType& value) {
std::lock_guard lg{_lock};
_frames.push_back(value);
return true;
}
};
struct DebugVideoTapSink : public FrameStream2SinkI<SDLVideoFrame> {
TextureUploaderI& _tu;
@ -80,7 +48,7 @@ struct DebugVideoTapSink : public FrameStream2SinkI<SDLVideoFrame> {
float _v_interval_avg {0.f}; // s
} view;
std::shared_ptr<LockedFrameStream2<SDLVideoFrame>> stream;
std::shared_ptr<PushConversionVideoStream<LockedFrameStream2<SDLVideoFrame>>> stream;
};
std::vector<Writer> _writers;
@ -91,7 +59,7 @@ struct DebugVideoTapSink : public FrameStream2SinkI<SDLVideoFrame> {
std::shared_ptr<FrameStream2I<SDLVideoFrame>> subscribe(void) override {
_writers.emplace_back(Writer{
Writer::View{_id_counter++},
std::make_shared<LockedFrameStream2<SDLVideoFrame>>()
std::make_shared<PushConversionVideoStream<LockedFrameStream2<SDLVideoFrame>>>(SDL_PIXELFORMAT_RGBA32)
});
return _writers.back().stream;
@ -127,7 +95,7 @@ struct DebugVideoTestSource : public FrameStream2SourceI<SDLVideoFrame> {
_thread = std::thread([this](void) {
while (!_stop) {
if (!_readers.empty()) {
auto* surf = SDL_CreateSurface(960, 720, SDL_PIXELFORMAT_ARGB32);
auto* surf = SDL_CreateSurface(960, 720, SDL_PIXELFORMAT_RGBA32);
// color
static auto start_time = Message::getTimeMS();
@ -220,7 +188,7 @@ float DebugVideoTap::render(void) {
for (auto& [view, stream] : dvtsw) {
std::string window_title {"DebugVideoTap #"};
window_title += std::to_string(view._id);
ImGui::SetNextWindowSize({250, 250}, ImGuiCond_Appearing);
ImGui::SetNextWindowSize({400, 420}, ImGuiCond_Appearing);
if (ImGui::Begin(window_title.c_str())) {
while (auto new_frame_opt = stream->pop()) {
// timing
@ -233,7 +201,7 @@ float DebugVideoTap::render(void) {
if (view._v_interval_avg == 0) {
view._v_interval_avg = delta/1'000'000.f;
} else {
const float r = 0.2f;
const float r = 0.05f;
view._v_interval_avg = view._v_interval_avg * (1.f-r) + (delta/1'000'000.f) * r;
}
}
@ -277,7 +245,7 @@ float DebugVideoTap::render(void) {
// img here
if (view._tex != 0) {
ImGui::SameLine();
ImGui::Text("moving avg interval: %f", view._v_interval_avg);
ImGui::Text("%dx%d ~avg interval: %.0fms (%.2ffps)", view._tex_w, view._tex_h, view._v_interval_avg*1000.f, 1.f/view._v_interval_avg);
const float img_w = ImGui::GetContentRegionAvail().x;
ImGui::Image(
reinterpret_cast<ImTextureID>(view._tex),
@ -287,6 +255,9 @@ float DebugVideoTap::render(void) {
);
}
if (view._v_interval_avg > 0) {
min_interval = std::min(min_interval, view._v_interval_avg);
}
}
ImGui::End();
}

View File

@ -0,0 +1,187 @@
#include "./sdl_video_frame_stream2.hpp"
#include <chrono>
#include <iostream>
SDLVideo2InputDevice::SDLVideo2InputDevice(void) {
int devcount {0};
SDL_CameraID *devices = SDL_GetCameras(&devcount);
std::cout << "SDLVID: SDL Camera Driver: " << SDL_GetCurrentCameraDriver() << "\n";
if (devices == nullptr || devcount < 1) {
throw int(2); // TODO: proper error code
}
std::cout << "SDLVID: found cameras:\n";
for (int i = 0; i < devcount; i++) {
const SDL_CameraID device = devices[i];
const char *name = SDL_GetCameraName(device);
std::cout << " - Camera #" << i << ": " << name << "\n";
int speccount {0};
SDL_CameraSpec** specs = SDL_GetCameraSupportedFormats(device, &speccount);
if (specs == nullptr) {
std::cout << " - no supported spec\n";
} else {
for (int spec_i = 0; spec_i < speccount; spec_i++) {
std::cout << " - " << specs[spec_i]->width << "x" << specs[spec_i]->height << "@" << float(specs[spec_i]->framerate_numerator)/specs[spec_i]->framerate_denominator << "fps " << SDL_GetPixelFormatName(specs[spec_i]->format) << "\n";
}
SDL_free(specs);
}
}
SDL_free(devices);
}
SDLVideo2InputDevice::~SDLVideo2InputDevice(void) {
}
std::shared_ptr<FrameStream2I<SDLVideoFrame>> SDLVideo2InputDevice::subscribe(void) {
const int prev_ref = _ref++;
if (prev_ref == 0) {
// there was previously no stream, we assume no thread
// open device here? or on the thread?
int devcount {0};
SDL_CameraID *devices = SDL_GetCameras(&devcount);
if (devices == nullptr || devcount < 1) {
_ref--;
// error/no devices, should we do this in the constructor?
SDL_free(devices);
return nullptr;
}
auto device = devices[0];
//auto device = devices[devcount-1];
SDL_CameraSpec spec {
// FORCE a different pixel format
SDL_PIXELFORMAT_UNKNOWN,
//SDL_PIXELFORMAT_YUY2,
SDL_COLORSPACE_UNKNOWN,
//SDL_COLORSPACE_YUV_DEFAULT,
1280, 720,
60, 1
};
// choose a good spec, large res but <= 1080p
int speccount {0};
SDL_CameraSpec** specs = SDL_GetCameraSupportedFormats(device, &speccount);
if (specs != nullptr) {
spec = *specs[0];
for (int spec_i = 1; spec_i < speccount; spec_i++) {
if (specs[spec_i]->height > 1080) {
continue;
}
if (spec.height > specs[spec_i]->height) {
continue;
}
if (
float(spec.framerate_numerator)/float(spec.framerate_denominator)
>
float(specs[spec_i]->framerate_numerator)/float(specs[spec_i]->framerate_denominator)
) {
continue;
}
if (spec.format == SDL_PIXELFORMAT_NV12 && specs[spec_i]->format == SDL_PIXELFORMAT_YUY2) {
// HACK: prefer nv12 over yuy2
continue;
}
// seems to be better
spec = *specs[spec_i];
}
SDL_free(specs);
}
std::unique_ptr<SDL_Camera, decltype(&SDL_CloseCamera)> camera {nullptr, &SDL_CloseCamera};
camera = {
//SDL_OpenCamera(device, nullptr),
SDL_OpenCamera(device, &spec),
&SDL_CloseCamera
};
SDL_free(devices);
if (!camera) {
std::cerr << "SDLVID error: failed opening camera device\n";
_ref--;
return nullptr;
}
// seems like we need this before get format() ?
// TODO: best would be waiting in thread, but that obv does not work well
// TODO: sometimes if the device is/was in use it will stay 0 for ever
while (SDL_GetCameraPermissionState(camera.get()) == 0) {
//std::cerr << "permission for camera not granted\n";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
if (SDL_GetCameraPermissionState(camera.get()) <= 0) {
std::cerr << "SDLVID error: user denied camera permission\n";
_ref--;
return nullptr;
}
float fps {1.f};
if (!SDL_GetCameraFormat(camera.get(), &spec)) {
// meh
_ref--;
return nullptr;
} else {
fps = float(spec.framerate_numerator)/float(spec.framerate_denominator);
std::cout << "SDLVID: camera fps: " << fps << "fps (" << spec.framerate_numerator << "/" << spec.framerate_denominator << ")\n";
auto* format_name = SDL_GetPixelFormatName(spec.format);
std::cout << "SDLVID: camera format: " << format_name << "\n";
}
_thread = std::thread([this, camera = std::move(camera), fps](void) {
while (_ref > 0) {
Uint64 timestampNS = 0;
// aquire frame
SDL_Surface* sdl_frame_next = SDL_AcquireCameraFrame(camera.get(), &timestampNS);
if (sdl_frame_next != nullptr) {
SDLVideoFrame new_frame_non_owning {
timestampNS/1000,
sdl_frame_next
};
// creates surface copies
push(new_frame_non_owning);
SDL_ReleaseCameraFrame(camera.get(), sdl_frame_next);
}
// sleep for interval
// TODO: do we really need half?
std::this_thread::sleep_for(std::chrono::milliseconds(int64_t((1000/fps)*0.5)));
}
// camera destructor closes device here
});
std::cout << "SDLVID: started new cam thread\n";
}
return FrameStream2MultiSource<SDLVideoFrame>::subscribe();
}
bool SDLVideo2InputDevice::unsubscribe(const std::shared_ptr<FrameStream2I<SDLVideoFrame>>& sub) {
if (FrameStream2MultiSource<SDLVideoFrame>::unsubscribe(sub)) {
if (--_ref == 0) {
// was last stream, close device and thread
_thread.join(); // TODO: defer to destructor or new thread?
// this might take a moment and lock up the main thread
std::cout << "SDLVID: ended cam thread\n";
}
return true;
}
return false;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "./video.hpp"
#include "../frame_stream2.hpp"
#include "../multi_source.hpp"
#include <atomic>
#include <thread>
// tips: you can force a SDL vido driver by setting an env:
// SDL_CAMERA_DRIVER=v4l2
// SDL_CAMERA_DRIVER=pipewire
// etc.
// while a stream is subscribed, have the camera device open
// and aquire and push frames from a thread
struct SDLVideo2InputDevice : public FrameStream2MultiSource<SDLVideoFrame> {
std::atomic_uint _ref {0};
std::thread _thread;
// TODO: device id
SDLVideo2InputDevice(void);
virtual ~SDLVideo2InputDevice(void);
// we hook int multi source
std::shared_ptr<FrameStream2I<SDLVideoFrame>> subscribe(void) override;
bool unsubscribe(const std::shared_ptr<FrameStream2I<SDLVideoFrame>>& sub) override;
};

View File

@ -1,58 +0,0 @@
#include "./video_push_converter.hpp"
SDL_Surface* convertYUY2_IYUV(SDL_Surface* surf) {
if (surf->format != SDL_PIXELFORMAT_YUY2) {
return nullptr;
}
if ((surf->w % 2) != 0) {
SDL_SetError("YUY2->IYUV does not support odd widths");
// hmmm, we dont handle odd widths
return nullptr;
}
SDL_LockSurface(surf);
SDL_Surface* conv_surf = SDL_CreateSurface(surf->w, surf->h, SDL_PIXELFORMAT_IYUV);
SDL_LockSurface(conv_surf);
// YUY2 is 4:2:2 packed
// Y is simple, we just copy it over
// U V are double the resolution (vertically), so we avg both
// Packed mode: Y0+U0+Y1+V0 (1 plane)
uint8_t* y_plane = static_cast<uint8_t*>(conv_surf->pixels);
uint8_t* u_plane = static_cast<uint8_t*>(conv_surf->pixels) + conv_surf->w*conv_surf->h;
uint8_t* v_plane = static_cast<uint8_t*>(conv_surf->pixels) + conv_surf->w*conv_surf->h + (conv_surf->w/2)*(conv_surf->h/2);
const uint8_t* yuy2_data = static_cast<const uint8_t*>(surf->pixels);
for (int y = 0; y < surf->h; y++) {
for (int x = 0; x < surf->w; x += 2) {
// every pixel uses 2 bytes
const uint8_t* yuy2_curser = yuy2_data + y*surf->w*2 + x*2;
uint8_t src_y0 = yuy2_curser[0];
uint8_t src_u = yuy2_curser[1];
uint8_t src_y1 = yuy2_curser[2];
uint8_t src_v = yuy2_curser[3];
y_plane[y*conv_surf->w + x] = src_y0;
y_plane[y*conv_surf->w + x+1] = src_y1;
size_t uv_index = (y/2) * (conv_surf->w/2) + x/2;
if (y % 2 == 0) {
// first write
u_plane[uv_index] = src_u;
v_plane[uv_index] = src_v;
} else {
// second write, mix with existing value
u_plane[uv_index] = (int(u_plane[uv_index]) + int(src_u)) / 2;
v_plane[uv_index] = (int(v_plane[uv_index]) + int(src_v)) / 2;
}
}
}
SDL_UnlockSurface(conv_surf);
SDL_UnlockSurface(surf);
return conv_surf;
}

View File

@ -7,24 +7,10 @@
#include <iostream> // meh
static bool isFormatYUV(SDL_PixelFormat f) {
return
f == SDL_PIXELFORMAT_YV12 ||
f == SDL_PIXELFORMAT_IYUV ||
f == SDL_PIXELFORMAT_YUY2 ||
f == SDL_PIXELFORMAT_UYVY ||
f == SDL_PIXELFORMAT_YVYU ||
f == SDL_PIXELFORMAT_NV12 ||
f == SDL_PIXELFORMAT_NV21 ||
f == SDL_PIXELFORMAT_P010
;
}
SDL_Surface* convertYUY2_IYUV(SDL_Surface* surf);
template<typename RealStream>
struct PushConversionVideoStream : public RealStream {
SDL_PixelFormat _forced_format {SDL_PIXELFORMAT_IYUV};
// TODO: force colorspace?
template<typename... Args>
PushConversionVideoStream(SDL_PixelFormat forced_format, Args&&... args) : RealStream(std::forward<Args>(args)...), _forced_format(forced_format) {}
@ -33,41 +19,33 @@ struct PushConversionVideoStream : public RealStream {
bool push(const SDLVideoFrame& value) override {
SDL_Surface* surf = value.surface.get();
if (surf->format != _forced_format) {
//std::cerr << "DTC: need to convert from " << SDL_GetPixelFormatName(converted_surf->format) << " to SDL_PIXELFORMAT_IYUV\n";
if (surf->format == SDL_PIXELFORMAT_YUY2 && _forced_format == SDL_PIXELFORMAT_IYUV) {
// optimized custom impl
//std::cerr << "PCVS: need to convert from " << SDL_GetPixelFormatName(surf->format) << " to " << SDL_GetPixelFormatName(_forced_format) << "\n";
if ((surf = SDL_ConvertSurface(surf, _forced_format)) == nullptr) {
surf = value.surface.get(); // reset ptr
//std::cerr << "PCVS warning: default conversion failed: " << SDL_GetError() << "\n";
//auto start = Message::getTimeMS();
surf = convertYUY2_IYUV(surf);
//auto end = Message::getTimeMS();
// 3ms
//std::cerr << "DTC: timing " << SDL_GetPixelFormatName(converted_surf->format) << "->SDL_PIXELFORMAT_IYUV: " << end-start << "ms\n";
} else if (isFormatYUV(surf->format)) {
// TODO: fix sdl rgb->yuv conversion resulting in too dark (colorspace) issues
// https://github.com/libsdl-org/SDL/issues/10877
// meh, need to convert to rgb as a stopgap
//auto start = Message::getTimeMS();
SDL_Surface* tmp_conv_surf = SDL_ConvertSurfaceAndColorspace(surf, SDL_PIXELFORMAT_RGB24, nullptr, SDL_COLORSPACE_RGB_DEFAULT, 0);
//auto end = Message::getTimeMS();
// 1ms
//std::cerr << "DTC: timing " << SDL_GetPixelFormatName(converted_surf->format) << "->SDL_PIXELFORMAT_RGB24: " << end-start << "ms\n";
//start = Message::getTimeMS();
surf = SDL_ConvertSurfaceAndColorspace(tmp_conv_surf, _forced_format, nullptr, SDL_COLORSPACE_YUV_DEFAULT, 0);
//end = Message::getTimeMS();
// 60ms
//std::cerr << "DTC: timing SDL_PIXELFORMAT_RGB24->" << SDL_GetPixelFormatName(_forced_format) << ": " << end-start << "ms\n";
SDL_DestroySurface(tmp_conv_surf);
} else {
surf = SDL_ConvertSurface(surf, _forced_format);
// sdl hardcodes BT709_LIMITED
if ((surf = SDL_ConvertSurfaceAndColorspace(surf, _forced_format, nullptr, SDL_GetSurfaceColorspace(surf), 0)) == nullptr) {
//if ((surf = SDL_ConvertSurfaceAndColorspace(surf, _forced_format, nullptr, SDL_COLORSPACE_BT709_LIMITED, 0)) == nullptr) {
surf = value.surface.get(); // reset ptr
//std::cerr << "PCVS warning: default conversion with same colorspace failed: " << SDL_GetError() << "\n";
// simple convert failed, fall back to ->rgb->yuv
//SDL_Surface* tmp_conv_surf = SDL_ConvertSurfaceAndColorspace(surf, SDL_PIXELFORMAT_RGB24, nullptr, SDL_COLORSPACE_RGB_DEFAULT, 0);
SDL_Surface* tmp_conv_surf = SDL_ConvertSurface(surf, SDL_PIXELFORMAT_RGB24);
if (tmp_conv_surf == nullptr) {
std::cerr << "PCVS error: conversion to RGB failed: " << SDL_GetError() << "\n";
} else {
//surf = SDL_ConvertSurfaceAndColorspace(tmp_conv_surf, _forced_format, nullptr, SDL_COLORSPACE_YUV_DEFAULT, 0);
surf = SDL_ConvertSurface(tmp_conv_surf, _forced_format);
//surf = SDL_ConvertSurfaceAndColorspace(tmp_conv_surf, _forced_format, nullptr, SDL_COLORSPACE_BT601_LIMITED, 0);
SDL_DestroySurface(tmp_conv_surf);
}
}
}
if (surf == nullptr) {
// oh god
std::cerr << "DTC error: failed to convert surface to IYUV: " << SDL_GetError() << "\n";
std::cerr << "PCVS error: failed to convert surface to IYUV: " << SDL_GetError() << "\n";
return false;
}
}

View File

@ -194,7 +194,7 @@ bool StreamManager::connect(Object src, Object sink, bool threaded) {
std::move(our_data),
[](Connection& con) -> void {
// there might be more stored
for (size_t i = 0; i < 10; i++) {
for (size_t i = 0; i < 64; i++) {
auto new_frame_opt = static_cast<inlineData*>(con.data.get())->reader->pop();
// TODO: frame interval estimates
if (new_frame_opt.has_value()) {

View File

@ -6,6 +6,7 @@
#include <solanaceae/contact/components.hpp>
#include "./frame_streams/sdl/sdl_audio2_frame_stream2.hpp"
#include "./frame_streams/sdl/sdl_video_frame_stream2.hpp"
#include <imgui/imgui.h>
@ -178,6 +179,27 @@ MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme
} else {
std::cerr << "MS warning: no sdl audio: " << SDL_GetError() << "\n";
}
if (SDL_InitSubSystem(SDL_INIT_CAMERA)) {
{ // video in
ObjectHandle vsrc {os.registry(), os.registry().create()};
try {
vsrc.emplace<Components::FrameStream2Source<SDLVideoFrame>>(
std::make_unique<SDLVideo2InputDevice>()
);
vsrc.emplace<Components::StreamSource>(Components::StreamSource::create<SDLVideoFrame>("SDL Video Default Recording Device"));
vsrc.emplace<Components::TagDefaultTarget>();
os.throwEventConstruct(vsrc);
} catch (...) {
std::cerr << "MS error: failed constructing default video input source\n";
os.registry().destroy(vsrc);
}
}
} else {
std::cerr << "MS warning: no sdl camera: " << SDL_GetError() << "\n";
}
}
MainScreen::~MainScreen(void) {
@ -324,6 +346,11 @@ Screen* MainScreen::render(float time_delta, bool&) {
ImGui::SetItemTooltip("Limiting compute can slow down things like filetransfers!");
}
ImGui::Separator();
ImGui::Text("render interval: %.0fms (%.2ffps)", _render_interval*1000.f, 1.f/_render_interval);
ImGui::Text("tick interval: %.0fms (%.2ftps)", _min_tick_interval*1000.f, 1.f/_min_tick_interval);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Settings")) {
@ -482,12 +509,12 @@ Screen* MainScreen::render(float time_delta, bool&) {
// min over non animations in all cases
_render_interval = std::min<float>(pm_interval, cg_interval);
_render_interval = std::min<float>(_render_interval, tc_unfinished_queue_interval);
_render_interval = std::min<float>(_render_interval, dvt_interval);
// low delay time window
if (!_window_hidden && _time_since_event < curr_profile.low_delay_window) {
_render_interval = std::min<float>(_render_interval, ctc_interval);
_render_interval = std::min<float>(_render_interval, msgtc_interval);
_render_interval = std::min<float>(_render_interval, dvt_interval);
_render_interval = std::clamp(
_render_interval,
@ -498,7 +525,6 @@ Screen* MainScreen::render(float time_delta, bool&) {
} else if (!_window_hidden && _time_since_event < curr_profile.mid_delay_window) {
_render_interval = std::min<float>(_render_interval, ctc_interval);
_render_interval = std::min<float>(_render_interval, msgtc_interval);
_render_interval = std::min<float>(_render_interval, dvt_interval);
_render_interval = std::clamp(
_render_interval,

View File

@ -701,7 +701,9 @@ bool ToxAVVoIPModel::onEvent(const Events::FriendVideoFrame& e) {
vsrc.get<FrameStream2MultiSource<SDLVideoFrame>*>()->push({
// ms -> us
Message::getTimeMS() * 1000, // TODO: make more precise
// would be nice if we had been giving this from toxcore
// TODO: make more precise
Message::getTimeMS() * 1000,
new_surf
});