[go: nahoru, domu]

blob: 6cb9071a6b54087e6f23229d2c750f618f64c335 [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"
mostynb6682b1c42016-04-19 10:17:3010#include "base/logging.h"
posciakd94b2b082015-09-18 04:03:4011#include "media/base/limits.h"
markdittmer6e70beb82016-05-02 05:40:4712#include "media/gpu/vp9_decoder.h"
posciakd94b2b082015-09-18 04:03:4013
markdittmer6e70beb82016-05-02 05:40:4714namespace media {
posciakd94b2b082015-09-18 04:03:4015
16VP9Decoder::VP9Accelerator::VP9Accelerator() {}
17
18VP9Decoder::VP9Accelerator::~VP9Accelerator() {}
19
Fredrik Hubinette3cebc622018-10-27 01:01:1220VP9Decoder::VP9Decoder(std::unique_ptr<VP9Accelerator> accelerator,
21 const VideoColorSpace& container_color_space)
posciak77118c92016-08-28 13:18:3922 : state_(kNeedStreamMetadata),
Fredrik Hubinette3cebc622018-10-27 01:01:1223 container_color_space_(container_color_space),
Miguel Casas2d5ecad82018-02-22 19:03:0524 accelerator_(std::move(accelerator)),
25 parser_(accelerator_->IsFrameContextRequired()) {
posciakd94b2b082015-09-18 04:03:4026}
27
Miguel Casas2d5ecad82018-02-22 19:03:0528VP9Decoder::~VP9Decoder() = default;
posciakd94b2b082015-09-18 04:03:4029
Miguel Casas22094b82018-05-22 21:16:4830void VP9Decoder::SetStream(int32_t id,
31 const uint8_t* ptr,
32 size_t size,
33 const DecryptConfig* decrypt_config) {
posciakd94b2b082015-09-18 04:03:4034 DCHECK(ptr);
35 DCHECK(size);
Pawel Osciakec6e21b2018-03-19 09:13:0636 DVLOG(4) << "New input stream id: " << id << " at: " << (void*)ptr
37 << " size: " << size;
38 stream_id_ = id;
Ted Meyer0b35c5fd2018-11-27 22:29:2939 if (decrypt_config) {
40 parser_.SetStream(ptr, size, decrypt_config->Clone());
41 } else {
42 parser_.SetStream(ptr, size, nullptr);
43 }
posciakd94b2b082015-09-18 04:03:4044}
45
46bool VP9Decoder::Flush() {
47 DVLOG(2) << "Decoder flush";
48 Reset();
49 return true;
50}
51
52void VP9Decoder::Reset() {
53 curr_frame_hdr_ = nullptr;
Sreerenj Balachandran1beb5482019-04-03 03:40:0554
55 ref_frames_.Clear();
posciakd94b2b082015-09-18 04:03:4056
57 parser_.Reset();
58
59 if (state_ == kDecoding)
60 state_ = kAfterReset;
61}
62
63VP9Decoder::DecodeResult VP9Decoder::Decode() {
64 while (1) {
65 // Read a new frame header if one is not awaiting decoding already.
Ted Meyer0b35c5fd2018-11-27 22:29:2966 std::unique_ptr<DecryptConfig> decrypt_config;
posciakd94b2b082015-09-18 04:03:4067 if (!curr_frame_hdr_) {
xhwang60f96672016-06-14 21:47:5368 std::unique_ptr<Vp9FrameHeader> hdr(new Vp9FrameHeader());
Ted Meyer0b35c5fd2018-11-27 22:29:2969 Vp9Parser::Result res =
70 parser_.ParseNextFrame(hdr.get(), &decrypt_config);
posciakd94b2b082015-09-18 04:03:4071 switch (res) {
xhwang60f96672016-06-14 21:47:5372 case Vp9Parser::kOk:
brusi_roy8e7155962016-09-14 18:22:5873 curr_frame_hdr_ = std::move(hdr);
posciakd94b2b082015-09-18 04:03:4074 break;
75
xhwang60f96672016-06-14 21:47:5376 case Vp9Parser::kEOStream:
posciakd94b2b082015-09-18 04:03:4077 return kRanOutOfStreamData;
78
xhwang60f96672016-06-14 21:47:5379 case Vp9Parser::kInvalidStream:
posciakd94b2b082015-09-18 04:03:4080 DVLOG(1) << "Error parsing stream";
81 SetError();
82 return kDecodeError;
kcwue5a9a6292016-08-17 03:40:0283
84 case Vp9Parser::kAwaitingRefresh:
posciak77118c92016-08-28 13:18:3985 DVLOG(4) << "Awaiting context update";
86 return kNeedContextUpdate;
posciakd94b2b082015-09-18 04:03:4087 }
88 }
89
90 if (state_ != kDecoding) {
91 // Not kDecoding, so we need a resume point (a keyframe), as we are after
92 // reset or at the beginning of the stream. Drop anything that is not
93 // a keyframe in such case, and continue looking for a keyframe.
Sreerenj Balachandran57163302018-11-28 02:45:5794 // Only exception is when the stream/sequence starts with an Intra only
95 // frame.
96 if (curr_frame_hdr_->IsKeyframe() ||
97 (curr_frame_hdr_->IsIntra() && pic_size_.IsEmpty())) {
posciakd94b2b082015-09-18 04:03:4098 state_ = kDecoding;
99 } else {
100 curr_frame_hdr_.reset();
101 continue;
102 }
103 }
104
105 if (curr_frame_hdr_->show_existing_frame) {
106 // This frame header only instructs us to display one of the
107 // previously-decoded frames, but has no frame data otherwise. Display
108 // and continue decoding subsequent frames.
kcwue5a9a6292016-08-17 03:40:02109 size_t frame_to_show = curr_frame_hdr_->frame_to_show_map_idx;
Sreerenj Balachandran1beb5482019-04-03 03:40:05110 if (frame_to_show >= kVp9NumRefFrames ||
111 !ref_frames_.GetFrame(frame_to_show)) {
posciakd94b2b082015-09-18 04:03:40112 DVLOG(1) << "Request to show an invalid frame";
113 SetError();
114 return kDecodeError;
115 }
116
Chih-Yu Huangcd5181e2018-10-23 06:33:06117 // Duplicate the VP9Picture and set the current bitstream id to keep the
118 // correct timestamp.
Sreerenj Balachandran1beb5482019-04-03 03:40:05119 scoped_refptr<VP9Picture> pic =
120 ref_frames_.GetFrame(frame_to_show)->Duplicate();
Chih-Yu Huangcd5181e2018-10-23 06:33:06121 if (pic == nullptr) {
122 DVLOG(1) << "Failed to duplicate the VP9Picture.";
123 SetError();
124 return kDecodeError;
125 }
126 pic->set_bitstream_id(stream_id_);
127 if (!accelerator_->OutputPicture(std::move(pic))) {
posciakd94b2b082015-09-18 04:03:40128 SetError();
129 return kDecodeError;
130 }
131
132 curr_frame_hdr_.reset();
133 continue;
134 }
135
kcwue5a9a6292016-08-17 03:40:02136 gfx::Size new_pic_size(curr_frame_hdr_->frame_width,
137 curr_frame_hdr_->frame_height);
Hirokazu Honda436cf27b2019-05-21 10:44:39138 gfx::Rect new_render_rect(curr_frame_hdr_->render_width,
139 curr_frame_hdr_->render_height);
140 // For safety, check the validity of render size or leave it as (0, 0).
141 if (!gfx::Rect(new_pic_size).Contains(new_render_rect)) {
142 DVLOG(1) << "Render size exceeds picture size. render size: "
143 << new_render_rect.ToString()
144 << ", picture size: " << new_pic_size.ToString();
145 new_render_rect = gfx::Rect();
146 }
posciakd94b2b082015-09-18 04:03:40147
Hirokazu Honda436cf27b2019-05-21 10:44:39148 DCHECK(!new_pic_size.IsEmpty());
posciakd94b2b082015-09-18 04:03:40149 if (new_pic_size != pic_size_) {
150 DVLOG(1) << "New resolution: " << new_pic_size.ToString();
151
Sreerenj Balachandran57163302018-11-28 02:45:57152 if (!curr_frame_hdr_->IsKeyframe() &&
153 (curr_frame_hdr_->IsIntra() && pic_size_.IsEmpty())) {
posciakd94b2b082015-09-18 04:03:40154 // TODO(posciak): This is doable, but requires a few modifications to
155 // VDA implementations to allow multiple picture buffer sets in flight.
Dongseong Hwang4f20ebb2018-06-07 00:28:20156 // http://crbug.com/832264
Sreerenj Balachandran57163302018-11-28 02:45:57157 DVLOG(1) << "Resolution change currently supported for keyframes and "
158 "sequence begins with Intra only when there is no prior "
159 "frames in the context";
Dongseong Hwang4f20ebb2018-06-07 00:28:20160 if (++size_change_failure_counter_ > kVPxMaxNumOfSizeChangeFailures) {
161 SetError();
162 return kDecodeError;
163 }
164
165 curr_frame_hdr_.reset();
166 return kRanOutOfStreamData;
posciakd94b2b082015-09-18 04:03:40167 }
168
169 // TODO(posciak): This requires us to be on a keyframe (see above) and is
170 // required, because VDA clients expect all surfaces to be returned before
171 // they can cycle surface sets after receiving kAllocateNewSurfaces.
172 // This is only an implementation detail of VDAs and can be improved.
Sreerenj Balachandran1beb5482019-04-03 03:40:05173 ref_frames_.Clear();
posciakd94b2b082015-09-18 04:03:40174
175 pic_size_ = new_pic_size;
Hirokazu Honda436cf27b2019-05-21 10:44:39176 visible_rect_ = new_render_rect;
Dongseong Hwang4f20ebb2018-06-07 00:28:20177 size_change_failure_counter_ = 0;
posciakd94b2b082015-09-18 04:03:40178 return kAllocateNewSurfaces;
179 }
180
181 scoped_refptr<VP9Picture> pic = accelerator_->CreateVP9Picture();
182 if (!pic)
183 return kRanOutOfSurfaces;
johnylin74410872017-06-19 13:05:30184 DVLOG(2) << "Render resolution: " << new_render_rect.ToString();
185
Pawel Osciakec6e21b2018-03-19 09:13:06186 pic->set_visible_rect(new_render_rect);
187 pic->set_bitstream_id(stream_id_);
Fredrik Hubinette3cebc622018-10-27 01:01:12188
Ted Meyer0b35c5fd2018-11-27 22:29:29189 pic->set_decrypt_config(std::move(decrypt_config));
190
Fredrik Hubinette3cebc622018-10-27 01:01:12191 // For VP9, container color spaces override video stream color spaces.
192 if (container_color_space_.IsSpecified()) {
193 pic->set_colorspace(container_color_space_);
194 } else if (curr_frame_hdr_) {
195 pic->set_colorspace(curr_frame_hdr_->GetColorSpace());
196 }
kokihoonfb941e92018-07-10 18:04:24197 pic->frame_hdr = std::move(curr_frame_hdr_);
posciakd94b2b082015-09-18 04:03:40198
199 if (!DecodeAndOutputPicture(pic)) {
200 SetError();
201 return kDecodeError;
202 }
203 }
204}
205
posciak77118c92016-08-28 13:18:39206void VP9Decoder::UpdateFrameContext(
Ted Meyer4fac4f62019-05-08 22:57:15207 scoped_refptr<VP9Picture> pic,
posciak77118c92016-08-28 13:18:39208 const base::Callback<void(const Vp9FrameContext&)>& context_refresh_cb) {
Dale Curtise25163812018-09-21 22:13:39209 DCHECK(context_refresh_cb);
posciak77118c92016-08-28 13:18:39210 Vp9FrameContext frame_ctx;
211 memset(&frame_ctx, 0, sizeof(frame_ctx));
212
Ted Meyer4fac4f62019-05-08 22:57:15213 if (!accelerator_->GetFrameContext(std::move(pic), &frame_ctx)) {
posciak77118c92016-08-28 13:18:39214 SetError();
215 return;
216 }
217
218 context_refresh_cb.Run(frame_ctx);
219}
220
posciakd94b2b082015-09-18 04:03:40221bool VP9Decoder::DecodeAndOutputPicture(scoped_refptr<VP9Picture> pic) {
222 DCHECK(!pic_size_.IsEmpty());
223 DCHECK(pic->frame_hdr);
224
posciak77118c92016-08-28 13:18:39225 base::Closure done_cb;
226 const auto& context_refresh_cb =
227 parser_.GetContextRefreshCb(pic->frame_hdr->frame_context_idx);
Dale Curtise25163812018-09-21 22:13:39228 if (context_refresh_cb)
posciak77118c92016-08-28 13:18:39229 done_cb = base::Bind(&VP9Decoder::UpdateFrameContext,
230 base::Unretained(this), pic, context_refresh_cb);
231
232 const Vp9Parser::Context& context = parser_.context();
233 if (!accelerator_->SubmitDecode(pic, context.segmentation(),
234 context.loop_filter(), ref_frames_, done_cb))
posciakd94b2b082015-09-18 04:03:40235 return false;
236
237 if (pic->frame_hdr->show_frame) {
238 if (!accelerator_->OutputPicture(pic))
239 return false;
240 }
241
Ted Meyer4fac4f62019-05-08 22:57:15242 ref_frames_.Refresh(std::move(pic));
posciakd94b2b082015-09-18 04:03:40243 return true;
244}
245
246void VP9Decoder::SetError() {
247 Reset();
248 state_ = kError;
249}
250
251gfx::Size VP9Decoder::GetPicSize() const {
252 return pic_size_;
253}
254
Hirokazu Honda436cf27b2019-05-21 10:44:39255gfx::Rect VP9Decoder::GetVisibleRect() const {
256 return visible_rect_;
257}
258
posciakd94b2b082015-09-18 04:03:40259size_t VP9Decoder::GetRequiredNumOfPictures() const {
Miguel Casas477a7062019-01-04 19:13:45260 constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1;
261 return kPicsInPipeline + GetNumReferenceFrames();
262}
263
264size_t VP9Decoder::GetNumReferenceFrames() const {
Miguel Casas3dd7e562019-02-14 17:38:46265 // Maximum number of reference frames
266 return kVp9NumRefFrames;
posciakd94b2b082015-09-18 04:03:40267}
268
markdittmer6e70beb82016-05-02 05:40:47269} // namespace media