[go: nahoru, domu]

blob: bdaba5787498183ae9f4960b25a51de505d2ddb3 [file] [log] [blame]
posciakd94b2b082015-09-18 04:03:401// Copyright 2015 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
markdittmer6e70beb82016-05-02 05:40:475#include "media/gpu/vp9_decoder.h"
mostynb6682b1c42016-04-19 10:17:306
7#include <memory>
8
posciak77118c92016-08-28 13:18:399#include "base/bind.h"
Hirokazu Honda10df95d2019-07-19 19:31:4310#include "base/feature_list.h"
mostynb6682b1c42016-04-19 10:17:3011#include "base/logging.h"
Hirokazu Honda967b9192019-08-27 00:59:4212#include "build/build_config.h"
Yuta Hijikata29f67812020-10-24 01:15:4413#include "build/chromeos_buildflags.h"
posciakd94b2b082015-09-18 04:03:4014#include "media/base/limits.h"
Hirokazu Honda10df95d2019-07-19 19:31:4315#include "media/base/media_switches.h"
markdittmer6e70beb82016-05-02 05:40:4716#include "media/gpu/vp9_decoder.h"
posciakd94b2b082015-09-18 04:03:4017
markdittmer6e70beb82016-05-02 05:40:4718namespace media {
posciakd94b2b082015-09-18 04:03:4019
Hirokazu Honda10df95d2019-07-19 19:31:4320namespace {
21std::vector<uint32_t> GetSpatialLayerFrameSize(
22 const DecoderBuffer& decoder_buffer) {
Yuta Hijikata29f67812020-10-24 01:15:4423#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_ASH)
Hirokazu Honda10df95d2019-07-19 19:31:4324 const uint32_t* cue_data =
25 reinterpret_cast<const uint32_t*>(decoder_buffer.side_data());
Jose Lopes24d1cda82020-02-21 13:22:3626 if (!cue_data) {
Hirokazu Honda10df95d2019-07-19 19:31:4327 return {};
Jose Lopes24d1cda82020-02-21 13:22:3628 }
Hirokazu Honda10df95d2019-07-19 19:31:4329 if (!base::FeatureList::IsEnabled(media::kVp9kSVCHWDecoding)) {
30 DLOG(ERROR) << "Vp9Parser doesn't support parsing SVC stream";
31 return {};
32 }
33
34 size_t num_of_layers = decoder_buffer.side_data_size() / sizeof(uint32_t);
35 if (num_of_layers > 3u) {
36 DLOG(WARNING) << "The maximum number of spatial layers in VP9 is three";
37 return {};
38 }
39 return std::vector<uint32_t>(cue_data, cue_data + num_of_layers);
Yuta Hijikata29f67812020-10-24 01:15:4440#endif // defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_ASH)
Hirokazu Honda967b9192019-08-27 00:59:4241 return {};
Hirokazu Honda10df95d2019-07-19 19:31:4342}
Hirokazu Honda7ec32652019-11-22 09:40:2143
44VideoCodecProfile VP9ProfileToVideoCodecProfile(uint8_t profile) {
45 switch (profile) {
46 case 0:
47 return VP9PROFILE_PROFILE0;
48 case 1:
49 return VP9PROFILE_PROFILE1;
50 case 2:
51 return VP9PROFILE_PROFILE2;
52 case 3:
53 return VP9PROFILE_PROFILE3;
54 default:
55 return VIDEO_CODEC_PROFILE_UNKNOWN;
56 }
57}
58
Hirokazu Honda963303782020-12-03 05:57:0459bool IsValidBitDepth(uint8_t bit_depth, VideoCodecProfile profile) {
60 // Spec 7.2.
61 switch (profile) {
62 case VP9PROFILE_PROFILE0:
63 case VP9PROFILE_PROFILE1:
64 return bit_depth == 8u;
65 case VP9PROFILE_PROFILE2:
66 case VP9PROFILE_PROFILE3:
67 return bit_depth == 10u || bit_depth == 12u;
68 default:
69 NOTREACHED();
70 return false;
71 }
72}
Hirokazu Honda10df95d2019-07-19 19:31:4373} // namespace
74
posciakd94b2b082015-09-18 04:03:4075VP9Decoder::VP9Accelerator::VP9Accelerator() {}
76
77VP9Decoder::VP9Accelerator::~VP9Accelerator() {}
78
Fredrik Hubinette3cebc622018-10-27 01:01:1279VP9Decoder::VP9Decoder(std::unique_ptr<VP9Accelerator> accelerator,
Hirokazu Honda7ec32652019-11-22 09:40:2180 VideoCodecProfile profile,
Fredrik Hubinette3cebc622018-10-27 01:01:1281 const VideoColorSpace& container_color_space)
posciak77118c92016-08-28 13:18:3982 : state_(kNeedStreamMetadata),
Fredrik Hubinette3cebc622018-10-27 01:01:1283 container_color_space_(container_color_space),
Hirokazu Honda7ec32652019-11-22 09:40:2184 // TODO(hiroh): Set profile to UNKNOWN.
85 profile_(profile),
Miguel Casas2d5ecad82018-02-22 19:03:0586 accelerator_(std::move(accelerator)),
Hirokazu Honda7ec32652019-11-22 09:40:2187 parser_(accelerator_->IsFrameContextRequired()) {}
posciakd94b2b082015-09-18 04:03:4088
Miguel Casas2d5ecad82018-02-22 19:03:0589VP9Decoder::~VP9Decoder() = default;
posciakd94b2b082015-09-18 04:03:4090
Hirokazu Honda23132c32019-07-09 14:31:2091void VP9Decoder::SetStream(int32_t id, const DecoderBuffer& decoder_buffer) {
92 const uint8_t* ptr = decoder_buffer.data();
93 const size_t size = decoder_buffer.data_size();
94 const DecryptConfig* decrypt_config = decoder_buffer.decrypt_config();
95
posciakd94b2b082015-09-18 04:03:4096 DCHECK(ptr);
97 DCHECK(size);
Pawel Osciakec6e21b2018-03-19 09:13:0698 DVLOG(4) << "New input stream id: " << id << " at: " << (void*)ptr
99 << " size: " << size;
100 stream_id_ = id;
Ted Meyer0b35c5fd2018-11-27 22:29:29101 if (decrypt_config) {
Hirokazu Honda10df95d2019-07-19 19:31:43102 parser_.SetStream(ptr, size, GetSpatialLayerFrameSize(decoder_buffer),
103 decrypt_config->Clone());
Ted Meyer0b35c5fd2018-11-27 22:29:29104 } else {
Hirokazu Honda10df95d2019-07-19 19:31:43105 parser_.SetStream(ptr, size, GetSpatialLayerFrameSize(decoder_buffer),
106 nullptr);
Ted Meyer0b35c5fd2018-11-27 22:29:29107 }
posciakd94b2b082015-09-18 04:03:40108}
109
110bool VP9Decoder::Flush() {
111 DVLOG(2) << "Decoder flush";
112 Reset();
113 return true;
114}
115
116void VP9Decoder::Reset() {
117 curr_frame_hdr_ = nullptr;
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13118 pending_pic_.reset();
Sreerenj Balachandran1beb5482019-04-03 03:40:05119
120 ref_frames_.Clear();
posciakd94b2b082015-09-18 04:03:40121
122 parser_.Reset();
123
Jose Lopes24d1cda82020-02-21 13:22:36124 if (state_ == kDecoding) {
posciakd94b2b082015-09-18 04:03:40125 state_ = kAfterReset;
Jose Lopes24d1cda82020-02-21 13:22:36126 }
posciakd94b2b082015-09-18 04:03:40127}
128
129VP9Decoder::DecodeResult VP9Decoder::Decode() {
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13130 while (true) {
131 // If we have a pending picture to decode, try that first.
132 if (pending_pic_) {
133 VP9Accelerator::Status status = DecodeAndOutputPicture(pending_pic_);
134 if (status == VP9Accelerator::Status::kFail) {
135 pending_pic_.reset();
136 SetError();
137 return kDecodeError;
138 }
139 if (status == VP9Accelerator::Status::kTryAgain)
140 return kTryAgain;
141
142 pending_pic_.reset();
143 }
144
posciakd94b2b082015-09-18 04:03:40145 // Read a new frame header if one is not awaiting decoding already.
Ted Meyer0b35c5fd2018-11-27 22:29:29146 std::unique_ptr<DecryptConfig> decrypt_config;
posciakd94b2b082015-09-18 04:03:40147 if (!curr_frame_hdr_) {
Hirokazu Honda10df95d2019-07-19 19:31:43148 gfx::Size allocate_size;
xhwang60f96672016-06-14 21:47:53149 std::unique_ptr<Vp9FrameHeader> hdr(new Vp9FrameHeader());
Ted Meyer0b35c5fd2018-11-27 22:29:29150 Vp9Parser::Result res =
Hirokazu Honda10df95d2019-07-19 19:31:43151 parser_.ParseNextFrame(hdr.get(), &allocate_size, &decrypt_config);
posciakd94b2b082015-09-18 04:03:40152 switch (res) {
xhwang60f96672016-06-14 21:47:53153 case Vp9Parser::kOk:
brusi_roy8e7155962016-09-14 18:22:58154 curr_frame_hdr_ = std::move(hdr);
Hirokazu Honda10df95d2019-07-19 19:31:43155 curr_frame_size_ = allocate_size;
posciakd94b2b082015-09-18 04:03:40156 break;
157
xhwang60f96672016-06-14 21:47:53158 case Vp9Parser::kEOStream:
posciakd94b2b082015-09-18 04:03:40159 return kRanOutOfStreamData;
160
xhwang60f96672016-06-14 21:47:53161 case Vp9Parser::kInvalidStream:
posciakd94b2b082015-09-18 04:03:40162 DVLOG(1) << "Error parsing stream";
163 SetError();
164 return kDecodeError;
kcwue5a9a6292016-08-17 03:40:02165
166 case Vp9Parser::kAwaitingRefresh:
posciak77118c92016-08-28 13:18:39167 DVLOG(4) << "Awaiting context update";
168 return kNeedContextUpdate;
posciakd94b2b082015-09-18 04:03:40169 }
170 }
171
172 if (state_ != kDecoding) {
173 // Not kDecoding, so we need a resume point (a keyframe), as we are after
174 // reset or at the beginning of the stream. Drop anything that is not
175 // a keyframe in such case, and continue looking for a keyframe.
Sreerenj Balachandran57163302018-11-28 02:45:57176 // Only exception is when the stream/sequence starts with an Intra only
177 // frame.
178 if (curr_frame_hdr_->IsKeyframe() ||
179 (curr_frame_hdr_->IsIntra() && pic_size_.IsEmpty())) {
posciakd94b2b082015-09-18 04:03:40180 state_ = kDecoding;
181 } else {
182 curr_frame_hdr_.reset();
183 continue;
184 }
185 }
186
187 if (curr_frame_hdr_->show_existing_frame) {
188 // This frame header only instructs us to display one of the
189 // previously-decoded frames, but has no frame data otherwise. Display
190 // and continue decoding subsequent frames.
kcwue5a9a6292016-08-17 03:40:02191 size_t frame_to_show = curr_frame_hdr_->frame_to_show_map_idx;
Sreerenj Balachandran1beb5482019-04-03 03:40:05192 if (frame_to_show >= kVp9NumRefFrames ||
193 !ref_frames_.GetFrame(frame_to_show)) {
posciakd94b2b082015-09-18 04:03:40194 DVLOG(1) << "Request to show an invalid frame";
195 SetError();
196 return kDecodeError;
197 }
198
Chih-Yu Huangcd5181e2018-10-23 06:33:06199 // Duplicate the VP9Picture and set the current bitstream id to keep the
200 // correct timestamp.
Sreerenj Balachandran1beb5482019-04-03 03:40:05201 scoped_refptr<VP9Picture> pic =
202 ref_frames_.GetFrame(frame_to_show)->Duplicate();
Chih-Yu Huangcd5181e2018-10-23 06:33:06203 if (pic == nullptr) {
204 DVLOG(1) << "Failed to duplicate the VP9Picture.";
205 SetError();
206 return kDecodeError;
207 }
208 pic->set_bitstream_id(stream_id_);
209 if (!accelerator_->OutputPicture(std::move(pic))) {
posciakd94b2b082015-09-18 04:03:40210 SetError();
211 return kDecodeError;
212 }
213
214 curr_frame_hdr_.reset();
215 continue;
216 }
217
Hirokazu Honda10df95d2019-07-19 19:31:43218 gfx::Size new_pic_size = curr_frame_size_;
Hirokazu Honda436cf27b2019-05-21 10:44:39219 gfx::Rect new_render_rect(curr_frame_hdr_->render_width,
220 curr_frame_hdr_->render_height);
Hirokazu Hondacffd0ef2020-02-28 03:32:31221 // For safety, check the validity of render size or leave it as pic size.
Hirokazu Honda436cf27b2019-05-21 10:44:39222 if (!gfx::Rect(new_pic_size).Contains(new_render_rect)) {
223 DVLOG(1) << "Render size exceeds picture size. render size: "
224 << new_render_rect.ToString()
225 << ", picture size: " << new_pic_size.ToString();
Hirokazu Hondacffd0ef2020-02-28 03:32:31226 new_render_rect = gfx::Rect(new_pic_size);
Hirokazu Honda436cf27b2019-05-21 10:44:39227 }
Hirokazu Honda7ec32652019-11-22 09:40:21228 VideoCodecProfile new_profile =
229 VP9ProfileToVideoCodecProfile(curr_frame_hdr_->profile);
230 if (new_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
231 VLOG(1) << "Invalid profile: " << curr_frame_hdr_->profile;
232 return kDecodeError;
233 }
Hirokazu Honda963303782020-12-03 05:57:04234 if (!IsValidBitDepth(curr_frame_hdr_->bit_depth, new_profile)) {
235 DVLOG(1) << "Invalid bit depth="
236 << base::strict_cast<int>(curr_frame_hdr_->bit_depth)
237 << ", profile=" << GetProfileName(new_profile);
238 return kDecodeError;
239 }
posciakd94b2b082015-09-18 04:03:40240
Hirokazu Honda436cf27b2019-05-21 10:44:39241 DCHECK(!new_pic_size.IsEmpty());
Hirokazu Honda963303782020-12-03 05:57:04242 if (new_pic_size != pic_size_ || new_profile != profile_ ||
243 curr_frame_hdr_->bit_depth != bit_depth_) {
Hirokazu Honda7ec32652019-11-22 09:40:21244 DVLOG(1) << "New profile: " << GetProfileName(new_profile)
Hirokazu Honda963303782020-12-03 05:57:04245 << ", New resolution: " << new_pic_size.ToString()
246 << ", New bit depth: "
247 << base::strict_cast<int>(curr_frame_hdr_->bit_depth);
posciakd94b2b082015-09-18 04:03:40248
Sreerenj Balachandran57163302018-11-28 02:45:57249 if (!curr_frame_hdr_->IsKeyframe() &&
Hirokazu Honda7ec32652019-11-22 09:40:21250 !(curr_frame_hdr_->IsIntra() && pic_size_.IsEmpty())) {
posciakd94b2b082015-09-18 04:03:40251 // TODO(posciak): This is doable, but requires a few modifications to
252 // VDA implementations to allow multiple picture buffer sets in flight.
Dongseong Hwang4f20ebb2018-06-07 00:28:20253 // http://crbug.com/832264
Sreerenj Balachandran57163302018-11-28 02:45:57254 DVLOG(1) << "Resolution change currently supported for keyframes and "
255 "sequence begins with Intra only when there is no prior "
256 "frames in the context";
Dongseong Hwang4f20ebb2018-06-07 00:28:20257 if (++size_change_failure_counter_ > kVPxMaxNumOfSizeChangeFailures) {
258 SetError();
259 return kDecodeError;
260 }
261
262 curr_frame_hdr_.reset();
263 return kRanOutOfStreamData;
posciakd94b2b082015-09-18 04:03:40264 }
265
266 // TODO(posciak): This requires us to be on a keyframe (see above) and is
267 // required, because VDA clients expect all surfaces to be returned before
Hirokazu Honda7ec32652019-11-22 09:40:21268 // they can cycle surface sets after receiving kConfigChange.
posciakd94b2b082015-09-18 04:03:40269 // This is only an implementation detail of VDAs and can be improved.
Sreerenj Balachandran1beb5482019-04-03 03:40:05270 ref_frames_.Clear();
posciakd94b2b082015-09-18 04:03:40271
272 pic_size_ = new_pic_size;
Hirokazu Honda436cf27b2019-05-21 10:44:39273 visible_rect_ = new_render_rect;
Hirokazu Honda7ec32652019-11-22 09:40:21274 profile_ = new_profile;
Hirokazu Honda963303782020-12-03 05:57:04275 bit_depth_ = curr_frame_hdr_->bit_depth;
Dongseong Hwang4f20ebb2018-06-07 00:28:20276 size_change_failure_counter_ = 0;
Hirokazu Honda7ec32652019-11-22 09:40:21277 return kConfigChange;
posciakd94b2b082015-09-18 04:03:40278 }
279
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13280 pending_pic_ = accelerator_->CreateVP9Picture();
281 if (!pending_pic_) {
posciakd94b2b082015-09-18 04:03:40282 return kRanOutOfSurfaces;
Jose Lopes24d1cda82020-02-21 13:22:36283 }
johnylin74410872017-06-19 13:05:30284 DVLOG(2) << "Render resolution: " << new_render_rect.ToString();
285
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13286 pending_pic_->set_visible_rect(new_render_rect);
287 pending_pic_->set_bitstream_id(stream_id_);
Fredrik Hubinette3cebc622018-10-27 01:01:12288
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13289 pending_pic_->set_decrypt_config(std::move(decrypt_config));
Ted Meyer0b35c5fd2018-11-27 22:29:29290
Fredrik Hubinette3cebc622018-10-27 01:01:12291 // For VP9, container color spaces override video stream color spaces.
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13292 if (container_color_space_.IsSpecified())
293 pending_pic_->set_colorspace(container_color_space_);
294 else if (curr_frame_hdr_)
295 pending_pic_->set_colorspace(curr_frame_hdr_->GetColorSpace());
posciakd94b2b082015-09-18 04:03:40296
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13297 pending_pic_->frame_hdr = std::move(curr_frame_hdr_);
298
299 VP9Accelerator::Status status = DecodeAndOutputPicture(pending_pic_);
300 if (status == VP9Accelerator::Status::kFail) {
301 pending_pic_.reset();
posciakd94b2b082015-09-18 04:03:40302 SetError();
303 return kDecodeError;
304 }
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13305 if (status == VP9Accelerator::Status::kTryAgain)
306 return kTryAgain;
307
308 pending_pic_.reset();
posciakd94b2b082015-09-18 04:03:40309 }
310}
311
posciak77118c92016-08-28 13:18:39312void VP9Decoder::UpdateFrameContext(
Ted Meyer4fac4f62019-05-08 22:57:15313 scoped_refptr<VP9Picture> pic,
Jose Lopes24d1cda82020-02-21 13:22:36314 Vp9Parser::ContextRefreshCallback context_refresh_cb) {
Dale Curtise25163812018-09-21 22:13:39315 DCHECK(context_refresh_cb);
posciak77118c92016-08-28 13:18:39316 Vp9FrameContext frame_ctx;
317 memset(&frame_ctx, 0, sizeof(frame_ctx));
318
Ted Meyer4fac4f62019-05-08 22:57:15319 if (!accelerator_->GetFrameContext(std::move(pic), &frame_ctx)) {
posciak77118c92016-08-28 13:18:39320 SetError();
321 return;
322 }
323
Jose Lopes24d1cda82020-02-21 13:22:36324 std::move(context_refresh_cb).Run(frame_ctx);
posciak77118c92016-08-28 13:18:39325}
326
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13327VP9Decoder::VP9Accelerator::Status VP9Decoder::DecodeAndOutputPicture(
328 scoped_refptr<VP9Picture> pic) {
posciakd94b2b082015-09-18 04:03:40329 DCHECK(!pic_size_.IsEmpty());
330 DCHECK(pic->frame_hdr);
331
Chih-Yu Huangcc6b1b92019-12-19 08:57:16332 base::OnceClosure done_cb;
Jose Lopes24d1cda82020-02-21 13:22:36333 Vp9Parser::ContextRefreshCallback context_refresh_cb =
posciak77118c92016-08-28 13:18:39334 parser_.GetContextRefreshCb(pic->frame_hdr->frame_context_idx);
Jose Lopes24d1cda82020-02-21 13:22:36335 if (context_refresh_cb) {
336 done_cb =
337 base::BindOnce(&VP9Decoder::UpdateFrameContext, base::Unretained(this),
338 pic, std::move(context_refresh_cb));
339 }
posciak77118c92016-08-28 13:18:39340
341 const Vp9Parser::Context& context = parser_.context();
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13342 VP9Accelerator::Status status = accelerator_->SubmitDecode(
343 pic, context.segmentation(), context.loop_filter(), ref_frames_,
344 std::move(done_cb));
345 if (status != VP9Accelerator::Status::kOk)
346 return status;
posciakd94b2b082015-09-18 04:03:40347
348 if (pic->frame_hdr->show_frame) {
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13349 if (!accelerator_->OutputPicture(pic))
350 return VP9Accelerator::Status::kFail;
posciakd94b2b082015-09-18 04:03:40351 }
352
Ted Meyer4fac4f62019-05-08 22:57:15353 ref_frames_.Refresh(std::move(pic));
Jeffrey Kardatzke5e36baf2020-11-20 22:17:13354 return status;
posciakd94b2b082015-09-18 04:03:40355}
356
357void VP9Decoder::SetError() {
358 Reset();
359 state_ = kError;
360}
361
362gfx::Size VP9Decoder::GetPicSize() const {
363 return pic_size_;
364}
365
Hirokazu Honda436cf27b2019-05-21 10:44:39366gfx::Rect VP9Decoder::GetVisibleRect() const {
367 return visible_rect_;
368}
369
Hirokazu Honda7ec32652019-11-22 09:40:21370VideoCodecProfile VP9Decoder::GetProfile() const {
371 return profile_;
372}
373
Hirokazu Honda963303782020-12-03 05:57:04374uint8_t VP9Decoder::GetBitDepth() const {
375 return bit_depth_;
376}
377
posciakd94b2b082015-09-18 04:03:40378size_t VP9Decoder::GetRequiredNumOfPictures() const {
Miguel Casas477a7062019-01-04 19:13:45379 constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1;
380 return kPicsInPipeline + GetNumReferenceFrames();
381}
382
383size_t VP9Decoder::GetNumReferenceFrames() const {
Miguel Casas3dd7e562019-02-14 17:38:46384 // Maximum number of reference frames
385 return kVp9NumRefFrames;
posciakd94b2b082015-09-18 04:03:40386}
387
markdittmer6e70beb82016-05-02 05:40:47388} // namespace media