| 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 VideoDecoder implementations used in this class |
| 114 // which is close for most decoders, which only decode one buffer at a time. | 113 // (media::FFmpegVideoDecoder and media::VpxVideoDecoder) always generate |
| 114 // corresponding frames before decode is finished. |decode_id_| is used to |
| 115 // store id of the current buffer while Decode() call is pending. |
| 115 uint32_t decode_id_; | 116 uint32_t decode_id_; |
| 116 }; | 117 }; |
| 117 | 118 |
| 118 VideoDecoderShim::DecoderImpl::DecoderImpl( | 119 VideoDecoderShim::DecoderImpl::DecoderImpl( |
| 119 const base::WeakPtr<VideoDecoderShim>& proxy) | 120 const base::WeakPtr<VideoDecoderShim>& proxy) |
| 120 : shim_(proxy), | 121 : shim_(proxy), |
| 121 main_message_loop_(base::MessageLoopProxy::current()), | 122 main_message_loop_(base::MessageLoopProxy::current()), |
| 122 max_decodes_at_decoder_(0), | 123 awaiting_decoder_(false), |
| 123 num_decodes_at_decoder_(0), | |
| 124 decode_id_(0) { | 124 decode_id_(0) { |
| 125 } | 125 } |
| 126 | 126 |
| 127 VideoDecoderShim::DecoderImpl::~DecoderImpl() { | 127 VideoDecoderShim::DecoderImpl::~DecoderImpl() { |
| 128 DCHECK(pending_decodes_.empty()); | 128 DCHECK(pending_decodes_.empty()); |
| 129 } | 129 } |
| 130 | 130 |
| 131 void VideoDecoderShim::DecoderImpl::Initialize( | 131 void VideoDecoderShim::DecoderImpl::Initialize( |
| 132 media::VideoDecoderConfig config) { | 132 media::VideoDecoderConfig config) { |
| 133 DCHECK(!decoder_); | 133 DCHECK(!decoder_); |
| 134 #if !defined(MEDIA_DISABLE_LIBVPX) | 134 #if !defined(MEDIA_DISABLE_LIBVPX) |
| 135 if (config.codec() == media::kCodecVP9) { | 135 if (config.codec() == media::kCodecVP9) { |
| 136 decoder_.reset( | 136 decoder_.reset( |
| 137 new media::VpxVideoDecoder(base::MessageLoopProxy::current())); | 137 new media::VpxVideoDecoder(base::MessageLoopProxy::current())); |
| 138 } else | 138 } else |
| 139 #endif | 139 #endif |
| 140 { | 140 { |
| 141 scoped_ptr<media::FFmpegVideoDecoder> ffmpeg_video_decoder( | 141 scoped_ptr<media::FFmpegVideoDecoder> ffmpeg_video_decoder( |
| 142 new media::FFmpegVideoDecoder(base::MessageLoopProxy::current())); | 142 new media::FFmpegVideoDecoder(base::MessageLoopProxy::current())); |
| 143 ffmpeg_video_decoder->set_decode_nalus(true); | 143 ffmpeg_video_decoder->set_decode_nalus(true); |
| 144 decoder_ = ffmpeg_video_decoder.Pass(); | 144 decoder_ = ffmpeg_video_decoder.Pass(); |
| 145 } | 145 } |
| 146 max_decodes_at_decoder_ = decoder_->GetMaxDecodeRequests(); | 146 |
| 147 // VpxVideoDecoder and FFmpegVideoDecoder support only one pending Decode() |
| 148 // request. |
| 149 DCHECK_EQ(decoder_->GetMaxDecodeRequests(), 1); |
| 150 |
| 147 // We can use base::Unretained() safely in decoder callbacks because | 151 // We can use base::Unretained() safely in decoder callbacks because |
| 148 // |decoder_| is owned by DecoderImpl. During Stop(), the |decoder_| will be | 152 // |decoder_| is owned by DecoderImpl. During Stop(), the |decoder_| will be |
| 149 // destroyed and all outstanding callbacks will be fired. | 153 // destroyed and all outstanding callbacks will be fired. |
| 150 decoder_->Initialize( | 154 decoder_->Initialize( |
| 151 config, | 155 config, |
| 152 true /* low_delay */, | 156 true /* low_delay */, |
| 153 base::Bind(&VideoDecoderShim::DecoderImpl::OnPipelineStatus, | 157 base::Bind(&VideoDecoderShim::DecoderImpl::OnPipelineStatus, |
| 154 base::Unretained(this)), | 158 base::Unretained(this)), |
| 155 base::Bind(&VideoDecoderShim::DecoderImpl::OnOutputComplete, | 159 base::Bind(&VideoDecoderShim::DecoderImpl::OnOutputComplete, |
| 156 base::Unretained(this))); | 160 base::Unretained(this))); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 break; | 204 break; |
| 201 case media::DECODER_ERROR_NOT_SUPPORTED: | 205 case media::DECODER_ERROR_NOT_SUPPORTED: |
| 202 result = PP_ERROR_NOTSUPPORTED; | 206 result = PP_ERROR_NOTSUPPORTED; |
| 203 break; | 207 break; |
| 204 default: | 208 default: |
| 205 result = PP_ERROR_FAILED; | 209 result = PP_ERROR_FAILED; |
| 206 break; | 210 break; |
| 207 } | 211 } |
| 208 | 212 |
| 209 // Calculate how many textures the shim should create. | 213 // Calculate how many textures the shim should create. |
| 210 uint32_t shim_texture_pool_size = | 214 uint32_t shim_texture_pool_size = media::limits::kMaxVideoFrames + 1; |
| 211 max_decodes_at_decoder_ + media::limits::kMaxVideoFrames; | |
| 212 main_message_loop_->PostTask( | 215 main_message_loop_->PostTask( |
| 213 FROM_HERE, | 216 FROM_HERE, |
| 214 base::Bind(&VideoDecoderShim::OnInitializeComplete, | 217 base::Bind(&VideoDecoderShim::OnInitializeComplete, |
| 215 shim_, | 218 shim_, |
| 216 result, | 219 result, |
| 217 shim_texture_pool_size)); | 220 shim_texture_pool_size)); |
| 218 } | 221 } |
| 219 | 222 |
| 220 void VideoDecoderShim::DecoderImpl::DoDecode() { | 223 void VideoDecoderShim::DecoderImpl::DoDecode() { |
| 221 while (!pending_decodes_.empty() && | 224 if (pending_decodes_.empty() || awaiting_decoder_) |
| 222 num_decodes_at_decoder_ < max_decodes_at_decoder_) { | 225 return; |
| 223 num_decodes_at_decoder_++; | 226 |
| 224 const PendingDecode& decode = pending_decodes_.front(); | 227 awaiting_decoder_ = true; |
| 225 decoder_->Decode( | 228 const PendingDecode& decode = pending_decodes_.front(); |
| 226 decode.buffer, | 229 decode_id_ = decode.decode_id; |
| 227 base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete, | 230 decoder_->Decode(decode.buffer, |
| 228 base::Unretained(this), | 231 base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete, |
| 229 decode.decode_id)); | 232 base::Unretained(this))); |
| 230 pending_decodes_.pop(); | 233 pending_decodes_.pop(); |
| 231 } | |
| 232 } | 234 } |
| 233 | 235 |
| 234 void VideoDecoderShim::DecoderImpl::OnDecodeComplete( | 236 void VideoDecoderShim::DecoderImpl::OnDecodeComplete( |
| 235 uint32_t decode_id, | |
| 236 media::VideoDecoder::Status status) { | 237 media::VideoDecoder::Status status) { |
| 237 num_decodes_at_decoder_--; | 238 DCHECK(awaiting_decoder_); |
| 238 decode_id_ = decode_id; | 239 awaiting_decoder_ = false; |
| 239 | 240 |
| 240 int32_t result; | 241 int32_t result; |
| 241 switch (status) { | 242 switch (status) { |
| 242 case media::VideoDecoder::kOk: | 243 case media::VideoDecoder::kOk: |
| 243 case media::VideoDecoder::kAborted: | 244 case media::VideoDecoder::kAborted: |
| 244 result = PP_OK; | 245 result = PP_OK; |
| 245 break; | 246 break; |
| 246 case media::VideoDecoder::kDecodeError: | 247 case media::VideoDecoder::kDecodeError: |
| 247 result = PP_ERROR_RESOURCE_FAILED; | 248 result = PP_ERROR_RESOURCE_FAILED; |
| 248 break; | 249 break; |
| 249 default: | 250 default: |
| 250 NOTREACHED(); | 251 NOTREACHED(); |
| 251 result = PP_ERROR_FAILED; | 252 result = PP_ERROR_FAILED; |
| 252 break; | 253 break; |
| 253 } | 254 } |
| 254 | 255 |
| 255 main_message_loop_->PostTask( | 256 main_message_loop_->PostTask( |
| 256 FROM_HERE, | 257 FROM_HERE, |
| 257 base::Bind( | 258 base::Bind( |
| 258 &VideoDecoderShim::OnDecodeComplete, shim_, result, decode_id)); | 259 &VideoDecoderShim::OnDecodeComplete, shim_, result, decode_id_)); |
| 259 | 260 |
| 260 DoDecode(); | 261 DoDecode(); |
| 261 } | 262 } |
| 262 | 263 |
| 263 void VideoDecoderShim::DecoderImpl::OnOutputComplete( | 264 void VideoDecoderShim::DecoderImpl::OnOutputComplete( |
| 264 const scoped_refptr<media::VideoFrame>& frame) { | 265 const scoped_refptr<media::VideoFrame>& frame) { |
| 266 // Software decoders are expected to generated frames only when a Decode() |
| 267 // call is pending. |
| 268 DCHECK(awaiting_decoder_); |
| 269 |
| 265 scoped_ptr<PendingFrame> pending_frame; | 270 scoped_ptr<PendingFrame> pending_frame; |
| 266 if (!frame->end_of_stream()) { | 271 if (!frame->end_of_stream()) { |
| 267 pending_frame.reset(new PendingFrame( | 272 pending_frame.reset(new PendingFrame( |
| 268 decode_id_, frame->coded_size(), frame->visible_rect())); | 273 decode_id_, frame->coded_size(), frame->visible_rect())); |
| 269 // Convert the VideoFrame pixels to ABGR to match VideoDecodeAccelerator. | 274 // Convert the VideoFrame pixels to ABGR to match VideoDecodeAccelerator. |
| 270 libyuv::I420ToABGR(frame->data(media::VideoFrame::kYPlane), | 275 libyuv::I420ToABGR(frame->data(media::VideoFrame::kYPlane), |
| 271 frame->stride(media::VideoFrame::kYPlane), | 276 frame->stride(media::VideoFrame::kYPlane), |
| 272 frame->data(media::VideoFrame::kUPlane), | 277 frame->data(media::VideoFrame::kUPlane), |
| 273 frame->stride(media::VideoFrame::kUPlane), | 278 frame->stride(media::VideoFrame::kUPlane), |
| 274 frame->data(media::VideoFrame::kVPlane), | 279 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) { | 593 void VideoDecoderShim::DeleteTexture(uint32_t texture_id) { |
| 589 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); | 594 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); |
| 590 gles2->DeleteTextures(1, &texture_id); | 595 gles2->DeleteTextures(1, &texture_id); |
| 591 } | 596 } |
| 592 | 597 |
| 593 void VideoDecoderShim::FlushCommandBuffer() { | 598 void VideoDecoderShim::FlushCommandBuffer() { |
| 594 context_provider_->ContextGL()->Flush(); | 599 context_provider_->ContextGL()->Flush(); |
| 595 } | 600 } |
| 596 | 601 |
| 597 } // namespace content | 602 } // namespace content |
| OLD | NEW |