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