Shaka Packager SDK
webm_video_client.cc
1 // Copyright 2014 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 <packager/media/formats/webm/webm_video_client.h>
6 
7 #include <absl/log/log.h>
8 
9 #include <packager/macros/logging.h>
10 #include <packager/media/base/video_util.h>
11 #include <packager/media/codecs/av1_codec_configuration_record.h>
12 #include <packager/media/codecs/vp_codec_configuration_record.h>
13 #include <packager/media/formats/webm/webm_constants.h>
14 
15 namespace {
16 
17 // Timestamps are represented in double in WebM. Convert to int64_t in us.
18 const int32_t kWebMTimeScale = 1000000;
19 
20 } // namespace
21 
22 namespace shaka {
23 namespace media {
24 
25 WebMVideoClient::WebMVideoClient() {}
26 
27 WebMVideoClient::~WebMVideoClient() {}
28 
30  pixel_width_ = -1;
31  pixel_height_ = -1;
32  crop_bottom_ = -1;
33  crop_top_ = -1;
34  crop_left_ = -1;
35  crop_right_ = -1;
36  display_width_ = -1;
37  display_height_ = -1;
38  display_unit_ = -1;
39  alpha_mode_ = -1;
40 
41  matrix_coefficients_ = -1;
42  bits_per_channel_ = -1;
43  chroma_subsampling_horz_ = -1;
44  chroma_subsampling_vert_ = -1;
45  chroma_siting_horz_ = -1;
46  chroma_siting_vert_ = -1;
47  color_range_ = -1;
48  transfer_characteristics_ = -1;
49  color_primaries_ = -1;
50 }
51 
52 std::shared_ptr<VideoStreamInfo> WebMVideoClient::GetVideoStreamInfo(
53  int64_t track_num,
54  const std::string& codec_id,
55  const std::vector<uint8_t>& codec_private,
56  bool is_encrypted) {
57  std::string codec_string;
58  Codec video_codec = kUnknownCodec;
59  if (codec_id == "V_AV1") {
60  video_codec = kCodecAV1;
61 
62  // CodecPrivate is mandatory per AV in Matroska / WebM specification.
63  // https://github.com/Matroska-Org/matroska-specification/blob/av1-mappin/codec/av1.md#codecprivate-1
64  AV1CodecConfigurationRecord av1_config;
65  if (!av1_config.Parse(codec_private)) {
66  LOG(ERROR) << "Failed to parse AV1 codec_private.";
67  return nullptr;
68  }
69  codec_string = av1_config.GetCodecString();
70  } else if (codec_id == "V_VP8") {
71  video_codec = kCodecVP8;
72  // codec_string for VP8 is parsed later.
73  } else if (codec_id == "V_VP9") {
74  video_codec = kCodecVP9;
75  // codec_string for VP9 is parsed later.
76  } else {
77  LOG(ERROR) << "Unsupported video codec_id " << codec_id;
78  return nullptr;
79  }
80 
81  if (pixel_width_ <= 0 || pixel_height_ <= 0)
82  return nullptr;
83 
84  // Set crop and display unit defaults if these elements are not present.
85  if (crop_bottom_ == -1)
86  crop_bottom_ = 0;
87 
88  if (crop_top_ == -1)
89  crop_top_ = 0;
90 
91  if (crop_left_ == -1)
92  crop_left_ = 0;
93 
94  if (crop_right_ == -1)
95  crop_right_ = 0;
96 
97  if (display_unit_ == -1)
98  display_unit_ = 0;
99 
100  uint16_t width_after_crop = pixel_width_ - (crop_left_ + crop_right_);
101  uint16_t height_after_crop = pixel_height_ - (crop_top_ + crop_bottom_);
102 
103  if (display_unit_ == 0) {
104  if (display_width_ <= 0)
105  display_width_ = width_after_crop;
106  if (display_height_ <= 0)
107  display_height_ = height_after_crop;
108  } else if (display_unit_ == 3) {
109  if (display_width_ <= 0 || display_height_ <= 0)
110  return nullptr;
111  } else {
112  LOG(ERROR) << "Unsupported display unit type " << display_unit_;
113  return nullptr;
114  }
115 
116  // Calculate sample aspect ratio.
117  uint32_t pixel_width;
118  uint32_t pixel_height;
119  DerivePixelWidthHeight(width_after_crop, height_after_crop, display_width_,
120  display_height_, &pixel_width, &pixel_height);
121 
122  // |codec_private| may be overriden later for some codecs, e.g. VP9 since for
123  // VP9, the format for MP4 and WebM are different; MP4 format is used as the
124  // intermediate format.
125  return std::make_shared<VideoStreamInfo>(
126  track_num, kWebMTimeScale, 0, video_codec, H26xStreamFormat::kUnSpecified,
127  codec_string, codec_private.data(), codec_private.size(),
128  width_after_crop, height_after_crop, pixel_width, pixel_height, 0, 0, 0,
129  0, 0, std::string(), is_encrypted);
130 }
131 
133  const std::vector<uint8_t>& codec_private) {
134  VPCodecConfigurationRecord vp_config;
135  vp_config.ParseWebM(codec_private);
136  if (matrix_coefficients_ != -1) {
137  vp_config.set_matrix_coefficients(matrix_coefficients_);
138  }
139  if (bits_per_channel_ != -1) {
140  vp_config.set_bit_depth(bits_per_channel_);
141  }
142  if (chroma_subsampling_horz_ != -1 && chroma_subsampling_vert_ != -1) {
143  vp_config.SetChromaSubsampling(chroma_subsampling_horz_,
144  chroma_subsampling_vert_);
145  }
146  if (chroma_siting_horz_ != -1 && chroma_siting_vert_ != -1) {
147  vp_config.SetChromaLocation(chroma_siting_horz_, chroma_siting_vert_);
148  }
149  if (color_range_ != -1) {
150  if (color_range_ == 0)
151  vp_config.set_video_full_range_flag(false);
152  else if (color_range_ == 1)
153  vp_config.set_video_full_range_flag(true);
154  // Ignore for other values.
155  }
156  if (transfer_characteristics_ != -1) {
157  vp_config.set_transfer_characteristics(transfer_characteristics_);
158  }
159  if (color_primaries_ != -1) {
160  vp_config.set_color_primaries(color_primaries_);
161  }
162  return vp_config;
163 }
164 
165 WebMParserClient* WebMVideoClient::OnListStart(int id) {
166  return id == kWebMIdColor || id == kWebMIdProjection
167  ? this
168  : WebMParserClient::OnListStart(id);
169 }
170 
171 bool WebMVideoClient::OnListEnd(int id) {
172  return id == kWebMIdColor || id == kWebMIdProjection
173  ? true
174  : WebMParserClient::OnListEnd(id);
175 }
176 
177 bool WebMVideoClient::OnUInt(int id, int64_t val) {
178  int64_t* dst = nullptr;
179 
180  switch (id) {
181  case kWebMIdPixelWidth:
182  dst = &pixel_width_;
183  break;
184  case kWebMIdPixelHeight:
185  dst = &pixel_height_;
186  break;
187  case kWebMIdPixelCropTop:
188  dst = &crop_top_;
189  break;
190  case kWebMIdPixelCropBottom:
191  dst = &crop_bottom_;
192  break;
193  case kWebMIdPixelCropLeft:
194  dst = &crop_left_;
195  break;
196  case kWebMIdPixelCropRight:
197  dst = &crop_right_;
198  break;
199  case kWebMIdDisplayWidth:
200  dst = &display_width_;
201  break;
202  case kWebMIdDisplayHeight:
203  dst = &display_height_;
204  break;
205  case kWebMIdDisplayUnit:
206  dst = &display_unit_;
207  break;
208  case kWebMIdAlphaMode:
209  dst = &alpha_mode_;
210  break;
211  case kWebMIdColorMatrixCoefficients:
212  dst = &matrix_coefficients_;
213  break;
214  case kWebMIdColorBitsPerChannel:
215  dst = &bits_per_channel_;
216  break;
217  case kWebMIdColorChromaSubsamplingHorz:
218  dst = &chroma_subsampling_horz_;
219  break;
220  case kWebMIdColorChromaSubsamplingVert:
221  dst = &chroma_subsampling_vert_;
222  break;
223  case kWebMIdColorChromaSitingHorz:
224  dst = &chroma_siting_horz_;
225  break;
226  case kWebMIdColorChromaSitingVert:
227  dst = &chroma_siting_vert_;
228  break;
229  case kWebMIdColorRange:
230  dst = &color_range_;
231  break;
232  case kWebMIdColorTransferCharacteristics:
233  dst = &transfer_characteristics_;
234  break;
235  case kWebMIdColorPrimaries:
236  dst = &color_primaries_;
237  break;
238  case kWebMIdColorMaxCLL:
239  case kWebMIdColorMaxFALL:
240  NOTIMPLEMENTED() << "HDR is not supported yet.";
241  return true;
242  case kWebMIdProjectionType:
243  LOG(WARNING) << "Ignoring ProjectionType with value " << val;
244  return true;
245  default:
246  return true;
247  }
248 
249  if (*dst != -1) {
250  LOG(ERROR) << "Multiple values for id " << std::hex << id << " specified ("
251  << *dst << " and " << val << ")";
252  return false;
253  }
254 
255  *dst = val;
256  return true;
257 }
258 
259 bool WebMVideoClient::OnBinary(int /*id*/,
260  const uint8_t* /*data*/,
261  int /*size*/) {
262  // Accept binary fields we don't care about for now.
263  return true;
264 }
265 
266 bool WebMVideoClient::OnFloat(int /*id*/, double /*val*/) {
267  // Accept float fields we don't care about for now.
268  return true;
269 }
270 
271 } // namespace media
272 } // namespace shaka
Class for parsing AV1 codec configuration record.
bool Parse(const std::vector< uint8_t > &data)
Class for parsing or writing VP codec configuration record.
bool ParseWebM(const std::vector< uint8_t > &data)
std::shared_ptr< VideoStreamInfo > GetVideoStreamInfo(int64_t track_num, const std::string &codec_id, const std::vector< uint8_t > &codec_private, bool is_encrypted)
VPCodecConfigurationRecord GetVpCodecConfig(const std::vector< uint8_t > &codec_private)
void Reset()
Reset this object's state so it can process a new video track element.
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66