blob: c792390805b3a57344ff8455f4c5e8492773c279 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/formats/webm/webm_projection_parser.h"
#include "base/check.h"
#include "base/logging.h"
#include "media/formats/webm/webm_constants.h"
namespace {
int64_t INVALID_PROJECTION_TYPE = -1;
double INVALID_ANGLE = -1000;
bool IsValidAngle(double val, double min, double max) {
return (val >= min && val <= max);
}
// Values for "ProjectionType" are spec'd here:
// https://www.matroska.org/technical/elements.html#ProjectionType
bool IsValidProjectionType(int64_t projection_type_code) {
const int64_t projection_type_min = 0; // rectangular
const int64_t projection_type_max = 3; // mesh
return projection_type_code >= projection_type_min &&
projection_type_code <= projection_type_max;
}
} // namespace
namespace media {
WebMProjectionParser::WebMProjectionParser(MediaLog* media_log)
: media_log_(media_log) {
Reset();
}
WebMProjectionParser::~WebMProjectionParser() = default;
void WebMProjectionParser::Reset() {
projection_type_ = INVALID_PROJECTION_TYPE;
pose_yaw_ = INVALID_ANGLE;
pose_pitch_ = INVALID_ANGLE;
pose_roll_ = INVALID_ANGLE;
}
// WebMParserClient
bool WebMProjectionParser::OnUInt(int id, int64_t val) {
if (id != kWebMIdProjectionType) {
MEDIA_LOG(ERROR, media_log_)
<< "Unexpected id in Projection: 0x" << std::hex << id;
return false;
}
if (projection_type_ != INVALID_PROJECTION_TYPE) {
MEDIA_LOG(ERROR, media_log_)
<< "Multiple values for id: 0x" << std::hex << id << " specified ("
<< projection_type_ << " and " << val << ")";
return false;
}
if (!IsValidProjectionType(val)) {
MEDIA_LOG(ERROR, media_log_)
<< "Unexpected value for ProjectionType: 0x" << std::hex << val;
return false;
}
projection_type_ = val;
return true;
}
// WebMParserClient
bool WebMProjectionParser::OnFloat(int id, double val) {
double* dst = NULL;
bool is_valid = false;
switch (id) {
case kWebMIdProjectionPoseYaw:
dst = &pose_yaw_;
// Valid range defined:
// https://www.matroska.org/technical/elements.html#ProjectionPoseYaw
is_valid = IsValidAngle(val, -180, 180);
break;
case kWebMIdProjectionPosePitch:
dst = &pose_pitch_;
// Valid range defined:
// https://www.matroska.org/technical/elements.html#ProjectionPosePitch
is_valid = IsValidAngle(val, -90, 90);
break;
case kWebMIdProjectionPoseRoll:
dst = &pose_roll_;
// Valid range defined:
// https://www.matroska.org/technical/elements.html#ProjectionPoseRoll
is_valid = IsValidAngle(val, -180, 180);
break;
default:
MEDIA_LOG(ERROR, media_log_)
<< "Unexpected id in Projection: 0x" << std::hex << id;
return false;
}
if (*dst != INVALID_ANGLE) {
MEDIA_LOG(ERROR, media_log_)
<< "Multiple values for id: 0x" << std::hex << id << " specified ("
<< *dst << " and " << val << ")";
return false;
}
if (!is_valid) {
MEDIA_LOG(ERROR, media_log_) << "Value not within valid range. id: 0x"
<< std::hex << id << " val:" << val;
return false;
}
*dst = val;
return true;
}
bool WebMProjectionParser::Validate() const {
if (projection_type_ == INVALID_PROJECTION_TYPE) {
MEDIA_LOG(ERROR, media_log_)
<< "Projection element is incomplete; ProjectionType required.";
return false;
}
if (pose_yaw_ == INVALID_ANGLE) {
MEDIA_LOG(ERROR, media_log_)
<< "Projection element is incomplete; ProjectionPoseYaw required.";
return false;
}
if (pose_pitch_ == INVALID_ANGLE) {
MEDIA_LOG(ERROR, media_log_)
<< "Projection element is incomplete; ProjectionPosePitch required.";
return false;
}
if (pose_roll_ == INVALID_ANGLE) {
MEDIA_LOG(ERROR, media_log_)
<< "Projection element is incomplete; ProjectionPoseRoll required.";
return false;
}
return true;
}
} // namespace media