blob: eba3fab328a55c1eda7c71aa08671e4b2306456f [file] [log] [blame]
/*
* Copyright 2020 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef CAMERA_COMMON_LIBCAMERA_CONNECTOR_TEST_I420_BUFFER_H_
#define CAMERA_COMMON_LIBCAMERA_CONNECTOR_TEST_I420_BUFFER_H_
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include <linux/videodev2.h>
#include <libyuv.h>
#include "common/libcamera_connector_test/util.h"
#include "cros-camera/camera_service_connector.h"
namespace cros {
namespace tests {
class I420Buffer {
public:
explicit I420Buffer(int width = 0, int height = 0)
: width_(width), height_(height), data_(DataSize()) {}
static I420Buffer Create(const cros_cam_frame_t* frame) {
const cros_cam_format_info_t& format = frame->format;
I420Buffer buf(format.width, format.height);
const cros_cam_plane_t* planes = frame->planes;
auto expect_empty = [&](const cros_cam_plane_t& plane) {
EXPECT_EQ(plane.size, 0);
EXPECT_EQ(plane.stride, 0);
EXPECT_EQ(plane.data, nullptr);
};
switch (format.fourcc) {
case V4L2_PIX_FMT_NV12: {
expect_empty(planes[2]);
expect_empty(planes[3]);
int ret = libyuv::NV12ToI420(
planes[0].data, planes[0].stride, planes[1].data, planes[1].stride,
buf.DataY(), buf.StrideY(), buf.DataU(), buf.StrideU(), buf.DataY(),
buf.StrideV(), buf.Width(), buf.Height());
EXPECT_EQ(ret, 0) << "invalid NV12 frame";
break;
}
case V4L2_PIX_FMT_MJPEG: {
expect_empty(planes[1]);
expect_empty(planes[2]);
expect_empty(planes[3]);
int ret = libyuv::MJPGToI420(
planes[0].data, planes[0].size, buf.DataY(), buf.StrideY(),
buf.DataU(), buf.StrideU(), buf.DataV(), buf.StrideV(),
format.width, format.height, buf.Width(), buf.Height());
EXPECT_EQ(ret, 0) << "invalid MJPEG frame";
break;
}
default:
ADD_FAILURE() << "unexpected fourcc: " << FourccToString(format.fourcc);
}
return buf;
}
int Width() const { return width_; }
int Height() const { return height_; }
int StrideY() const { return width_; }
int StrideU() const { return (width_ + 1) / 2; }
int StrideV() const { return (width_ + 1) / 2; }
uint8_t* DataY() { return data_.data(); }
uint8_t* DataU() { return DataY() + StrideY() * Height(); }
uint8_t* DataV() { return DataU() + StrideU() * HalfHeight(); }
private:
int HalfHeight() const { return (height_ + 1) / 2; }
int HalfWidth() const { return (width_ + 1) / 2; }
int DataSize() const {
return StrideY() * Height() + (StrideU() + StrideV()) * HalfHeight();
}
int width_;
int height_;
std::vector<uint8_t> data_;
};
} // namespace tests
} // namespace cros
#endif // CAMERA_COMMON_LIBCAMERA_CONNECTOR_TEST_I420_BUFFER_H_