所有权指针明确

This commit is contained in:
2026-08-28 13:33:17 +08:00
parent 0bc281b6b9
commit e07d16ea74
70 changed files with 1387 additions and 960 deletions
+2 -2
View File
@@ -284,8 +284,8 @@ void Gallery_Video_Stream::Private::update_metrics(
metric_pixel_start = pixel_frame_count;
metric_sample_start = sampler_state.sampled_frames;
metric_clock_start = clock_total;
object->template update_state<&State::diagnostics>(std::move(output));
object->template publish_state<Base_Tag>();
(*object)->template update_state<&State::diagnostics>(std::move(output));
(*object)->template publish_state<Base_Tag>();
}
void Gallery_Video_Stream::Private::sample_media_frame() {
active_sample.reset();
+3 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "frame_sampling/Frame_Sampler.hpp"
#include <frame_statistics.hpp>
#include <ownership.hpp>
#include <atomic>
#include <chrono>
namespace aethera::web {
@@ -19,7 +20,7 @@ struct Gallery_Video_Stream::Private : Prev_Private {
std::shared_ptr<const Transport_Diagnostics> diagnostics{}; /* 连接自己的传输诊断来源。 */
};
using Consumers = std::vector<Consumer>;
Object* object{}; /* Def 机制所属最终对象。 */
std::optional<not_null<Object*>> object{}; /* Def 机制所属最终对象bind_private_crtp 后有效。 */
Sliding_Statistics compose_ms{600}; /* 图集采样与变更槽复制统计计算器。 */
Sliding_Statistics sample_delay_ms{600}; /* 固定 deadline 到实际采样的调度延迟。 */
Sliding_Statistics encode_ms{600}; /* H.264 编码统计计算器。 */
@@ -54,7 +55,7 @@ struct Gallery_Video_Stream::Private : Prev_Private {
template <Attached Attached_Object>
void bind_private_crtp(Attached_Object* attached) {
Prev_Private::bind_private_crtp(attached);
object = static_cast<Object*>(attached);
object = not_null{static_cast<Object*>(attached)};
}
void initialize(std::vector<Plot_Entry> plots);
[[nodiscard]] bool consumer_accepts(
+27 -23
View File
@@ -1,4 +1,5 @@
#include "H264_Encoder.hpp"
#include <ownership.hpp>
#include <algorithm>
#include <array>
#include <cmath>
@@ -138,12 +139,12 @@ struct H264_Encoder::Private {
}
double frame_rate{}; /* 页面媒体时钟频率,也是 GOP 的计算基准。 */
AVCodecContext* codec_context{}; /* 当前图集尺寸对应的唯一硬件编码上下文。 */
AVFrame* software_frame{}; /* 当前硬件路径需要的复用 CPU 输入帧。 */
AVPacket* packet{}; /* 接收单个 H.264 access unit 的复用包。 */
AVBufferRef* hardware_device{}; /* Vulkan Video 后端的 FFmpeg Device。 */
AVBufferRef* hardware_frames{}; /* Vulkan Video NV12 帧池。 */
SwsContext* converter{}; /* Vulkan Video 的 RGBA/BGRA 到 NV12 转换器。 */
owner<AVCodecContext*> codec_context{}; /* 当前图集尺寸对应的唯一硬件编码上下文。 */
owner<AVFrame*> software_frame{}; /* 当前硬件路径需要的复用 CPU 输入帧。 */
owner<AVPacket*> packet{}; /* 接收单个 H.264 access unit 的复用包。 */
owner<AVBufferRef*> hardware_device{}; /* Vulkan Video 后端的 FFmpeg Device。 */
owner<AVBufferRef*> hardware_frames{}; /* Vulkan Video NV12 帧池。 */
owner<SwsContext*> converter{}; /* Vulkan Video 的 RGBA/BGRA 到 NV12 转换器。 */
std::optional<Video_Encoder_Backend> backend{}; /* 当前成功配置的唯一实际编码后端。 */
std::deque<Submitted_Frame> submitted_frames{}; /* 延迟输出 access unit 的身份队列。 */
std::uint32_t width{}; /* 当前硬件编码图集宽度。 */
@@ -221,12 +222,13 @@ struct H264_Encoder::Private {
Configuration configure_nvenc(std::uint32_t next_width,
std::uint32_t next_height,
Video_Pixel_Layout next_layout) const {
const AVCodec* codec = avcodec_find_encoder_by_name("h264_nvenc");
if (!codec)
const auto codec_address = avcodec_find_encoder_by_name("h264_nvenc");
if (!codec_address)
throw std::runtime_error("FFmpeg h264_nvenc encoder is unavailable");
const not_null<const AVCodec*> codec{codec_address};
Configuration result;
result.backend = Video_Encoder_Backend::nvenc;
result.codec_context.reset(avcodec_alloc_context3(codec));
result.codec_context.reset(avcodec_alloc_context3(codec.get()));
if (!result.codec_context) throw std::bad_alloc{};
configure_common(*result.codec_context, next_width, next_height,
input_pixel_format(next_layout));
@@ -263,7 +265,7 @@ struct H264_Encoder::Private {
require_ffmpeg(av_opt_set_int(result.codec_context->priv_data,
"no-scenecut", 1, 0),
"disabling NVENC scene-cut frames");
require_ffmpeg(avcodec_open2(result.codec_context.get(), codec, nullptr),
require_ffmpeg(avcodec_open2(result.codec_context.get(), codec.get(), nullptr),
"opening h264_nvenc encoder");
result.software_frame = make_software_frame(
result.codec_context->pix_fmt, next_width, next_height,
@@ -276,12 +278,13 @@ struct H264_Encoder::Private {
Configuration configure_vulkan(std::uint32_t next_width,
std::uint32_t next_height,
Video_Pixel_Layout next_layout) const {
const AVCodec* codec = avcodec_find_encoder_by_name("h264_vulkan");
if (!codec)
const auto codec_address = avcodec_find_encoder_by_name("h264_vulkan");
if (!codec_address)
throw std::runtime_error("FFmpeg h264_vulkan encoder is unavailable");
const not_null<const AVCodec*> codec{codec_address};
Configuration result;
result.backend = Video_Encoder_Backend::vulkan_video;
AVBufferRef* device{};
owner<AVBufferRef*> device{};
require_ffmpeg(av_hwdevice_ctx_create(
&device, AV_HWDEVICE_TYPE_VULKAN,
nullptr, nullptr, 0),
@@ -290,8 +293,9 @@ struct H264_Encoder::Private {
result.hardware_frames.reset(
av_hwframe_ctx_alloc(result.hardware_device.get()));
if (!result.hardware_frames) throw std::bad_alloc{};
auto* frames = reinterpret_cast<AVHWFramesContext*>(
result.hardware_frames->data);
const not_null<AVHWFramesContext*> frames{
reinterpret_cast<AVHWFramesContext*>(
result.hardware_frames->data)};
frames->format = AV_PIX_FMT_VULKAN;
frames->sw_format = AV_PIX_FMT_NV12;
frames->width = static_cast<int>(next_width);
@@ -300,7 +304,7 @@ struct H264_Encoder::Private {
require_ffmpeg(av_hwframe_ctx_init(result.hardware_frames.get()),
"creating the Vulkan Video NV12 frame pool");
result.codec_context.reset(avcodec_alloc_context3(codec));
result.codec_context.reset(avcodec_alloc_context3(codec.get()));
if (!result.codec_context) throw std::bad_alloc{};
configure_common(*result.codec_context, next_width, next_height,
AV_PIX_FMT_VULKAN);
@@ -331,7 +335,7 @@ struct H264_Encoder::Private {
require_ffmpeg(av_opt_set_int(result.codec_context->priv_data,
"async_depth", 3, 0),
"setting Vulkan Video pipeline depth");
require_ffmpeg(avcodec_open2(result.codec_context.get(), codec, nullptr),
require_ffmpeg(avcodec_open2(result.codec_context.get(), codec.get(), nullptr),
"opening h264_vulkan encoder");
result.software_frame = make_software_frame(
@@ -488,10 +492,10 @@ std::optional<Encoded_Video_Frame> H264_Encoder::encode(
d->fill_software_frame(pixels);
Frame_Owner hardware_frame;
AVFrame* input = d->software_frame;
not_null<AVFrame*> input{d->software_frame};
if (d->backend == Video_Encoder_Backend::vulkan_video) {
hardware_frame = d->make_vulkan_frame();
input = hardware_frame.get();
input = not_null{hardware_frame.get()};
}
input->pts = presentation_time.count();
input->duration = static_cast<std::int64_t>(
@@ -501,7 +505,7 @@ std::optional<Encoded_Video_Frame> H264_Encoder::encode(
: AV_PICTURE_TYPE_NONE;
d->submitted_frames.push_back({sequence, presentation_time});
const int submitted = avcodec_send_frame(d->codec_context, input);
const int submitted = avcodec_send_frame(d->codec_context, input.get());
if (submitted < 0) {
d->submitted_frames.pop_back();
throw ffmpeg_failure("submitting a frame to the hardware encoder",
@@ -515,9 +519,9 @@ std::optional<Encoded_Video_Frame> H264_Encoder::encode(
"receiving a H.264 access unit from the hardware encoder");
struct Packet_Unref_Scope {
AVPacket* packet{}; /* 输出复制完成或抛出后统一归还复用包。 */
~Packet_Unref_Scope() { av_packet_unref(packet); }
} packet_scope{d->packet};
not_null<AVPacket*> packet; /* 输出复制完成或抛出后统一归还复用包。 */
~Packet_Unref_Scope() { av_packet_unref(packet.get()); }
} packet_scope{not_null{d->packet}};
if (d->submitted_frames.empty())
throw std::logic_error("hardware encoder produced an uncorrelated frame");
+4 -2
View File
@@ -19,13 +19,15 @@ TEST(Gallery_Plots, Catalog_Is_Complete_And_Unique) {
EXPECT_NE(definition.create, nullptr);
EXPECT_TRUE(identifiers.insert(definition.id).second)
<< "duplicate plot id: " << definition.id;
EXPECT_EQ(find_gallery_plot_definition(definition.id), &definition);
const auto found = find_gallery_plot_definition(definition.id);
ASSERT_TRUE(found);
EXPECT_EQ(found->get(), &definition);
has_2d |= definition.dimension == Plot_Dimension::two_d;
has_3d |= definition.dimension == Plot_Dimension::three_d;
}
EXPECT_TRUE(has_2d);
EXPECT_TRUE(has_3d);
EXPECT_EQ(find_gallery_plot_definition("not-a-plot"), nullptr);
EXPECT_FALSE(find_gallery_plot_definition("not-a-plot"));
}
}
}