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