mkvparser: Add support for the Colour element and its children.
Change-Id: Idffafaee221e2949c21f56c81df6e4d1c3e959a5
This commit is contained in:
parent
22bfdf7d99
commit
fb1406ec3b
198
mkvparser.cpp
198
mkvparser.cpp
@ -17,6 +17,7 @@
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
|
||||
#include "webmids.hpp"
|
||||
@ -4977,9 +4978,199 @@ BlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; }
|
||||
|
||||
const Block* Track::EOSBlock::GetBlock() const { return NULL; }
|
||||
|
||||
bool PrimaryChromaticity::Parse(IMkvReader* reader, long long read_pos,
|
||||
long long value_size, bool is_x,
|
||||
PrimaryChromaticity** chromaticity) {
|
||||
if (!reader)
|
||||
return false;
|
||||
|
||||
std::auto_ptr<PrimaryChromaticity> chromaticity_ptr;
|
||||
|
||||
if (!*chromaticity) {
|
||||
chromaticity_ptr.reset(new PrimaryChromaticity());
|
||||
} else {
|
||||
chromaticity_ptr.reset(*chromaticity);
|
||||
}
|
||||
|
||||
if (!chromaticity_ptr.get())
|
||||
return false;
|
||||
|
||||
double* value = is_x ? &chromaticity_ptr->x : &chromaticity_ptr->y;
|
||||
|
||||
const long long value_parse_status =
|
||||
UnserializeFloat(reader, read_pos, value_size, *value);
|
||||
|
||||
if (value_parse_status < 0 || *value < 0.0 || *value > 1.0)
|
||||
return false;
|
||||
|
||||
*chromaticity = chromaticity_ptr.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start,
|
||||
long long mm_size, MasteringMetadata** mm) {
|
||||
if (!reader || *mm)
|
||||
return false;
|
||||
|
||||
std::auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
|
||||
if (!mm_ptr.get())
|
||||
return false;
|
||||
|
||||
const long long mm_end = mm_start + mm_size;
|
||||
long long read_pos = mm_start;
|
||||
|
||||
while (read_pos < mm_end) {
|
||||
long long child_id = 0;
|
||||
long long child_size = 0;
|
||||
|
||||
const long long status =
|
||||
ParseElementHeader(reader, read_pos, mm_end, child_id, child_size);
|
||||
if (status < 0)
|
||||
return false;
|
||||
|
||||
if (child_id == mkvmuxer::kMkvLuminanceMax) {
|
||||
const long long value_parse_status =
|
||||
UnserializeFloat(reader, read_pos, child_size, mm_ptr->luminance_max);
|
||||
if (value_parse_status < 0 || mm_ptr->luminance_max < 0.0 ||
|
||||
mm_ptr->luminance_max > 9999.99) {
|
||||
return false;
|
||||
}
|
||||
} else if (child_id == mkvmuxer::kMkvLuminanceMin) {
|
||||
const long long value_parse_status =
|
||||
UnserializeFloat(reader, read_pos, child_size, mm_ptr->luminance_min);
|
||||
if (value_parse_status < 0 || mm_ptr->luminance_min < 0.0 ||
|
||||
mm_ptr->luminance_min > 999.9999) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
bool is_x = false;
|
||||
PrimaryChromaticity** chromaticity;
|
||||
switch (child_id) {
|
||||
case mkvmuxer::kMkvPrimaryRChromaticityX:
|
||||
case mkvmuxer::kMkvPrimaryRChromaticityY:
|
||||
is_x = child_id == mkvmuxer::kMkvPrimaryRChromaticityX;
|
||||
chromaticity = &mm_ptr->r;
|
||||
break;
|
||||
case mkvmuxer::kMkvPrimaryGChromaticityX:
|
||||
case mkvmuxer::kMkvPrimaryGChromaticityY:
|
||||
is_x = child_id == mkvmuxer::kMkvPrimaryGChromaticityX;
|
||||
chromaticity = &mm_ptr->g;
|
||||
break;
|
||||
case mkvmuxer::kMkvPrimaryBChromaticityX:
|
||||
case mkvmuxer::kMkvPrimaryBChromaticityY:
|
||||
is_x = child_id == mkvmuxer::kMkvPrimaryBChromaticityX;
|
||||
chromaticity = &mm_ptr->b;
|
||||
break;
|
||||
case mkvmuxer::kMkvWhitePointChromaticityX:
|
||||
case mkvmuxer::kMkvWhitePointChromaticityY:
|
||||
is_x = child_id == mkvmuxer::kMkvWhitePointChromaticityX;
|
||||
chromaticity = &mm_ptr->white_point;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
const bool value_parse_status = PrimaryChromaticity::Parse(
|
||||
reader, read_pos, child_size, is_x, chromaticity);
|
||||
if (!value_parse_status)
|
||||
return false;
|
||||
}
|
||||
|
||||
read_pos += child_size;
|
||||
if (read_pos > mm_end)
|
||||
return false;
|
||||
}
|
||||
|
||||
*mm = mm_ptr.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Colour::Parse(IMkvReader* reader, long long colour_start,
|
||||
long long colour_size, Colour** colour) {
|
||||
if (!reader || *colour)
|
||||
return false;
|
||||
|
||||
std::auto_ptr<Colour> colour_ptr(new Colour());
|
||||
if (!colour_ptr.get())
|
||||
return false;
|
||||
|
||||
const long long colour_end = colour_start + colour_size;
|
||||
long long read_pos = colour_start;
|
||||
|
||||
while (read_pos < colour_end) {
|
||||
long long child_id = 0;
|
||||
long long child_size = 0;
|
||||
|
||||
const long status =
|
||||
ParseElementHeader(reader, read_pos, colour_end, child_id, child_size);
|
||||
if (status < 0)
|
||||
return false;
|
||||
|
||||
if (child_id == mkvmuxer::kMkvMatrix) {
|
||||
colour_ptr->matrix = UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->matrix < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvBitsPerChannel) {
|
||||
colour_ptr->bits_per_channel =
|
||||
UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->bits_per_channel < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvChromaSubsampling) {
|
||||
colour_ptr->chroma_subsampling =
|
||||
UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->chroma_subsampling < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvChromaSitingHorz) {
|
||||
colour_ptr->chroma_siting_horz =
|
||||
UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->chroma_siting_horz < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvChromaSitingVert) {
|
||||
colour_ptr->chroma_siting_vert =
|
||||
UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->chroma_siting_vert < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvRange) {
|
||||
colour_ptr->range = UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->range < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvTransferFunction) {
|
||||
colour_ptr->transfer_function =
|
||||
UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->transfer_function < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvPrimaries) {
|
||||
colour_ptr->primaries = UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->primaries < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvMaxCLL) {
|
||||
colour_ptr->max_cll = UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->max_cll < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvMaxFALL) {
|
||||
colour_ptr->max_fall = UnserializeUInt(reader, read_pos, child_size);
|
||||
if (colour_ptr->max_fall < 0)
|
||||
return false;
|
||||
} else if (child_id == mkvmuxer::kMkvMasteringMetadata) {
|
||||
if (!MasteringMetadata::Parse(reader, read_pos, child_size,
|
||||
&colour_ptr->mastering_metadata))
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
read_pos += child_size;
|
||||
if (read_pos > colour_end)
|
||||
return false;
|
||||
}
|
||||
*colour = colour_ptr.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
VideoTrack::VideoTrack(Segment* pSegment, long long element_start,
|
||||
long long element_size)
|
||||
: Track(pSegment, element_start, element_size) {}
|
||||
: Track(pSegment, element_start, element_size), m_colour(NULL) {}
|
||||
|
||||
VideoTrack::~VideoTrack() { delete m_colour; }
|
||||
|
||||
long VideoTrack::Parse(Segment* pSegment, const Info& info,
|
||||
long long element_start, long long element_size,
|
||||
@ -5056,6 +5247,9 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
|
||||
|
||||
if (rate <= 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
} else if (id == mkvmuxer::kMkvColour) {
|
||||
if (!Colour::Parse(pReader, pos, size, &pResult->m_colour))
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
pos += size; // consume payload
|
||||
@ -5184,6 +5378,8 @@ long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Colour* VideoTrack::GetColour() const { return m_colour; }
|
||||
|
||||
long long VideoTrack::GetWidth() const { return m_width; }
|
||||
|
||||
long long VideoTrack::GetHeight() const { return m_height; }
|
||||
|
@ -392,6 +392,78 @@ class Track {
|
||||
ContentEncoding** content_encoding_entries_end_;
|
||||
};
|
||||
|
||||
struct PrimaryChromaticity {
|
||||
PrimaryChromaticity() : x(0), y(0) {}
|
||||
~PrimaryChromaticity() {}
|
||||
static bool Parse(IMkvReader* reader, long long read_pos,
|
||||
long long value_size, bool is_x,
|
||||
PrimaryChromaticity** chromaticity);
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
struct MasteringMetadata {
|
||||
MasteringMetadata()
|
||||
: r(NULL),
|
||||
g(NULL),
|
||||
b(NULL),
|
||||
white_point(NULL),
|
||||
luminance_max(0),
|
||||
luminance_min(0) {}
|
||||
~MasteringMetadata() {
|
||||
delete r;
|
||||
delete g;
|
||||
delete b;
|
||||
delete white_point;
|
||||
}
|
||||
|
||||
static bool Parse(IMkvReader* reader, long long element_start,
|
||||
long long element_size,
|
||||
MasteringMetadata** mastering_metadata);
|
||||
|
||||
PrimaryChromaticity* r;
|
||||
PrimaryChromaticity* g;
|
||||
PrimaryChromaticity* b;
|
||||
PrimaryChromaticity* white_point;
|
||||
double luminance_max;
|
||||
double luminance_min;
|
||||
};
|
||||
|
||||
struct Colour {
|
||||
// Unless otherwise noted all values assigned upon construction are the
|
||||
// equivalent of unspecified/default.
|
||||
Colour()
|
||||
: matrix(2),
|
||||
bits_per_channel(0),
|
||||
chroma_subsampling(0),
|
||||
chroma_siting_horz(0),
|
||||
chroma_siting_vert(0),
|
||||
range(0),
|
||||
transfer_function(2),
|
||||
primaries(2),
|
||||
mastering_metadata(NULL) {}
|
||||
~Colour() {
|
||||
delete mastering_metadata;
|
||||
mastering_metadata = NULL;
|
||||
}
|
||||
|
||||
static bool Parse(IMkvReader* reader, long long element_start,
|
||||
long long element_size, Colour** colour);
|
||||
|
||||
long long matrix;
|
||||
long long bits_per_channel;
|
||||
long long chroma_subsampling;
|
||||
long long chroma_siting_horz;
|
||||
long long chroma_siting_vert;
|
||||
long long range;
|
||||
long long transfer_function;
|
||||
long long primaries;
|
||||
long long max_cll;
|
||||
long long max_fall;
|
||||
|
||||
MasteringMetadata* mastering_metadata;
|
||||
};
|
||||
|
||||
class VideoTrack : public Track {
|
||||
VideoTrack(const VideoTrack&);
|
||||
VideoTrack& operator=(const VideoTrack&);
|
||||
@ -399,6 +471,7 @@ class VideoTrack : public Track {
|
||||
VideoTrack(Segment*, long long element_start, long long element_size);
|
||||
|
||||
public:
|
||||
virtual ~VideoTrack();
|
||||
static long Parse(Segment*, const Info&, long long element_start,
|
||||
long long element_size, VideoTrack*&);
|
||||
|
||||
@ -413,6 +486,8 @@ class VideoTrack : public Track {
|
||||
bool VetEntry(const BlockEntry*) const;
|
||||
long Seek(long long time_ns, const BlockEntry*&) const;
|
||||
|
||||
Colour* GetColour() const;
|
||||
|
||||
private:
|
||||
long long m_width;
|
||||
long long m_height;
|
||||
@ -422,6 +497,8 @@ class VideoTrack : public Track {
|
||||
long long m_stereo_mode;
|
||||
|
||||
double m_rate;
|
||||
|
||||
Colour* m_colour;
|
||||
};
|
||||
|
||||
class AudioTrack : public Track {
|
||||
|
26
webmids.hpp
26
webmids.hpp
@ -95,6 +95,32 @@ enum MkvId {
|
||||
kMkvAspectRatioType = 0x54B3,
|
||||
kMkvFrameRate = 0x2383E3,
|
||||
// end video
|
||||
// colour
|
||||
kMkvColour = 0x55B0,
|
||||
kMkvMatrix = 0x55B1,
|
||||
kMkvBitsPerChannel = 0x55B2,
|
||||
kMkvChromaSubsampling = 0x55B3,
|
||||
kMkvChromaSitingHorz = 0x55B4,
|
||||
kMkvChromaSitingVert = 0x55B5,
|
||||
kMkvRange = 0x55B6,
|
||||
kMkvTransferFunction = 0x55B7,
|
||||
kMkvPrimaries = 0x55B8,
|
||||
kMkvMaxCLL = 0x55B9,
|
||||
kMkvMaxFALL = 0x55BA,
|
||||
// mastering metadata
|
||||
kMkvMasteringMetadata = 0x55D0,
|
||||
kMkvPrimaryRChromaticityX = 0x55D1,
|
||||
kMkvPrimaryRChromaticityY = 0x55D2,
|
||||
kMkvPrimaryGChromaticityX = 0x55D3,
|
||||
kMkvPrimaryGChromaticityY = 0x55D4,
|
||||
kMkvPrimaryBChromaticityX = 0x55D5,
|
||||
kMkvPrimaryBChromaticityY = 0x55D6,
|
||||
kMkvWhitePointChromaticityX = 0x55D7,
|
||||
kMkvWhitePointChromaticityY = 0x55D8,
|
||||
kMkvLuminanceMax = 0x55D9,
|
||||
kMkvLuminanceMin = 0x55DA,
|
||||
// end mastering metadata
|
||||
// end colour
|
||||
// audio
|
||||
kMkvAudio = 0xE1,
|
||||
kMkvSamplingFrequency = 0xB5,
|
||||
|
Loading…
Reference in New Issue
Block a user