Compare commits
No commits in common. "18af7a7a38e82a77729ec306a8c891e2a9ab51c6" and "fa7a77ca143445a87d7f96432f349d1981a6fd1b" have entirely different histories.
18af7a7a38
...
fa7a77ca14
@ -71,7 +71,6 @@ extra_data = {
|
||||
"//c-toxcore/toxcore:logger",
|
||||
"//c-toxcore/toxcore:mono_time",
|
||||
"//c-toxcore/toxcore:net_crypto",
|
||||
"//c-toxcore/toxcore:net_profile",
|
||||
"//c-toxcore/toxcore:network",
|
||||
"//c-toxcore/toxcore:onion",
|
||||
"//c-toxcore/toxcore:onion_announce",
|
||||
|
39
external/toxcore/c-toxcore/toxav/toxav.c
vendored
39
external/toxcore/c-toxcore/toxav/toxav.c
vendored
@ -24,8 +24,19 @@
|
||||
#include "../toxcore/tox_struct.h" // IWYU pragma: keep
|
||||
#include "../toxcore/util.h"
|
||||
|
||||
// TODO(zoff99): don't hardcode this, let the application choose it
|
||||
// VPX Info: Time to spend encoding, in microseconds (it's a *soft* deadline)
|
||||
#define WANTED_MAX_ENCODER_FPS 40
|
||||
#define MAX_ENCODE_TIME_US (1000000 / WANTED_MAX_ENCODER_FPS) // to allow x fps
|
||||
|
||||
#define VIDEO_SEND_X_KEYFRAMES_FIRST 7 // force the first n frames to be keyframes!
|
||||
|
||||
/*
|
||||
* VPX_DL_REALTIME (1) deadline parameter analogous to VPx REALTIME mode.
|
||||
* VPX_DL_GOOD_QUALITY (1000000) deadline parameter analogous to VPx GOOD QUALITY mode.
|
||||
* VPX_DL_BEST_QUALITY (0) deadline parameter analogous to VPx BEST QUALITY mode.
|
||||
*/
|
||||
|
||||
// iteration interval that is used when no call is active
|
||||
#define IDLE_ITERATION_INTERVAL_MS 200
|
||||
|
||||
@ -1044,7 +1055,6 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
// we start with I-frames (full frames) and then switch to normal mode later
|
||||
if (call->video_rtp->ssrc < VIDEO_SEND_X_KEYFRAMES_FIRST) {
|
||||
// Key frame flag for first frames
|
||||
vpx_encode_flags = VPX_EFLAG_FORCE_KF;
|
||||
@ -1059,16 +1069,10 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u
|
||||
++call->video_rtp->ssrc;
|
||||
}
|
||||
|
||||
// we start with I-frames (full frames) and then switch to normal mode later
|
||||
|
||||
{ /* Encode */
|
||||
vpx_image_t img;
|
||||
// TODO(Green-Sky): figure out stride_align
|
||||
// TODO(Green-Sky): check memory alignment?
|
||||
if (vpx_img_wrap(&img, VPX_IMG_FMT_I420, width, height, 0, (uint8_t *)y) != nullptr) {
|
||||
// vpx_img_wrap assumes contigues memory, so we fix that
|
||||
img.planes[VPX_PLANE_U] = (uint8_t *)u;
|
||||
img.planes[VPX_PLANE_V] = (uint8_t *)v;
|
||||
} else {
|
||||
// call to wrap failed, falling back to copy
|
||||
img.w = 0;
|
||||
img.h = 0;
|
||||
img.d_w = 0;
|
||||
@ -1081,13 +1085,9 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u
|
||||
memcpy(img.planes[VPX_PLANE_Y], y, width * height);
|
||||
memcpy(img.planes[VPX_PLANE_U], u, (width / 2) * (height / 2));
|
||||
memcpy(img.planes[VPX_PLANE_V], v, (width / 2) * (height / 2));
|
||||
}
|
||||
|
||||
// TODO(zoff99): don't hardcode this, let the application choose it
|
||||
const unsigned long deadline = VPX_DL_REALTIME;
|
||||
|
||||
const vpx_codec_err_t vrc = vpx_codec_encode(call->video->encoder, &img,
|
||||
call->video->frame_counter, 1, vpx_encode_flags, deadline);
|
||||
call->video->frame_counter, 1, vpx_encode_flags, MAX_ENCODE_TIME_US);
|
||||
|
||||
vpx_img_free(&img);
|
||||
|
||||
@ -1304,11 +1304,14 @@ static bool audio_bit_rate_invalid(uint32_t bit_rate)
|
||||
|
||||
static bool video_bit_rate_invalid(uint32_t bit_rate)
|
||||
{
|
||||
/* Cap the target rate to 1000 Mbps to avoid some integer overflows in
|
||||
* target bandwidth calculations.
|
||||
* https://github.com/webmproject/libvpx/blob/027bbee30a0103b99d86327b48d29567fed11688/vp8/vp8_cx_iface.c#L350-L352
|
||||
/* https://www.webmproject.org/docs/webm-sdk/structvpx__codec__enc__cfg.html shows the following:
|
||||
* unsigned int rc_target_bitrate
|
||||
* the range of uint varies from platform to platform
|
||||
* though, uint32_t should be large enough to store bitrates,
|
||||
* we may want to prevent from passing overflowed bitrates to libvpx
|
||||
* more in detail, it's the case where bit_rate is larger than uint, but smaller than uint32_t
|
||||
*/
|
||||
return bit_rate > 1000000;
|
||||
return bit_rate > UINT32_MAX;
|
||||
}
|
||||
|
||||
static bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state)
|
||||
|
23
external/toxcore/c-toxcore/toxav/video.c
vendored
23
external/toxcore/c-toxcore/toxav/video.c
vendored
@ -15,6 +15,27 @@
|
||||
#include "../toxcore/logger.h"
|
||||
#include "../toxcore/mono_time.h"
|
||||
|
||||
/**
|
||||
* Soft deadline the decoder should attempt to meet, in "us" (microseconds).
|
||||
* Set to zero for unlimited.
|
||||
*
|
||||
* By convention, the value 1 is used to mean "return as fast as possible."
|
||||
*/
|
||||
// TODO(zoff99): don't hardcode this, let the application choose it
|
||||
#define WANTED_MAX_DECODER_FPS 40
|
||||
|
||||
/**
|
||||
* VPX_DL_REALTIME (1)
|
||||
* deadline parameter analogous to VPx REALTIME mode.
|
||||
*
|
||||
* VPX_DL_GOOD_QUALITY (1000000)
|
||||
* deadline parameter analogous to VPx GOOD QUALITY mode.
|
||||
*
|
||||
* VPX_DL_BEST_QUALITY (0)
|
||||
* deadline parameter analogous to VPx BEST QUALITY mode.
|
||||
*/
|
||||
#define MAX_DECODE_TIME_US (1000000 / WANTED_MAX_DECODER_FPS) // to allow x fps
|
||||
|
||||
/**
|
||||
* Codec control function to set encoder internal speed settings. Changes in
|
||||
* this value influences, among others, the encoder's selection of motion
|
||||
@ -299,7 +320,7 @@ void vc_iterate(VCSession *vc)
|
||||
|
||||
LOGGER_DEBUG(vc->log, "vc_iterate: rb_read p->len=%d p->header.xe=%d", (int)full_data_len, p->header.xe);
|
||||
LOGGER_DEBUG(vc->log, "vc_iterate: rb_read rb size=%d", (int)log_rb_size);
|
||||
const vpx_codec_err_t rc = vpx_codec_decode(vc->decoder, p->data, full_data_len, nullptr, 0);
|
||||
const vpx_codec_err_t rc = vpx_codec_decode(vc->decoder, p->data, full_data_len, nullptr, MAX_DECODE_TIME_US);
|
||||
free(p);
|
||||
|
||||
if (rc != VPX_CODEC_OK) {
|
||||
|
@ -358,10 +358,6 @@ cc_library(
|
||||
name = "net_profile",
|
||||
srcs = ["net_profile.c"],
|
||||
hdrs = ["net_profile.h"],
|
||||
visibility = [
|
||||
"//c-toxcore/auto_tests:__pkg__",
|
||||
"//c-toxcore/testing/fuzzing:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":attributes",
|
||||
":ccompat",
|
||||
@ -559,7 +555,6 @@ cc_fuzz_test(
|
||||
deps = [
|
||||
":DHT",
|
||||
":mem_test_util",
|
||||
":net_profile",
|
||||
"//c-toxcore/testing/fuzzing:fuzz_support",
|
||||
],
|
||||
)
|
||||
@ -786,7 +781,6 @@ cc_fuzz_test(
|
||||
":TCP_client",
|
||||
":mem_test_util",
|
||||
":net_crypto",
|
||||
":net_profile",
|
||||
":network",
|
||||
"//c-toxcore/testing/fuzzing:fuzz_support",
|
||||
"//c-toxcore/testing/fuzzing:fuzz_tox",
|
||||
|
@ -1626,7 +1626,7 @@ int group_packet_wrap(
|
||||
* Returns true on success.
|
||||
*/
|
||||
non_null()
|
||||
static bool send_lossy_group_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
|
||||
static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
|
||||
uint16_t length, uint8_t packet_type)
|
||||
{
|
||||
assert(length <= MAX_GC_CUSTOM_LOSSY_PACKET_SIZE);
|
||||
@ -2236,7 +2236,7 @@ static int handle_gc_invite_response_reject(const GC_Session *c, GC_Chat *chat,
|
||||
* Return true on success.
|
||||
*/
|
||||
non_null()
|
||||
static bool send_gc_invite_response_reject(const GC_Chat *chat, GC_Connection *gconn, uint8_t type)
|
||||
static bool send_gc_invite_response_reject(const GC_Chat *chat, const GC_Connection *gconn, uint8_t type)
|
||||
{
|
||||
if (type >= GJ_INVALID) {
|
||||
type = GJ_INVITE_FAILED;
|
||||
@ -2353,7 +2353,7 @@ static bool send_gc_lossy_packet_all_peers(const GC_Chat *chat, const uint8_t *d
|
||||
uint32_t confirmed_peers = 0;
|
||||
|
||||
for (uint32_t i = 1; i < chat->numpeers; ++i) {
|
||||
GC_Connection *gconn = get_gc_connection(chat, i);
|
||||
const GC_Connection *gconn = get_gc_connection(chat, i);
|
||||
|
||||
assert(gconn != nullptr);
|
||||
|
||||
@ -7072,7 +7072,7 @@ static void do_peer_delete(const GC_Session *c, GC_Chat *chat, void *userdata)
|
||||
* Return true on success.
|
||||
*/
|
||||
non_null()
|
||||
static bool ping_peer(const GC_Chat *chat, GC_Connection *gconn)
|
||||
static bool ping_peer(const GC_Chat *chat, const GC_Connection *gconn)
|
||||
{
|
||||
const uint16_t buf_size = GC_PING_PACKET_MIN_DATA_SIZE + sizeof(IP_Port);
|
||||
uint8_t *data = (uint8_t *)mem_balloc(chat->mem, buf_size);
|
||||
|
@ -115,7 +115,6 @@ typedef struct GC_Connection {
|
||||
uint64_t last_sent_tcp_relays_time; /* the last time we attempted to send this peer our tcp relays */
|
||||
uint16_t tcp_relay_share_index;
|
||||
uint64_t last_received_direct_time; /* the last time we received a direct UDP packet from this connection */
|
||||
uint64_t last_sent_direct_try_time; /* the last time we tried sending a direct UDP packet */
|
||||
uint64_t last_sent_ip_time; /* the last time we sent our ip info to this peer in a ping packet */
|
||||
|
||||
Node_format connected_tcp_relays[MAX_FRIEND_TCP_CONNECTIONS];
|
||||
|
@ -29,9 +29,6 @@
|
||||
/** Seconds since last direct UDP packet was received before the connection is considered dead */
|
||||
#define GCC_UDP_DIRECT_TIMEOUT (GC_PING_TIMEOUT + 4)
|
||||
|
||||
/** Seconds since last direct UDP packet was sent before we can try again. Cheap NAT hole punch */
|
||||
#define GCC_UDP_DIRECT_RETRY 1
|
||||
|
||||
/** Returns true if array entry does not contain an active packet. */
|
||||
non_null()
|
||||
static bool array_entry_is_empty(const GC_Message_Array_Entry *array_entry)
|
||||
@ -598,7 +595,7 @@ void gcc_resend_packets(const GC_Chat *chat, GC_Connection *gconn)
|
||||
}
|
||||
}
|
||||
|
||||
bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *packet, uint16_t length)
|
||||
bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *packet, uint16_t length)
|
||||
{
|
||||
if (packet == nullptr || length == 0) {
|
||||
return false;
|
||||
@ -611,20 +608,16 @@ bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *p
|
||||
return (uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length;
|
||||
}
|
||||
|
||||
if (gcc_conn_should_try_direct(chat->mono_time, gconn)) {
|
||||
gconn->last_sent_direct_try_time = mono_time_get(chat->mono_time);
|
||||
|
||||
if ((uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length) {
|
||||
direct_send_attempt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int ret = send_packet_tcp_connection(chat->tcp_conn, gconn->tcp_connection_num, packet, length);
|
||||
return ret == 0 || direct_send_attempt;
|
||||
}
|
||||
|
||||
int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
|
||||
int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
|
||||
uint16_t length, uint64_t message_id, uint8_t packet_type)
|
||||
{
|
||||
const uint16_t packet_size = gc_get_wrapped_packet_size(length, NET_PACKET_GC_LOSSLESS);
|
||||
@ -666,11 +659,6 @@ bool gcc_conn_is_direct(const Mono_Time *mono_time, const GC_Connection *gconn)
|
||||
return GCC_UDP_DIRECT_TIMEOUT + gconn->last_received_direct_time > mono_time_get(mono_time);
|
||||
}
|
||||
|
||||
bool gcc_conn_should_try_direct(const Mono_Time *mono_time, const GC_Connection *gconn)
|
||||
{
|
||||
return mono_time_is_timeout(mono_time, gconn->last_sent_direct_try_time, GCC_UDP_DIRECT_RETRY);
|
||||
}
|
||||
|
||||
bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn)
|
||||
{
|
||||
return !net_family_is_unspec(gconn->addr.ip_port.ip.family) && !net_family_is_unspec(net_family(chat->net));
|
||||
|
@ -135,10 +135,6 @@ void gcc_make_session_shared_key(GC_Connection *gconn, const uint8_t *sender_pk)
|
||||
non_null()
|
||||
bool gcc_conn_is_direct(const Mono_Time *mono_time, const GC_Connection *gconn);
|
||||
|
||||
/** @brief Return true if we can try a direct connection with `gconn` again. */
|
||||
non_null()
|
||||
bool gcc_conn_should_try_direct(const Mono_Time *mono_time, const GC_Connection *gconn);
|
||||
|
||||
/** @brief Return true if a direct UDP connection is possible with `gconn`. */
|
||||
non_null()
|
||||
bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn);
|
||||
@ -150,7 +146,7 @@ bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn
|
||||
* Return true on success.
|
||||
*/
|
||||
non_null()
|
||||
bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *packet, uint16_t length);
|
||||
bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *packet, uint16_t length);
|
||||
|
||||
/** @brief Sends a lossless packet to `gconn` comprised of `data` of size `length`.
|
||||
*
|
||||
@ -188,7 +184,7 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon
|
||||
* Return -2 if the packet fails to send.
|
||||
*/
|
||||
non_null(1, 2) nullable(3)
|
||||
int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
|
||||
int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
|
||||
uint16_t length, uint64_t message_id, uint8_t packet_type);
|
||||
|
||||
/** @brief Called when a peer leaves the group. */
|
||||
|
@ -190,8 +190,7 @@ float DebugVideoTap::render(void) {
|
||||
std::string window_title {"DebugVideoTap #"};
|
||||
window_title += std::to_string(view._id);
|
||||
ImGui::SetNextWindowSize({400, 420}, ImGuiCond_Appearing);
|
||||
bool window_open = true;
|
||||
if (ImGui::Begin(window_title.c_str(), &window_open, ImGuiWindowFlags_NoScrollbar)) {
|
||||
if (ImGui::Begin(window_title.c_str(), nullptr, ImGuiWindowFlags_NoScrollbar)) {
|
||||
while (auto new_frame_opt = stream->pop()) {
|
||||
// timing
|
||||
if (view._v_last_ts == 0) {
|
||||
@ -209,25 +208,40 @@ float DebugVideoTap::render(void) {
|
||||
}
|
||||
|
||||
SDL_Surface* new_frame_surf = new_frame_opt.value().surface.get();
|
||||
SDL_LockSurface(new_frame_surf);
|
||||
if (view._tex == 0 || (int)view._tex_w != new_frame_surf->w || (int)view._tex_h != new_frame_surf->h) {
|
||||
|
||||
SDL_Surface* converted_surf = new_frame_surf;
|
||||
//if (new_frame_surf->format != SDL_PIXELFORMAT_RGBA32) {
|
||||
// // we need to convert
|
||||
// //std::cerr << "DVT: need to convert\n";
|
||||
// converted_surf = SDL_ConvertSurfaceAndColorspace(new_frame_surf, SDL_PIXELFORMAT_RGBA32, nullptr, SDL_COLORSPACE_RGB_DEFAULT, 0);
|
||||
// assert(converted_surf->format == SDL_PIXELFORMAT_RGBA32);
|
||||
//}
|
||||
|
||||
SDL_LockSurface(converted_surf);
|
||||
if (view._tex == 0 || (int)view._tex_w != converted_surf->w || (int)view._tex_h != converted_surf->h) {
|
||||
_tu.destroy(view._tex);
|
||||
view._tex = _tu.upload(
|
||||
static_cast<const uint8_t*>(new_frame_surf->pixels),
|
||||
new_frame_surf->w,
|
||||
new_frame_surf->h,
|
||||
static_cast<const uint8_t*>(converted_surf->pixels),
|
||||
converted_surf->w,
|
||||
converted_surf->h,
|
||||
TextureUploaderI::IYUV, // forced conversion
|
||||
TextureUploaderI::LINEAR,
|
||||
TextureUploaderI::STREAMING
|
||||
);
|
||||
|
||||
view._tex_w = new_frame_surf->w;
|
||||
view._tex_h = new_frame_surf->h;
|
||||
view._tex_w = converted_surf->w;
|
||||
view._tex_h = converted_surf->h;
|
||||
} else {
|
||||
//_tu.update(view._tex, static_cast<const uint8_t*>(converted_surf->pixels), converted_surf->w * converted_surf->h * 4);
|
||||
_tu.update(view._tex, static_cast<const uint8_t*>(new_frame_surf->pixels), new_frame_surf->w * new_frame_surf->h * 3/2);
|
||||
_tu.update(view._tex, static_cast<const uint8_t*>(converted_surf->pixels), converted_surf->w * converted_surf->h * 3/2);
|
||||
//_tu.updateRGBA(view._tex, static_cast<const uint8_t*>(converted_surf->pixels), converted_surf->w * converted_surf->h * 4);
|
||||
}
|
||||
SDL_UnlockSurface(new_frame_surf);
|
||||
SDL_UnlockSurface(converted_surf);
|
||||
|
||||
//if (new_frame_surf != converted_surf) {
|
||||
// // clean up temp
|
||||
// SDL_DestroySurface(converted_surf);
|
||||
//}
|
||||
}
|
||||
|
||||
ImGui::Checkbox("mirror ", &view._mirror);
|
||||
@ -250,15 +264,6 @@ float DebugVideoTap::render(void) {
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (!window_open) {
|
||||
_sm.forEachConnectedExt(_tap, [this, stream_ptr = stream.get()](ObjectHandle o, const void*, const void* writer) {
|
||||
// very hacky
|
||||
if (writer == stream_ptr) {
|
||||
_sm.disconnect(o, _tap);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return min_interval;
|
||||
|
@ -86,7 +86,7 @@ bool StreamManager::connect(Object src, Object sink, bool threaded) {
|
||||
bool StreamManager::disconnect(Object src, Object sink) {
|
||||
auto res = std::find_if(
|
||||
_connections.cbegin(), _connections.cend(),
|
||||
[src, sink](const auto& a) { return a->src == src && a->sink == sink; }
|
||||
[&](const auto& a) { return a->src == src && a->sink == sink; }
|
||||
);
|
||||
if (res == _connections.cend()) {
|
||||
// not found
|
||||
|
@ -52,14 +52,6 @@ namespace Components {
|
||||
template<typename FrameType>
|
||||
using FrameStream2Sink = std::unique_ptr<FrameStream2SinkI<FrameType>>;
|
||||
|
||||
// supported sources/sinks have this component
|
||||
// to signal the backend sender/encoder a generic bitrate
|
||||
// TODO: split into advanced encoder bitrate / target / range
|
||||
struct Bitrate {
|
||||
// in kilo bits per second
|
||||
int64_t rate{0};
|
||||
};
|
||||
|
||||
} // Components
|
||||
|
||||
|
||||
@ -74,8 +66,6 @@ class StreamManager : protected ObjectStoreEventI {
|
||||
|
||||
struct Data {
|
||||
virtual ~Data(void) {}
|
||||
virtual const void* getReaderStream(void) = 0;
|
||||
virtual const void* getWriterStream(void) = 0;
|
||||
};
|
||||
std::unique_ptr<Data> data; // stores reader writer type erased
|
||||
std::function<void(Connection&)> pump_fn; // TODO: make it return next interval?
|
||||
@ -126,29 +116,6 @@ class StreamManager : protected ObjectStoreEventI {
|
||||
bool disconnect(Object src, Object sink);
|
||||
bool disconnectAll(Object o);
|
||||
|
||||
template<typename FN>
|
||||
void forEachConnected(ObjectHandle o, FN&& fn) {
|
||||
for (const auto& con : _connections) {
|
||||
if (con->src == o) {
|
||||
fn(con->sink);
|
||||
} else if (con->sink == o) {
|
||||
fn(con->src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FN>
|
||||
void forEachConnectedExt(ObjectHandle o, FN&& fn) {
|
||||
for (const auto& con : _connections) {
|
||||
if (con->src == o) {
|
||||
// TODO: very ugly
|
||||
fn(con->sink, con->data.get()->getReaderStream(), con->data.get()->getWriterStream());
|
||||
} else if (con->sink == o) {
|
||||
fn(con->src, con->data.get()->getReaderStream(), con->data.get()->getWriterStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do we need the time delta?
|
||||
float tick(float);
|
||||
|
||||
@ -216,11 +183,9 @@ bool StreamManager::connect(Object src, Object sink, bool threaded) {
|
||||
auto& sink_stream = h_sink.get<Components::FrameStream2Sink<FrameType>>();
|
||||
|
||||
struct inlineData : public Connection::Data {
|
||||
~inlineData(void) {}
|
||||
virtual ~inlineData(void) {}
|
||||
std::shared_ptr<FrameStream2I<FrameType>> reader;
|
||||
std::shared_ptr<FrameStream2I<FrameType>> writer;
|
||||
const void* getReaderStream(void) override { return reader.get(); }
|
||||
const void* getWriterStream(void) override { return writer.get(); }
|
||||
};
|
||||
|
||||
auto our_data = std::make_unique<inlineData>();
|
||||
|
@ -56,16 +56,6 @@ struct ToxAVCallAudioSink : public FrameStream2SinkI<AudioFrame2> {
|
||||
}
|
||||
}
|
||||
|
||||
bool setBitrate(uint64_t rate) {
|
||||
// TODO: prevent disable active?
|
||||
auto err = _toxav.toxavAudioSetBitRate(_fid, rate);
|
||||
if (err == TOXAV_ERR_BIT_RATE_SET_OK) {
|
||||
_audio_bitrate = rate;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// sink
|
||||
std::shared_ptr<FrameStream2I<AudioFrame2>> subscribe(void) override {
|
||||
if (_writer) {
|
||||
@ -126,16 +116,6 @@ struct ToxAVCallVideoSink : public FrameStream2SinkI<SDLVideoFrame> {
|
||||
}
|
||||
}
|
||||
|
||||
bool setBitrate(uint64_t rate) {
|
||||
// TODO: prevent disable active?
|
||||
auto err = _toxav.toxavVideoSetBitRate(_fid, rate);
|
||||
if (err == TOXAV_ERR_BIT_RATE_SET_OK) {
|
||||
_video_bitrate = rate;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// sink
|
||||
std::shared_ptr<FrameStream2I<SDLVideoFrame>> subscribe(void) override {
|
||||
if (_writer) {
|
||||
@ -207,7 +187,6 @@ void ToxAVVoIPModel::addAudioSink(ObjectHandle session, uint32_t friend_number)
|
||||
|
||||
auto new_asink = std::make_unique<ToxAVCallAudioSink>(_av, friend_number);
|
||||
auto* new_asink_ptr = new_asink.get();
|
||||
outgoing_audio.emplace<Components::Bitrate>(new_asink_ptr->_audio_bitrate);
|
||||
outgoing_audio.emplace<ToxAVCallAudioSink*>(new_asink_ptr);
|
||||
outgoing_audio.emplace<Components::FrameStream2Sink<AudioFrame2>>(std::move(new_asink));
|
||||
outgoing_audio.emplace<Components::StreamSink>(Components::StreamSink::create<AudioFrame2>("ToxAV Friend Call Outgoing Audio"));
|
||||
@ -261,7 +240,6 @@ void ToxAVVoIPModel::addVideoSink(ObjectHandle session, uint32_t friend_number)
|
||||
|
||||
auto new_vsink = std::make_unique<ToxAVCallVideoSink>(_av, friend_number);
|
||||
auto* new_vsink_ptr = new_vsink.get();
|
||||
outgoing_video.emplace<Components::Bitrate>(new_vsink_ptr->_video_bitrate);
|
||||
outgoing_video.emplace<ToxAVCallVideoSink*>(new_vsink_ptr);
|
||||
outgoing_video.emplace<Components::FrameStream2Sink<SDLVideoFrame>>(std::move(new_vsink));
|
||||
outgoing_video.emplace<Components::StreamSink>(Components::StreamSink::create<SDLVideoFrame>("ToxAV Friend Call Outgoing Video"));
|
||||
@ -545,7 +523,7 @@ void ToxAVVoIPModel::handleEvent(const Events::FriendCallState& e) {
|
||||
}
|
||||
|
||||
ToxAVVoIPModel::ToxAVVoIPModel(ObjectStore2& os, ToxAVI& av, ContactStore4I& cs, ToxContactModel2& tcm) :
|
||||
_os(os), _os_sr(_os.newSubRef(this)), _av(av), _av_sr(_av.newSubRef(this)), _cs(cs), _cs_sr(_cs.newSubRef(this)), _tcm(tcm)
|
||||
_os(os), _av(av), _av_sr(_av.newSubRef(this)), _cs(cs), _cs_sr(_cs.newSubRef(this)), _tcm(tcm)
|
||||
{
|
||||
_av_sr
|
||||
.subscribe(ToxAV_Event::friend_call)
|
||||
@ -570,10 +548,6 @@ ToxAVVoIPModel::ToxAVVoIPModel(ObjectStore2& os, ToxAVI& av, ContactStore4I& cs,
|
||||
.subscribe(ContactStore4_Event::contact_construct)
|
||||
.subscribe(ContactStore4_Event::contact_update)
|
||||
;
|
||||
|
||||
_os_sr
|
||||
.subscribe(ObjectStore_Event::object_update)
|
||||
;
|
||||
}
|
||||
|
||||
ToxAVVoIPModel::~ToxAVVoIPModel(void) {
|
||||
@ -899,32 +873,3 @@ bool ToxAVVoIPModel::onEvent(const ContactStore::Events::Contact4Destory&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ToxAVVoIPModel::onEvent(const ObjectStore::Events::ObjectConstruct&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ToxAVVoIPModel::onEvent(const ObjectStore::Events::ObjectUpdate& e) {
|
||||
if (e.e.all_of<ToxAVCallVideoSink*>()) {
|
||||
auto& rate = e.e.get_or_emplace<Components::Bitrate>().rate;
|
||||
if (rate <= 0) {
|
||||
rate = 0;
|
||||
}
|
||||
if (!e.e.get<ToxAVCallVideoSink*>()->setBitrate(rate)) {
|
||||
rate = e.e.get<ToxAVCallVideoSink*>()->_video_bitrate;
|
||||
}
|
||||
} else if (e.e.all_of<ToxAVCallAudioSink*>()) {
|
||||
auto& rate = e.e.get_or_emplace<Components::Bitrate>().rate;
|
||||
if (rate <= 0) {
|
||||
rate = 0;
|
||||
}
|
||||
if (!e.e.get<ToxAVCallAudioSink*>()->setBitrate(rate)) {
|
||||
rate = e.e.get<ToxAVCallAudioSink*>()->_audio_bitrate;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ToxAVVoIPModel::onEvent(const ObjectStore::Events::ObjectDestory&) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/object_store/object_store.hpp>
|
||||
#include <solanaceae/object_store/fwd.hpp>
|
||||
#include <solanaceae/contact/contact_store_i.hpp>
|
||||
#include <solanaceae/tox_contacts/tox_contact_model2.hpp>
|
||||
#include "./frame_streams/voip_model.hpp"
|
||||
@ -16,9 +16,8 @@
|
||||
struct ToxAVCallAudioSink;
|
||||
struct ToxAVCallVideoSink;
|
||||
|
||||
class ToxAVVoIPModel : protected ToxAVEventI, protected ContactStore4EventI, protected ObjectStoreEventI, public VoIPModelI {
|
||||
class ToxAVVoIPModel : protected ToxAVEventI, protected ContactStore4EventI, public VoIPModelI {
|
||||
ObjectStore2& _os;
|
||||
ObjectStore2::SubscriptionReference _os_sr;
|
||||
ToxAVI& _av;
|
||||
ToxAVI::SubscriptionReference _av_sr;
|
||||
ContactStore4I& _cs;
|
||||
@ -94,10 +93,5 @@ class ToxAVVoIPModel : protected ToxAVEventI, protected ContactStore4EventI, pro
|
||||
bool onEvent(const ContactStore::Events::Contact4Construct&) override;
|
||||
bool onEvent(const ContactStore::Events::Contact4Update&) override;
|
||||
bool onEvent(const ContactStore::Events::Contact4Destory&) override;
|
||||
|
||||
protected: // object events
|
||||
bool onEvent(const ObjectStore::Events::ObjectConstruct&) override;
|
||||
bool onEvent(const ObjectStore::Events::ObjectUpdate&) override;
|
||||
bool onEvent(const ObjectStore::Events::ObjectDestory&) override;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user