1 // 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.
5 #include "content/common/gpu/media/vp8_decoder.h"
6 #include "media/base/limits.h"
10 VP8Decoder::VP8Accelerator::VP8Accelerator() {
13 VP8Decoder::VP8Accelerator::~VP8Accelerator() {
16 VP8Decoder::VP8Decoder(VP8Accelerator
* accelerator
)
17 : state_(kNeedStreamMetadata
),
18 curr_frame_start_(nullptr),
20 accelerator_(accelerator
) {
24 VP8Decoder::~VP8Decoder() {
27 bool VP8Decoder::Flush() {
28 DVLOG(2) << "Decoder flush";
33 void VP8Decoder::SetStream(const uint8_t* ptr
, size_t size
) {
37 curr_frame_start_
= ptr
;
39 DVLOG(4) << "New input stream at: " << (void*)ptr
<< " size: " << size
;
42 void VP8Decoder::Reset() {
44 curr_frame_hdr_
= nullptr;
45 curr_frame_start_
= nullptr;
48 last_frame_
= nullptr;
49 golden_frame_
= nullptr;
52 if (state_
== kDecoding
)
56 VP8Decoder::DecodeResult
VP8Decoder::Decode() {
57 if (!curr_frame_start_
|| frame_size_
== 0)
58 return kRanOutOfStreamData
;
60 if (!curr_frame_hdr_
) {
61 curr_frame_hdr_
.reset(new media::Vp8FrameHeader());
62 if (!parser_
.ParseFrame(curr_frame_start_
, frame_size_
,
63 curr_frame_hdr_
.get())) {
64 DVLOG(1) << "Error during decode";
70 if (curr_frame_hdr_
->IsKeyframe()) {
71 gfx::Size
new_pic_size(curr_frame_hdr_
->width
, curr_frame_hdr_
->height
);
72 if (new_pic_size
.IsEmpty())
75 if (new_pic_size
!= pic_size_
) {
76 DVLOG(2) << "New resolution: " << new_pic_size
.ToString();
77 pic_size_
= new_pic_size
;
80 last_frame_
= nullptr;
81 golden_frame_
= nullptr;
84 return kAllocateNewSurfaces
;
89 if (state_
!= kDecoding
) {
90 // Need a resume point.
91 curr_frame_hdr_
.reset();
92 return kRanOutOfStreamData
;
96 curr_pic_
= accelerator_
->CreateVP8Picture();
98 return kRanOutOfSurfaces
;
100 if (!DecodeAndOutputCurrentFrame())
103 return kRanOutOfStreamData
;
106 void VP8Decoder::RefreshReferenceFrames() {
107 if (curr_frame_hdr_
->IsKeyframe()) {
108 last_frame_
= curr_pic_
;
109 golden_frame_
= curr_pic_
;
110 alt_frame_
= curr_pic_
;
114 // Save current golden since we overwrite it here,
115 // but may have to use it to update alt below.
116 scoped_refptr
<VP8Picture
> curr_golden
= golden_frame_
;
118 if (curr_frame_hdr_
->refresh_golden_frame
) {
119 golden_frame_
= curr_pic_
;
121 switch (curr_frame_hdr_
->copy_buffer_to_golden
) {
122 case media::Vp8FrameHeader::COPY_LAST_TO_GOLDEN
:
124 golden_frame_
= last_frame_
;
127 case media::Vp8FrameHeader::COPY_ALT_TO_GOLDEN
:
129 golden_frame_
= alt_frame_
;
134 if (curr_frame_hdr_
->refresh_alternate_frame
) {
135 alt_frame_
= curr_pic_
;
137 switch (curr_frame_hdr_
->copy_buffer_to_alternate
) {
138 case media::Vp8FrameHeader::COPY_LAST_TO_ALT
:
140 alt_frame_
= last_frame_
;
143 case media::Vp8FrameHeader::COPY_GOLDEN_TO_ALT
:
145 alt_frame_
= curr_golden
;
150 if (curr_frame_hdr_
->refresh_last
)
151 last_frame_
= curr_pic_
;
154 bool VP8Decoder::DecodeAndOutputCurrentFrame() {
155 DCHECK(!pic_size_
.IsEmpty());
157 DCHECK(curr_frame_hdr_
);
159 if (curr_frame_hdr_
->IsKeyframe()) {
160 horizontal_scale_
= curr_frame_hdr_
->horizontal_scale
;
161 vertical_scale_
= curr_frame_hdr_
->vertical_scale
;
163 // Populate fields from decoder state instead.
164 curr_frame_hdr_
->width
= pic_size_
.width();
165 curr_frame_hdr_
->height
= pic_size_
.height();
166 curr_frame_hdr_
->horizontal_scale
= horizontal_scale_
;
167 curr_frame_hdr_
->vertical_scale
= vertical_scale_
;
170 if (!accelerator_
->SubmitDecode(curr_pic_
, curr_frame_hdr_
.get(), last_frame_
,
171 golden_frame_
, alt_frame_
))
174 if (curr_frame_hdr_
->show_frame
)
175 if (!accelerator_
->OutputPicture(curr_pic_
))
178 RefreshReferenceFrames();
181 curr_frame_hdr_
= nullptr;
182 curr_frame_start_
= nullptr;
187 gfx::Size
VP8Decoder::GetPicSize() const {
191 size_t VP8Decoder::GetRequiredNumOfPictures() const {
192 const size_t kVP8NumFramesActive
= 4;
193 const size_t kPicsInPipeline
= media::limits::kMaxVideoFrames
+ 2;
194 return kVP8NumFramesActive
+ kPicsInPipeline
;
197 } // namespace content