Shaka Packager SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
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  Reset();
32 }
33 
34 WebMVideoClient::~WebMVideoClient() {
35 }
36 
38  pixel_width_ = -1;
39  pixel_height_ = -1;
40  crop_bottom_ = -1;
41  crop_top_ = -1;
42  crop_left_ = -1;
43  crop_right_ = -1;
44  display_width_ = -1;
45  display_height_ = -1;
46  display_unit_ = -1;
47  alpha_mode_ = -1;
48 
49  vp_config_ = VPCodecConfigurationRecord();
50  chroma_subsampling_horz_ = -1;
51  chroma_subsampling_vert_ = -1;
52  chroma_siting_horz_ = -1;
53  chroma_siting_vert_ = -1;
54 }
55 
56 std::shared_ptr<VideoStreamInfo> WebMVideoClient::GetVideoStreamInfo(
57  int64_t track_num,
58  const std::string& codec_id,
59  bool is_encrypted) {
60  Codec video_codec = kUnknownCodec;
61  if (codec_id == "V_VP8") {
62  video_codec = kCodecVP8;
63  } else if (codec_id == "V_VP9") {
64  video_codec = kCodecVP9;
65  // The codec private data is in WebM format, but needs to be converted to
66  // MP4 format. Don't do it yet, it will be handled in
67  // webm_cluster_parser.cc
68  } else if (codec_id == "V_VP10") {
69  video_codec = kCodecVP10;
70  } else {
71  LOG(ERROR) << "Unsupported video codec_id " << codec_id;
72  return std::shared_ptr<VideoStreamInfo>();
73  }
74 
75  if (pixel_width_ <= 0 || pixel_height_ <= 0)
76  return std::shared_ptr<VideoStreamInfo>();
77 
78  // Set crop and display unit defaults if these elements are not present.
79  if (crop_bottom_ == -1)
80  crop_bottom_ = 0;
81 
82  if (crop_top_ == -1)
83  crop_top_ = 0;
84 
85  if (crop_left_ == -1)
86  crop_left_ = 0;
87 
88  if (crop_right_ == -1)
89  crop_right_ = 0;
90 
91  if (display_unit_ == -1)
92  display_unit_ = 0;
93 
94  uint16_t width_after_crop = pixel_width_ - (crop_left_ + crop_right_);
95  uint16_t height_after_crop = pixel_height_ - (crop_top_ + crop_bottom_);
96 
97  if (display_unit_ == 0) {
98  if (display_width_ <= 0)
99  display_width_ = width_after_crop;
100  if (display_height_ <= 0)
101  display_height_ = height_after_crop;
102  } else if (display_unit_ == 3) {
103  if (display_width_ <= 0 || display_height_ <= 0)
104  return std::shared_ptr<VideoStreamInfo>();
105  } else {
106  LOG(ERROR) << "Unsupported display unit type " << display_unit_;
107  return std::shared_ptr<VideoStreamInfo>();
108  }
109  // Calculate sample aspect ratio.
110  int64_t sar_x = display_width_ * height_after_crop;
111  int64_t sar_y = display_height_ * width_after_crop;
112  int64_t gcd = GetGreatestCommonDivisor(sar_x, sar_y);
113  sar_x /= gcd;
114  sar_y /= gcd;
115 
116  return std::make_shared<VideoStreamInfo>(
117  track_num, kWebMTimeScale, 0, video_codec, H26xStreamFormat::kUnSpecified,
118  std::string(), nullptr, 0, width_after_crop, height_after_crop, sar_x,
119  sar_y, 0, 0, std::string(), is_encrypted);
120 }
121 
123  const std::vector<uint8_t>& codec_private) {
124  vp_config_.ParseWebM(codec_private);
125  if (chroma_subsampling_horz_ != -1 && chroma_subsampling_vert_ != -1) {
126  vp_config_.SetChromaSubsampling(chroma_subsampling_horz_,
127  chroma_subsampling_vert_);
128  }
129  if (chroma_siting_horz_ != -1 && chroma_siting_vert_ != -1) {
130  vp_config_.SetChromaLocation(chroma_siting_horz_, chroma_siting_vert_);
131  }
132  return vp_config_;
133 }
134 
135 WebMParserClient* WebMVideoClient::OnListStart(int id) {
136  return id == kWebMIdColor ? this : WebMParserClient::OnListStart(id);
137 }
138 
139 bool WebMVideoClient::OnListEnd(int id) {
140  return id == kWebMIdColor ? true : WebMParserClient::OnListEnd(id);
141 }
142 
143 bool WebMVideoClient::OnUInt(int id, int64_t val) {
144  VPCodecConfigurationRecord vp_config;
145  int64_t* dst = NULL;
146 
147  switch (id) {
148  case kWebMIdPixelWidth:
149  dst = &pixel_width_;
150  break;
151  case kWebMIdPixelHeight:
152  dst = &pixel_height_;
153  break;
154  case kWebMIdPixelCropTop:
155  dst = &crop_top_;
156  break;
157  case kWebMIdPixelCropBottom:
158  dst = &crop_bottom_;
159  break;
160  case kWebMIdPixelCropLeft:
161  dst = &crop_left_;
162  break;
163  case kWebMIdPixelCropRight:
164  dst = &crop_right_;
165  break;
166  case kWebMIdDisplayWidth:
167  dst = &display_width_;
168  break;
169  case kWebMIdDisplayHeight:
170  dst = &display_height_;
171  break;
172  case kWebMIdDisplayUnit:
173  dst = &display_unit_;
174  break;
175  case kWebMIdAlphaMode:
176  dst = &alpha_mode_;
177  break;
178  case kWebMIdColorMatrixCoefficients:
179  vp_config.set_matrix_coefficients(static_cast<uint8_t>(val));
180  break;
181  case kWebMIdColorBitsPerChannel:
182  vp_config.set_bit_depth(static_cast<uint8_t>(val));
183  break;
184  case kWebMIdColorChromaSubsamplingHorz:
185  dst = &chroma_subsampling_horz_;
186  break;
187  case kWebMIdColorChromaSubsamplingVert:
188  dst = &chroma_subsampling_vert_;
189  break;
190  case kWebMIdColorChromaSitingHorz:
191  dst = &chroma_siting_horz_;
192  break;
193  case kWebMIdColorChromaSitingVert:
194  dst = &chroma_siting_vert_;
195  break;
196  case kWebMIdColorRange:
197  if (val == 0)
198  vp_config.set_video_full_range_flag(false);
199  else if (val == 1)
200  vp_config.set_video_full_range_flag(true);
201  // Ignore for other values of val.
202  break;
203  case kWebMIdColorTransferCharacteristics:
204  vp_config.set_transfer_characteristics(static_cast<uint8_t>(val));
205  break;
206  case kWebMIdColorPrimaries:
207  vp_config.set_color_primaries(static_cast<uint8_t>(val));
208  break;
209  case kWebMIdColorMaxCLL:
210  case kWebMIdColorMaxFALL:
211  NOTIMPLEMENTED() << "HDR is not supported yet.";
212  return true;
213  default:
214  return true;
215  }
216 
217  if (*dst != -1) {
218  LOG(ERROR) << "Multiple values for id " << std::hex << id << " specified ("
219  << *dst << " and " << val << ")";
220  return false;
221  }
222 
223  *dst = val;
224  return true;
225 }
226 
227 bool WebMVideoClient::OnBinary(int id, const uint8_t* data, int size) {
228  // Accept binary fields we don't care about for now.
229  return true;
230 }
231 
232 bool WebMVideoClient::OnFloat(int id, double val) {
233  // Accept float fields we don't care about for now.
234  return true;
235 }
236 
237 } // namespace media
238 } // namespace shaka
void Reset()
Reset this object'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)
const VPCodecConfigurationRecord & GetVpCodecConfig(const std::vector< uint8_t > &codec_private)
bool ParseWebM(const std::vector< uint8_t > &data)