shaka-packager/packager/media/formats/dvb/dvb_image.h

138 lines
4.9 KiB
C++

// Copyright 2020 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef PACKAGER_MEDIA_DVB_DVB_IMAGE_H_
#define PACKAGER_MEDIA_DVB_DVB_IMAGE_H_
#include <memory>
#include <type_traits>
namespace shaka {
namespace media {
struct RgbaColor {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
bool operator==(const RgbaColor& other) const {
return r == other.r && g == other.g && b == other.b && a == other.a;
}
bool operator!=(const RgbaColor& other) const { return !(*this == other); }
};
// To avoid copying, we pass an RgbaColor array as a uint8_t* pointer to libpng
// for RGBA.
static_assert(std::is_pod<RgbaColor>::value, "RgbaColor must be POD");
static_assert(sizeof(RgbaColor) == 4, "RgbaColor not packed correctly");
enum class BitDepth : uint8_t {
k2Bit,
k4Bit,
k8Bit,
};
/// Defines a color-space for DVB-sub images. This maps to a single CLUT in the
/// spec. This holds a map of the byte codes to the respective RGB colors.
/// This also handles getting the default colors when none are provided and
/// converting between bit-depths if applicable.
///
/// When handling bit-depths, this will attempt to use the bit-depth provided
/// before converting upward then downward. Each color is only set for that
/// specific bit-depth; meaning different bit-depths can have different colors
/// mapped to the same byte-code.
class DvbImageColorSpace {
public:
DvbImageColorSpace();
~DvbImageColorSpace();
DvbImageColorSpace(const DvbImageColorSpace&) = delete;
DvbImageColorSpace& operator=(const DvbImageColorSpace&) = delete;
RgbaColor GetColor(BitDepth bit_depth, uint8_t entry_id) const;
void SetColor(BitDepth bit_depth, uint8_t entry_id, RgbaColor color);
/// Must pass a 4-element array; elements are copied over.
void Set2To4BitDepthMap(const uint8_t* map);
/// Must pass a 4-element array; elements are copied over.
void Set2To8BitDepthMap(const uint8_t* map);
/// Must pass a 16-element array; elements are copied over.
void Set4To8BitDepthMap(const uint8_t* map);
private:
RgbaColor GetColorRaw(BitDepth bit_depth, uint8_t entry_id) const;
// These hold the colors for each entry ID. Each value is initialized to the
// special value kNoColor meaning there isn't a value present.
RgbaColor color_map_2_[4];
RgbaColor color_map_4_[16];
RgbaColor color_map_8_[256];
// See ETSI EN 300 743 Sections 10.4, 10.5, 10.6 for defaults.
uint8_t bit_depth_2_to_4_[4] = {0x0, 0x7, 0x8, 0xf};
uint8_t bit_depth_2_to_8_[4] = {0x0, 0x77, 0x88, 0xff};
uint8_t bit_depth_4_to_8_[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
0xcc, 0xdd, 0xee, 0xff};
};
/// Defines a builder that generates an image from a DVB-sub byte stream. This
/// allocates a single buffer big enough to hold the max-sized image and fills
/// it in series. The NewRow() method must be called to start a new line of the
/// image.
///
/// This adds pixels in an interlaced format. Adding pixels and new rows on
/// top-rows doesn't affect the bottom-rows. Top-rows refers to even-indexed
/// lines (e.g. 0,2,4).
class DvbImageBuilder {
public:
DvbImageBuilder(const DvbImageColorSpace* color_space,
const RgbaColor& default_color,
uint16_t max_width,
uint16_t max_height);
~DvbImageBuilder();
DvbImageBuilder(const DvbImageBuilder&) = delete;
DvbImageBuilder& operator=(const DvbImageBuilder&) = delete;
uint16_t max_width() const { return max_width_; }
uint16_t max_height() const { return max_height_; }
bool AddPixel(BitDepth bit_depth, uint8_t byte_code, bool is_top_rows);
void NewRow(bool is_top_rows);
/// Copies the top-rows to the bottom rows.
void MirrorToBottomRows();
/// Gets the pixel buffer. Each row is based on the max_width field, but
/// the max filled row with will be given in `width`. This assumes that
/// NewRow was called recently and we are at the beginning of the rows.
///
/// @param pixels A pointer to a RgbaColor* variable that will be set to the
/// pixel data pointer.
/// @param width Will be filled with the max width of all rows.
/// @param height Will be filled with the number of rows set.
/// @return True on success, false on error.
bool GetPixels(const RgbaColor** pixels,
uint16_t* width,
uint16_t* height) const;
private:
struct Position {
uint16_t x, y;
};
const std::unique_ptr<RgbaColor[]> pixels_;
const DvbImageColorSpace* const color_space_;
Position top_pos_, bottom_pos_;
const uint16_t max_width_;
const uint16_t max_height_;
uint16_t width_;
};
} // namespace media
} // namespace shaka
#endif // PACKAGER_MEDIA_DVB_DVB_IMAGE_H_