所有权指针明确
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user