OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/pepper/video_decoder_shim.h" | 5 #include "content/renderer/pepper/video_decoder_shim.h" |
6 | 6 |
7 #include <GLES2/gl2.h> | 7 #include <GLES2/gl2.h> |
8 #include <GLES2/gl2ext.h> | 8 #include <GLES2/gl2ext.h> |
9 #include <GLES2/gl2extchromium.h> | 9 #include <GLES2/gl2extchromium.h> |
10 | 10 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 ~DecoderImpl(); | 89 ~DecoderImpl(); |
90 | 90 |
91 void Initialize(media::VideoDecoderConfig config); | 91 void Initialize(media::VideoDecoderConfig config); |
92 void Decode(uint32_t decode_id, scoped_refptr<media::DecoderBuffer> buffer); | 92 void Decode(uint32_t decode_id, scoped_refptr<media::DecoderBuffer> buffer); |
93 void Reset(); | 93 void Reset(); |
94 void Stop(); | 94 void Stop(); |
95 | 95 |
96 private: | 96 private: |
97 void OnPipelineStatus(media::PipelineStatus status); | 97 void OnPipelineStatus(media::PipelineStatus status); |
98 void DoDecode(); | 98 void DoDecode(); |
99 void OnDecodeComplete(uint32_t decode_id, media::VideoDecoder::Status status); | 99 void OnDecodeComplete(media::VideoDecoder::Status status); |
100 void OnOutputComplete(const scoped_refptr<media::VideoFrame>& frame); | 100 void OnOutputComplete(const scoped_refptr<media::VideoFrame>& frame); |
101 void OnResetComplete(); | 101 void OnResetComplete(); |
102 | 102 |
103 // WeakPtr is bound to main_message_loop_. Use only in shim callbacks. | 103 // WeakPtr is bound to main_message_loop_. Use only in shim callbacks. |
104 base::WeakPtr<VideoDecoderShim> shim_; | 104 base::WeakPtr<VideoDecoderShim> shim_; |
105 scoped_ptr<media::VideoDecoder> decoder_; | 105 scoped_ptr<media::VideoDecoder> decoder_; |
106 scoped_refptr<base::MessageLoopProxy> main_message_loop_; | 106 scoped_refptr<base::MessageLoopProxy> main_message_loop_; |
107 // Queue of decodes waiting for the decoder. | 107 // Queue of decodes waiting for the decoder. |
108 typedef std::queue<PendingDecode> PendingDecodeQueue; | 108 typedef std::queue<PendingDecode> PendingDecodeQueue; |
109 PendingDecodeQueue pending_decodes_; | 109 PendingDecodeQueue pending_decodes_; |
110 int max_decodes_at_decoder_; | 110 bool waiting_decoder_; |
bbudge
2015/01/15 21:21:00
nit: s/waiting/awaiting
Sergey Ulanov
2015/01/16 00:46:39
Done.
| |
111 int num_decodes_at_decoder_; | |
112 // VideoDecoder returns pictures without information about the decode buffer | 111 // VideoDecoder returns pictures without information about the decode buffer |
113 // that generated it. Save the decode_id from the last decode that completed, | 112 // that generated it, but software decoder always generate corresponding |
bbudge
2015/01/15 21:21:00
nit: s/decoder/decoders
Sergey Ulanov
2015/01/16 00:46:39
Done.
| |
114 // which is close for most decoders, which only decode one buffer at a time. | 113 // frames before decode is finished. |
115 uint32_t decode_id_; | 114 uint32_t decode_id_; |
116 }; | 115 }; |
117 | 116 |
118 VideoDecoderShim::DecoderImpl::DecoderImpl( | 117 VideoDecoderShim::DecoderImpl::DecoderImpl( |
119 const base::WeakPtr<VideoDecoderShim>& proxy) | 118 const base::WeakPtr<VideoDecoderShim>& proxy) |
120 : shim_(proxy), | 119 : shim_(proxy), |
121 main_message_loop_(base::MessageLoopProxy::current()), | 120 main_message_loop_(base::MessageLoopProxy::current()), |
122 max_decodes_at_decoder_(0), | 121 waiting_decoder_(0), |
bbudge
2015/01/15 21:21:00
s/0/false
Sergey Ulanov
2015/01/16 00:46:39
Done.
| |
123 num_decodes_at_decoder_(0), | |
124 decode_id_(0) { | 122 decode_id_(0) { |
125 } | 123 } |
126 | 124 |
127 VideoDecoderShim::DecoderImpl::~DecoderImpl() { | 125 VideoDecoderShim::DecoderImpl::~DecoderImpl() { |
128 DCHECK(pending_decodes_.empty()); | 126 DCHECK(pending_decodes_.empty()); |
129 } | 127 } |
130 | 128 |
131 void VideoDecoderShim::DecoderImpl::Initialize( | 129 void VideoDecoderShim::DecoderImpl::Initialize( |
132 media::VideoDecoderConfig config) { | 130 media::VideoDecoderConfig config) { |
133 DCHECK(!decoder_); | 131 DCHECK(!decoder_); |
134 #if !defined(MEDIA_DISABLE_LIBVPX) | 132 #if !defined(MEDIA_DISABLE_LIBVPX) |
135 if (config.codec() == media::kCodecVP9) { | 133 if (config.codec() == media::kCodecVP9) { |
136 decoder_.reset( | 134 decoder_.reset( |
137 new media::VpxVideoDecoder(base::MessageLoopProxy::current())); | 135 new media::VpxVideoDecoder(base::MessageLoopProxy::current())); |
138 } else | 136 } else |
139 #endif | 137 #endif |
140 { | 138 { |
141 scoped_ptr<media::FFmpegVideoDecoder> ffmpeg_video_decoder( | 139 scoped_ptr<media::FFmpegVideoDecoder> ffmpeg_video_decoder( |
142 new media::FFmpegVideoDecoder(base::MessageLoopProxy::current())); | 140 new media::FFmpegVideoDecoder(base::MessageLoopProxy::current())); |
143 ffmpeg_video_decoder->set_decode_nalus(true); | 141 ffmpeg_video_decoder->set_decode_nalus(true); |
144 decoder_ = ffmpeg_video_decoder.Pass(); | 142 decoder_ = ffmpeg_video_decoder.Pass(); |
145 } | 143 } |
146 max_decodes_at_decoder_ = decoder_->GetMaxDecodeRequests(); | 144 |
145 // VpxVideoDecoder and FFmpegVideoDecoder support only one pending Decode() | |
146 // request. | |
147 DCHECK_EQ(decoder_->GetMaxDecodeRequests(), 1); | |
148 | |
147 // We can use base::Unretained() safely in decoder callbacks because | 149 // We can use base::Unretained() safely in decoder callbacks because |
148 // |decoder_| is owned by DecoderImpl. During Stop(), the |decoder_| will be | 150 // |decoder_| is owned by DecoderImpl. During Stop(), the |decoder_| will be |
149 // destroyed and all outstanding callbacks will be fired. | 151 // destroyed and all outstanding callbacks will be fired. |
150 decoder_->Initialize( | 152 decoder_->Initialize( |
151 config, | 153 config, |
152 true /* low_delay */, | 154 true /* low_delay */, |
153 base::Bind(&VideoDecoderShim::DecoderImpl::OnPipelineStatus, | 155 base::Bind(&VideoDecoderShim::DecoderImpl::OnPipelineStatus, |
154 base::Unretained(this)), | 156 base::Unretained(this)), |
155 base::Bind(&VideoDecoderShim::DecoderImpl::OnOutputComplete, | 157 base::Bind(&VideoDecoderShim::DecoderImpl::OnOutputComplete, |
156 base::Unretained(this))); | 158 base::Unretained(this))); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 break; | 202 break; |
201 case media::DECODER_ERROR_NOT_SUPPORTED: | 203 case media::DECODER_ERROR_NOT_SUPPORTED: |
202 result = PP_ERROR_NOTSUPPORTED; | 204 result = PP_ERROR_NOTSUPPORTED; |
203 break; | 205 break; |
204 default: | 206 default: |
205 result = PP_ERROR_FAILED; | 207 result = PP_ERROR_FAILED; |
206 break; | 208 break; |
207 } | 209 } |
208 | 210 |
209 // Calculate how many textures the shim should create. | 211 // Calculate how many textures the shim should create. |
210 uint32_t shim_texture_pool_size = | 212 uint32_t shim_texture_pool_size = media::limits::kMaxVideoFrames + 1; |
211 max_decodes_at_decoder_ + media::limits::kMaxVideoFrames; | |
212 main_message_loop_->PostTask( | 213 main_message_loop_->PostTask( |
213 FROM_HERE, | 214 FROM_HERE, |
214 base::Bind(&VideoDecoderShim::OnInitializeComplete, | 215 base::Bind(&VideoDecoderShim::OnInitializeComplete, |
215 shim_, | 216 shim_, |
216 result, | 217 result, |
217 shim_texture_pool_size)); | 218 shim_texture_pool_size)); |
218 } | 219 } |
219 | 220 |
220 void VideoDecoderShim::DecoderImpl::DoDecode() { | 221 void VideoDecoderShim::DecoderImpl::DoDecode() { |
221 while (!pending_decodes_.empty() && | 222 if (pending_decodes_.empty() || waiting_decoder_) |
222 num_decodes_at_decoder_ < max_decodes_at_decoder_) { | 223 return; |
223 num_decodes_at_decoder_++; | 224 |
224 const PendingDecode& decode = pending_decodes_.front(); | 225 waiting_decoder_ = true; |
225 decoder_->Decode( | 226 const PendingDecode& decode = pending_decodes_.front(); |
226 decode.buffer, | 227 decode_id_ = decode.decode_id; |
227 base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete, | 228 decoder_->Decode(decode.buffer, |
228 base::Unretained(this), | 229 base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete, |
229 decode.decode_id)); | 230 base::Unretained(this))); |
230 pending_decodes_.pop(); | 231 pending_decodes_.pop(); |
231 } | |
232 } | 232 } |
233 | 233 |
234 void VideoDecoderShim::DecoderImpl::OnDecodeComplete( | 234 void VideoDecoderShim::DecoderImpl::OnDecodeComplete( |
235 uint32_t decode_id, | |
236 media::VideoDecoder::Status status) { | 235 media::VideoDecoder::Status status) { |
237 num_decodes_at_decoder_--; | 236 DCHECK(waiting_decoder_); |
238 decode_id_ = decode_id; | 237 waiting_decoder_ = false; |
239 | 238 |
240 int32_t result; | 239 int32_t result; |
241 switch (status) { | 240 switch (status) { |
242 case media::VideoDecoder::kOk: | 241 case media::VideoDecoder::kOk: |
243 case media::VideoDecoder::kAborted: | 242 case media::VideoDecoder::kAborted: |
244 result = PP_OK; | 243 result = PP_OK; |
245 break; | 244 break; |
246 case media::VideoDecoder::kDecodeError: | 245 case media::VideoDecoder::kDecodeError: |
247 result = PP_ERROR_RESOURCE_FAILED; | 246 result = PP_ERROR_RESOURCE_FAILED; |
248 break; | 247 break; |
249 default: | 248 default: |
250 NOTREACHED(); | 249 NOTREACHED(); |
251 result = PP_ERROR_FAILED; | 250 result = PP_ERROR_FAILED; |
252 break; | 251 break; |
253 } | 252 } |
254 | 253 |
255 main_message_loop_->PostTask( | 254 main_message_loop_->PostTask( |
256 FROM_HERE, | 255 FROM_HERE, |
257 base::Bind( | 256 base::Bind( |
258 &VideoDecoderShim::OnDecodeComplete, shim_, result, decode_id)); | 257 &VideoDecoderShim::OnDecodeComplete, shim_, result, decode_id_)); |
259 | 258 |
260 DoDecode(); | 259 DoDecode(); |
261 } | 260 } |
262 | 261 |
263 void VideoDecoderShim::DecoderImpl::OnOutputComplete( | 262 void VideoDecoderShim::DecoderImpl::OnOutputComplete( |
264 const scoped_refptr<media::VideoFrame>& frame) { | 263 const scoped_refptr<media::VideoFrame>& frame) { |
264 // Software decoders are expected to generated frames only when Decode() call | |
bbudge
2015/01/15 21:21:00
s/generated/generate
s/Decode()/a Decode()
Sergey Ulanov
2015/01/16 00:46:39
Done.
| |
265 // is pending. | |
266 DCHECK(waiting_decoder_); | |
267 | |
265 scoped_ptr<PendingFrame> pending_frame; | 268 scoped_ptr<PendingFrame> pending_frame; |
266 if (!frame->end_of_stream()) { | 269 if (!frame->end_of_stream()) { |
267 pending_frame.reset(new PendingFrame( | 270 pending_frame.reset(new PendingFrame( |
268 decode_id_, frame->coded_size(), frame->visible_rect())); | 271 decode_id_, frame->coded_size(), frame->visible_rect())); |
269 // Convert the VideoFrame pixels to ABGR to match VideoDecodeAccelerator. | 272 // Convert the VideoFrame pixels to ABGR to match VideoDecodeAccelerator. |
270 libyuv::I420ToABGR(frame->data(media::VideoFrame::kYPlane), | 273 libyuv::I420ToABGR(frame->data(media::VideoFrame::kYPlane), |
271 frame->stride(media::VideoFrame::kYPlane), | 274 frame->stride(media::VideoFrame::kYPlane), |
272 frame->data(media::VideoFrame::kUPlane), | 275 frame->data(media::VideoFrame::kUPlane), |
273 frame->stride(media::VideoFrame::kUPlane), | 276 frame->stride(media::VideoFrame::kUPlane), |
274 frame->data(media::VideoFrame::kVPlane), | 277 frame->data(media::VideoFrame::kVPlane), |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 void VideoDecoderShim::DeleteTexture(uint32_t texture_id) { | 591 void VideoDecoderShim::DeleteTexture(uint32_t texture_id) { |
589 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); | 592 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); |
590 gles2->DeleteTextures(1, &texture_id); | 593 gles2->DeleteTextures(1, &texture_id); |
591 } | 594 } |
592 | 595 |
593 void VideoDecoderShim::FlushCommandBuffer() { | 596 void VideoDecoderShim::FlushCommandBuffer() { |
594 context_provider_->ContextGL()->Flush(); | 597 context_provider_->ContextGL()->Flush(); |
595 } | 598 } |
596 | 599 |
597 } // namespace content | 600 } // namespace content |
OLD | NEW |