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
84
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/macro_support.h
vendored
Normal file
84
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/macro_support.h
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// 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 UTIL_TRACE_LOGGING_MACRO_SUPPORT_H_
|
||||
#define UTIL_TRACE_LOGGING_MACRO_SUPPORT_H_
|
||||
|
||||
#ifndef INCLUDING_FROM_UTIL_TRACE_LOGGING_H_
|
||||
#error "Do not include this header directly. Use util/trace_logging.h."
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_TRACE_LOGGING
|
||||
#error "BUG: This file should not have been reached."
|
||||
#endif
|
||||
|
||||
#include "platform/api/trace_logging_platform.h"
|
||||
#include "platform/base/trace_logging_activation.h"
|
||||
#include "platform/base/trace_logging_types.h"
|
||||
#include "util/trace_logging/scoped_trace_operations.h"
|
||||
|
||||
// Helper macros. These are used to simplify the macros below.
|
||||
// NOTE: These cannot be #undef'd or they will stop working outside this file.
|
||||
// NOTE: Two of these below macros are intentionally the same. This is to work
|
||||
// around optimizations in the C++ Precompiler.
|
||||
#define TRACE_INTERNAL_CONCAT(a, b) a##b
|
||||
#define TRACE_INTERNAL_CONCAT_CONST(a, b) TRACE_INTERNAL_CONCAT(a, b)
|
||||
#define TRACE_INTERNAL_UNIQUE_VAR_NAME(a) \
|
||||
TRACE_INTERNAL_CONCAT_CONST(a, __LINE__)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
inline bool IsTraceLoggingEnabled(TraceCategory category) {
|
||||
const CurrentTracingDestination destination;
|
||||
return destination && destination->IsTraceLoggingEnabled(category);
|
||||
}
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#define TRACE_IS_ENABLED(category) \
|
||||
openscreen::internal::IsTraceLoggingEnabled(category)
|
||||
|
||||
// Internal logging macros.
|
||||
#define TRACE_SET_HIERARCHY_INTERNAL(line, ids) \
|
||||
alignas(32) uint8_t TRACE_INTERNAL_CONCAT_CONST( \
|
||||
tracing_storage, line)[sizeof(openscreen::internal::TraceIdSetter)]; \
|
||||
[[maybe_unused]] \
|
||||
const auto TRACE_INTERNAL_UNIQUE_VAR_NAME(trace_ref_) = \
|
||||
TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
||||
? openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::TraceIdSetter>:: \
|
||||
Create(TRACE_INTERNAL_CONCAT_CONST(tracing_storage, line), \
|
||||
ids) \
|
||||
: openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::TraceIdSetter>::Empty()
|
||||
|
||||
#define TRACE_SCOPED_INTERNAL(line, category, name, ...) \
|
||||
alignas(32) uint8_t TRACE_INTERNAL_CONCAT_CONST( \
|
||||
tracing_storage, \
|
||||
line)[sizeof(openscreen::internal::SynchronousTraceLogger)]; \
|
||||
[[maybe_unused]] \
|
||||
const auto TRACE_INTERNAL_UNIQUE_VAR_NAME(trace_ref_) = \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::SynchronousTraceLogger>:: \
|
||||
Create(TRACE_INTERNAL_CONCAT_CONST(tracing_storage, line), \
|
||||
category, name, __FILE__, __LINE__, ##__VA_ARGS__) \
|
||||
: openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::SynchronousTraceLogger>::Empty()
|
||||
|
||||
#define TRACE_ASYNC_START_INTERNAL(line, category, name, ...) \
|
||||
alignas(32) uint8_t TRACE_INTERNAL_CONCAT_CONST( \
|
||||
temp_storage, \
|
||||
line)[sizeof(openscreen::internal::AsynchronousTraceLogger)]; \
|
||||
[[maybe_unused]] \
|
||||
const auto TRACE_INTERNAL_UNIQUE_VAR_NAME(trace_ref_) = \
|
||||
TRACE_IS_ENABLED(category) \
|
||||
? openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::AsynchronousTraceLogger>:: \
|
||||
Create(TRACE_INTERNAL_CONCAT_CONST(temp_storage, line), \
|
||||
category, name, __FILE__, __LINE__, ##__VA_ARGS__) \
|
||||
: openscreen::internal::TraceInstanceHelper< \
|
||||
openscreen::internal::AsynchronousTraceLogger>::Empty()
|
||||
|
||||
#endif // UTIL_TRACE_LOGGING_MACRO_SUPPORT_H_
|
||||
160
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.cc
vendored
Normal file
160
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.cc
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "util/trace_logging/scoped_trace_operations.h"
|
||||
|
||||
#include "platform/api/trace_logging_platform.h"
|
||||
#include "platform/base/trace_logging_activation.h"
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
#if defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
// static
|
||||
bool ScopedTraceOperation::TraceAsyncEnd(const uint32_t line,
|
||||
const char* file,
|
||||
TraceId id,
|
||||
Error::Code e) {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
TraceEvent end_event;
|
||||
end_event.start_time = Clock::now();
|
||||
end_event.line_number = line;
|
||||
end_event.file_name = file;
|
||||
end_event.ids.current = id;
|
||||
end_event.result = e;
|
||||
destination->LogAsyncEnd(std::move(end_event));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool ScopedTraceOperation::TraceFlow(
|
||||
TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
uint64_t flow_id,
|
||||
FlowType type,
|
||||
std::optional<Clock::time_point> timestamp) {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
const auto start_time = timestamp ? *timestamp : Clock::now();
|
||||
TraceEvent event(category, start_time, name, file, line);
|
||||
event.flow_ids.push_back(flow_id);
|
||||
destination->LogFlow(std::move(event), type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedTraceOperation::ScopedTraceOperation(TraceId trace_id,
|
||||
TraceId parent_id,
|
||||
TraceId root_id) {
|
||||
if (traces_ == nullptr) {
|
||||
// Create the stack if it doesnt' exist.
|
||||
traces_ = new TraceStack();
|
||||
|
||||
// Create a new root node. This will re-call this constructor and add the
|
||||
// root node to the stack before proceeding with the original node.
|
||||
root_node_ = new TraceIdSetter(TraceIdHierarchy::Empty());
|
||||
OSP_CHECK(!traces_->empty());
|
||||
}
|
||||
|
||||
// Setting trace id fields.
|
||||
root_id_ = root_id != kUnsetTraceId ? root_id : traces_->top()->root_id_;
|
||||
parent_id_ =
|
||||
parent_id != kUnsetTraceId ? parent_id : traces_->top()->trace_id_;
|
||||
trace_id_ =
|
||||
trace_id != kUnsetTraceId ? trace_id : trace_id_counter_.fetch_add(1);
|
||||
|
||||
// Add this item to the stack.
|
||||
traces_->push(this);
|
||||
OSP_CHECK_LT(traces_->size(), 1024);
|
||||
}
|
||||
|
||||
ScopedTraceOperation::~ScopedTraceOperation() {
|
||||
OSP_CHECK(traces_ != nullptr && !traces_->empty());
|
||||
OSP_CHECK_EQ(traces_->top(), this);
|
||||
traces_->pop();
|
||||
|
||||
// If there's only one item left, it must be the root node. Deleting the root
|
||||
// node will re-call this destructor and delete the traces_ stack.
|
||||
if (traces_->size() == 1) {
|
||||
OSP_CHECK_EQ(traces_->top(), root_node_);
|
||||
delete root_node_;
|
||||
root_node_ = nullptr;
|
||||
} else if (traces_->empty()) {
|
||||
delete traces_;
|
||||
traces_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
thread_local ScopedTraceOperation::TraceStack* ScopedTraceOperation::traces_ =
|
||||
nullptr;
|
||||
|
||||
// static
|
||||
thread_local ScopedTraceOperation* ScopedTraceOperation::root_node_ = nullptr;
|
||||
|
||||
// static
|
||||
std::atomic<std::uint64_t> ScopedTraceOperation::trace_id_counter_{
|
||||
uint64_t{0x01} << (sizeof(TraceId) * 8 - 1)};
|
||||
|
||||
TraceLoggerBase::TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments,
|
||||
TraceId current,
|
||||
TraceId parent,
|
||||
TraceId root)
|
||||
: ScopedTraceOperation(current, parent, root),
|
||||
event_(category, Clock::now(), name, file, line) {
|
||||
event_.arguments = std::move(arguments);
|
||||
event_.TruncateStrings();
|
||||
}
|
||||
|
||||
TraceLoggerBase::TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments,
|
||||
TraceIdHierarchy ids)
|
||||
: TraceLoggerBase(category,
|
||||
name,
|
||||
file,
|
||||
line,
|
||||
std::move(arguments),
|
||||
ids.current,
|
||||
ids.parent,
|
||||
ids.root) {}
|
||||
|
||||
SynchronousTraceLogger::~SynchronousTraceLogger() {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
const auto end_time = Clock::now();
|
||||
event_.ids = to_hierarchy();
|
||||
destination->LogTrace(event_, end_time);
|
||||
}
|
||||
}
|
||||
|
||||
AsynchronousTraceLogger::~AsynchronousTraceLogger() {
|
||||
const CurrentTracingDestination destination;
|
||||
if (destination) {
|
||||
event_.ids = to_hierarchy();
|
||||
destination->LogAsyncStart(event_);
|
||||
}
|
||||
}
|
||||
|
||||
TraceIdSetter::TraceIdSetter(TraceIdHierarchy ids)
|
||||
: ScopedTraceOperation(ids.current, ids.parent, ids.root) {}
|
||||
|
||||
TraceIdSetter::~TraceIdSetter() = default;
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#endif // defined(ENABLE_TRACE_LOGGING)
|
||||
224
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.h
vendored
Normal file
224
breadcast-caststream-sys/vendor/openscreen/util/trace_logging/scoped_trace_operations.h
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
// 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 UTIL_TRACE_LOGGING_SCOPED_TRACE_OPERATIONS_H_
|
||||
#define UTIL_TRACE_LOGGING_SCOPED_TRACE_OPERATIONS_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "platform/api/time.h"
|
||||
#include "platform/api/trace_logging_platform.h"
|
||||
#include "platform/base/error.h"
|
||||
#include "platform/base/trace_logging_types.h"
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
#if defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
namespace openscreen::internal {
|
||||
|
||||
// A base class for all trace logging objects which will create new entries in
|
||||
// the Trace Hierarchy.
|
||||
// 1) The sharing of all static and thread_local variables across template
|
||||
// specializations.
|
||||
// 2) Including all children in the same traces vector.
|
||||
class ScopedTraceOperation {
|
||||
public:
|
||||
// Define the destructor to remove this item from the stack when it's
|
||||
// destroyed.
|
||||
virtual ~ScopedTraceOperation();
|
||||
|
||||
ScopedTraceOperation(const ScopedTraceOperation&) = delete;
|
||||
ScopedTraceOperation(ScopedTraceOperation&&) noexcept = delete;
|
||||
ScopedTraceOperation& operator=(const ScopedTraceOperation&) = delete;
|
||||
ScopedTraceOperation& operator=(ScopedTraceOperation&&) = delete;
|
||||
|
||||
// Getters the current Trace Hierarchy. If the traces_ stack hasn't been
|
||||
// created yet, return as if the empty root node is there.
|
||||
static TraceId current_id() {
|
||||
return traces_ == nullptr ? kEmptyTraceId : traces_->top()->trace_id_;
|
||||
}
|
||||
|
||||
static TraceId root_id() {
|
||||
return traces_ == nullptr ? kEmptyTraceId : traces_->top()->root_id_;
|
||||
}
|
||||
|
||||
static TraceIdHierarchy hierarchy() {
|
||||
if (traces_ == nullptr) {
|
||||
return TraceIdHierarchy::Empty();
|
||||
}
|
||||
|
||||
return traces_->top()->to_hierarchy();
|
||||
}
|
||||
|
||||
// Static method to set the result of the most recent trace.
|
||||
static void set_result(const Error& error) { set_result(error.code()); }
|
||||
static void set_result(Error::Code error) {
|
||||
if (traces_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
traces_->top()->SetTraceResult(error);
|
||||
}
|
||||
|
||||
// Traces the end of an asynchronous call.
|
||||
// NOTE: This returns a bool rather than a void because it keeps the syntax of
|
||||
// the ternary operator in the macros simpler.
|
||||
static bool TraceAsyncEnd(const uint32_t line,
|
||||
const char* file,
|
||||
TraceId id,
|
||||
Error::Code e);
|
||||
|
||||
// Traces a flow event.
|
||||
static bool TraceFlow(
|
||||
TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
uint64_t flow_id,
|
||||
FlowType type,
|
||||
std::optional<Clock::time_point> timestamp = std::nullopt);
|
||||
|
||||
protected:
|
||||
// Sets the result of this trace log.
|
||||
// NOTE: this must be define in this class rather than TraceLogger so that it
|
||||
// can be called on traces.back() without a potentially unsafe cast or type
|
||||
// checking at runtime.
|
||||
virtual void SetTraceResult(Error::Code error) = 0;
|
||||
|
||||
// Constructor to set all trace id information.
|
||||
ScopedTraceOperation(TraceId current_id = kUnsetTraceId,
|
||||
TraceId parent_id = kUnsetTraceId,
|
||||
TraceId root_id = kUnsetTraceId);
|
||||
|
||||
// Current TraceId information.
|
||||
TraceId trace_id_;
|
||||
TraceId parent_id_;
|
||||
TraceId root_id_;
|
||||
|
||||
TraceIdHierarchy to_hierarchy() { return {trace_id_, parent_id_, root_id_}; }
|
||||
|
||||
private:
|
||||
// NOTE: A std::vector is used for backing the stack because it provides the
|
||||
// best perf. Further perf improvement could be achieved later by swapping
|
||||
// this out for a circular buffer once OSP supports that. Additional details
|
||||
// can be found here:
|
||||
// https://www.codeproject.com/Articles/1185449/Performance-of-a-Circular-Buffer-vs-Vector-Deque-a
|
||||
using TraceStack =
|
||||
std::stack<ScopedTraceOperation*, std::vector<ScopedTraceOperation*>>;
|
||||
|
||||
// Counter to pick IDs when it is not provided.
|
||||
static std::atomic<std::uint64_t> trace_id_counter_;
|
||||
|
||||
// The LIFO stack of TraceLoggers currently being watched by this
|
||||
// thread.
|
||||
static thread_local TraceStack* traces_;
|
||||
static thread_local ScopedTraceOperation* root_node_;
|
||||
};
|
||||
|
||||
// The class which does actual trace logging.
|
||||
class TraceLoggerBase : public ScopedTraceOperation {
|
||||
public:
|
||||
TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments = {},
|
||||
TraceId current = kUnsetTraceId,
|
||||
TraceId parent = kUnsetTraceId,
|
||||
TraceId root = kUnsetTraceId);
|
||||
|
||||
TraceLoggerBase(TraceCategory category,
|
||||
const char* name,
|
||||
const char* file,
|
||||
uint32_t line,
|
||||
std::vector<TraceEvent::Argument> arguments,
|
||||
TraceIdHierarchy ids);
|
||||
|
||||
TraceLoggerBase(const TraceLoggerBase&) = delete;
|
||||
TraceLoggerBase(TraceLoggerBase&&) noexcept = delete;
|
||||
TraceLoggerBase& operator=(const TraceLoggerBase&) = delete;
|
||||
TraceLoggerBase& operator=(TraceLoggerBase&&) = delete;
|
||||
|
||||
protected:
|
||||
// Set the result.
|
||||
void SetTraceResult(Error::Code error) override { event_.result = error; }
|
||||
|
||||
TraceEvent event_;
|
||||
};
|
||||
|
||||
class SynchronousTraceLogger : public TraceLoggerBase {
|
||||
public:
|
||||
using TraceLoggerBase::TraceLoggerBase;
|
||||
|
||||
SynchronousTraceLogger(const SynchronousTraceLogger&) = delete;
|
||||
SynchronousTraceLogger(SynchronousTraceLogger&&) noexcept = delete;
|
||||
SynchronousTraceLogger& operator=(const SynchronousTraceLogger&) = delete;
|
||||
SynchronousTraceLogger& operator=(SynchronousTraceLogger&&) = delete;
|
||||
|
||||
~SynchronousTraceLogger() override;
|
||||
};
|
||||
|
||||
class AsynchronousTraceLogger : public TraceLoggerBase {
|
||||
public:
|
||||
using TraceLoggerBase::TraceLoggerBase;
|
||||
|
||||
AsynchronousTraceLogger(const AsynchronousTraceLogger&) = delete;
|
||||
AsynchronousTraceLogger(AsynchronousTraceLogger&&) noexcept = delete;
|
||||
AsynchronousTraceLogger& operator=(const AsynchronousTraceLogger&) = delete;
|
||||
AsynchronousTraceLogger& operator=(AsynchronousTraceLogger&&) = delete;
|
||||
|
||||
~AsynchronousTraceLogger() override;
|
||||
};
|
||||
|
||||
// Inserts a fake element into the ScopedTraceOperation stack to set
|
||||
// the current TraceId Hierarchy manually.
|
||||
class TraceIdSetter final : public ScopedTraceOperation {
|
||||
public:
|
||||
explicit TraceIdSetter(TraceIdHierarchy ids);
|
||||
TraceIdSetter(const TraceIdSetter&) = delete;
|
||||
TraceIdSetter(TraceIdSetter&&) noexcept = delete;
|
||||
TraceIdSetter& operator=(const TraceIdSetter&) = delete;
|
||||
TraceIdSetter& operator=(TraceIdSetter&&) = delete;
|
||||
~TraceIdSetter() final;
|
||||
|
||||
// Creates a new TraceIdSetter to set the full TraceId Hierarchy to default
|
||||
// values and does not push it to the traces stack.
|
||||
static TraceIdSetter* CreateStackRootNode();
|
||||
|
||||
private:
|
||||
// Implement abstract method for use in Macros.
|
||||
void SetTraceResult(Error::Code error) {}
|
||||
};
|
||||
|
||||
// This helper object allows us to delete objects allocated on the stack in a
|
||||
// unique_ptr.
|
||||
template <class T>
|
||||
class TraceInstanceHelper {
|
||||
private:
|
||||
class TraceOperationOnStackDeleter {
|
||||
public:
|
||||
void operator()(T* ptr) { ptr->~T(); }
|
||||
};
|
||||
|
||||
using TraceInstanceWrapper = std::unique_ptr<T, TraceOperationOnStackDeleter>;
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
static TraceInstanceWrapper Create(uint8_t storage[sizeof(T)], Args... args) {
|
||||
return TraceInstanceWrapper(new (storage) T(std::forward<Args&&>(args)...));
|
||||
}
|
||||
|
||||
static TraceInstanceWrapper Empty() { return TraceInstanceWrapper(); }
|
||||
};
|
||||
|
||||
} // namespace openscreen::internal
|
||||
|
||||
#endif // defined(ENABLE_TRACE_LOGGING)
|
||||
|
||||
#endif // UTIL_TRACE_LOGGING_SCOPED_TRACE_OPERATIONS_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue