Commit 0f9265df authored by Dale Curtis's avatar Dale Curtis Committed by Commit Bot

Port color parsing metadata from Cobalt to Chrome.

Adds support for specifying the VideoColorSpace and HDRMetadata fields
in the VideoDecoderConfig. This shouldn't change anything at present
unless someone sets the the HDRMetadata field for H264 or VP9 in MP4
on Windows. Otherwise we generally prefer the frame color space
information.
Signed-off-by: default avatarDale Curtis <dalecurtis@chromium.org>
Bug: b/143382177
Change-Id: I39bfb06228f5f5f67b858551e9fe67a74c79d20e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2001248Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#731777}
parent 50fb856d
...@@ -71,6 +71,27 @@ base::Optional<DOVIDecoderConfigurationRecord> ParseDOVIConfig( ...@@ -71,6 +71,27 @@ base::Optional<DOVIDecoderConfigurationRecord> ParseDOVIConfig(
} }
#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
// Read color coordinate value as defined in the MasteringDisplayColorVolume
// ('mdcv') box. Each coordinate is a float encoded in uint16_t, with upper
// bound set to 50000.
bool ReadMdcvColorCoordinate(BoxReader* reader,
float* normalized_value_in_float) {
const float kColorCoordinateUpperBound = 50000.;
uint16_t value_in_uint16;
RCHECK(reader->Read2(&value_in_uint16));
float value_in_float = static_cast<float>(value_in_uint16);
if (value_in_float >= kColorCoordinateUpperBound) {
*normalized_value_in_float = 1.f;
return true;
}
*normalized_value_in_float = value_in_float / kColorCoordinateUpperBound;
return true;
}
} // namespace } // namespace
FileType::FileType() = default; FileType::FileType() = default;
...@@ -783,11 +804,77 @@ PixelAspectRatioBox::~PixelAspectRatioBox() = default; ...@@ -783,11 +804,77 @@ PixelAspectRatioBox::~PixelAspectRatioBox() = default;
FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; } FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
bool PixelAspectRatioBox::Parse(BoxReader* reader) { bool PixelAspectRatioBox::Parse(BoxReader* reader) {
RCHECK(reader->Read4(&h_spacing) && RCHECK(reader->Read4(&h_spacing) && reader->Read4(&v_spacing));
reader->Read4(&v_spacing)); return true;
}
ColorParameterInformation::ColorParameterInformation() = default;
ColorParameterInformation::ColorParameterInformation(
const ColorParameterInformation& other) = default;
ColorParameterInformation::~ColorParameterInformation() = default;
FourCC ColorParameterInformation::BoxType() const {
return FOURCC_COLR;
}
bool ColorParameterInformation::Parse(BoxReader* reader) {
FourCC type;
RCHECK(reader->ReadFourCC(&type));
// TODO: Support 'nclc', 'rICC', and 'prof'.
RCHECK(type == FOURCC_NCLX);
uint8_t full_range_byte;
RCHECK(reader->Read2(&colour_primaries) &&
reader->Read2(&transfer_characteristics) &&
reader->Read2(&matrix_coefficients) &&
reader->Read1(&full_range_byte));
full_range = full_range_byte & 0x80;
return true;
}
MasteringDisplayColorVolume::MasteringDisplayColorVolume() = default;
MasteringDisplayColorVolume::MasteringDisplayColorVolume(
const MasteringDisplayColorVolume& other) = default;
MasteringDisplayColorVolume::~MasteringDisplayColorVolume() = default;
FourCC MasteringDisplayColorVolume::BoxType() const {
return FOURCC_MDCV;
}
bool MasteringDisplayColorVolume::Parse(BoxReader* reader) {
// Technically the color coordinates may be in any order. The spec recommends
// GBR and it is assumed that the color coordinates are in such order.
RCHECK(ReadMdcvColorCoordinate(reader, &display_primaries_gx) &&
ReadMdcvColorCoordinate(reader, &display_primaries_gy) &&
ReadMdcvColorCoordinate(reader, &display_primaries_bx) &&
ReadMdcvColorCoordinate(reader, &display_primaries_by) &&
ReadMdcvColorCoordinate(reader, &display_primaries_rx) &&
ReadMdcvColorCoordinate(reader, &display_primaries_ry) &&
ReadMdcvColorCoordinate(reader, &white_point_x) &&
ReadMdcvColorCoordinate(reader, &white_point_y) &&
reader->Read4(&max_display_mastering_luminance) &&
reader->Read4(&min_display_mastering_luminance));
const uint32_t kUnitOfMasteringLuminance = 10000;
max_display_mastering_luminance /= kUnitOfMasteringLuminance;
min_display_mastering_luminance /= kUnitOfMasteringLuminance;
return true; return true;
} }
ContentLightLevelInformation::ContentLightLevelInformation() = default;
ContentLightLevelInformation::ContentLightLevelInformation(
const ContentLightLevelInformation& other) = default;
ContentLightLevelInformation::~ContentLightLevelInformation() = default;
FourCC ContentLightLevelInformation::BoxType() const {
return FOURCC_CLLI;
}
bool ContentLightLevelInformation::Parse(BoxReader* reader) {
return reader->Read2(&max_content_light_level) &&
reader->Read2(&max_pic_average_light_level);
}
VideoSampleEntry::VideoSampleEntry() VideoSampleEntry::VideoSampleEntry()
: format(FOURCC_NULL), : format(FOURCC_NULL),
data_reference_index(0), data_reference_index(0),
...@@ -937,6 +1024,24 @@ bool VideoSampleEntry::Parse(BoxReader* reader) { ...@@ -937,6 +1024,24 @@ bool VideoSampleEntry::Parse(BoxReader* reader) {
frame_bitstream_converter = nullptr; frame_bitstream_converter = nullptr;
video_codec = kCodecAV1; video_codec = kCodecAV1;
video_codec_profile = av1_config.profile; video_codec_profile = av1_config.profile;
ColorParameterInformation color_parameter_information;
if (reader->HasChild(&color_parameter_information)) {
RCHECK(reader->ReadChild(&color_parameter_information));
this->color_parameter_information = color_parameter_information;
}
MasteringDisplayColorVolume mastering_display_color_volume;
if (reader->HasChild(&mastering_display_color_volume)) {
RCHECK(reader->ReadChild(&mastering_display_color_volume));
this->mastering_display_color_volume = mastering_display_color_volume;
}
ContentLightLevelInformation content_light_level_information;
if (reader->HasChild(&content_light_level_information)) {
RCHECK(reader->ReadChild(&content_light_level_information));
this->content_light_level_information = content_light_level_information;
}
break; break;
} }
#endif #endif
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <vector> #include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/optional.h"
#include "media/base/decrypt_config.h" #include "media/base/decrypt_config.h"
#include "media/base/media_export.h" #include "media/base/media_export.h"
#include "media/base/media_log.h" #include "media/base/media_log.h"
...@@ -265,6 +266,37 @@ struct MEDIA_EXPORT PixelAspectRatioBox : Box { ...@@ -265,6 +266,37 @@ struct MEDIA_EXPORT PixelAspectRatioBox : Box {
uint32_t v_spacing; uint32_t v_spacing;
}; };
struct MEDIA_EXPORT ColorParameterInformation : Box {
DECLARE_BOX_METHODS(ColorParameterInformation);
uint16_t colour_primaries;
uint16_t transfer_characteristics;
uint16_t matrix_coefficients;
bool full_range;
};
struct MEDIA_EXPORT MasteringDisplayColorVolume : Box {
DECLARE_BOX_METHODS(MasteringDisplayColorVolume);
float display_primaries_gx;
float display_primaries_gy;
float display_primaries_bx;
float display_primaries_by;
float display_primaries_rx;
float display_primaries_ry;
float white_point_x;
float white_point_y;
uint32_t max_display_mastering_luminance;
uint32_t min_display_mastering_luminance;
};
struct MEDIA_EXPORT ContentLightLevelInformation : Box {
DECLARE_BOX_METHODS(ContentLightLevelInformation);
uint16_t max_content_light_level;
uint16_t max_pic_average_light_level;
};
struct MEDIA_EXPORT VideoSampleEntry : Box { struct MEDIA_EXPORT VideoSampleEntry : Box {
DECLARE_BOX_METHODS(VideoSampleEntry); DECLARE_BOX_METHODS(VideoSampleEntry);
...@@ -280,6 +312,10 @@ struct MEDIA_EXPORT VideoSampleEntry : Box { ...@@ -280,6 +312,10 @@ struct MEDIA_EXPORT VideoSampleEntry : Box {
VideoCodecProfile video_codec_profile; VideoCodecProfile video_codec_profile;
VideoCodecLevel video_codec_level; VideoCodecLevel video_codec_level;
base::Optional<ColorParameterInformation> color_parameter_information;
base::Optional<MasteringDisplayColorVolume> mastering_display_color_volume;
base::Optional<ContentLightLevelInformation> content_light_level_information;
bool IsFormatValid() const; bool IsFormatValid() const;
scoped_refptr<BitstreamConverter> frame_bitstream_converter; scoped_refptr<BitstreamConverter> frame_bitstream_converter;
......
...@@ -28,7 +28,9 @@ enum FourCC { ...@@ -28,7 +28,9 @@ enum FourCC {
FOURCC_BLOC = 0x626C6F63, FOURCC_BLOC = 0x626C6F63,
FOURCC_CBCS = 0x63626373, FOURCC_CBCS = 0x63626373,
FOURCC_CENC = 0x63656e63, FOURCC_CENC = 0x63656e63,
FOURCC_CLLI = 0x636c6c69,
FOURCC_CO64 = 0x636f3634, FOURCC_CO64 = 0x636f3634,
FOURCC_COLR = 0x636f6c72,
FOURCC_CTTS = 0x63747473, FOURCC_CTTS = 0x63747473,
FOURCC_DFLA = 0x64664c61, // "dfLa" FOURCC_DFLA = 0x64664c61, // "dfLa"
FOURCC_DINF = 0x64696e66, FOURCC_DINF = 0x64696e66,
...@@ -63,6 +65,7 @@ enum FourCC { ...@@ -63,6 +65,7 @@ enum FourCC {
FOURCC_ID32 = 0x49443332, FOURCC_ID32 = 0x49443332,
FOURCC_IODS = 0x696f6473, FOURCC_IODS = 0x696f6473,
FOURCC_MDAT = 0x6d646174, FOURCC_MDAT = 0x6d646174,
FOURCC_MDCV = 0x6d646376,
FOURCC_MDHD = 0x6d646864, FOURCC_MDHD = 0x6d646864,
FOURCC_MDIA = 0x6d646961, FOURCC_MDIA = 0x6d646961,
FOURCC_MECO = 0x6d65636f, FOURCC_MECO = 0x6d65636f,
...@@ -81,6 +84,7 @@ enum FourCC { ...@@ -81,6 +84,7 @@ enum FourCC {
FOURCC_MP4V = 0x6d703476, FOURCC_MP4V = 0x6d703476,
FOURCC_MVEX = 0x6d766578, FOURCC_MVEX = 0x6d766578,
FOURCC_MVHD = 0x6d766864, FOURCC_MVHD = 0x6d766864,
FOURCC_NCLX = 0x6e636c78,
FOURCC_OPUS = 0x4f707573, // "Opus" FOURCC_OPUS = 0x4f707573, // "Opus"
FOURCC_PASP = 0x70617370, FOURCC_PASP = 0x70617370,
FOURCC_PDIN = 0x7064696e, FOURCC_PDIN = 0x7064696e,
......
...@@ -59,6 +59,44 @@ EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) { ...@@ -59,6 +59,44 @@ EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) {
} }
return EncryptionScheme::kUnencrypted; return EncryptionScheme::kUnencrypted;
} }
VideoColorSpace ConvertColorParameterInformationToColorSpace(
const ColorParameterInformation& info) {
auto primary_id =
static_cast<VideoColorSpace::PrimaryID>(info.colour_primaries);
auto transfer_id =
static_cast<VideoColorSpace::TransferID>(info.transfer_characteristics);
auto matrix_id =
static_cast<VideoColorSpace::MatrixID>(info.matrix_coefficients);
// Note that we don't check whether the embedded ids are valid. We rely on
// the underlying video decoder to reject any ids that it doesn't support.
return VideoColorSpace(primary_id, transfer_id, matrix_id,
info.full_range ? gfx::ColorSpace::RangeID::FULL
: gfx::ColorSpace::RangeID::LIMITED);
}
MasteringMetadata ConvertMdcvToMasteringMetadata(
const MasteringDisplayColorVolume& mdcv) {
MasteringMetadata mastering_metadata;
mastering_metadata.primary_r = MasteringMetadata::Chromaticity(
mdcv.display_primaries_rx, mdcv.display_primaries_ry);
mastering_metadata.primary_g = MasteringMetadata::Chromaticity(
mdcv.display_primaries_gx, mdcv.display_primaries_gy);
mastering_metadata.primary_b = MasteringMetadata::Chromaticity(
mdcv.display_primaries_bx, mdcv.display_primaries_by);
mastering_metadata.white_point =
MasteringMetadata::Chromaticity(mdcv.white_point_x, mdcv.white_point_y);
mastering_metadata.luminance_max =
static_cast<float>(mdcv.max_display_mastering_luminance);
mastering_metadata.luminance_min =
static_cast<float>(mdcv.min_display_mastering_luminance);
return mastering_metadata;
}
} // namespace } // namespace
MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types,
...@@ -516,6 +554,30 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { ...@@ -516,6 +554,30 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
EmptyExtraData(), scheme); EmptyExtraData(), scheme);
video_config.set_level(entry.video_codec_level); video_config.set_level(entry.video_codec_level);
if (entry.color_parameter_information) {
video_config.set_color_space_info(
ConvertColorParameterInformationToColorSpace(
*entry.color_parameter_information));
if (entry.mastering_display_color_volume ||
entry.content_light_level_information) {
HDRMetadata hdr_metadata;
if (entry.mastering_display_color_volume) {
hdr_metadata.mastering_metadata = ConvertMdcvToMasteringMetadata(
*entry.mastering_display_color_volume);
}
if (entry.content_light_level_information) {
hdr_metadata.max_content_light_level =
entry.content_light_level_information->max_content_light_level;
hdr_metadata.max_frame_average_light_level =
entry.content_light_level_information
->max_pic_average_light_level;
}
video_config.set_hdr_metadata(hdr_metadata);
}
}
DVLOG(1) << "video_track_id=" << video_track_id DVLOG(1) << "video_track_id=" << video_track_id
<< " config=" << video_config.AsHumanReadableString(); << " config=" << video_config.AsHumanReadableString();
if (!video_config.IsValidConfig()) { if (!video_config.IsValidConfig()) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment