mkvmuxer: Add support for the Colour element and its children.
Change-Id: I8026a2ba6c664cbf0ce0a6602a79942283b194b1
This commit is contained in:
parent
41a9147f2a
commit
a281a22955
283
mkvmuxer.cpp
283
mkvmuxer.cpp
@ -8,11 +8,13 @@
|
||||
|
||||
#include "mkvmuxer.hpp"
|
||||
|
||||
#include <cfloat>
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
|
||||
#include "mkvmuxerutil.hpp"
|
||||
@ -27,6 +29,9 @@
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
const float MasteringMetadata::kUnspecifiedMmValue = FLT_MAX;
|
||||
const uint64 Colour::kUnspecifiedColourValue = UINT64_MAX;
|
||||
|
||||
namespace {
|
||||
// Deallocate the string designated by |dst|, and then copy the |src|
|
||||
// string to |dst|. The caller owns both the |src| string and the
|
||||
@ -55,6 +60,20 @@ bool StrCpy(const char* src, char** dst_ptr) {
|
||||
strcpy(dst, src); // NOLINT
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef std::auto_ptr<PrimaryChromaticity> PrimaryChromaticityPtr;
|
||||
bool CopyChromaticity(const PrimaryChromaticity* src,
|
||||
PrimaryChromaticityPtr* dst) {
|
||||
if (!dst)
|
||||
return false;
|
||||
|
||||
dst->reset(new (std::nothrow) PrimaryChromaticity(src->x, src->y));
|
||||
if (!dst->get())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
@ -842,6 +861,231 @@ void Track::set_name(const char* name) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Colour and its child elements
|
||||
|
||||
uint64 PrimaryChromaticity::PrimaryChromaticityPayloadSize(MkvId x_id,
|
||||
MkvId y_id) const {
|
||||
return EbmlElementSize(x_id, x) + EbmlElementSize(y_id, y);
|
||||
}
|
||||
|
||||
bool PrimaryChromaticity::Write(IMkvWriter* writer, MkvId x_id,
|
||||
MkvId y_id) const {
|
||||
return WriteEbmlElement(writer, x_id, x) && WriteEbmlElement(writer, y_id, y);
|
||||
}
|
||||
|
||||
uint64 MasteringMetadata::MasteringMetadataPayloadSize() const {
|
||||
uint64 size = 0;
|
||||
|
||||
if (luminance_max != kUnspecifiedMmValue)
|
||||
size += EbmlElementSize(kMkvLuminanceMax, luminance_max);
|
||||
if (luminance_min != kUnspecifiedMmValue)
|
||||
size += EbmlElementSize(kMkvLuminanceMin, luminance_min);
|
||||
|
||||
if (r_) {
|
||||
size += r_->PrimaryChromaticityPayloadSize(kMkvPrimaryRChromaticityX,
|
||||
kMkvPrimaryRChromaticityY);
|
||||
}
|
||||
if (g_) {
|
||||
size += g_->PrimaryChromaticityPayloadSize(kMkvPrimaryGChromaticityX,
|
||||
kMkvPrimaryGChromaticityY);
|
||||
}
|
||||
if (b_) {
|
||||
size += b_->PrimaryChromaticityPayloadSize(kMkvPrimaryBChromaticityX,
|
||||
kMkvPrimaryBChromaticityY);
|
||||
}
|
||||
if (white_point_) {
|
||||
size += white_point_->PrimaryChromaticityPayloadSize(
|
||||
kMkvWhitePointChromaticityX, kMkvWhitePointChromaticityY);
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
size += EbmlMasterElementSize(kMkvMasteringMetadata, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool MasteringMetadata::Write(IMkvWriter* writer) const {
|
||||
const uint64 size = MasteringMetadataPayloadSize();
|
||||
|
||||
// Don't write an empty element.
|
||||
if (size == 0)
|
||||
return true;
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, kMkvMasteringMetadata, size))
|
||||
return false;
|
||||
if (luminance_max != kUnspecifiedMmValue &&
|
||||
!WriteEbmlElement(writer, kMkvLuminanceMax, luminance_max)) {
|
||||
return false;
|
||||
}
|
||||
if (luminance_min != kUnspecifiedMmValue &&
|
||||
!WriteEbmlElement(writer, kMkvLuminanceMin, luminance_min)) {
|
||||
return false;
|
||||
}
|
||||
if (r_ &&
|
||||
!r_->Write(writer, kMkvPrimaryRChromaticityX,
|
||||
kMkvPrimaryRChromaticityY)) {
|
||||
return false;
|
||||
}
|
||||
if (g_ &&
|
||||
!g_->Write(writer, kMkvPrimaryGChromaticityX,
|
||||
kMkvPrimaryGChromaticityY)) {
|
||||
return false;
|
||||
}
|
||||
if (b_ &&
|
||||
!b_->Write(writer, kMkvPrimaryBChromaticityX,
|
||||
kMkvPrimaryBChromaticityY)) {
|
||||
return false;
|
||||
}
|
||||
if (white_point_ &&
|
||||
!white_point_->Write(writer, kMkvWhitePointChromaticityX,
|
||||
kMkvWhitePointChromaticityY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MasteringMetadata::SetChromaticity(
|
||||
const PrimaryChromaticity* r, const PrimaryChromaticity* g,
|
||||
const PrimaryChromaticity* b, const PrimaryChromaticity* white_point) {
|
||||
PrimaryChromaticityPtr r_ptr(NULL);
|
||||
if (r) {
|
||||
if (!CopyChromaticity(r, &r_ptr))
|
||||
return false;
|
||||
}
|
||||
PrimaryChromaticityPtr g_ptr(NULL);
|
||||
if (g) {
|
||||
if (!CopyChromaticity(g, &g_ptr))
|
||||
return false;
|
||||
}
|
||||
PrimaryChromaticityPtr b_ptr(NULL);
|
||||
if (b) {
|
||||
if (!CopyChromaticity(b, &b_ptr))
|
||||
return false;
|
||||
}
|
||||
PrimaryChromaticityPtr wp_ptr(NULL);
|
||||
if (white_point) {
|
||||
if (!CopyChromaticity(white_point, &wp_ptr))
|
||||
return false;
|
||||
}
|
||||
|
||||
r_ = r_ptr.release();
|
||||
g_ = g_ptr.release();
|
||||
b_ = b_ptr.release();
|
||||
white_point_ = wp_ptr.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 Colour::ColourPayloadSize() const {
|
||||
uint64 size = 0;
|
||||
|
||||
if (matrix != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvMatrix, matrix);
|
||||
if (bits_per_channel != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvBitsPerChannel, bits_per_channel);
|
||||
if (chroma_subsampling != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvChromaSubsampling, chroma_subsampling);
|
||||
if (chroma_siting_horz != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvChromaSitingHorz, chroma_siting_horz);
|
||||
if (chroma_siting_vert != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvChromaSitingVert, chroma_siting_vert);
|
||||
if (range != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvRange, range);
|
||||
if (transfer_function != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvTransferFunction, transfer_function);
|
||||
if (primaries != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvPrimaries, primaries);
|
||||
if (max_cll != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvMaxCLL, max_cll);
|
||||
if (max_fall != kUnspecifiedColourValue)
|
||||
size += EbmlElementSize(kMkvMaxFALL, max_fall);
|
||||
|
||||
if (mastering_metadata_)
|
||||
size += mastering_metadata_->MasteringMetadataPayloadSize();
|
||||
|
||||
if (size > 0)
|
||||
size += EbmlMasterElementSize(kMkvColour, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Colour::Write(IMkvWriter* writer) const {
|
||||
const uint64 size = ColourPayloadSize();
|
||||
|
||||
// Don't write an empty element.
|
||||
if (size == 0)
|
||||
return true;
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, kMkvColour, size))
|
||||
return false;
|
||||
|
||||
if (matrix != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvMatrix, matrix)) {
|
||||
return false;
|
||||
}
|
||||
if (bits_per_channel != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvBitsPerChannel, bits_per_channel)) {
|
||||
return false;
|
||||
}
|
||||
if (chroma_subsampling != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvChromaSubsampling, chroma_subsampling)) {
|
||||
return false;
|
||||
}
|
||||
if (chroma_siting_horz != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvChromaSitingHorz, chroma_siting_horz)) {
|
||||
return false;
|
||||
}
|
||||
if (chroma_siting_vert != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvChromaSitingVert, chroma_siting_vert)) {
|
||||
return false;
|
||||
}
|
||||
if (range != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvRange, range)) {
|
||||
return false;
|
||||
}
|
||||
if (transfer_function != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvTransferFunction, transfer_function)) {
|
||||
return false;
|
||||
}
|
||||
if (primaries != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvPrimaries, primaries)) {
|
||||
return false;
|
||||
}
|
||||
if (max_cll != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvMaxCLL, max_cll)) {
|
||||
return false;
|
||||
}
|
||||
if (max_fall != kUnspecifiedColourValue &&
|
||||
!WriteEbmlElement(writer, kMkvMaxFALL, max_fall)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mastering_metadata_ && !mastering_metadata_->Write(writer))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Colour::SetMasteringMetadata(const MasteringMetadata& mastering_metadata) {
|
||||
std::auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
|
||||
if (!mm_ptr.get())
|
||||
return false;
|
||||
|
||||
mm_ptr->luminance_max = mastering_metadata.luminance_max;
|
||||
mm_ptr->luminance_min = mastering_metadata.luminance_min;
|
||||
|
||||
if (!mm_ptr->SetChromaticity(mastering_metadata.r(), mastering_metadata.g(),
|
||||
mastering_metadata.b(),
|
||||
mastering_metadata.white_point())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete mastering_metadata_;
|
||||
mastering_metadata_ = mm_ptr.release();
|
||||
return true;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VideoTrack Class
|
||||
@ -858,9 +1102,10 @@ VideoTrack::VideoTrack(unsigned int* seed)
|
||||
height_(0),
|
||||
stereo_mode_(0),
|
||||
alpha_mode_(0),
|
||||
width_(0) {}
|
||||
width_(0),
|
||||
colour_(NULL) {}
|
||||
|
||||
VideoTrack::~VideoTrack() {}
|
||||
VideoTrack::~VideoTrack() { delete colour_; }
|
||||
|
||||
bool VideoTrack::SetStereoMode(uint64 stereo_mode) {
|
||||
if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst &&
|
||||
@ -945,6 +1190,10 @@ bool VideoTrack::Write(IMkvWriter* writer) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (colour_) {
|
||||
if (!colour_->Write(writer))
|
||||
return false;
|
||||
}
|
||||
|
||||
const int64 stop_position = writer->Position();
|
||||
if (stop_position < 0 ||
|
||||
@ -955,6 +1204,30 @@ bool VideoTrack::Write(IMkvWriter* writer) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VideoTrack::SetColour(const Colour& colour) {
|
||||
std::auto_ptr<Colour> colour_ptr(new Colour());
|
||||
if (!colour_ptr.get())
|
||||
return false;
|
||||
|
||||
if (colour.mastering_metadata()) {
|
||||
if (!colour_ptr->SetMasteringMetadata(*colour.mastering_metadata()))
|
||||
return false;
|
||||
}
|
||||
|
||||
colour_ptr->matrix = colour.matrix;
|
||||
colour_ptr->primaries = colour.bits_per_channel;
|
||||
colour_ptr->chroma_subsampling = colour.chroma_subsampling;
|
||||
colour_ptr->chroma_siting_horz = colour.chroma_siting_horz;
|
||||
colour_ptr->chroma_siting_vert = colour.chroma_siting_vert;
|
||||
colour_ptr->range = colour.range;
|
||||
colour_ptr->transfer_function = colour.transfer_function;
|
||||
colour_ptr->primaries = colour.primaries;
|
||||
colour_ptr->max_cll = colour.max_cll;
|
||||
colour_ptr->max_fall = colour.max_fall;
|
||||
colour_ = colour_ptr.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 VideoTrack::VideoPayloadSize() const {
|
||||
uint64 size = EbmlElementSize(kMkvPixelWidth, width_);
|
||||
size += EbmlElementSize(kMkvPixelHeight, height_);
|
||||
@ -976,6 +1249,8 @@ uint64 VideoTrack::VideoPayloadSize() const {
|
||||
size += EbmlElementSize(kMkvAlphaMode, alpha_mode_);
|
||||
if (frame_rate_ > 0.0)
|
||||
size += EbmlElementSize(kMkvFrameRate, static_cast<float>(frame_rate_));
|
||||
if (colour_)
|
||||
size += colour_->ColourPayloadSize();
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -1048,9 +1323,7 @@ const char Tracks::kVp9CodecId[] = "V_VP9";
|
||||
const char Tracks::kVp10CodecId[] = "V_VP10";
|
||||
|
||||
Tracks::Tracks()
|
||||
: track_entries_(NULL),
|
||||
track_entries_size_(0),
|
||||
wrote_tracks_(false) {}
|
||||
: track_entries_(NULL), track_entries_size_(0), wrote_tracks_(false) {}
|
||||
|
||||
Tracks::~Tracks() {
|
||||
if (track_entries_) {
|
||||
|
104
mkvmuxer.hpp
104
mkvmuxer.hpp
@ -9,7 +9,10 @@
|
||||
#ifndef MKVMUXER_HPP
|
||||
#define MKVMUXER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "mkvmuxertypes.hpp"
|
||||
#include "webmids.hpp"
|
||||
|
||||
// For a description of the WebM elements see
|
||||
// http://www.webmproject.org/code/specs/container/.
|
||||
@ -329,6 +332,100 @@ class ContentEncoding {
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Colour element.
|
||||
struct PrimaryChromaticity {
|
||||
PrimaryChromaticity(float x_val, float y_val) : x(x_val), y(y_val) {}
|
||||
PrimaryChromaticity() : x(0), y(0) {}
|
||||
~PrimaryChromaticity() {}
|
||||
uint64 PrimaryChromaticityPayloadSize(MkvId x_id, MkvId y_id) const;
|
||||
bool Write(IMkvWriter* writer, MkvId x_id, MkvId y_id) const;
|
||||
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
class MasteringMetadata {
|
||||
public:
|
||||
static const float kUnspecifiedMmValue;
|
||||
|
||||
MasteringMetadata()
|
||||
: luminance_max(kUnspecifiedMmValue),
|
||||
luminance_min(kUnspecifiedMmValue),
|
||||
r_(NULL),
|
||||
g_(NULL),
|
||||
b_(NULL),
|
||||
white_point_(NULL) {}
|
||||
~MasteringMetadata() {
|
||||
delete r_;
|
||||
delete g_;
|
||||
delete b_;
|
||||
delete white_point_;
|
||||
}
|
||||
uint64 MasteringMetadataPayloadSize() const;
|
||||
bool Write(IMkvWriter* writer) const;
|
||||
|
||||
// Copies non-null chromaticity.
|
||||
bool SetChromaticity(const PrimaryChromaticity* r,
|
||||
const PrimaryChromaticity* g,
|
||||
const PrimaryChromaticity* b,
|
||||
const PrimaryChromaticity* white_point);
|
||||
const PrimaryChromaticity* r() const { return r_; }
|
||||
const PrimaryChromaticity* g() const { return g_; }
|
||||
const PrimaryChromaticity* b() const { return b_; }
|
||||
const PrimaryChromaticity* white_point() const { return white_point_; }
|
||||
|
||||
float luminance_max;
|
||||
float luminance_min;
|
||||
|
||||
private:
|
||||
PrimaryChromaticity* r_;
|
||||
PrimaryChromaticity* g_;
|
||||
PrimaryChromaticity* b_;
|
||||
PrimaryChromaticity* white_point_;
|
||||
};
|
||||
|
||||
class Colour {
|
||||
public:
|
||||
static const uint64 kUnspecifiedColourValue;
|
||||
Colour()
|
||||
: matrix(kUnspecifiedColourValue),
|
||||
bits_per_channel(kUnspecifiedColourValue),
|
||||
chroma_subsampling(kUnspecifiedColourValue),
|
||||
chroma_siting_horz(kUnspecifiedColourValue),
|
||||
chroma_siting_vert(kUnspecifiedColourValue),
|
||||
range(kUnspecifiedColourValue),
|
||||
transfer_function(kUnspecifiedColourValue),
|
||||
primaries(kUnspecifiedColourValue),
|
||||
max_cll(kUnspecifiedColourValue),
|
||||
max_fall(kUnspecifiedColourValue),
|
||||
mastering_metadata_(NULL) {}
|
||||
~Colour() { delete mastering_metadata_; }
|
||||
uint64 ColourPayloadSize() const;
|
||||
bool Write(IMkvWriter* writer) const;
|
||||
|
||||
// Deep copies |mastering_metadata|.
|
||||
bool SetMasteringMetadata(const MasteringMetadata& mastering_metadata);
|
||||
|
||||
const MasteringMetadata* mastering_metadata() const {
|
||||
return mastering_metadata_;
|
||||
}
|
||||
|
||||
uint64 matrix;
|
||||
uint64 bits_per_channel;
|
||||
uint64 chroma_subsampling;
|
||||
uint64 chroma_siting_horz;
|
||||
uint64 chroma_siting_vert;
|
||||
uint64 range;
|
||||
uint64 transfer_function;
|
||||
uint64 primaries;
|
||||
uint64 max_cll;
|
||||
uint64 max_fall;
|
||||
|
||||
private:
|
||||
MasteringMetadata* mastering_metadata_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Track element.
|
||||
class Track {
|
||||
@ -471,6 +568,11 @@ class VideoTrack : public Track {
|
||||
void set_width(uint64 width) { width_ = width; }
|
||||
uint64 width() const { return width_; }
|
||||
|
||||
Colour* colour() { return colour_; }
|
||||
|
||||
// Deep copies |colour|.
|
||||
bool SetColour(const Colour& colour);
|
||||
|
||||
private:
|
||||
// Returns the size in bytes of the Video element.
|
||||
uint64 VideoPayloadSize() const;
|
||||
@ -488,6 +590,8 @@ class VideoTrack : public Track {
|
||||
uint64 alpha_mode_;
|
||||
uint64 width_;
|
||||
|
||||
Colour* colour_;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user