原始像素太卡 走ffmpeg
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <web_server/src/H264_Encoder.hpp>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace aethera::web {
|
||||
namespace {
|
||||
std::vector<std::byte> test_pattern(std::uint32_t width,
|
||||
std::uint32_t height) {
|
||||
std::vector<std::byte> result(
|
||||
static_cast<std::size_t>(width) * height * 4U);
|
||||
for (std::uint32_t y = 0; y < height; ++y) {
|
||||
for (std::uint32_t x = 0; x < width; ++x) {
|
||||
const auto offset =
|
||||
(static_cast<std::size_t>(y) * width + x) * 4U;
|
||||
result[offset] =
|
||||
std::byte{static_cast<std::uint8_t>(x)};
|
||||
result[offset + 1U] =
|
||||
std::byte{static_cast<std::uint8_t>(y)};
|
||||
result[offset + 2U] =
|
||||
std::byte{static_cast<std::uint8_t>(x ^ y)};
|
||||
result[offset + 3U] = std::byte{255};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(H264_Encoder, Rejects_Invalid_Input_Before_FFmpeg) {
|
||||
H264_Encoder encoder(30.0);
|
||||
const auto pixels = test_pattern(320, 180);
|
||||
EXPECT_THROW(static_cast<void>(encoder.encode(
|
||||
pixels, 319, 180, Video_Pixel_Layout::rgba,
|
||||
1, std::chrono::microseconds{33'333})),
|
||||
std::invalid_argument);
|
||||
EXPECT_THROW(static_cast<void>(encoder.encode(
|
||||
std::span<const std::byte>{pixels}.first(
|
||||
pixels.size() - 1U),
|
||||
320, 180, Video_Pixel_Layout::rgba,
|
||||
1, std::chrono::microseconds{33'333})),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(H264_Encoder, Libx264_Produces_Ordered_Annex_B_Access_Units) {
|
||||
/* 四个 720x420 Plot 组成的一行真实 Gallery 图集。 */
|
||||
constexpr std::uint32_t width{2'880};
|
||||
constexpr std::uint32_t height{420};
|
||||
H264_Encoder encoder(30.0);
|
||||
auto pixels = test_pattern(width, height);
|
||||
std::optional<Encoded_Video_Frame> first;
|
||||
std::uint64_t produced{};
|
||||
for (std::uint64_t sequence = 1; sequence <= 4; ++sequence) {
|
||||
pixels[0] = std::byte{static_cast<std::uint8_t>(sequence)};
|
||||
auto encoded = encoder.encode(
|
||||
pixels, width, height, Video_Pixel_Layout::rgba, sequence,
|
||||
std::chrono::microseconds{
|
||||
static_cast<std::int64_t>(sequence * 33'333)});
|
||||
if (!encoded) continue;
|
||||
if (!first) first = encoded;
|
||||
EXPECT_EQ(encoded->sequence, sequence);
|
||||
EXPECT_EQ(encoded->backend, Video_Encoder_Backend::libx264);
|
||||
EXPECT_FALSE(encoded->annex_b.empty());
|
||||
++produced;
|
||||
}
|
||||
ASSERT_TRUE(first);
|
||||
EXPECT_TRUE(first->key_frame);
|
||||
ASSERT_GE(first->annex_b.size(), 4U);
|
||||
EXPECT_EQ(first->annex_b[0], std::byte{0});
|
||||
EXPECT_EQ(first->annex_b[1], std::byte{0});
|
||||
EXPECT_TRUE(first->annex_b[2] == std::byte{1} ||
|
||||
(first->annex_b[2] == std::byte{0} &&
|
||||
first->annex_b[3] == std::byte{1}));
|
||||
EXPECT_EQ(produced, 4U);
|
||||
EXPECT_EQ(video_encoder_backend_name(first->backend), "libx264");
|
||||
EXPECT_EQ(h264_profile_level_id(), "640033");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user