Skip to content

Commit

Permalink
mkvparser: Add Projection element support.
Browse files Browse the repository at this point in the history
Part of the Spherical Video V2 draft specification:
https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md

Change-Id: I431349898b4018189cc58ce2cd67158ffb4c7f80
  • Loading branch information
tomfinegan committed Aug 29, 2016
1 parent 483a0ff commit 41e814a
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 2 deletions.
93 changes: 91 additions & 2 deletions mkvparser/mkvparser.cc
Expand Up @@ -25,6 +25,7 @@
namespace mkvparser {
const float MasteringMetadata::kValueNotPresent = FLT_MAX;
const long long Colour::kValueNotPresent = LLONG_MAX;
const float Projection::kValueNotPresent = FLT_MAX;

#ifdef MSC_COMPAT
inline bool isnan(double val) { return !!_isnan(val); }
Expand Down Expand Up @@ -5188,11 +5189,92 @@ bool Colour::Parse(IMkvReader* reader, long long colour_start,
return true;
}

bool Projection::Parse(IMkvReader* reader, long long start, long long size,
Projection** projection) {
if (!reader || *projection)
return false;

std::auto_ptr<Projection> projection_ptr(new Projection());
if (!projection_ptr.get())
return false;

const long long end = start + size;
long long read_pos = start;

while (read_pos < end) {
long long child_id = 0;
long long child_size = 0;

const long long status =
ParseElementHeader(reader, read_pos, end, child_id, child_size);
if (status < 0)
return false;

if (child_id == libwebm::kMkvProjectionType) {
long long projection_type = kTypeNotPresent;
projection_type = UnserializeUInt(reader, read_pos, child_size);
if (projection_type < 0)
return false;

projection_ptr->type = static_cast<ProjectionType>(projection_type);
} else if (child_id == libwebm::kMkvProjectionPrivate) {
unsigned char* data = SafeArrayAlloc<unsigned char>(1, child_size);

if (data == NULL)
return false;

const int status =
reader->Read(read_pos, static_cast<long>(child_size), data);

if (status) {
delete[] data;
return status;
}

projection_ptr->private_data = data;
projection_ptr->private_data_length = static_cast<size_t>(child_size);
} else {
double value = 0;
const long long value_parse_status =
UnserializeFloat(reader, read_pos, child_size, value);
if (value_parse_status < 0) {
return false;
}

switch (child_id) {
case libwebm::kMkvProjectionPoseYaw:
projection_ptr->pose_yaw = static_cast<float>(value);
break;
case libwebm::kMkvProjectionPosePitch:
projection_ptr->pose_pitch = static_cast<float>(value);
break;
case libwebm::kMkvProjectionPoseRoll:
projection_ptr->pose_roll = static_cast<float>(value);
break;
default:
return false;
}
}

read_pos += child_size;
if (read_pos > end)
return false;
}

*projection = projection_ptr.release();
return true;
}

VideoTrack::VideoTrack(Segment* pSegment, long long element_start,
long long element_size)
: Track(pSegment, element_start, element_size), m_colour(NULL) {}
: Track(pSegment, element_start, element_size),
m_colour(NULL),
m_projection(NULL) {}

VideoTrack::~VideoTrack() { delete m_colour; }
VideoTrack::~VideoTrack() {
delete m_colour;
delete m_projection;
}

long VideoTrack::Parse(Segment* pSegment, const Info& info,
long long element_start, long long element_size,
Expand Down Expand Up @@ -5224,6 +5306,7 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
const long long stop = pos + s.size;

Colour* colour = NULL;
Projection* projection = NULL;

while (pos < stop) {
long long id, size;
Expand Down Expand Up @@ -5274,6 +5357,9 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
} else if (id == libwebm::kMkvColour) {
if (!Colour::Parse(pReader, pos, size, &colour))
return E_FILE_FORMAT_INVALID;
} else if (id == libwebm::kMkvProjection) {
if (!Projection::Parse(pReader, pos, size, &projection))
return E_FILE_FORMAT_INVALID;
}

pos += size; // consume payload
Expand Down Expand Up @@ -5305,6 +5391,7 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
pTrack->m_stereo_mode = stereo_mode;
pTrack->m_rate = rate;
pTrack->m_colour = colour;
pTrack->m_projection = projection;

pResult = pTrack;
return 0; // success
Expand Down Expand Up @@ -5405,6 +5492,8 @@ long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {

Colour* VideoTrack::GetColour() const { return m_colour; }

Projection* VideoTrack::GetProjection() const { return m_projection; }

long long VideoTrack::GetWidth() const { return m_width; }

long long VideoTrack::GetHeight() const { return m_height; }
Expand Down
31 changes: 31 additions & 0 deletions mkvparser/mkvparser.h
Expand Up @@ -473,6 +473,34 @@ struct Colour {
MasteringMetadata* mastering_metadata;
};

struct Projection {
enum ProjectionType {
kTypeNotPresent = -1,
kRectangular = 0,
kEquirectangular = 1,
kCubeMap = 2,
kMesh = 3,
};
static const float kValueNotPresent;
Projection()
: type(kTypeNotPresent),
private_data(NULL),
private_data_length(0),
pose_yaw(kValueNotPresent),
pose_pitch(kValueNotPresent),
pose_roll(kValueNotPresent) {}
~Projection() { delete[] private_data; }
static bool Parse(IMkvReader* reader, long long element_start,
long long element_size, Projection** projection);

ProjectionType type;
unsigned char* private_data;
size_t private_data_length;
float pose_yaw;
float pose_pitch;
float pose_roll;
};

class VideoTrack : public Track {
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
Expand All @@ -497,6 +525,8 @@ class VideoTrack : public Track {

Colour* GetColour() const;

Projection* GetProjection() const;

private:
long long m_width;
long long m_height;
Expand All @@ -508,6 +538,7 @@ class VideoTrack : public Track {
double m_rate;

Colour* m_colour;
Projection* m_projection;
};

class AudioTrack : public Track {
Expand Down

0 comments on commit 41e814a

Please sign in to comment.