// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_ASH_SERVICES_RECORDING_RGB_VIDEO_FRAME_H_
#define CHROMEOS_ASH_SERVICES_RECORDING_RGB_VIDEO_FRAME_H_
#include <cstdint>
#include <memory>
#include "base/time/time.h"
#include "media/base/video_frame.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkTypes.h"
namespace recording {
// Defines a type for conveniently accessing the color components of the pixels
// as they're natively stored in a `kN32_SkColorType`-color-type bitmap, and
// comparing instances while ignoring the alpha component.
struct RgbColor {
RgbColor() = default;
RgbColor(uint8_t red, uint8_t green, uint8_t blue)
#if SK_PMCOLOR_BYTE_ORDER(B, G, R, A)
: b(blue),
g(green),
r(red)
#elif SK_PMCOLOR_BYTE_ORDER(R, G, B, A)
: r(red),
g(green),
b(blue)
#else
#error "The color format must be either BGRA or RGBA"
#endif
{
}
bool operator==(const RgbColor& rhs) const {
return r == rhs.r && g == rhs.g && b == rhs.b;
}
// The order of the color components depends on the platform.
// The alpha component is ignored and never used as it's not important for
// GIF recording.
#if SK_PMCOLOR_BYTE_ORDER(B, G, R, A)
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t ignored_a;
#elif SK_PMCOLOR_BYTE_ORDER(R, G, B, A)
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t ignored_a;
#else
#error "The color format must be either BGRA or RGBA"
#endif
};
static_assert(sizeof(RgbColor) == sizeof(SkPMColor));
// Defines a video frame that is composed of as many `RgbColor`s as there are
// number of pixels in the frame represented by the given `bitmap`. The color
// type of the given `bitmap` must be `kN32_SkColorType`, which is either
// `kBGRA_8888_SkColorType` or `kRGBA_8888_SkColorType` depending on the
// platform (see above `RgbColor` members order).
class RgbVideoFrame {
public:
explicit RgbVideoFrame(const media::VideoFrame& video_frame);
RgbVideoFrame(const SkBitmap& bitmap, base::TimeTicks frame_time);
RgbVideoFrame(RgbVideoFrame&&);
RgbVideoFrame& operator=(const RgbVideoFrame&) = delete;
~RgbVideoFrame();
int width() const { return width_; }
int height() const { return height_; }
base::TimeTicks frame_time() const { return frame_time_; }
size_t num_pixels() const { return width_ * height_; }
// Returns the color of the pixel at `row` and `column`. The non-const version
// can be used to change the color of the pixel.
RgbColor& pixel_color(int row, int column) {
return data_[row * width_ + column];
}
const RgbColor& pixel_color(int row, int column) const {
return const_cast<RgbVideoFrame*>(this)->pixel_color(row, column);
}
RgbVideoFrame Clone() const;
private:
// Copy constructor made private so as not to be used implicitly. `Clone()`
// above should be used explicitly if needed.
RgbVideoFrame(const RgbVideoFrame& other);
// The width and height of the video frame.
const int width_;
const int height_;
const base::TimeTicks frame_time_;
// The pixel color data.
std::unique_ptr<RgbColor[]> data_;
};
} // namespace recording
#endif // CHROMEOS_ASH_SERVICES_RECORDING_RGB_VIDEO_FRAME_H_