Shaka Packager SDK
Loading...
Searching...
No Matches
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
15namespace {
16
17// Timestamps are represented in double in WebM. Convert to int64_t in us.
18const int32_t kWebMTimeScale = 1000000;
19
20} // namespace
21
22namespace shaka {
23namespace media {
24
25WebMVideoClient::WebMVideoClient() {}
26
27WebMVideoClient::~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
52std::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
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) {
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
165WebMParserClient* WebMVideoClient::OnListStart(int id) {
166 return id == kWebMIdColor || id == kWebMIdProjection
167 ? this
168 : WebMParserClient::OnListStart(id);
169}
170
171bool WebMVideoClient::OnListEnd(int id) {
172 return id == kWebMIdColor || id == kWebMIdProjection
173 ? true
174 : WebMParserClient::OnListEnd(id);
175}
176
177bool 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
259bool 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
266bool 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.