mkvparser: Add support for the Colour element and its children.
Change-Id: Idffafaee221e2949c21f56c81df6e4d1c3e959a5
This commit is contained in:
198
mkvparser.cpp
198
mkvparser.cpp
@@ -17,6 +17,7 @@
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "webmids.hpp"
|
#include "webmids.hpp"
|
||||||
@@ -4977,9 +4978,199 @@ BlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; }
|
|||||||
|
|
||||||
const Block* Track::EOSBlock::GetBlock() const { return NULL; }
|
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,
|
VideoTrack::VideoTrack(Segment* pSegment, long long element_start,
|
||||||
long long element_size)
|
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 VideoTrack::Parse(Segment* pSegment, const Info& info,
|
||||||
long long element_start, long long element_size,
|
long long element_start, long long element_size,
|
||||||
@@ -5056,6 +5247,9 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
|
|||||||
|
|
||||||
if (rate <= 0)
|
if (rate <= 0)
|
||||||
return E_FILE_FORMAT_INVALID;
|
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
|
pos += size; // consume payload
|
||||||
@@ -5184,6 +5378,8 @@ long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Colour* VideoTrack::GetColour() const { return m_colour; }
|
||||||
|
|
||||||
long long VideoTrack::GetWidth() const { return m_width; }
|
long long VideoTrack::GetWidth() const { return m_width; }
|
||||||
|
|
||||||
long long VideoTrack::GetHeight() const { return m_height; }
|
long long VideoTrack::GetHeight() const { return m_height; }
|
||||||
|
@@ -392,6 +392,78 @@ class Track {
|
|||||||
ContentEncoding** content_encoding_entries_end_;
|
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 {
|
class VideoTrack : public Track {
|
||||||
VideoTrack(const VideoTrack&);
|
VideoTrack(const VideoTrack&);
|
||||||
VideoTrack& operator=(const VideoTrack&);
|
VideoTrack& operator=(const VideoTrack&);
|
||||||
@@ -399,6 +471,7 @@ class VideoTrack : public Track {
|
|||||||
VideoTrack(Segment*, long long element_start, long long element_size);
|
VideoTrack(Segment*, long long element_start, long long element_size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~VideoTrack();
|
||||||
static long Parse(Segment*, const Info&, long long element_start,
|
static long Parse(Segment*, const Info&, long long element_start,
|
||||||
long long element_size, VideoTrack*&);
|
long long element_size, VideoTrack*&);
|
||||||
|
|
||||||
@@ -413,6 +486,8 @@ class VideoTrack : public Track {
|
|||||||
bool VetEntry(const BlockEntry*) const;
|
bool VetEntry(const BlockEntry*) const;
|
||||||
long Seek(long long time_ns, const BlockEntry*&) const;
|
long Seek(long long time_ns, const BlockEntry*&) const;
|
||||||
|
|
||||||
|
Colour* GetColour() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
long long m_width;
|
long long m_width;
|
||||||
long long m_height;
|
long long m_height;
|
||||||
@@ -422,6 +497,8 @@ class VideoTrack : public Track {
|
|||||||
long long m_stereo_mode;
|
long long m_stereo_mode;
|
||||||
|
|
||||||
double m_rate;
|
double m_rate;
|
||||||
|
|
||||||
|
Colour* m_colour;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AudioTrack : public Track {
|
class AudioTrack : public Track {
|
||||||
|
26
webmids.hpp
26
webmids.hpp
@@ -95,6 +95,32 @@ enum MkvId {
|
|||||||
kMkvAspectRatioType = 0x54B3,
|
kMkvAspectRatioType = 0x54B3,
|
||||||
kMkvFrameRate = 0x2383E3,
|
kMkvFrameRate = 0x2383E3,
|
||||||
// end video
|
// 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
|
// audio
|
||||||
kMkvAudio = 0xE1,
|
kMkvAudio = 0xE1,
|
||||||
kMkvSamplingFrequency = 0xB5,
|
kMkvSamplingFrequency = 0xB5,
|
||||||
|
Reference in New Issue
Block a user