Skip to content

Commit

Permalink
No public description
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 702261726
  • Loading branch information
MediaPipe Team authored and copybara-github committed Dec 3, 2024
1 parent 2d2932f commit b746d22
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 2 deletions.
10 changes: 10 additions & 0 deletions mediapipe/framework/formats/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -688,3 +688,13 @@ cc_test(
"//mediapipe/framework/port:status",
],
)

cc_test(
name = "yuv_image_test",
srcs = ["yuv_image_test.cc"],
deps = [
":yuv_image",
"//mediapipe/framework/port:gtest_main",
"@libyuv",
],
)
22 changes: 20 additions & 2 deletions mediapipe/framework/formats/yuv_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
#ifndef MEDIAPIPE_FRAMEWORK_FORMATS_YUV_IMAGE_H_
#define MEDIAPIPE_FRAMEWORK_FORMATS_YUV_IMAGE_H_

#include <algorithm>
#include <cstdint>
#include <functional>
#include <memory>
#include <utility>

#include "libyuv/video_common.h"

Expand Down Expand Up @@ -121,8 +123,24 @@ class YUVImage {
// YUVImage is neither copyable nor movable.
YUVImage(const YUVImage&) = delete;
YUVImage& operator=(const YUVImage&) = delete;
YUVImage(YUVImage&&) = delete;
YUVImage& operator=(YUVImage&&) = delete;
YUVImage(YUVImage&& b) { *this = std::move(b); }

YUVImage& operator=(YUVImage&& b) {
if (this != &b) {
Clear();
deallocation_function_ = std::exchange(b.deallocation_function_, nullptr);
fourcc_ = std::exchange(b.fourcc_, libyuv::FOURCC_ANY);
std::swap_ranges(data_, data_ + kMaxNumPlanes, b.data_);
std::swap_ranges(stride_, stride_ + kMaxNumPlanes, b.stride_);
width_ = std::exchange(b.width_, 0);
height_ = std::exchange(b.height_, 0);
bit_depth_ = std::exchange(b.bit_depth_, 0);
matrix_coefficients_ = std::exchange(
b.matrix_coefficients_, COLOR_MATRIX_COEFFICIENTS_UNSPECIFIED);
full_range_ = std::exchange(b.full_range_, false);
}
return *this;
}

// Convenience constructor
YUVImage(libyuv::FourCC fourcc, //
Expand Down
171 changes: 171 additions & 0 deletions mediapipe/framework/formats/yuv_image_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
#include "mediapipe/framework/formats/yuv_image.h"

#include <cstdint>
#include <utility>

#include "libyuv/video_common.h"
#include "mediapipe/framework/port/gtest.h"

namespace mediapipe {
namespace {

// See:
// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/use-after-move.html
template <class T>
void SILENCE_USE_AFTER_MOVE(T&) {}

TEST(YUVImageTest, TestInitializeAndDestruct) {
uint8_t data0 = 0, data1 = 1, data2 = 2;
const libyuv::FourCC fourcc = libyuv::FOURCC_I420;
const int stride0 = 100, stride1 = 50, stride2 = 50;
const int width = 100, height = 60;
const int bit_depth = 4;
int deallocation_counter = 0;
auto deallocation_function = [&deallocation_counter] {
++deallocation_counter;
};
{
YUVImage yuv_image;
yuv_image.Initialize(fourcc, deallocation_function, //
&data0, stride0, //
&data1, stride1, //
&data2, stride2, //
width, height, bit_depth);

EXPECT_EQ(yuv_image.fourcc(), fourcc);
EXPECT_EQ(yuv_image.data(0), &data0);
EXPECT_EQ(yuv_image.data(1), &data1);
EXPECT_EQ(yuv_image.data(2), &data2);
EXPECT_EQ(yuv_image.stride(0), stride0);
EXPECT_EQ(yuv_image.stride(1), stride1);
EXPECT_EQ(yuv_image.stride(2), stride2);
EXPECT_EQ(yuv_image.width(), width);
EXPECT_EQ(yuv_image.height(), height);
EXPECT_EQ(yuv_image.bit_depth(), bit_depth);
}
EXPECT_EQ(deallocation_counter, 1);
}

TEST(YUVImageTest, TestMoveConstructor) {
uint8_t data0 = 0, data1 = 1, data2 = 2;
const libyuv::FourCC fourcc = libyuv::FOURCC_I420;
const int stride0 = 100, stride1 = 50, stride2 = 50;
const int width = 100, height = 60;
const int bit_depth = 4;
int deallocation_counter = 0;
auto deallocation_function = [&deallocation_counter] {
++deallocation_counter;
};
{
YUVImage yuv_image;
yuv_image.Initialize(fourcc, deallocation_function, //
&data0, stride0, //
&data1, stride1, //
&data2, stride2, //
width, height, bit_depth);

EXPECT_EQ(yuv_image.fourcc(), fourcc);
EXPECT_EQ(yuv_image.data(0), &data0);
EXPECT_EQ(yuv_image.data(1), &data1);
EXPECT_EQ(yuv_image.data(2), &data2);
EXPECT_EQ(yuv_image.stride(0), stride0);
EXPECT_EQ(yuv_image.stride(1), stride1);
EXPECT_EQ(yuv_image.stride(2), stride2);
EXPECT_EQ(yuv_image.width(), width);
EXPECT_EQ(yuv_image.height(), height);
EXPECT_EQ(yuv_image.bit_depth(), bit_depth);

YUVImage yuv_image2(std::move(yuv_image));

// ClangTidy will complain about accessing yuv_image after it has been moved
// from. The C++ standard says that "moved-from objects shall be placed in a
// valid but unspecified state". These tests are here to ensure that.
SILENCE_USE_AFTER_MOVE(yuv_image);
EXPECT_EQ(yuv_image.fourcc(), libyuv::FOURCC_ANY);
EXPECT_EQ(yuv_image.data(0), nullptr);
EXPECT_EQ(yuv_image.data(1), nullptr);
EXPECT_EQ(yuv_image.data(2), nullptr);
EXPECT_EQ(yuv_image.stride(0), 0);
EXPECT_EQ(yuv_image.stride(1), 0);
EXPECT_EQ(yuv_image.stride(2), 0);
EXPECT_EQ(yuv_image.width(), 0);
EXPECT_EQ(yuv_image.height(), 0);
EXPECT_EQ(yuv_image.bit_depth(), 0);

EXPECT_EQ(yuv_image2.fourcc(), fourcc);
EXPECT_EQ(yuv_image2.data(0), &data0);
EXPECT_EQ(yuv_image2.data(1), &data1);
EXPECT_EQ(yuv_image2.data(2), &data2);
EXPECT_EQ(yuv_image2.stride(0), stride0);
EXPECT_EQ(yuv_image2.stride(1), stride1);
EXPECT_EQ(yuv_image2.stride(2), stride2);
EXPECT_EQ(yuv_image2.width(), width);
EXPECT_EQ(yuv_image2.height(), height);
EXPECT_EQ(yuv_image2.bit_depth(), bit_depth);
}
EXPECT_EQ(deallocation_counter, 1);
}

TEST(YUVImageTest, TestMoveAssignment) {
uint8_t data0 = 0, data1 = 1, data2 = 2;
const libyuv::FourCC fourcc = libyuv::FOURCC_I420;
const int stride0 = 100, stride1 = 50, stride2 = 50;
const int width = 100, height = 60;
const int bit_depth = 4;
int deallocation_counter = 0;
auto deallocation_function = [&deallocation_counter] {
++deallocation_counter;
};
{
YUVImage yuv_image;
yuv_image.Initialize(fourcc, deallocation_function, //
&data0, stride0, //
&data1, stride1, //
&data2, stride2, //
width, height, bit_depth);

EXPECT_EQ(yuv_image.fourcc(), fourcc);
EXPECT_EQ(yuv_image.data(0), &data0);
EXPECT_EQ(yuv_image.data(1), &data1);
EXPECT_EQ(yuv_image.data(2), &data2);
EXPECT_EQ(yuv_image.stride(0), stride0);
EXPECT_EQ(yuv_image.stride(1), stride1);
EXPECT_EQ(yuv_image.stride(2), stride2);
EXPECT_EQ(yuv_image.width(), width);
EXPECT_EQ(yuv_image.height(), height);
EXPECT_EQ(yuv_image.bit_depth(), bit_depth);

YUVImage yuv_image2;
yuv_image2 = std::move(yuv_image);

// ClangTidy will complain about accessing yuv_image after it has been moved
// from. The C++ standard says that "moved-from objects shall be placed in a
// valid but unspecified state". These tests are here to ensure that.
SILENCE_USE_AFTER_MOVE(yuv_image);
EXPECT_EQ(yuv_image.fourcc(), libyuv::FOURCC_ANY);
EXPECT_EQ(yuv_image.data(0), nullptr);
EXPECT_EQ(yuv_image.data(1), nullptr);
EXPECT_EQ(yuv_image.data(2), nullptr);
EXPECT_EQ(yuv_image.stride(0), 0);
EXPECT_EQ(yuv_image.stride(1), 0);
EXPECT_EQ(yuv_image.stride(2), 0);
EXPECT_EQ(yuv_image.width(), 0);
EXPECT_EQ(yuv_image.height(), 0);
EXPECT_EQ(yuv_image.bit_depth(), 0);

EXPECT_EQ(yuv_image2.fourcc(), fourcc);
EXPECT_EQ(yuv_image2.data(0), &data0);
EXPECT_EQ(yuv_image2.data(1), &data1);
EXPECT_EQ(yuv_image2.data(2), &data2);
EXPECT_EQ(yuv_image2.stride(0), stride0);
EXPECT_EQ(yuv_image2.stride(1), stride1);
EXPECT_EQ(yuv_image2.stride(2), stride2);
EXPECT_EQ(yuv_image2.width(), width);
EXPECT_EQ(yuv_image2.height(), height);
EXPECT_EQ(yuv_image2.bit_depth(), bit_depth);
}
EXPECT_EQ(deallocation_counter, 1);
}

} // namespace
} // namespace mediapipe

0 comments on commit b746d22

Please sign in to comment.