| 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 awaiting_decoder_; |
| 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 decoders always generate corresponding |
| 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 awaiting_decoder_(false), |
| 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() || awaiting_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 awaiting_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(awaiting_decoder_); |
| 238 decode_id_ = decode_id; | 237 awaiting_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 a Decode() |
| 265 // call is pending. |
| 266 DCHECK(awaiting_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 |