Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content dev (more like stream dev) #14

Closed
wants to merge 34 commits into from
Closed

Content dev (more like stream dev) #14

wants to merge 34 commits into from

Conversation

Green-Sky
Copy link
Owner

No description provided.

@Green-Sky Green-Sky force-pushed the content_dev branch 4 times, most recently from 3be43bd to 65de2c9 Compare April 27, 2024 20:03
@Green-Sky Green-Sky force-pushed the content_dev branch 3 times, most recently from 1eaf514 to 184e351 Compare May 22, 2024 13:27
@Green-Sky Green-Sky force-pushed the content_dev branch 3 times, most recently from bad140d to ac28217 Compare May 29, 2024 13:36
@Green-Sky Green-Sky force-pushed the content_dev branch 2 times, most recently from 1f0ca2e to 8ded5b3 Compare June 2, 2024 15:14
@Green-Sky Green-Sky force-pushed the content_dev branch 2 times, most recently from 11d1b99 to ca65a90 Compare June 16, 2024 15:36
@Green-Sky Green-Sky force-pushed the content_dev branch 7 times, most recently from af21503 to 5a3130b Compare July 20, 2024 11:50
@Green-Sky Green-Sky changed the title Content dev Content dev (more like stream dev) Jul 20, 2024
@Green-Sky Green-Sky force-pushed the content_dev branch 3 times, most recently from a3739ab to c98acf5 Compare August 13, 2024 14:12
@Green-Sky Green-Sky force-pushed the content_dev branch 2 times, most recently from 7e0da74 to 0387404 Compare September 19, 2024 19:42
@Green-Sky
Copy link
Owner Author

diff --git a/src/content/audio_stream.hpp b/src/content/audio_stream.hpp
index 82d3f899d8e..5800adb237d 100644
--- a/src/content/audio_stream.hpp
+++ b/src/content/audio_stream.hpp
@@ -12,6 +12,12 @@
 // channels make samples interleaved,
 // planar channels are not supported
 struct AudioFrame {
+	struct Hint {
+		// desired audio frame lenght in ms
+		uint32_t frame_length_ms {0};
+	};
+	using pop_hint_t = Hint;
+
 	// sequence number, to detect gaps
 	uint32_t seq {0};
 	// TODO: maybe use ts instead to discard old?
diff --git a/src/content/frame_stream2.hpp b/src/content/frame_stream2.hpp
index 9e1d31c3c29..28597362bd4 100644
--- a/src/content/frame_stream2.hpp
+++ b/src/content/frame_stream2.hpp
@@ -19,6 +19,9 @@

 template<typename FrameType>
 struct FrameStream2I {
+	// will be inspected in the connection and given the other side's pop
+	typename FrameType::pop_hint_t pop_hint {};
+
 	virtual ~FrameStream2I(void) {}

 	// get number of available frames
@@ -27,7 +30,7 @@ struct FrameStream2I {
 	// get next frame
 	// TODO: optional instead?
 	// data sharing? -> no, data is copied for each fsr, if concurency supported
-	[[nodiscard]] virtual std::optional<FrameType> pop(void) = 0;
+	[[nodiscard]] virtual std::optional<FrameType> pop(const typename FrameType::pop_hint_t& hint = {}) = 0;

 	// returns true if there are readers (or we dont know)
 	virtual bool push(const FrameType& value) = 0;
@@ -65,7 +68,7 @@ struct QueuedFrameStream2 : public FrameStream2I<FrameType> {
 		return _queue.size();
 	}

-	std::optional<FrameType> pop(void) override {
+	std::optional<FrameType> pop(const typename FrameType::pop_hint_t& = {}) override {
 		auto* ret_ptr = _queue.front();
 		if (ret_ptr == nullptr) {
 			return std::nullopt;
@@ -132,7 +135,7 @@ struct FrameStream2MultiSource : public FrameStream2SourceI<FrameType>, public F
 		return -1;
 	}

-	std::optional<FrameType> pop(void) override {
+	std::optional<FrameType> pop(const typename FrameType::pop_hint_t& = {}) override {
 		// nope
 		assert(false && "this logic is very frame type specific, provide an impl");
 		return std::nullopt;
diff --git a/src/content/sdl_audio_frame_stream2.cpp b/src/content/sdl_audio_frame_stream2.cpp
index ab51b082a7a..b4828be4b25 100644
--- a/src/content/sdl_audio_frame_stream2.cpp
+++ b/src/content/sdl_audio_frame_stream2.cpp
@@ -1,6 +1,8 @@
 #include "./sdl_audio_frame_stream2.hpp"

+#include <cstdint>
 #include <iostream>
+#include <optional>

 // "thin" wrapper around sdl audio streams
 // we dont needs to get fance, as they already provide everything we need
@@ -39,29 +41,57 @@ struct SDLAudioStreamReader : public AudioFrameStream2I {
 		return -1;
 	}

-	std::optional<AudioFrame> pop(void) override {
+	std::optional<AudioFrame> pop(const AudioFrame::pop_hint_t& hint = {}) override {
 		assert(_stream);
 		assert(_format == SDL_AUDIO_S16);

-		static const size_t buffer_size {960*_channels};
-		_buffer.resize(buffer_size); // noop?
+		if (hint.frame_length_ms > 0) {
+			const size_t avail_samples_nom = (SDL_GetAudioStreamAvailable(_stream.get()) / sizeof(int16_t)) / _channels;
+			const uint32_t avail_ms = (avail_samples_nom / _sample_rate) * 1000;
+			if (avail_ms < hint.frame_length_ms) {
+				// not enough data for desired frame length
+				return std::nullopt;
+			}
+
+			const size_t buffer_size {(_channels * hint.frame_length_ms * _sample_rate)/1000};
+			_buffer.resize(buffer_size); // likely noop
+		} else {
+			static const size_t buffer_size {960*_channels};
+			_buffer.resize(buffer_size); // likely noop
+		}

-		const auto read_bytes = SDL_GetAudioStreamData(
-			_stream.get(),
-			_buffer.data(),
-			_buffer.size()*sizeof(int16_t)
-		);
+		// we piece together data, until we hit the requested length
+		// sdl seems to have a max buffer size we can query
+		size_t total_read_bytes {0};
+		do {
+			const auto read_bytes = SDL_GetAudioStreamData(
+				_stream.get(),
+				_buffer.data()+(total_read_bytes/sizeof(int16_t)),
+				(_buffer.size()*sizeof(int16_t)) - total_read_bytes
+			);
+
+			// no new frame yet, or error
+			if (read_bytes <= 0) {
+				//return std::nullopt;
+				break;
+			//} else if (size_t(read_bytes) < sizeof(int16_t)*_buffer.size()) {
+			//    // we read less than we requested
+			//    // TODO: do something here?
+			//    std::cerr << "SDLASR warning: read less than requested (" << read_bytes << " instead of " << sizeof(int16_t)*_buffer.size() << ")\n";
+			}
+
+			total_read_bytes += read_bytes;
+		} while (total_read_bytes < sizeof(int16_t)*_buffer.size());

-		// no new frame yet, or error
-		if (read_bytes <= 0) {
+		if (total_read_bytes == 0) {
 			return std::nullopt;
+		} else {
+			return AudioFrame {
+				_seq_counter++,
+				_sample_rate, _channels,
+				Span<int16_t>(_buffer.data(), total_read_bytes/sizeof(int16_t)),
+			};
 		}
-
-		return AudioFrame {
-			_seq_counter++,
-			_sample_rate, _channels,
-			Span<int16_t>(_buffer.data(), read_bytes/sizeof(int16_t)),
-		};
 	}

 	bool push(const AudioFrame&) override {
@@ -96,7 +126,7 @@ std::shared_ptr<FrameStream2I<AudioFrame>> SDLAudioInputDevice::subscribe(void)
 		// this spec is more like a hint to the hardware
 		SDL_AudioSpec spec {
 			SDL_AUDIO_S16,
-			1, // TODO: conf
+			2, // TODO: conf
 			48'000,
 		};
 		_virtual_device_id = SDL_OpenAudioDevice(_configured_device_id, &spec);
@@ -109,13 +139,13 @@ std::shared_ptr<FrameStream2I<AudioFrame>> SDLAudioInputDevice::subscribe(void)

 	SDL_AudioSpec spec {
 		SDL_AUDIO_S16,
-		1, // TODO: conf
+		2, // TODO: conf
 		48'000,
 	};

 	SDL_AudioSpec device_spec {
 		SDL_AUDIO_S16,
-		1, // TODO: conf
+		2, // TODO: conf
 		48'000,
 	};
 	// TODO: error check
@@ -172,11 +202,12 @@ struct SDLAudioOutputDeviceDefaultInstance : public AudioFrameStream2I {
 	~SDLAudioOutputDeviceDefaultInstance(void);

 	int32_t size(void) override;
-	std::optional<AudioFrame> pop(void) override;
+	std::optional<AudioFrame> pop(const AudioFrame::pop_hint_t& hint = {}) override;
 	bool push(const AudioFrame& value) override;
 };

 SDLAudioOutputDeviceDefaultInstance::SDLAudioOutputDeviceDefaultInstance(void) : _stream(nullptr, nullptr) {
+	pop_hint.frame_length_ms = 5;
 }

 SDLAudioOutputDeviceDefaultInstance::SDLAudioOutputDeviceDefaultInstance(SDLAudioOutputDeviceDefaultInstance&& other) : _stream(std::move(other._stream)) {
@@ -188,7 +219,7 @@ int32_t SDLAudioOutputDeviceDefaultInstance::size(void) {
 	return -1;
 }

-std::optional<AudioFrame> SDLAudioOutputDeviceDefaultInstance::pop(void) {
+std::optional<AudioFrame> SDLAudioOutputDeviceDefaultInstance::pop(const AudioFrame::pop_hint_t&) {
 	assert(false);
 	// this is an output device, there is no data to pop
 	return std::nullopt;
diff --git a/src/content/sdl_video_frame_stream2.cpp b/src/content/sdl_video_frame_stream2.cpp
index a5b8517e795..f321318e4f1 100644
--- a/src/content/sdl_video_frame_stream2.cpp
+++ b/src/content/sdl_video_frame_stream2.cpp
@@ -1,6 +1,4 @@
 #include "./sdl_video_frame_stream2.hpp"
-#include "SDL3/SDL_camera.h"
-#include "SDL3/SDL_pixels.h"

 #include <chrono>
 #include <cstdint>
diff --git a/src/content/sdl_video_frame_stream2.hpp b/src/content/sdl_video_frame_stream2.hpp
index 9461655acd8..f48d84bcfda 100644
--- a/src/content/sdl_video_frame_stream2.hpp
+++ b/src/content/sdl_video_frame_stream2.hpp
@@ -11,6 +11,8 @@ inline void nopSurfaceDestructor(SDL_Surface*) {}

 // this is very sdl specific
 struct SDLVideoFrame {
+	using pop_hint_t = int;
+
 	// TODO: sequence numbering?
 	// micro seconds (nano is way too much)
 	uint64_t timestampUS {0};
diff --git a/src/debug_tox_call.cpp b/src/debug_tox_call.cpp
index c6b8a38ce8e..1dc919dd625 100644
--- a/src/debug_tox_call.cpp
+++ b/src/debug_tox_call.cpp
@@ -212,6 +212,9 @@ struct ToxAVCallAudioSink : public FrameStream2SinkI<AudioFrame> {
 	// bitrate for enabled state
 	uint32_t _audio_bitrate {32};

+	// prefered size of frame in ms
+	uint32_t _audio_frame_size_ms {5};
+
 	uint32_t _fid;
 	std::shared_ptr<QueuedFrameStream2<AudioFrame>> _writer;

@@ -236,6 +239,7 @@ struct ToxAVCallAudioSink : public FrameStream2SinkI<AudioFrame> {
 		}

 		_writer = std::make_shared<QueuedFrameStream2<AudioFrame>>(10, false);
+		_writer->pop_hint.frame_length_ms = _audio_frame_size_ms;

 		return _writer;
 	}
@@ -345,9 +349,8 @@ void DebugToxCall::tick(float) {
 //*   `((sample rate) * (audio length) / 1000)`, where audio length can be
 //*   2.5, 5, 10, 20, 40 or 60 milliseconds.

-			// we likely needs to subdivide/repackage
+			// if the hint was ignored, we need to subdivide/repackage
 			// frame size should be an option exposed to the user
-			// with 10ms as a default ?
 			// the larger the frame size, the less overhead but the more delay

 			auto err = _toxav.toxavAudioSendFrame(
diff --git a/src/stream_manager.hpp b/src/stream_manager.hpp
index e19aa068db8..375063983f9 100644
--- a/src/stream_manager.hpp
+++ b/src/stream_manager.hpp
@@ -169,10 +169,11 @@ class StreamManager {
 				[](Connection& con) -> void {
 					// there might be more stored
 					for (size_t i = 0; i < 10; i++) {
-						auto new_frame_opt = static_cast<inlineData*>(con.data.get())->reader->pop();
-						// TODO: frame interval estimates
+						auto* idat = static_cast<inlineData*>(con.data.get());
+						auto new_frame_opt = idat->reader->pop(idat->writer->pop_hint);
+						// TODO: frame interval estimates?
 						if (new_frame_opt.has_value()) {
-							static_cast<inlineData*>(con.data.get())->writer->push(new_frame_opt.value());
+							idat->writer->push(new_frame_opt.value());
 						} else {
 							break;
 						}

@Green-Sky Green-Sky closed this Sep 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant