Implement Cast Streaming mirroring, DLNA casting, daemon+GUI, and breadd integration
Some checks failed
dev release / build (push) Failing after 12s
Some checks failed
dev release / build (push) Failing after 12s
Builds out the full v1 scope: a vendored+patched openscreen subset for low-latency Cast Streaming (Mirroring receiver 0F5096E8) alongside the existing Cast V2/HLS and new DLNA/AVTransport casting paths, breadcastd's Idle/Casting state machine with a private IPC socket, the breadcast GTK4 popup as a thin IPC client, and bread.cast.*/bread.command.cast.* breadd integration (device discovery, start/stop, mirroring lifecycle events). Also adds bakery/systemd/Forgejo CI packaging. Validated end-to-end against a real Chromecast/Google TV: negotiated Cast Streaming session, live pipeline playback, and daemon+GUI click-to-cast/ stop through the actual popup.
This commit is contained in:
parent
887c29002f
commit
8c745d18e0
283 changed files with 36788 additions and 0 deletions
150
breadcast-caststream-sys/vendor/openscreen/platform/impl/task_runner.h
vendored
Normal file
150
breadcast-caststream-sys/vendor/openscreen/platform/impl/task_runner.h
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef PLATFORM_IMPL_TASK_RUNNER_H_
|
||||
#define PLATFORM_IMPL_TASK_RUNNER_H_
|
||||
|
||||
#include <condition_variable> // NOLINT
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "platform/api/task_runner.h"
|
||||
#include "platform/api/time.h"
|
||||
#include "platform/base/error.h"
|
||||
#include "util/raw_ptr.h"
|
||||
#include "util/thread_annotations.h"
|
||||
#include "util/trace_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
class TaskRunnerImpl : public TaskRunner {
|
||||
public:
|
||||
using Task = TaskRunner::Task;
|
||||
|
||||
class TaskWaiter {
|
||||
public:
|
||||
virtual ~TaskWaiter();
|
||||
|
||||
// These calls should be thread-safe. The absolute minimum is that
|
||||
// OnTaskPosted must be safe to call from another thread while this is
|
||||
// inside WaitForTaskToBePosted. NOTE: There may be spurious wakeups from
|
||||
// WaitForTaskToBePosted depending on whether the specific implementation
|
||||
// chooses to clear queued WakeUps before entering WaitForTaskToBePosted.
|
||||
|
||||
// Blocks until some event occurs, which means new tasks may have been
|
||||
// posted. Wait may only block up to `timeout` where 0 means don't block at
|
||||
// all (not block forever).
|
||||
virtual Error WaitForTaskToBePosted(Clock::duration timeout) = 0;
|
||||
|
||||
// If a WaitForTaskToBePosted call is currently blocking, unblock it
|
||||
// immediately.
|
||||
virtual void OnTaskPosted() = 0;
|
||||
};
|
||||
|
||||
explicit TaskRunnerImpl(
|
||||
ClockNowFunctionPtr now_function,
|
||||
TaskWaiter* event_waiter = nullptr,
|
||||
Clock::duration waiter_timeout = std::chrono::milliseconds(100));
|
||||
TaskRunnerImpl(const TaskRunnerImpl&) = delete;
|
||||
TaskRunnerImpl(TaskRunnerImpl&&) noexcept = delete;
|
||||
TaskRunnerImpl& operator=(const TaskRunnerImpl&) = delete;
|
||||
TaskRunnerImpl& operator=(TaskRunnerImpl&&) = delete;
|
||||
|
||||
// TaskRunner overrides
|
||||
~TaskRunnerImpl() override;
|
||||
void PostPackagedTask(Task task) override;
|
||||
void PostPackagedTaskWithDelay(Task task, Clock::duration delay) override;
|
||||
bool IsRunningOnTaskRunner() override;
|
||||
|
||||
// Blocks the current thread, executing tasks from the queue with the desired
|
||||
// timing; and does not return until some time after RequestStopSoon() is
|
||||
// called.
|
||||
virtual void RunUntilStopped();
|
||||
|
||||
// Blocks the current thread, executing tasks from the queue with the desired
|
||||
// timing; and does not return until some time after the current process is
|
||||
// signaled with SIGINT or SIGTERM, or after RequestStopSoon() is called.
|
||||
virtual void RunUntilSignaled();
|
||||
|
||||
// Thread-safe method for requesting the TaskRunner to stop running after all
|
||||
// non-delayed tasks in the queue have run. This behavior allows final
|
||||
// clean-up tasks to be executed before the TaskRunner stops.
|
||||
//
|
||||
// If any non-delayed tasks post additional non-delayed tasks, those will be
|
||||
// run as well before returning.
|
||||
virtual void RequestStopSoon();
|
||||
|
||||
private:
|
||||
#if defined(ENABLE_TRACE_LOGGING)
|
||||
// Wrapper around a Task used to store the TraceId Metadata along with the
|
||||
// task itself, and to set the current TraceIdHierarchy before executing the
|
||||
// task.
|
||||
class TaskWithMetadata {
|
||||
public:
|
||||
// NOTE: 'explicit' keyword omitted so that conversion construtor can be
|
||||
// used. This simplifies switching between 'Task' and 'TaskWithMetadata'
|
||||
// based on the compilation flag.
|
||||
TaskWithMetadata(Task task) // NOLINT
|
||||
: task_(std::move(task)), trace_ids_(TRACE_HIERARCHY) {}
|
||||
|
||||
void operator()() {
|
||||
TRACE_SET_HIERARCHY(trace_ids_);
|
||||
std::move(task_)();
|
||||
}
|
||||
|
||||
private:
|
||||
Task task_;
|
||||
TraceIdHierarchy trace_ids_;
|
||||
};
|
||||
#else // !defined(ENABLE_TRACE_LOGGING)
|
||||
using TaskWithMetadata = Task;
|
||||
#endif // defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
// Helper that runs all tasks in `running_tasks_` and then clears it.
|
||||
void RunRunnableTasks();
|
||||
|
||||
// Look at all tasks in the delayed task queue, then schedule them if the
|
||||
// minimum delay time has elapsed.
|
||||
void ScheduleDelayedTasks();
|
||||
|
||||
// Transfers all ready-to-run tasks from `tasks_` to `running_tasks_`. If
|
||||
// there are no ready-to-run tasks, and `is_running_` is true, this method
|
||||
// will block waiting for new tasks. Returns true if any tasks were
|
||||
// transferred.
|
||||
bool GrabMoreRunnableTasks() OSP_NO_THREAD_SAFETY_ANALYSIS;
|
||||
|
||||
const ClockNowFunctionPtr now_function_;
|
||||
|
||||
// Flag that indicates whether the task runner loop should continue. This is
|
||||
// only meant to be read/written on the thread executing RunUntilStopped().
|
||||
bool is_running_;
|
||||
|
||||
// This mutex is used for `tasks_` and `delayed_tasks_`, and also for
|
||||
// notifying the run loop to wake up when it is waiting for a task to be added
|
||||
// to the queue in `run_loop_wakeup_`.
|
||||
std::mutex task_mutex_;
|
||||
std::vector<TaskWithMetadata> tasks_ OSP_GUARDED_BY(task_mutex_);
|
||||
std::multimap<Clock::time_point, TaskWithMetadata> delayed_tasks_ OSP_GUARDED_BY(task_mutex_);
|
||||
|
||||
// When `task_waiter_` is nullptr, `run_loop_wakeup_` is used for sleeping the
|
||||
// task runner. Otherwise, `run_loop_wakeup_` isn't used and `task_waiter_`
|
||||
// is used instead (along with `waiter_timeout_`).
|
||||
std::condition_variable run_loop_wakeup_;
|
||||
const raw_ptr<TaskWaiter> task_waiter_;
|
||||
Clock::duration waiter_timeout_;
|
||||
|
||||
// To prevent excessive re-allocation of the underlying array of the `tasks_`
|
||||
// vector, use an A/B vector-swap mechanism. `running_tasks_` starts out
|
||||
// empty, and is swapped with `tasks_` when it is time to run the Tasks.
|
||||
std::vector<TaskWithMetadata> running_tasks_;
|
||||
|
||||
std::thread::id task_runner_thread_id_;
|
||||
};
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // PLATFORM_IMPL_TASK_RUNNER_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue