1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/formats/webm/webm_colour_parser.h"
6 
7 #include "base/logging.h"
8 #include "media/formats/webm/webm_constants.h"
9 #include "third_party/libwebm/source/mkvmuxer/mkvmuxer.h"
10 
11 namespace media {
12 
13 WebMColorMetadata::WebMColorMetadata() = default;
14 WebMColorMetadata::WebMColorMetadata(const WebMColorMetadata& rhs) = default;
15 
16 WebMMasteringMetadataParser::WebMMasteringMetadataParser() = default;
17 WebMMasteringMetadataParser::~WebMMasteringMetadataParser() = default;
18 
OnFloat(int id,double val)19 bool WebMMasteringMetadataParser::OnFloat(int id, double val) {
20   switch (id) {
21     case kWebMIdPrimaryRChromaticityX:
22       mastering_metadata_.primary_r.set_x(val);
23       break;
24     case kWebMIdPrimaryRChromaticityY:
25       mastering_metadata_.primary_r.set_y(val);
26       break;
27     case kWebMIdPrimaryGChromaticityX:
28       mastering_metadata_.primary_g.set_x(val);
29       break;
30     case kWebMIdPrimaryGChromaticityY:
31       mastering_metadata_.primary_g.set_y(val);
32       break;
33     case kWebMIdPrimaryBChromaticityX:
34       mastering_metadata_.primary_b.set_x(val);
35       break;
36     case kWebMIdPrimaryBChromaticityY:
37       mastering_metadata_.primary_b.set_y(val);
38       break;
39     case kWebMIdWhitePointChromaticityX:
40       mastering_metadata_.white_point.set_x(val);
41       break;
42     case kWebMIdWhitePointChromaticityY:
43       mastering_metadata_.white_point.set_y(val);
44       break;
45     case kWebMIdLuminanceMax:
46       mastering_metadata_.luminance_max = val;
47       break;
48     case kWebMIdLuminanceMin:
49       mastering_metadata_.luminance_min = val;
50       break;
51     default:
52       DVLOG(1) << "Unexpected id in MasteringMetadata: 0x" << std::hex << id;
53       return false;
54   }
55   return true;
56 }
57 
WebMColourParser()58 WebMColourParser::WebMColourParser() {
59   Reset();
60 }
61 
62 WebMColourParser::~WebMColourParser() = default;
63 
Reset()64 void WebMColourParser::Reset() {
65   matrix_coefficients_ = -1;
66   bits_per_channel_ = -1;
67   chroma_subsampling_horz_ = -1;
68   chroma_subsampling_vert_ = -1;
69   cb_subsampling_horz_ = -1;
70   cb_subsampling_vert_ = -1;
71   chroma_siting_horz_ = -1;
72   chroma_siting_vert_ = -1;
73   range_ = -1;
74   transfer_characteristics_ = -1;
75   primaries_ = -1;
76   max_content_light_level_ = -1;
77   max_frame_average_light_level_ = -1;
78 }
79 
OnListStart(int id)80 WebMParserClient* WebMColourParser::OnListStart(int id) {
81   if (id == kWebMIdMasteringMetadata) {
82     mastering_metadata_parsed_ = false;
83     return &mastering_metadata_parser_;
84   }
85 
86   return this;
87 }
88 
OnListEnd(int id)89 bool WebMColourParser::OnListEnd(int id) {
90   if (id == kWebMIdMasteringMetadata)
91     mastering_metadata_parsed_ = true;
92   return true;
93 }
94 
OnUInt(int id,int64_t val)95 bool WebMColourParser::OnUInt(int id, int64_t val) {
96   int64_t* dst = nullptr;
97 
98   switch (id) {
99     case kWebMIdMatrixCoefficients:
100       dst = &matrix_coefficients_;
101       break;
102     case kWebMIdBitsPerChannel:
103       dst = &bits_per_channel_;
104       break;
105     case kWebMIdChromaSubsamplingHorz:
106       dst = &chroma_subsampling_horz_;
107       break;
108     case kWebMIdChromaSubsamplingVert:
109       dst = &chroma_subsampling_vert_;
110       break;
111     case kWebMIdCbSubsamplingHorz:
112       dst = &cb_subsampling_horz_;
113       break;
114     case kWebMIdCbSubsamplingVert:
115       dst = &cb_subsampling_vert_;
116       break;
117     case kWebMIdChromaSitingHorz:
118       dst = &chroma_siting_horz_;
119       break;
120     case kWebMIdChromaSitingVert:
121       dst = &chroma_siting_vert_;
122       break;
123     case kWebMIdRange:
124       dst = &range_;
125       break;
126     case kWebMIdTransferCharacteristics:
127       dst = &transfer_characteristics_;
128       break;
129     case kWebMIdPrimaries:
130       dst = &primaries_;
131       break;
132     case kWebMIdMaxCLL:
133       dst = &max_content_light_level_;
134       break;
135     case kWebMIdMaxFALL:
136       dst = &max_frame_average_light_level_;
137       break;
138     default:
139       return true;
140   }
141 
142   DCHECK(dst);
143   if (*dst != -1) {
144     LOG(ERROR) << "Multiple values for id " << std::hex << id << " specified ("
145                << *dst << " and " << val << ")";
146     return false;
147   }
148 
149   *dst = val;
150   return true;
151 }
152 
GetWebMColorMetadata() const153 WebMColorMetadata WebMColourParser::GetWebMColorMetadata() const {
154   WebMColorMetadata color_metadata;
155 
156   if (bits_per_channel_ != -1)
157     color_metadata.BitsPerChannel = bits_per_channel_;
158 
159   if (chroma_subsampling_horz_ != -1)
160     color_metadata.ChromaSubsamplingHorz = chroma_subsampling_horz_;
161   if (chroma_subsampling_vert_ != -1)
162     color_metadata.ChromaSubsamplingVert = chroma_subsampling_vert_;
163   if (cb_subsampling_horz_ != -1)
164     color_metadata.CbSubsamplingHorz = cb_subsampling_horz_;
165   if (cb_subsampling_vert_ != -1)
166     color_metadata.CbSubsamplingVert = cb_subsampling_vert_;
167   if (chroma_siting_horz_ != -1)
168     color_metadata.ChromaSitingHorz = chroma_siting_horz_;
169   if (chroma_siting_vert_ != -1)
170     color_metadata.ChromaSitingVert = chroma_siting_vert_;
171 
172   gfx::ColorSpace::RangeID range_id = gfx::ColorSpace::RangeID::INVALID;
173   if (range_ >= static_cast<int64_t>(mkvmuxer::Colour::kUnspecifiedCr) &&
174       range_ <= static_cast<int64_t>(mkvmuxer::Colour::kMcTcDefined)) {
175     switch (range_) {
176       case mkvmuxer::Colour::kUnspecifiedCr:
177         range_id = gfx::ColorSpace::RangeID::INVALID;
178         break;
179       case mkvmuxer::Colour::kBroadcastRange:
180         range_id = gfx::ColorSpace::RangeID::LIMITED;
181         break;
182       case mkvmuxer::Colour::kFullRange:
183         range_id = gfx::ColorSpace::RangeID::FULL;
184         break;
185       case mkvmuxer::Colour::kMcTcDefined:
186         range_id = gfx::ColorSpace::RangeID::DERIVED;
187         break;
188     }
189   }
190   color_metadata.color_space = VideoColorSpace(
191       primaries_, transfer_characteristics_, matrix_coefficients_, range_id);
192 
193   if (max_content_light_level_ != -1 || max_frame_average_light_level_ != -1 ||
194       mastering_metadata_parsed_) {
195     color_metadata.hdr_metadata = gfx::HDRMetadata();
196 
197     if (max_content_light_level_ != -1) {
198       color_metadata.hdr_metadata->max_content_light_level =
199           max_content_light_level_;
200     }
201 
202     if (max_frame_average_light_level_ != -1) {
203       color_metadata.hdr_metadata->max_frame_average_light_level =
204           max_frame_average_light_level_;
205     }
206 
207     if (mastering_metadata_parsed_) {
208       color_metadata.hdr_metadata->mastering_metadata =
209           mastering_metadata_parser_.GetMasteringMetadata();
210     }
211   }
212 
213   return color_metadata;
214 }
215 
216 }  // namespace media
217