[go: nahoru, domu]

blob: 68188ea4df0d3a3a5424595030b4930993d90151 [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"
posciakd94b2b082015-09-18 04:03:4012#include "media/base/limits.h"
Hirokazu Honda10df95d2019-07-19 19:31:4313#include "media/base/media_switches.h"
markdittmer6e70beb82016-05-02 05:40:4714#include "media/gpu/vp9_decoder.h"
posciakd94b2b082015-09-18 04:03:4015
markdittmer6e70beb82016-05-02 05:40:4716namespace media {
posciakd94b2b082015-09-18 04:03:4017
Hirokazu Honda10df95d2019-07-19 19:31:4318namespace {
19std::vector<uint32_t> GetSpatialLayerFrameSize(
20 const DecoderBuffer& decoder_buffer) {
21 const uint32_t* cue_data =
22 reinterpret_cast<const uint32_t*>(decoder_buffer.side_data());
23 if (!cue_data)
24 return {};
25 if (!base::FeatureList::IsEnabled(media::kVp9kSVCHWDecoding)) {
26 DLOG(ERROR) << "Vp9Parser doesn't support parsing SVC stream";
27 return {};
28 }
29
30 size_t num_of_layers = decoder_buffer.side_data_size() / sizeof(uint32_t);
31 if (num_of_layers > 3u) {
32 DLOG(WARNING) << "The maximum number of spatial layers in VP9 is three";
33 return {};
34 }
35 return std::vector<uint32_t>(cue_data, cue_data + num_of_layers);
36}
37} // namespace
38
posciakd94b2b082015-09-18 04:03:4039VP9Decoder::VP9Accelerator::VP9Accelerator() {}
40
41VP9Decoder::VP9Accelerator::~VP9Accelerator() {}
42
Fredrik Hubinette3cebc622018-10-27 01:01:1243VP9Decoder::VP9Decoder(std::unique_ptr<VP9Accelerator> accelerator,
44 const VideoColorSpace& container_color_space)
posciak77118c92016-08-28 13:18:3945 : state_(kNeedStreamMetadata),
Fredrik Hubinette3cebc622018-10-27 01:01:1246 container_color_space_(container_color_space),
Miguel Casas2d5ecad82018-02-22 19:03:0547 accelerator_(std::move(accelerator)),
48 parser_(accelerator_->IsFrameContextRequired()) {
posciakd94b2b082015-09-18 04:03:4049}
50
Miguel Casas2d5ecad82018-02-22 19:03:0551VP9Decoder::~VP9Decoder() = default;
posciakd94b2b082015-09-18 04:03:4052
Hirokazu Honda23132c32019-07-09 14:31:2053void VP9Decoder::SetStream(int32_t id, const DecoderBuffer& decoder_buffer) {
54 const uint8_t* ptr = decoder_buffer.data();
55 const size_t size = decoder_buffer.data_size();
56 const DecryptConfig* decrypt_config = decoder_buffer.decrypt_config();
57
posciakd94b2b082015-09-18 04:03:4058 DCHECK(ptr);
59 DCHECK(size);
Pawel Osciakec6e21b2018-03-19 09:13:0660 DVLOG(4) << "New input stream id: " << id << " at: " << (void*)ptr
61 << " size: " << size;
62 stream_id_ = id;
Ted Meyer0b35c5fd2018-11-27 22:29:2963 if (decrypt_config) {
Hirokazu Honda10df95d2019-07-19 19:31:4364 parser_.SetStream(ptr, size, GetSpatialLayerFrameSize(decoder_buffer),
65 decrypt_config->Clone());
Ted Meyer0b35c5fd2018-11-27 22:29:2966 } else {
Hirokazu Honda10df95d2019-07-19 19:31:4367 parser_.SetStream(ptr, size, GetSpatialLayerFrameSize(decoder_buffer),
68 nullptr);
Ted Meyer0b35c5fd2018-11-27 22:29:2969 }
posciakd94b2b082015-09-18 04:03:4070}
71
72bool VP9Decoder::Flush() {
73 DVLOG(2) << "Decoder flush";
74 Reset();
75 return true;
76}
77
78void VP9Decoder::Reset() {
79 curr_frame_hdr_ = nullptr;
Sreerenj Balachandran1beb5482019-04-03 03:40:0580
81 ref_frames_.Clear();
posciakd94b2b082015-09-18 04:03:4082
83 parser_.Reset();
84
85 if (state_ == kDecoding)
86 state_ = kAfterReset;
87}
88
89VP9Decoder::DecodeResult VP9Decoder::Decode() {
90 while (1) {
91 // Read a new frame header if one is not awaiting decoding already.
Ted Meyer0b35c5fd2018-11-27 22:29:2992 std::unique_ptr<DecryptConfig> decrypt_config;
posciakd94b2b082015-09-18 04:03:4093 if (!curr_frame_hdr_) {
Hirokazu Honda10df95d2019-07-19 19:31:4394 gfx::Size allocate_size;
xhwang60f96672016-06-14 21:47:5395 std::unique_ptr<Vp9FrameHeader> hdr(new Vp9FrameHeader());
Ted Meyer0b35c5fd2018-11-27 22:29:2996 Vp9Parser::Result res =
Hirokazu Honda10df95d2019-07-19 19:31:4397 parser_.ParseNextFrame(hdr.get(), &allocate_size, &decrypt_config);
posciakd94b2b082015-09-18 04:03:4098 switch (res) {
xhwang60f96672016-06-14 21:47:5399 case Vp9Parser::kOk:
brusi_roy8e7155962016-09-14 18:22:58100 curr_frame_hdr_ = std::move(hdr);
Hirokazu Honda10df95d2019-07-19 19:31:43101 curr_frame_size_ = allocate_size;
posciakd94b2b082015-09-18 04:03:40102 break;
103
xhwang60f96672016-06-14 21:47:53104 case Vp9Parser::kEOStream:
posciakd94b2b082015-09-18 04:03:40105 return kRanOutOfStreamData;
106
xhwang60f96672016-06-14 21:47:53107 case Vp9Parser::kInvalidStream:
posciakd94b2b082015-09-18 04:03:40108 DVLOG(1) << "Error parsing stream";
109 SetError();
110 return kDecodeError;
kcwue5a9a6292016-08-17 03:40:02111
112 case Vp9Parser::kAwaitingRefresh:
posciak77118c92016-08-28 13:18:39113 DVLOG(4) << "Awaiting context update";
114 return kNeedContextUpdate;
posciakd94b2b082015-09-18 04:03:40115 }
116 }
117
118 if (state_ != kDecoding) {
119 // Not kDecoding, so we need a resume point (a keyframe), as we are after
120 // reset or at the beginning of the stream. Drop anything that is not
121 // a keyframe in such case, and continue looking for a keyframe.
Sreerenj Balachandran57163302018-11-28 02:45:57122 // Only exception is when the stream/sequence starts with an Intra only
123 // frame.
124 if (curr_frame_hdr_->IsKeyframe() ||
125 (curr_frame_hdr_->IsIntra() && pic_size_.IsEmpty())) {
posciakd94b2b082015-09-18 04:03:40126 state_ = kDecoding;
127 } else {
128 curr_frame_hdr_.reset();
129 continue;
130 }
131 }
132
133 if (curr_frame_hdr_->show_existing_frame) {
134 // This frame header only instructs us to display one of the
135 // previously-decoded frames, but has no frame data otherwise. Display
136 // and continue decoding subsequent frames.
kcwue5a9a6292016-08-17 03:40:02137 size_t frame_to_show = curr_frame_hdr_->frame_to_show_map_idx;
Sreerenj Balachandran1beb5482019-04-03 03:40:05138 if (frame_to_show >= kVp9NumRefFrames ||
139 !ref_frames_.GetFrame(frame_to_show)) {
posciakd94b2b082015-09-18 04:03:40140 DVLOG(1) << "Request to show an invalid frame";
141 SetError();
142 return kDecodeError;
143 }
144
Chih-Yu Huangcd5181e2018-10-23 06:33:06145 // Duplicate the VP9Picture and set the current bitstream id to keep the
146 // correct timestamp.
Sreerenj Balachandran1beb5482019-04-03 03:40:05147 scoped_refptr<VP9Picture> pic =
148 ref_frames_.GetFrame(frame_to_show)->Duplicate();
Chih-Yu Huangcd5181e2018-10-23 06:33:06149 if (pic == nullptr) {
150 DVLOG(1) << "Failed to duplicate the VP9Picture.";
151 SetError();
152 return kDecodeError;
153 }
154 pic->set_bitstream_id(stream_id_);
155 if (!accelerator_->OutputPicture(std::move(pic))) {
posciakd94b2b082015-09-18 04:03:40156 SetError();
157 return kDecodeError;
158 }
159
160 curr_frame_hdr_.reset();
161 continue;
162 }
163
Hirokazu Honda10df95d2019-07-19 19:31:43164 gfx::Size new_pic_size = curr_frame_size_;
Hirokazu Honda436cf27b2019-05-21 10:44:39165 gfx::Rect new_render_rect(curr_frame_hdr_->render_width,
166 curr_frame_hdr_->render_height);
167 // For safety, check the validity of render size or leave it as (0, 0).
168 if (!gfx::Rect(new_pic_size).Contains(new_render_rect)) {
169 DVLOG(1) << "Render size exceeds picture size. render size: "
170 << new_render_rect.ToString()
171 << ", picture size: " << new_pic_size.ToString();
172 new_render_rect = gfx::Rect();
173 }
posciakd94b2b082015-09-18 04:03:40174
Hirokazu Honda436cf27b2019-05-21 10:44:39175 DCHECK(!new_pic_size.IsEmpty());
posciakd94b2b082015-09-18 04:03:40176 if (new_pic_size != pic_size_) {
177 DVLOG(1) << "New resolution: " << new_pic_size.ToString();
178
Sreerenj Balachandran57163302018-11-28 02:45:57179 if (!curr_frame_hdr_->IsKeyframe() &&
180 (curr_frame_hdr_->IsIntra() && pic_size_.IsEmpty())) {
posciakd94b2b082015-09-18 04:03:40181 // TODO(posciak): This is doable, but requires a few modifications to
182 // VDA implementations to allow multiple picture buffer sets in flight.
Dongseong Hwang4f20ebb2018-06-07 00:28:20183 // http://crbug.com/832264
Sreerenj Balachandran57163302018-11-28 02:45:57184 DVLOG(1) << "Resolution change currently supported for keyframes and "
185 "sequence begins with Intra only when there is no prior "
186 "frames in the context";
Dongseong Hwang4f20ebb2018-06-07 00:28:20187 if (++size_change_failure_counter_ > kVPxMaxNumOfSizeChangeFailures) {
188 SetError();
189 return kDecodeError;
190 }
191
192 curr_frame_hdr_.reset();
193 return kRanOutOfStreamData;
posciakd94b2b082015-09-18 04:03:40194 }
195
196 // TODO(posciak): This requires us to be on a keyframe (see above) and is
197 // required, because VDA clients expect all surfaces to be returned before
198 // they can cycle surface sets after receiving kAllocateNewSurfaces.
199 // This is only an implementation detail of VDAs and can be improved.
Sreerenj Balachandran1beb5482019-04-03 03:40:05200 ref_frames_.Clear();
posciakd94b2b082015-09-18 04:03:40201
202 pic_size_ = new_pic_size;
Hirokazu Honda436cf27b2019-05-21 10:44:39203 visible_rect_ = new_render_rect;
Dongseong Hwang4f20ebb2018-06-07 00:28:20204 size_change_failure_counter_ = 0;
posciakd94b2b082015-09-18 04:03:40205 return kAllocateNewSurfaces;
206 }
207
208 scoped_refptr<VP9Picture> pic = accelerator_->CreateVP9Picture();
209 if (!pic)
210 return kRanOutOfSurfaces;
johnylin74410872017-06-19 13:05:30211 DVLOG(2) << "Render resolution: " << new_render_rect.ToString();
212
Pawel Osciakec6e21b2018-03-19 09:13:06213 pic->set_visible_rect(new_render_rect);
214 pic->set_bitstream_id(stream_id_);
Fredrik Hubinette3cebc622018-10-27 01:01:12215
Ted Meyer0b35c5fd2018-11-27 22:29:29216 pic->set_decrypt_config(std::move(decrypt_config));
217
Fredrik Hubinette3cebc622018-10-27 01:01:12218 // For VP9, container color spaces override video stream color spaces.
219 if (container_color_space_.IsSpecified()) {
220 pic->set_colorspace(container_color_space_);
221 } else if (curr_frame_hdr_) {
222 pic->set_colorspace(curr_frame_hdr_->GetColorSpace());
223 }
kokihoonfb941e92018-07-10 18:04:24224 pic->frame_hdr = std::move(curr_frame_hdr_);
posciakd94b2b082015-09-18 04:03:40225
226 if (!DecodeAndOutputPicture(pic)) {
227 SetError();
228 return kDecodeError;
229 }
230 }
231}
232
posciak77118c92016-08-28 13:18:39233void VP9Decoder::UpdateFrameContext(
Ted Meyer4fac4f62019-05-08 22:57:15234 scoped_refptr<VP9Picture> pic,
posciak77118c92016-08-28 13:18:39235 const base::Callback<void(const Vp9FrameContext&)>& context_refresh_cb) {
Dale Curtise25163812018-09-21 22:13:39236 DCHECK(context_refresh_cb);
posciak77118c92016-08-28 13:18:39237 Vp9FrameContext frame_ctx;
238 memset(&frame_ctx, 0, sizeof(frame_ctx));
239
Ted Meyer4fac4f62019-05-08 22:57:15240 if (!accelerator_->GetFrameContext(std::move(pic), &frame_ctx)) {
posciak77118c92016-08-28 13:18:39241 SetError();
242 return;
243 }
244
245 context_refresh_cb.Run(frame_ctx);
246}
247
posciakd94b2b082015-09-18 04:03:40248bool VP9Decoder::DecodeAndOutputPicture(scoped_refptr<VP9Picture> pic) {
249 DCHECK(!pic_size_.IsEmpty());
250 DCHECK(pic->frame_hdr);
251
posciak77118c92016-08-28 13:18:39252 base::Closure done_cb;
253 const auto& context_refresh_cb =
254 parser_.GetContextRefreshCb(pic->frame_hdr->frame_context_idx);
Dale Curtise25163812018-09-21 22:13:39255 if (context_refresh_cb)
posciak77118c92016-08-28 13:18:39256 done_cb = base::Bind(&VP9Decoder::UpdateFrameContext,
257 base::Unretained(this), pic, context_refresh_cb);
258
259 const Vp9Parser::Context& context = parser_.context();
260 if (!accelerator_->SubmitDecode(pic, context.segmentation(),
261 context.loop_filter(), ref_frames_, done_cb))
posciakd94b2b082015-09-18 04:03:40262 return false;
263
264 if (pic->frame_hdr->show_frame) {
265 if (!accelerator_->OutputPicture(pic))
266 return false;
267 }
268
Ted Meyer4fac4f62019-05-08 22:57:15269 ref_frames_.Refresh(std::move(pic));
posciakd94b2b082015-09-18 04:03:40270 return true;
271}
272
273void VP9Decoder::SetError() {
274 Reset();
275 state_ = kError;
276}
277
278gfx::Size VP9Decoder::GetPicSize() const {
279 return pic_size_;
280}
281
Hirokazu Honda436cf27b2019-05-21 10:44:39282gfx::Rect VP9Decoder::GetVisibleRect() const {
283 return visible_rect_;
284}
285
posciakd94b2b082015-09-18 04:03:40286size_t VP9Decoder::GetRequiredNumOfPictures() const {
Miguel Casas477a7062019-01-04 19:13:45287 constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1;
288 return kPicsInPipeline + GetNumReferenceFrames();
289}
290
291size_t VP9Decoder::GetNumReferenceFrames() const {
Miguel Casas3dd7e562019-02-14 17:38:46292 // Maximum number of reference frames
293 return kVp9NumRefFrames;
posciakd94b2b082015-09-18 04:03:40294}
295
markdittmer6e70beb82016-05-02 05:40:47296} // namespace media