OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/common/gpu/media/vp8_decoder.h" | |
6 #include "media/base/limits.h" | |
7 | |
8 namespace content { | |
9 | |
10 VP8Decoder::VP8Decoder(VP8Accelerator* accelerator) | |
11 : state_(kNeedStreamMetadata), | |
12 curr_frame_start_(nullptr), | |
13 frame_size_(0), | |
14 accelerator_(accelerator) { | |
15 DCHECK(accelerator_); | |
16 } | |
17 | |
18 VP8Decoder::~VP8Decoder() { | |
19 } | |
20 | |
21 bool VP8Decoder::Flush() { | |
22 DVLOG(2) << "Decoder flush"; | |
23 Reset(); | |
24 return true; | |
25 } | |
26 | |
27 void VP8Decoder::SetStream(const uint8_t* ptr, size_t size) { | |
28 DCHECK(ptr); | |
29 DCHECK(size); | |
30 | |
31 curr_frame_start_ = ptr; | |
32 frame_size_ = size; | |
33 DVLOG(4) << "New input stream at: " << (void*)ptr << " size: " << size; | |
34 } | |
35 | |
36 void VP8Decoder::Reset() { | |
37 curr_pic_ = nullptr; | |
38 curr_frame_hdr_ = nullptr; | |
39 curr_frame_start_ = nullptr; | |
40 frame_size_ = 0; | |
41 | |
42 last_frame_ = nullptr; | |
43 golden_frame_ = nullptr; | |
44 alt_frame_ = nullptr; | |
45 | |
46 if (state_ == kDecoding) | |
47 state_ = kAfterReset; | |
48 } | |
49 | |
50 VP8Decoder::DecResult VP8Decoder::Decode() { | |
51 if (!curr_frame_start_ || frame_size_ == 0) | |
52 return kRanOutOfStreamData; | |
53 | |
54 if (!curr_frame_hdr_) { | |
55 curr_frame_hdr_.reset(new media::VP8FrameHeader()); | |
56 if (!parser_.ParseFrame(curr_frame_start_, frame_size_, | |
57 curr_frame_hdr_.get())) { | |
58 DVLOG(1) << "Error during decode"; | |
59 state_ = kError; | |
60 return VP8Decoder::kDecodeError; | |
kcwu
2015/01/09 10:07:48
Maybe it is just not enough data, not really error
Pawel Osciak
2015/01/09 13:50:31
This would indicate a partial frame (since frame_s
| |
61 } | |
62 } | |
63 | |
64 if (curr_frame_hdr_->IsKeyframe()) { | |
65 gfx::Size new_pic_size(curr_frame_hdr_->width, curr_frame_hdr_->height); | |
66 if (new_pic_size.IsEmpty()) | |
67 return kDecodeError; | |
68 | |
69 if (pic_size_.IsEmpty() || new_pic_size != pic_size_) { | |
Owen Lin
2015/01/09 09:56:14
Do we need to test pic_size_.IsEmpty() ?
Since ne
kcwu
2015/01/09 10:07:48
"new_pic_size != pic_size_" is enough.
Pawel Osciak
2015/01/12 07:18:19
Done.
Pawel Osciak
2015/01/12 07:18:19
Done.
| |
70 DVLOG(2) << "New resolution: " << new_pic_size.ToString(); | |
71 pic_size_ = new_pic_size; | |
72 return kAllocateNewSurfaces; | |
73 } | |
74 | |
75 state_ = kDecoding; | |
76 } else { | |
77 if (state_ != kDecoding) { | |
78 // Need a resume point. | |
79 curr_frame_hdr_.reset(); | |
80 return kRanOutOfStreamData; | |
81 } | |
82 } | |
83 | |
84 curr_pic_ = accelerator_->CreateVP8Picture(); | |
85 if (!curr_pic_) | |
86 return kRanOutOfSurfaces; | |
87 | |
88 if (!DecodeAndOutputCurrentFrame()) | |
89 return kDecodeError; | |
90 | |
91 return kRanOutOfStreamData; | |
kcwu
2015/01/09 10:07:48
IIUC, you only decoded one frame and there may be
Pawel Osciak
2015/01/09 13:50:31
Hm, true, it doesn't happen now since Chrome segme
Pawel Osciak
2015/01/12 07:18:19
Actually, this would apply to H264, but for VP8 we
| |
92 } | |
93 | |
94 void VP8Decoder::RefreshReferenceFrames() { | |
95 if (curr_frame_hdr_->IsKeyframe()) { | |
96 last_frame_ = curr_pic_; | |
97 golden_frame_ = curr_pic_; | |
98 alt_frame_ = curr_pic_; | |
99 return; | |
100 } | |
101 | |
102 // Save current golden since we overwrite it here, | |
103 // but may have to use it to update alt below. | |
104 scoped_refptr<VP8Picture> curr_golden = golden_frame_; | |
105 | |
106 if (curr_frame_hdr_->refresh_golden_frame) { | |
107 golden_frame_ = curr_pic_; | |
108 } else { | |
109 switch (curr_frame_hdr_->copy_buffer_to_golden) { | |
110 case media::VP8FrameHeader::kCopyLastToGolden: | |
111 DCHECK(last_frame_); | |
Owen Lin
2015/01/09 09:56:14
Why it is not a decode error? I mean a bad stream
Pawel Osciak
2015/01/09 13:50:31
Ah good point.
Pawel Osciak
2015/01/12 07:18:19
Well, actually, recalling my original line of thou
| |
112 golden_frame_ = last_frame_; | |
113 break; | |
114 | |
115 case media::VP8FrameHeader::kCopyAltToGolden: | |
116 DCHECK(alt_frame_); | |
Owen Lin
2015/01/09 09:56:14
Same here.
Pawel Osciak
2015/01/12 07:18:19
As above.
| |
117 golden_frame_ = alt_frame_; | |
118 break; | |
119 } | |
120 } | |
121 | |
122 if (curr_frame_hdr_->refresh_alternate_frame) { | |
123 alt_frame_ = curr_pic_; | |
124 } else { | |
125 switch (curr_frame_hdr_->copy_buffer_to_alternate) { | |
126 case media::VP8FrameHeader::kCopyLastToAlt: | |
127 DCHECK(last_frame_); | |
128 alt_frame_ = last_frame_; | |
129 break; | |
130 | |
131 case media::VP8FrameHeader::kCopyGoldenToAlt: | |
132 DCHECK(curr_golden); | |
133 alt_frame_ = curr_golden; | |
134 break; | |
135 } | |
136 } | |
137 | |
138 if (curr_frame_hdr_->refresh_last) | |
139 last_frame_ = curr_pic_; | |
140 } | |
141 | |
142 void VP8Decoder::BeginFrame() { | |
143 if (curr_frame_hdr_->IsKeyframe()) { | |
144 horizontal_scale_ = curr_frame_hdr_->horizontal_scale; | |
145 vertical_scale_ = curr_frame_hdr_->vertical_scale; | |
146 } else { | |
147 // Populate fields from decoder state instead. | |
148 curr_frame_hdr_->width = pic_size_.width(); | |
149 curr_frame_hdr_->height = pic_size_.height(); | |
150 curr_frame_hdr_->horizontal_scale = horizontal_scale_; | |
151 curr_frame_hdr_->vertical_scale = vertical_scale_; | |
152 } | |
153 } | |
154 | |
155 bool VP8Decoder::DecodeAndOutputCurrentFrame() { | |
156 DCHECK(!pic_size_.IsEmpty()); | |
157 DCHECK(curr_pic_); | |
158 DCHECK(curr_frame_hdr_); | |
159 | |
160 BeginFrame(); | |
Owen Lin
2015/01/09 09:56:14
[optional] I am kind of thinking there is no need
Pawel Osciak
2015/01/12 07:18:19
Done.
| |
161 | |
162 if (!accelerator_->SubmitDecode(curr_pic_, curr_frame_hdr_.get(), last_frame_, | |
163 golden_frame_, alt_frame_)) | |
164 return false; | |
165 | |
166 if (!accelerator_->OutputPicture(curr_pic_)) | |
167 return false; | |
168 | |
169 RefreshReferenceFrames(); | |
170 | |
171 curr_pic_ = nullptr; | |
172 curr_frame_hdr_ = nullptr; | |
173 curr_frame_start_ = nullptr; | |
174 frame_size_ = 0; | |
kcwu
2015/01/09 10:07:48
maybe some data still remain after current frame?
Pawel Osciak
2015/01/12 07:18:19
Actually we can't use it, since we must be given f
| |
175 return true; | |
176 } | |
177 | |
178 size_t VP8Decoder::GetRequiredNumOfPictures() { | |
179 static const size_t kVP8NumFramesActive = 4; | |
kcwu
2015/01/09 10:07:48
no need "static"
Pawel Osciak
2015/01/12 07:18:19
Done.
| |
180 static const size_t kPicsInPipeline = media::limits::kMaxVideoFrames + 2; | |
Owen Lin
2015/01/09 09:56:14
remove static
Pawel Osciak
2015/01/12 07:18:19
Done.
| |
181 return kVP8NumFramesActive + kPicsInPipeline; | |
182 } | |
183 | |
184 } // namespace content | |
OLD | NEW |