2016-02-18 22:00:46 +01:00
|
|
|
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style license
|
|
|
|
// that can be found in the LICENSE file in the root of the source
|
|
|
|
// tree. An additional intellectual property rights grant can be found
|
|
|
|
// in the file PATENTS. All contributing project authors may
|
|
|
|
// be found in the AUTHORS file in the root of the source tree.
|
2016-03-07 20:09:44 +01:00
|
|
|
#include "hdr_util.h"
|
2016-02-18 22:00:46 +01:00
|
|
|
|
2016-03-09 23:18:42 +01:00
|
|
|
#include <cstddef>
|
|
|
|
#include <new>
|
|
|
|
|
2016-03-21 19:20:48 +01:00
|
|
|
#include "mkvparser/mkvparser.h"
|
2016-03-09 23:18:42 +01:00
|
|
|
|
2016-02-18 22:00:46 +01:00
|
|
|
namespace libwebm {
|
|
|
|
bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
|
|
|
|
PrimaryChromaticityPtr* muxer_pc) {
|
|
|
|
muxer_pc->reset(new (std::nothrow)
|
|
|
|
mkvmuxer::PrimaryChromaticity(parser_pc.x, parser_pc.y));
|
|
|
|
if (!muxer_pc->get())
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MasteringMetadataValuePresent(double value) {
|
|
|
|
return value != mkvparser::MasteringMetadata::kValueNotPresent;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm,
|
|
|
|
mkvmuxer::MasteringMetadata* muxer_mm) {
|
|
|
|
if (MasteringMetadataValuePresent(parser_mm.luminance_max))
|
|
|
|
muxer_mm->luminance_max = parser_mm.luminance_max;
|
|
|
|
if (MasteringMetadataValuePresent(parser_mm.luminance_min))
|
|
|
|
muxer_mm->luminance_min = parser_mm.luminance_min;
|
|
|
|
|
|
|
|
PrimaryChromaticityPtr r_ptr(NULL);
|
|
|
|
PrimaryChromaticityPtr g_ptr(NULL);
|
|
|
|
PrimaryChromaticityPtr b_ptr(NULL);
|
|
|
|
PrimaryChromaticityPtr wp_ptr(NULL);
|
|
|
|
|
|
|
|
if (parser_mm.r) {
|
|
|
|
if (!CopyPrimaryChromaticity(*parser_mm.r, &r_ptr))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (parser_mm.g) {
|
|
|
|
if (!CopyPrimaryChromaticity(*parser_mm.g, &g_ptr))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (parser_mm.b) {
|
|
|
|
if (!CopyPrimaryChromaticity(*parser_mm.b, &b_ptr))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (parser_mm.white_point) {
|
|
|
|
if (!CopyPrimaryChromaticity(*parser_mm.white_point, &wp_ptr))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!muxer_mm->SetChromaticity(r_ptr.get(), g_ptr.get(), b_ptr.get(),
|
|
|
|
wp_ptr.get())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ColourValuePresent(long long value) {
|
|
|
|
return value != mkvparser::Colour::kValueNotPresent;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CopyColour(const mkvparser::Colour& parser_colour,
|
|
|
|
mkvmuxer::Colour* muxer_colour) {
|
|
|
|
if (!muxer_colour)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ColourValuePresent(parser_colour.matrix_coefficients))
|
|
|
|
muxer_colour->matrix_coefficients = parser_colour.matrix_coefficients;
|
|
|
|
if (ColourValuePresent(parser_colour.bits_per_channel))
|
|
|
|
muxer_colour->bits_per_channel = parser_colour.bits_per_channel;
|
|
|
|
if (ColourValuePresent(parser_colour.chroma_subsampling_horz))
|
|
|
|
muxer_colour->chroma_subsampling_horz =
|
|
|
|
parser_colour.chroma_subsampling_horz;
|
|
|
|
if (ColourValuePresent(parser_colour.chroma_subsampling_vert))
|
|
|
|
muxer_colour->chroma_subsampling_vert =
|
|
|
|
parser_colour.chroma_subsampling_vert;
|
|
|
|
if (ColourValuePresent(parser_colour.cb_subsampling_horz))
|
|
|
|
muxer_colour->cb_subsampling_horz = parser_colour.cb_subsampling_horz;
|
|
|
|
if (ColourValuePresent(parser_colour.cb_subsampling_vert))
|
|
|
|
muxer_colour->cb_subsampling_vert = parser_colour.cb_subsampling_vert;
|
|
|
|
if (ColourValuePresent(parser_colour.chroma_siting_horz))
|
|
|
|
muxer_colour->chroma_siting_horz = parser_colour.chroma_siting_horz;
|
|
|
|
if (ColourValuePresent(parser_colour.chroma_siting_vert))
|
|
|
|
muxer_colour->chroma_siting_vert = parser_colour.chroma_siting_vert;
|
|
|
|
if (ColourValuePresent(parser_colour.range))
|
|
|
|
muxer_colour->range = parser_colour.range;
|
|
|
|
if (ColourValuePresent(parser_colour.transfer_characteristics))
|
|
|
|
muxer_colour->transfer_characteristics =
|
|
|
|
parser_colour.transfer_characteristics;
|
|
|
|
if (ColourValuePresent(parser_colour.primaries))
|
|
|
|
muxer_colour->primaries = parser_colour.primaries;
|
|
|
|
if (ColourValuePresent(parser_colour.max_cll))
|
|
|
|
muxer_colour->max_cll = parser_colour.max_cll;
|
|
|
|
if (ColourValuePresent(parser_colour.max_fall))
|
|
|
|
muxer_colour->max_fall = parser_colour.max_fall;
|
|
|
|
|
|
|
|
if (parser_colour.mastering_metadata) {
|
|
|
|
mkvmuxer::MasteringMetadata muxer_mm;
|
|
|
|
if (!CopyMasteringMetadata(*parser_colour.mastering_metadata, &muxer_mm))
|
|
|
|
return false;
|
2016-02-22 19:54:58 +01:00
|
|
|
if (!muxer_colour->SetMasteringMetadata(muxer_mm))
|
|
|
|
return false;
|
2016-02-18 22:00:46 +01:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2016-04-01 19:29:14 +02:00
|
|
|
|
|
|
|
// Format of VPx private data:
|
|
|
|
//
|
|
|
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
2016-04-13 08:00:03 +02:00
|
|
|
// | ID Byte | Length | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|
2016-04-01 19:29:14 +02:00
|
|
|
// | |
|
|
|
|
// : Bytes 1..Length of Codec Feature :
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
//
|
|
|
|
// ID Byte Format
|
|
|
|
// ID byte is an unsigned byte.
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
// +-+-+-+-+-+-+-+-+
|
|
|
|
// |X| ID |
|
|
|
|
// +-+-+-+-+-+-+-+-+
|
|
|
|
//
|
|
|
|
// The X bit is reserved.
|
|
|
|
//
|
2016-04-13 08:00:03 +02:00
|
|
|
// Currently only VP9 level is supported. ID byte must be set to 2, and
|
2016-04-01 19:29:14 +02:00
|
|
|
// length must be 1. Supported values are:
|
|
|
|
//
|
|
|
|
// 10: Level 1
|
|
|
|
// 11: Level 1.1
|
|
|
|
// 20: Level 2
|
|
|
|
// 21: Level 2.1
|
|
|
|
// 30: Level 3
|
|
|
|
// 31: Level 3.1
|
|
|
|
// 40: Level 4
|
|
|
|
// 41: Level 4.1
|
|
|
|
// 50: Level 5
|
|
|
|
// 51: Level 5.1
|
|
|
|
// 52: Level 5.2
|
|
|
|
// 60: Level 6
|
|
|
|
// 61: Level 6.1
|
|
|
|
// 62: Level 6.2
|
|
|
|
//
|
|
|
|
// See the following link for more information:
|
|
|
|
// http://www.webmproject.org/vp9/profiles/
|
|
|
|
int ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length) {
|
|
|
|
const int kVpxCodecPrivateLength = 3;
|
|
|
|
if (!private_data || length != kVpxCodecPrivateLength)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const uint8_t id_byte = *private_data;
|
2016-04-13 08:00:03 +02:00
|
|
|
const uint8_t kVp9LevelId = 2;
|
|
|
|
if (id_byte != kVp9LevelId)
|
2016-04-01 19:29:14 +02:00
|
|
|
return 0;
|
|
|
|
|
2016-04-13 08:00:03 +02:00
|
|
|
const int kVpxFeatureLength = 1;
|
2016-04-01 19:29:14 +02:00
|
|
|
const uint8_t length_byte = private_data[1];
|
2016-04-13 08:00:03 +02:00
|
|
|
if (length_byte != kVpxFeatureLength)
|
2016-04-01 19:29:14 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
const int level = static_cast<int>(private_data[2]);
|
|
|
|
|
|
|
|
const int kNumLevels = 14;
|
|
|
|
const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
|
|
|
|
41, 50, 51, 52, 60, 61, 62};
|
|
|
|
|
|
|
|
for (int i = 0; i < kNumLevels; ++i) {
|
|
|
|
if (level == levels[i])
|
|
|
|
return level;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-02-18 22:00:46 +01:00
|
|
|
} // namespace libwebm
|