| OLD | NEW |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 <GLES2/gl2.h> |
| 6 #include <GLES2/gl2ext.h> |
| 7 #include <GLES2/gl2extchromium.h> |
| 8 |
| 5 #include "content/renderer/pepper/pepper_video_decoder_host.h" | 9 #include "content/renderer/pepper/pepper_video_decoder_host.h" |
| 6 | 10 |
| 7 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/memory/ref_counted.h" |
| 8 #include "base/memory/shared_memory.h" | 13 #include "base/memory/shared_memory.h" |
| 9 #include "content/common/gpu/client/gpu_channel_host.h" | 14 #include "content/common/gpu/client/gpu_channel_host.h" |
| 10 #include "content/public/renderer/render_thread.h" | 15 #include "content/public/renderer/render_thread.h" |
| 11 #include "content/public/renderer/renderer_ppapi_host.h" | 16 #include "content/public/renderer/renderer_ppapi_host.h" |
| 12 #include "content/renderer/pepper/ppb_graphics_3d_impl.h" | 17 #include "content/renderer/pepper/ppb_graphics_3d_impl.h" |
| 13 #include "content/renderer/render_thread_impl.h" | 18 #include "content/renderer/render_thread_impl.h" |
| 14 #include "content/renderer/render_view_impl.h" | 19 #include "content/renderer/render_view_impl.h" |
| 20 #include "gpu/command_buffer/client/gles2_implementation.h" |
| 21 #include "media/base/decoder_buffer.h" |
| 22 #include "media/filters/ffmpeg_video_decoder.h" |
| 15 #include "media/video/picture.h" | 23 #include "media/video/picture.h" |
| 16 #include "media/video/video_decode_accelerator.h" | 24 #include "media/video/video_decode_accelerator.h" |
| 17 #include "ppapi/c/pp_completion_callback.h" | 25 #include "ppapi/c/pp_completion_callback.h" |
| 18 #include "ppapi/c/pp_errors.h" | 26 #include "ppapi/c/pp_errors.h" |
| 19 #include "ppapi/host/dispatch_host_message.h" | 27 #include "ppapi/host/dispatch_host_message.h" |
| 20 #include "ppapi/host/ppapi_host.h" | 28 #include "ppapi/host/ppapi_host.h" |
| 21 #include "ppapi/proxy/ppapi_messages.h" | 29 #include "ppapi/proxy/ppapi_messages.h" |
| 22 #include "ppapi/proxy/video_decoder_constants.h" | 30 #include "ppapi/proxy/video_decoder_constants.h" |
| 23 #include "ppapi/thunk/enter.h" | 31 #include "ppapi/thunk/enter.h" |
| 24 #include "ppapi/thunk/ppb_graphics_3d_api.h" | 32 #include "ppapi/thunk/ppb_graphics_3d_api.h" |
| 33 #include "third_party/libyuv/include/libyuv.h" |
| 34 #include "webkit/common/gpu/context_provider_web_context.h" |
| 25 | 35 |
| 26 using ppapi::proxy::SerializedHandle; | 36 using ppapi::proxy::SerializedHandle; |
| 27 using ppapi::thunk::EnterResourceNoLock; | 37 using ppapi::thunk::EnterResourceNoLock; |
| 28 using ppapi::thunk::PPB_Graphics3D_API; | 38 using ppapi::thunk::PPB_Graphics3D_API; |
| 29 | 39 |
| 30 namespace content { | 40 namespace content { |
| 31 | 41 |
| 32 namespace { | 42 namespace { |
| 33 | 43 |
| 34 media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) { | 44 media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 50 case PP_VIDEOPROFILE_H264SCALABLEBASELINE: | 60 case PP_VIDEOPROFILE_H264SCALABLEBASELINE: |
| 51 return media::H264PROFILE_SCALABLEBASELINE; | 61 return media::H264PROFILE_SCALABLEBASELINE; |
| 52 case PP_VIDEOPROFILE_H264SCALABLEHIGH: | 62 case PP_VIDEOPROFILE_H264SCALABLEHIGH: |
| 53 return media::H264PROFILE_SCALABLEHIGH; | 63 return media::H264PROFILE_SCALABLEHIGH; |
| 54 case PP_VIDEOPROFILE_H264STEREOHIGH: | 64 case PP_VIDEOPROFILE_H264STEREOHIGH: |
| 55 return media::H264PROFILE_STEREOHIGH; | 65 return media::H264PROFILE_STEREOHIGH; |
| 56 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH: | 66 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH: |
| 57 return media::H264PROFILE_MULTIVIEWHIGH; | 67 return media::H264PROFILE_MULTIVIEWHIGH; |
| 58 case PP_VIDEOPROFILE_VP8MAIN: | 68 case PP_VIDEOPROFILE_VP8MAIN: |
| 59 return media::VP8PROFILE_MAIN; | 69 return media::VP8PROFILE_MAIN; |
| 60 // No default case, to catch unhandled PP_VideoProfile values. | 70 // No default case, to catch unhandled PP_VideoProfile values. |
| 61 } | 71 } |
| 62 | 72 |
| 63 return media::VIDEO_CODEC_PROFILE_UNKNOWN; | 73 return media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| 64 } | 74 } |
| 65 | 75 |
| 76 int32_t MediaPipelineStatusToPepper(media::PipelineStatus status) { |
| 77 switch (status) { |
| 78 case media::PIPELINE_OK: |
| 79 return PP_OK; |
| 80 case media::DECODER_ERROR_NOT_SUPPORTED: |
| 81 return PP_ERROR_NOTSUPPORTED; |
| 82 default: |
| 83 return PP_ERROR_FAILED; |
| 84 } |
| 85 } |
| 86 |
| 66 } // namespace | 87 } // namespace |
| 67 | 88 |
| 89 // TODO |
| 90 // - variable # of shm buffers, depending on software or hardware. |
| 91 |
| 92 // This wrapper class calls methods on a media::VideoDecoder on the media thread |
| 93 // and relays results back to the host on the main thread. It should be created, |
| 94 // used, and destroyed on the main (render) thread. |
| 95 class SoftwareDecoder { |
| 96 public: |
| 97 explicit SoftwareDecoder(PepperVideoDecoderHost* host); |
| 98 ~SoftwareDecoder(); |
| 99 |
| 100 void Initialize(media::VideoCodecProfile profile); |
| 101 void Decode(uint32_t decode_id, |
| 102 const scoped_refptr<media::DecoderBuffer>& buffer); |
| 103 void AssignTextures(const std::vector<uint32_t>& plugin_texture_ids); |
| 104 void RecycleTexture(uint32_t plugin_texture_id); |
| 105 void Flush(); |
| 106 void Reset(); |
| 107 void Destroy(); |
| 108 |
| 109 private: |
| 110 struct PendingDecode { |
| 111 PendingDecode(uint32_t decode_id, |
| 112 const scoped_refptr<media::DecoderBuffer>& buffer); |
| 113 ~PendingDecode(); |
| 114 |
| 115 uint32_t decode_id; |
| 116 scoped_refptr<media::DecoderBuffer> buffer; |
| 117 }; |
| 118 |
| 119 struct PendingFrame { |
| 120 PendingFrame(uint32_t decode_id, const gfx::Size& size); |
| 121 ~PendingFrame(); |
| 122 |
| 123 uint32_t decode_id; |
| 124 gfx::Size size; |
| 125 std::vector<uint8_t> pixels; |
| 126 }; |
| 127 |
| 128 void InitializeOnMediaThread(media::VideoDecoderConfig config); |
| 129 void PipelineStatusOnMediaThread(media::PipelineStatus status); |
| 130 void PipelineStatusOnMainThread(media::PipelineStatus status); |
| 131 |
| 132 void ReceiveBufferOnMediaThread(uint32_t decode_id, |
| 133 scoped_refptr<media::DecoderBuffer> buffer); |
| 134 void DecodeOnMediaThread(); |
| 135 void ConvertFrameOnMediaThread(uint32_t decode_id, |
| 136 media::VideoDecoder::Status status, |
| 137 const scoped_refptr<media::VideoFrame>& frame); |
| 138 void ReceiveFrameOnMainThread(media::VideoDecoder::Status status, |
| 139 scoped_ptr<PendingFrame> frame); |
| 140 void SendPicturesOnMainThread(); |
| 141 |
| 142 void DoResetOnMediaThread(); |
| 143 void ResetCompleteOnMediaThread(); |
| 144 void ResetCompleteOnMainThread(); |
| 145 |
| 146 void DestroyOnMediaThread(); |
| 147 void DestroyOnMainThread(); |
| 148 |
| 149 void DeleteTextures(); |
| 150 void FlushCommandBuffer(); |
| 151 |
| 152 // These members are accessed only on the main thread. |
| 153 |
| 154 PepperVideoDecoderHost* host_; |
| 155 scoped_refptr<base::MessageLoopProxy> media_message_loop_; |
| 156 scoped_refptr<webkit::gpu::ContextProviderWebContext> context_provider_; |
| 157 // The current decoded frame size. |
| 158 gfx::Size texture_size_; |
| 159 // Map that takes the plugin's GL texture id to the renderer's GL texture id. |
| 160 typedef std::map<uint32_t, uint32_t> SharedTextureMap; |
| 161 SharedTextureMap shared_textures_; |
| 162 // Track available textures using the plugin's ids. |
| 163 std::vector<uint32_t> plugin_texture_ids_; |
| 164 // Mailboxes for pending texture requests, to write to plugin's textures. |
| 165 std::vector<gpu::Mailbox> pending_texture_mailboxes_; |
| 166 // Queue of pending decoded frames. These have been converted to RGB, and |
| 167 // await upload to a GL texture. |
| 168 typedef std::queue<PendingFrame*> PendingFrameQueue; |
| 169 PendingFrameQueue pending_frames_; |
| 170 uint32_t num_pending_decodes_; |
| 171 bool flushing_; |
| 172 bool resetting_; |
| 173 |
| 174 // These members are accessed only on the media thread. |
| 175 |
| 176 scoped_ptr<media::VideoDecoder> decoder_; |
| 177 scoped_refptr<base::MessageLoopProxy> main_message_loop_; |
| 178 // Queue of pending decodes. The front element is the buffer currently in |
| 179 // use by the software decoder. |
| 180 typedef std::queue<PendingDecode> PendingDecodeQueue; |
| 181 PendingDecodeQueue pending_decodes_; |
| 182 }; |
| 183 |
| 184 SoftwareDecoder::PendingDecode::PendingDecode( |
| 185 uint32_t decode_id, |
| 186 const scoped_refptr<media::DecoderBuffer>& buffer) |
| 187 : decode_id(decode_id), buffer(buffer) { |
| 188 } |
| 189 |
| 190 SoftwareDecoder::PendingDecode::~PendingDecode() { |
| 191 } |
| 192 |
| 193 SoftwareDecoder::PendingFrame::PendingFrame(uint32_t decode_id, |
| 194 const gfx::Size& size) |
| 195 : decode_id(decode_id), |
| 196 size(size), |
| 197 pixels(size.width() * size.height() * 4) { |
| 198 } |
| 199 |
| 200 SoftwareDecoder::PendingFrame::~PendingFrame() { |
| 201 } |
| 202 |
| 203 SoftwareDecoder::SoftwareDecoder(PepperVideoDecoderHost* host) |
| 204 : host_(host), |
| 205 media_message_loop_( |
| 206 RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()), |
| 207 context_provider_( |
| 208 RenderThreadImpl::current()->SharedMainThreadContextProvider()), |
| 209 num_pending_decodes_(0), |
| 210 flushing_(false), |
| 211 resetting_(false), |
| 212 main_message_loop_(base::MessageLoopProxy::current()) { |
| 213 DCHECK(host_); |
| 214 DCHECK(main_message_loop_); |
| 215 DCHECK(media_message_loop_); |
| 216 DCHECK(context_provider_); |
| 217 } |
| 218 |
| 219 SoftwareDecoder::~SoftwareDecoder() { |
| 220 DCHECK(RenderThreadImpl::current()); |
| 221 while (!pending_frames_.empty()) { |
| 222 delete pending_frames_.front(); |
| 223 pending_frames_.pop(); |
| 224 } |
| 225 DeleteTextures(); |
| 226 FlushCommandBuffer(); |
| 227 } |
| 228 |
| 229 void SoftwareDecoder::Initialize(media::VideoCodecProfile profile) { |
| 230 DCHECK(RenderThreadImpl::current()); |
| 231 DCHECK(!decoder_); |
| 232 media::VideoCodec codec = media::kUnknownVideoCodec; |
| 233 if (profile <= media::H264PROFILE_MAX) |
| 234 codec = media::kCodecH264; |
| 235 else if (profile <= media::VP8PROFILE_MAX) |
| 236 codec = media::kCodecVP8; |
| 237 DCHECK_NE(codec, media::kUnknownVideoCodec); |
| 238 |
| 239 media::VideoDecoderConfig config( |
| 240 codec, |
| 241 profile, |
| 242 media::VideoFrame::YV12, |
| 243 gfx::Size(32, 24), // Small sizes that won't fail. |
| 244 gfx::Rect(32, 24), |
| 245 gfx::Size(32, 24), |
| 246 NULL /* extra_data */, |
| 247 0 /* extra_data_size */, |
| 248 false /* decryption */); |
| 249 |
| 250 decoder_.reset(new media::FFmpegVideoDecoder(media_message_loop_)); |
| 251 |
| 252 media_message_loop_->PostTask( |
| 253 FROM_HERE, |
| 254 base::Bind(&SoftwareDecoder::InitializeOnMediaThread, |
| 255 base::Unretained(this), |
| 256 config)); |
| 257 } |
| 258 |
| 259 void SoftwareDecoder::Decode( |
| 260 uint32_t decode_id, |
| 261 const scoped_refptr<media::DecoderBuffer>& buffer) { |
| 262 DCHECK(RenderThreadImpl::current()); |
| 263 DCHECK(decoder_); |
| 264 DCHECK(!resetting_ && !flushing_); |
| 265 |
| 266 num_pending_decodes_++; |
| 267 |
| 268 media_message_loop_->PostTask( |
| 269 FROM_HERE, |
| 270 base::Bind(&SoftwareDecoder::ReceiveBufferOnMediaThread, |
| 271 base::Unretained(this), |
| 272 decode_id, |
| 273 buffer)); |
| 274 } |
| 275 |
| 276 void SoftwareDecoder::AssignTextures( |
| 277 const std::vector<uint32_t>& plugin_texture_ids) { |
| 278 DCHECK(RenderThreadImpl::current()); |
| 279 DCHECK(decoder_); |
| 280 DCHECK(plugin_texture_ids.size()); |
| 281 DCHECK_EQ(plugin_texture_ids.size(), pending_texture_mailboxes_.size()); |
| 282 uint32_t num_textures = static_cast<GLuint>(plugin_texture_ids.size()); |
| 283 std::vector<uint32_t> local_ids(num_textures); |
| 284 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); |
| 285 gles2->GenTextures(num_textures, &local_ids.front()); |
| 286 for (uint32_t i = 0; i < num_textures; i++) { |
| 287 gles2->ActiveTexture(GL_TEXTURE0); |
| 288 gles2->BindTexture(GL_TEXTURE_2D, local_ids[i]); |
| 289 gles2->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, |
| 290 pending_texture_mailboxes_[i].name); |
| 291 // Map the plugin texture id to the local texture id. |
| 292 shared_textures_.insert( |
| 293 std::make_pair(plugin_texture_ids[i], local_ids[i])); |
| 294 } |
| 295 pending_texture_mailboxes_.clear(); |
| 296 plugin_texture_ids_ = plugin_texture_ids; |
| 297 SendPicturesOnMainThread(); |
| 298 } |
| 299 |
| 300 void SoftwareDecoder::RecycleTexture(uint32_t plugin_texture_id) { |
| 301 DCHECK(RenderThreadImpl::current()); |
| 302 DCHECK(decoder_); |
| 303 // Make sure it is still a valid texture. |
| 304 SharedTextureMap::iterator it = shared_textures_.find(plugin_texture_id); |
| 305 if (it != shared_textures_.end()) { |
| 306 plugin_texture_ids_.push_back(plugin_texture_id); |
| 307 } |
| 308 SendPicturesOnMainThread(); |
| 309 } |
| 310 |
| 311 void SoftwareDecoder::Flush() { |
| 312 DCHECK(RenderThreadImpl::current()); |
| 313 DCHECK(decoder_); |
| 314 DCHECK(!resetting_ && !flushing_); |
| 315 flushing_ = true; |
| 316 } |
| 317 |
| 318 void SoftwareDecoder::Reset() { |
| 319 DCHECK(RenderThreadImpl::current()); |
| 320 DCHECK(decoder_); |
| 321 DCHECK(!resetting_ && !flushing_); |
| 322 printf("SoftwareDecoder::Reset\n"); |
| 323 resetting_ = true; |
| 324 media_message_loop_->PostTask( |
| 325 FROM_HERE, |
| 326 base::Bind(&SoftwareDecoder::DoResetOnMediaThread, |
| 327 base::Unretained(this))); |
| 328 } |
| 329 |
| 330 void SoftwareDecoder::Destroy() { |
| 331 DCHECK(RenderThreadImpl::current()); |
| 332 DCHECK(decoder_); |
| 333 DCHECK(host_); |
| 334 host_ = NULL; |
| 335 media_message_loop_->PostTask( |
| 336 FROM_HERE, |
| 337 base::Bind(&SoftwareDecoder::DestroyOnMediaThread, |
| 338 base::Unretained(this))); |
| 339 } |
| 340 |
| 341 void SoftwareDecoder::InitializeOnMediaThread( |
| 342 media::VideoDecoderConfig config) { |
| 343 DCHECK(decoder_); |
| 344 decoder_->Initialize(config, |
| 345 true /* low_delay */, |
| 346 base::Bind(&SoftwareDecoder::PipelineStatusOnMediaThread, |
| 347 base::Unretained(this))); |
| 348 } |
| 349 |
| 350 void SoftwareDecoder::PipelineStatusOnMediaThread( |
| 351 media::PipelineStatus status) { |
| 352 if (!host_) |
| 353 return; |
| 354 main_message_loop_->PostTask( |
| 355 FROM_HERE, |
| 356 base::Bind(&SoftwareDecoder::PipelineStatusOnMainThread, |
| 357 base::Unretained(this), |
| 358 status)); |
| 359 } |
| 360 |
| 361 void SoftwareDecoder::PipelineStatusOnMainThread(media::PipelineStatus status) { |
| 362 if (!host_) |
| 363 return; |
| 364 host_->OnInitializeComplete(status); |
| 365 } |
| 366 |
| 367 void SoftwareDecoder::ReceiveBufferOnMediaThread( |
| 368 uint32_t decode_id, |
| 369 scoped_refptr<media::DecoderBuffer> buffer) { |
| 370 bool decoder_busy = !pending_decodes_.empty(); |
| 371 pending_decodes_.push(PendingDecode(decode_id, buffer)); |
| 372 if (!decoder_busy) |
| 373 DecodeOnMediaThread(); |
| 374 } |
| 375 |
| 376 void SoftwareDecoder::DecodeOnMediaThread() { |
| 377 DCHECK(!pending_decodes_.empty()); |
| 378 PendingDecode& next_decode = pending_decodes_.front(); |
| 379 decoder_->Decode(next_decode.buffer, |
| 380 base::Bind(&SoftwareDecoder::ConvertFrameOnMediaThread, |
| 381 base::Unretained(this), |
| 382 next_decode.decode_id)); |
| 383 pending_decodes_.pop(); |
| 384 } |
| 385 |
| 386 void SoftwareDecoder::ConvertFrameOnMediaThread( |
| 387 uint32_t decode_id, |
| 388 media::VideoDecoder::Status status, |
| 389 const scoped_refptr<media::VideoFrame>& frame) { |
| 390 if (!host_) |
| 391 return; |
| 392 scoped_ptr<PendingFrame> pending_frame( |
| 393 new PendingFrame(decode_id, gfx::Size())); |
| 394 if (frame) { |
| 395 pending_frame->size = frame->coded_size(); |
| 396 pending_frame->pixels.resize(frame->coded_size().width() * |
| 397 frame->coded_size().height() * 4); |
| 398 // Convert the decoded frame to ARGB pixels. |
| 399 libyuv::I420ToARGB(frame->data(media::VideoFrame::kYPlane), |
| 400 frame->stride(media::VideoFrame::kYPlane), |
| 401 frame->data(media::VideoFrame::kUPlane), |
| 402 frame->stride(media::VideoFrame::kUPlane), |
| 403 frame->data(media::VideoFrame::kVPlane), |
| 404 frame->stride(media::VideoFrame::kVPlane), |
| 405 &pending_frame->pixels.front(), |
| 406 frame->coded_size().width() * 4, |
| 407 frame->coded_size().width(), |
| 408 frame->coded_size().height()); |
| 409 } |
| 410 |
| 411 main_message_loop_->PostTask( |
| 412 FROM_HERE, |
| 413 base::Bind(&SoftwareDecoder::ReceiveFrameOnMainThread, |
| 414 base::Unretained(this), |
| 415 status, |
| 416 base::Passed(&pending_frame))); |
| 417 |
| 418 if (!pending_decodes_.empty()) |
| 419 DecodeOnMediaThread(); |
| 420 } |
| 421 |
| 422 void SoftwareDecoder::ReceiveFrameOnMainThread( |
| 423 media::VideoDecoder::Status status, |
| 424 scoped_ptr<PendingFrame> frame) { |
| 425 DCHECK(RenderThreadImpl::current()); |
| 426 if (!host_) |
| 427 return; |
| 428 |
| 429 num_pending_decodes_--; |
| 430 |
| 431 if (frame->pixels.size()) { |
| 432 if (texture_size_ != frame->size) { |
| 433 // If the size has changed, dismiss all textures. TODO what if some are |
| 434 // in use? Dismiss free ones, mark busy ones, and wait for recycle? |
| 435 for (size_t i = 0; i < plugin_texture_ids_.size(); i++) |
| 436 host_->DismissPictureBuffer(plugin_texture_ids_[i]); |
| 437 plugin_texture_ids_.clear(); |
| 438 |
| 439 DeleteTextures(); |
| 440 |
| 441 DCHECK(pending_texture_mailboxes_.empty()); |
| 442 const uint32_t num_textures = 8; |
| 443 for (uint32_t i = 0; i < num_textures; i++) |
| 444 pending_texture_mailboxes_.push_back(gpu::Mailbox::Generate()); |
| 445 |
| 446 host_->RequestTextures( |
| 447 num_textures, frame->size, GL_TEXTURE_2D, pending_texture_mailboxes_); |
| 448 texture_size_ = frame->size; |
| 449 } |
| 450 |
| 451 pending_frames_.push(frame.release()); |
| 452 SendPicturesOnMainThread(); |
| 453 } else { |
| 454 host_->NotifyEndOfBitstreamBuffer(frame->decode_id); |
| 455 } |
| 456 } |
| 457 |
| 458 void SoftwareDecoder::SendPicturesOnMainThread() { |
| 459 DCHECK(RenderThreadImpl::current()); |
| 460 if (!host_) |
| 461 return; |
| 462 while (!pending_frames_.empty() && !plugin_texture_ids_.empty()) { |
| 463 scoped_ptr<PendingFrame> frame(pending_frames_.front()); |
| 464 pending_frames_.pop(); |
| 465 |
| 466 uint32_t plugin_texture_id = plugin_texture_ids_.back(); |
| 467 plugin_texture_ids_.pop_back(); |
| 468 |
| 469 uint32_t local_id = shared_textures_[plugin_texture_id]; |
| 470 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); |
| 471 gles2->ActiveTexture(GL_TEXTURE0); |
| 472 gles2->BindTexture(GL_TEXTURE_2D, local_id); |
| 473 gles2->TexImage2D(GL_TEXTURE_2D, |
| 474 0, |
| 475 GL_RGBA, |
| 476 texture_size_.width(), |
| 477 texture_size_.height(), |
| 478 0, |
| 479 GL_RGBA, |
| 480 GL_UNSIGNED_BYTE, |
| 481 &frame->pixels.front()); |
| 482 |
| 483 host_->NotifyEndOfBitstreamBuffer(frame->decode_id); |
| 484 host_->PictureReady(media::Picture(plugin_texture_id, frame->decode_id)); |
| 485 } |
| 486 |
| 487 FlushCommandBuffer(); |
| 488 |
| 489 if (flushing_ && !num_pending_decodes_ && pending_frames_.empty()) { |
| 490 flushing_ = false; |
| 491 host_->NotifyFlushDone(); |
| 492 } |
| 493 } |
| 494 |
| 495 void SoftwareDecoder::DoResetOnMediaThread() { |
| 496 printf("SoftwareDecoder::DoResetOnMediaThread\n"); |
| 497 decoder_->Reset(base::Bind(&SoftwareDecoder::ResetCompleteOnMediaThread, |
| 498 base::Unretained(this))); |
| 499 } |
| 500 |
| 501 void SoftwareDecoder::ResetCompleteOnMediaThread() { |
| 502 printf("SoftwareDecoder::ResetCompleteOnMediaThread\n"); |
| 503 // Cancel all remaining decodes, and notify the host so it can free the shm |
| 504 // buffers. We'll clear pending frames on the main thread. |
| 505 while (!pending_decodes_.empty()) { |
| 506 PendingDecode& next_decode = pending_decodes_.front(); |
| 507 scoped_ptr<PendingFrame> pending_frame( |
| 508 new PendingFrame(next_decode.decode_id, gfx::Size())); |
| 509 main_message_loop_->PostTask( |
| 510 FROM_HERE, |
| 511 base::Bind(&SoftwareDecoder::ReceiveFrameOnMainThread, |
| 512 base::Unretained(this), |
| 513 media::VideoDecoder::kAborted, |
| 514 base::Passed(&pending_frame))); |
| 515 pending_decodes_.pop(); |
| 516 } |
| 517 main_message_loop_->PostTask( |
| 518 FROM_HERE, |
| 519 base::Bind(&SoftwareDecoder::ResetCompleteOnMainThread, |
| 520 base::Unretained(this))); |
| 521 } |
| 522 |
| 523 void SoftwareDecoder::ResetCompleteOnMainThread() { |
| 524 if (!host_) |
| 525 return; |
| 526 printf("SoftwareDecoder::ResetCompleteOnMainThread\n"); |
| 527 |
| 528 while (!pending_frames_.empty()) { |
| 529 scoped_ptr<PendingFrame> frame(pending_frames_.front()); |
| 530 host_->NotifyEndOfBitstreamBuffer(frame->decode_id); |
| 531 pending_frames_.pop(); |
| 532 } |
| 533 |
| 534 resetting_ = false; |
| 535 host_->NotifyResetDone(); |
| 536 } |
| 537 |
| 538 void SoftwareDecoder::DestroyOnMediaThread() { |
| 539 DCHECK(decoder_); |
| 540 decoder_->Stop(); |
| 541 // All callbacks have been called on the media thread, and thus all tasks |
| 542 // posted for the main thread. This is our last task for the main thread. |
| 543 main_message_loop_->PostTask(FROM_HERE, |
| 544 base::Bind(&SoftwareDecoder::DestroyOnMainThread, |
| 545 base::Unretained(this))); |
| 546 } |
| 547 |
| 548 void SoftwareDecoder::DestroyOnMainThread() { |
| 549 DCHECK(RenderThreadImpl::current()); |
| 550 DCHECK(!host_); |
| 551 delete this; |
| 552 } |
| 553 |
| 554 void SoftwareDecoder::DeleteTextures() { |
| 555 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); |
| 556 SharedTextureMap::iterator it = shared_textures_.begin(); |
| 557 for (; it != shared_textures_.end(); ++it) |
| 558 gles2->DeleteTextures(1, &it->second); |
| 559 shared_textures_.clear(); |
| 560 } |
| 561 |
| 562 void SoftwareDecoder::FlushCommandBuffer() { |
| 563 DCHECK(RenderThreadImpl::current()); |
| 564 context_provider_->ContextGL()->Flush(); |
| 565 } |
| 566 |
| 68 PepperVideoDecoderHost::PendingDecode::PendingDecode( | 567 PepperVideoDecoderHost::PendingDecode::PendingDecode( |
| 69 uint32_t shm_id, | 568 uint32_t shm_id, |
| 70 const ppapi::host::ReplyMessageContext& reply_context) | 569 const ppapi::host::ReplyMessageContext& reply_context) |
| 71 : shm_id(shm_id), reply_context(reply_context) { | 570 : shm_id(shm_id), reply_context(reply_context) { |
| 72 } | 571 } |
| 73 | 572 |
| 74 PepperVideoDecoderHost::PendingDecode::~PendingDecode() { | 573 PepperVideoDecoderHost::PendingDecode::~PendingDecode() { |
| 75 } | 574 } |
| 76 | 575 |
| 77 PepperVideoDecoderHost::PepperVideoDecoderHost(RendererPpapiHost* host, | 576 PepperVideoDecoderHost::PepperVideoDecoderHost(RendererPpapiHost* host, |
| 78 PP_Instance instance, | 577 PP_Instance instance, |
| 79 PP_Resource resource) | 578 PP_Resource resource) |
| 80 : ResourceHost(host->GetPpapiHost(), instance, resource), | 579 : ResourceHost(host->GetPpapiHost(), instance, resource), |
| 81 renderer_ppapi_host_(host), | 580 renderer_ppapi_host_(host), |
| 82 initialized_(false) { | 581 initialized_(false) { |
| 83 } | 582 } |
| 84 | 583 |
| 85 PepperVideoDecoderHost::~PepperVideoDecoderHost() { | 584 PepperVideoDecoderHost::~PepperVideoDecoderHost() { |
| 585 // TODO DefaultDeleter. |
| 586 if (software_decoder_) |
| 587 software_decoder_.release()->Destroy(); |
| 86 } | 588 } |
| 87 | 589 |
| 88 int32_t PepperVideoDecoderHost::OnResourceMessageReceived( | 590 int32_t PepperVideoDecoderHost::OnResourceMessageReceived( |
| 89 const IPC::Message& msg, | 591 const IPC::Message& msg, |
| 90 ppapi::host::HostMessageContext* context) { | 592 ppapi::host::HostMessageContext* context) { |
| 91 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoDecoderHost, msg) | 593 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoDecoderHost, msg) |
| 92 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Initialize, | 594 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Initialize, |
| 93 OnHostMsgInitialize) | 595 OnHostMsgInitialize) |
| 94 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_GetShm, | 596 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_GetShm, |
| 95 OnHostMsgGetShm) | 597 OnHostMsgGetShm) |
| 96 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Decode, | 598 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Decode, |
| 97 OnHostMsgDecode) | 599 OnHostMsgDecode) |
| 98 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_AssignTextures, | 600 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_AssignTextures, |
| 99 OnHostMsgAssignTextures) | 601 OnHostMsgAssignTextures) |
| 100 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_RecyclePicture, | 602 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_RecyclePicture, |
| 101 OnHostMsgRecyclePicture) | 603 OnHostMsgRecyclePicture) |
| 102 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Flush, | 604 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Flush, |
| 103 OnHostMsgFlush) | 605 OnHostMsgFlush) |
| 104 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Reset, | 606 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Reset, |
| 105 OnHostMsgReset) | 607 OnHostMsgReset) |
| 106 PPAPI_END_MESSAGE_MAP() | 608 PPAPI_END_MESSAGE_MAP() |
| 107 return PP_ERROR_FAILED; | 609 return PP_ERROR_FAILED; |
| 108 } | 610 } |
| 109 | 611 |
| 110 int32_t PepperVideoDecoderHost::OnHostMsgInitialize( | 612 int32_t PepperVideoDecoderHost::OnHostMsgInitialize( |
| 111 ppapi::host::HostMessageContext* context, | 613 ppapi::host::HostMessageContext* context, |
| 112 const ppapi::HostResource& graphics_context, | 614 const ppapi::HostResource& graphics_context, |
| 113 PP_VideoProfile profile, | 615 PP_VideoProfile profile, |
| 114 bool allow_software_fallback) { | 616 bool allow_software_fallback) { |
| 115 if (initialized_) | 617 if (initialized_) |
| 116 return PP_ERROR_FAILED; | 618 return PP_ERROR_FAILED; |
| 117 | 619 |
| 118 EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics( | 620 EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics( |
| 119 graphics_context.host_resource(), true); | 621 graphics_context.host_resource(), true); |
| 120 if (enter_graphics.failed()) | 622 if (enter_graphics.failed()) |
| 121 return PP_ERROR_FAILED; | 623 return PP_ERROR_FAILED; |
| 122 graphics3d_ = static_cast<PPB_Graphics3D_Impl*>(enter_graphics.object()); | 624 PPB_Graphics3D_Impl* graphics3d = |
| 625 static_cast<PPB_Graphics3D_Impl*>(enter_graphics.object()); |
| 123 | 626 |
| 124 int command_buffer_route_id = graphics3d_->GetCommandBufferRouteId(); | 627 int command_buffer_route_id = graphics3d->GetCommandBufferRouteId(); |
| 125 if (!command_buffer_route_id) | 628 if (!command_buffer_route_id) |
| 126 return PP_ERROR_FAILED; | 629 return PP_ERROR_FAILED; |
| 127 | 630 |
| 128 media::VideoCodecProfile media_profile = PepperToMediaVideoProfile(profile); | 631 media::VideoCodecProfile media_profile = PepperToMediaVideoProfile(profile); |
| 129 | 632 |
| 130 // This is not synchronous, but subsequent IPC messages will be buffered, so | 633 // This is not synchronous, but subsequent IPC messages will be buffered, so |
| 131 // it is okay to immediately send IPC messages through the returned channel. | 634 // it is okay to immediately send IPC messages through the returned channel. |
| 132 GpuChannelHost* channel = graphics3d_->channel(); | 635 GpuChannelHost* channel = graphics3d->channel(); |
| 133 DCHECK(channel); | 636 DCHECK(channel); |
| 134 decoder_ = channel->CreateVideoDecoder(command_buffer_route_id); | 637 decoder_ = channel->CreateVideoDecoder(command_buffer_route_id); |
| 135 if (decoder_ && decoder_->Initialize(media_profile, this)) { | 638 if (decoder_ && decoder_->Initialize(media_profile, this)) { |
| 136 initialized_ = true; | 639 initialized_ = true; |
| 137 return PP_OK; | 640 return PP_OK; |
| 138 } | 641 } |
| 139 decoder_.reset(); | 642 decoder_.reset(); |
| 140 | 643 |
| 141 // TODO(bbudge) Implement software fallback. | 644 if (!allow_software_fallback) |
| 142 return PP_ERROR_NOTSUPPORTED; | 645 return PP_ERROR_NOTSUPPORTED; |
| 646 |
| 647 software_decoder_.reset(new SoftwareDecoder(this)); |
| 648 initialize_reply_context_ = context->MakeReplyMessageContext(); |
| 649 software_decoder_->Initialize(media_profile); |
| 650 |
| 651 return PP_OK_COMPLETIONPENDING; |
| 143 } | 652 } |
| 144 | 653 |
| 145 int32_t PepperVideoDecoderHost::OnHostMsgGetShm( | 654 int32_t PepperVideoDecoderHost::OnHostMsgGetShm( |
| 146 ppapi::host::HostMessageContext* context, | 655 ppapi::host::HostMessageContext* context, |
| 147 uint32_t shm_id, | 656 uint32_t shm_id, |
| 148 uint32_t shm_size) { | 657 uint32_t shm_size) { |
| 149 if (!initialized_) | 658 if (!initialized_) |
| 150 return PP_ERROR_FAILED; | 659 return PP_ERROR_FAILED; |
| 151 | 660 |
| 152 // Make the buffers larger since we hope to reuse them. | 661 // Make the buffers larger since we hope to reuse them. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 return PP_OK_COMPLETIONPENDING; | 710 return PP_OK_COMPLETIONPENDING; |
| 202 } | 711 } |
| 203 | 712 |
| 204 int32_t PepperVideoDecoderHost::OnHostMsgDecode( | 713 int32_t PepperVideoDecoderHost::OnHostMsgDecode( |
| 205 ppapi::host::HostMessageContext* context, | 714 ppapi::host::HostMessageContext* context, |
| 206 uint32_t shm_id, | 715 uint32_t shm_id, |
| 207 uint32_t size, | 716 uint32_t size, |
| 208 int32_t decode_id) { | 717 int32_t decode_id) { |
| 209 if (!initialized_) | 718 if (!initialized_) |
| 210 return PP_ERROR_FAILED; | 719 return PP_ERROR_FAILED; |
| 211 DCHECK(decoder_); | 720 DCHECK(decoder_ || software_decoder_); |
| 212 // |shm_id| is just an index into shm_buffers_. Make sure it's in range. | 721 // |shm_id| is just an index into shm_buffers_. Make sure it's in range. |
| 213 if (static_cast<size_t>(shm_id) >= shm_buffers_.size()) | 722 if (static_cast<size_t>(shm_id) >= shm_buffers_.size()) |
| 214 return PP_ERROR_FAILED; | 723 return PP_ERROR_FAILED; |
| 215 // Reject an attempt to pass a busy buffer to the decoder again. | 724 // Reject an attempt to pass a busy buffer to the decoder again. |
| 216 if (shm_buffer_busy_[shm_id]) | 725 if (shm_buffer_busy_[shm_id]) |
| 217 return PP_ERROR_FAILED; | 726 return PP_ERROR_FAILED; |
| 218 // Reject non-unique decode_id values. | 727 // Reject non-unique decode_id values. |
| 219 if (pending_decodes_.find(decode_id) != pending_decodes_.end()) | 728 if (pending_decodes_.find(decode_id) != pending_decodes_.end()) |
| 220 return PP_ERROR_FAILED; | 729 return PP_ERROR_FAILED; |
| 221 | 730 |
| 222 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) | 731 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) |
| 223 return PP_ERROR_FAILED; | 732 return PP_ERROR_FAILED; |
| 224 | 733 |
| 225 pending_decodes_.insert(std::make_pair( | 734 pending_decodes_.insert(std::make_pair( |
| 226 decode_id, PendingDecode(shm_id, context->MakeReplyMessageContext()))); | 735 decode_id, PendingDecode(shm_id, context->MakeReplyMessageContext()))); |
| 227 | 736 |
| 228 shm_buffer_busy_[shm_id] = true; | 737 shm_buffer_busy_[shm_id] = true; |
| 229 decoder_->Decode( | 738 base::SharedMemory* shm = shm_buffers_[shm_id]; |
| 230 media::BitstreamBuffer(decode_id, shm_buffers_[shm_id]->handle(), size)); | 739 if (decoder_) { |
| 740 decoder_->Decode(media::BitstreamBuffer(decode_id, shm->handle(), size)); |
| 741 } else { |
| 742 software_decoder_->Decode(decode_id, |
| 743 media::DecoderBuffer::CopyFrom( |
| 744 static_cast<uint8_t*>(shm->memory()), size)); |
| 745 } |
| 231 | 746 |
| 232 return PP_OK_COMPLETIONPENDING; | 747 return PP_OK_COMPLETIONPENDING; |
| 233 } | 748 } |
| 234 | 749 |
| 235 int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures( | 750 int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures( |
| 236 ppapi::host::HostMessageContext* context, | 751 ppapi::host::HostMessageContext* context, |
| 237 const PP_Size& size, | 752 const PP_Size& size, |
| 238 const std::vector<uint32_t>& texture_ids) { | 753 const std::vector<uint32_t>& texture_ids) { |
| 239 if (!initialized_) | 754 if (!initialized_) |
| 240 return PP_ERROR_FAILED; | 755 return PP_ERROR_FAILED; |
| 241 DCHECK(decoder_); | 756 DCHECK(decoder_ || software_decoder_); |
| 242 | 757 |
| 243 std::vector<media::PictureBuffer> picture_buffers; | 758 if (decoder_) { |
| 244 for (uint32 i = 0; i < texture_ids.size(); i++) { | 759 std::vector<media::PictureBuffer> picture_buffers; |
| 245 media::PictureBuffer buffer( | 760 for (uint32 i = 0; i < texture_ids.size(); i++) { |
| 246 texture_ids[i], // Use the texture_id to identify the buffer. | 761 media::PictureBuffer buffer( |
| 247 gfx::Size(size.width, size.height), | 762 texture_ids[i], // Use the texture_id to identify the buffer. |
| 248 texture_ids[i]); | 763 gfx::Size(size.width, size.height), |
| 249 picture_buffers.push_back(buffer); | 764 texture_ids[i]); |
| 765 picture_buffers.push_back(buffer); |
| 766 } |
| 767 decoder_->AssignPictureBuffers(picture_buffers); |
| 768 } else { |
| 769 software_decoder_->AssignTextures(texture_ids); |
| 250 } | 770 } |
| 251 decoder_->AssignPictureBuffers(picture_buffers); | |
| 252 return PP_OK; | 771 return PP_OK; |
| 253 } | 772 } |
| 254 | 773 |
| 255 int32_t PepperVideoDecoderHost::OnHostMsgRecyclePicture( | 774 int32_t PepperVideoDecoderHost::OnHostMsgRecyclePicture( |
| 256 ppapi::host::HostMessageContext* context, | 775 ppapi::host::HostMessageContext* context, |
| 257 uint32_t texture_id) { | 776 uint32_t texture_id) { |
| 258 if (!initialized_) | 777 if (!initialized_) |
| 259 return PP_ERROR_FAILED; | 778 return PP_ERROR_FAILED; |
| 260 DCHECK(decoder_); | 779 DCHECK(decoder_ || software_decoder_); |
| 261 if (reset_reply_context_.is_valid()) | 780 if (reset_reply_context_.is_valid()) |
| 262 return PP_ERROR_FAILED; | 781 return PP_ERROR_FAILED; |
| 263 | 782 if (decoder_) { |
| 264 decoder_->ReusePictureBuffer(texture_id); | 783 decoder_->ReusePictureBuffer(texture_id); |
| 784 } else { |
| 785 software_decoder_->RecycleTexture(texture_id); |
| 786 } |
| 265 | 787 |
| 266 return PP_OK; | 788 return PP_OK; |
| 267 } | 789 } |
| 268 | 790 |
| 269 int32_t PepperVideoDecoderHost::OnHostMsgFlush( | 791 int32_t PepperVideoDecoderHost::OnHostMsgFlush( |
| 270 ppapi::host::HostMessageContext* context) { | 792 ppapi::host::HostMessageContext* context) { |
| 271 if (!initialized_) | 793 if (!initialized_) |
| 272 return PP_ERROR_FAILED; | 794 return PP_ERROR_FAILED; |
| 273 DCHECK(decoder_); | 795 DCHECK(decoder_ || software_decoder_); |
| 274 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) | 796 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) |
| 275 return PP_ERROR_FAILED; | 797 return PP_ERROR_FAILED; |
| 276 | 798 |
| 277 flush_reply_context_ = context->MakeReplyMessageContext(); | 799 flush_reply_context_ = context->MakeReplyMessageContext(); |
| 278 decoder_->Flush(); | 800 if (decoder_) |
| 801 decoder_->Flush(); |
| 802 else |
| 803 software_decoder_->Flush(); |
| 279 | 804 |
| 280 return PP_OK_COMPLETIONPENDING; | 805 return PP_OK_COMPLETIONPENDING; |
| 281 } | 806 } |
| 282 | 807 |
| 283 int32_t PepperVideoDecoderHost::OnHostMsgReset( | 808 int32_t PepperVideoDecoderHost::OnHostMsgReset( |
| 284 ppapi::host::HostMessageContext* context) { | 809 ppapi::host::HostMessageContext* context) { |
| 285 if (!initialized_) | 810 if (!initialized_) |
| 286 return PP_ERROR_FAILED; | 811 return PP_ERROR_FAILED; |
| 287 DCHECK(decoder_); | 812 DCHECK(decoder_ || software_decoder_); |
| 288 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) | 813 if (flush_reply_context_.is_valid() || reset_reply_context_.is_valid()) |
| 289 return PP_ERROR_FAILED; | 814 return PP_ERROR_FAILED; |
| 815 printf("PepperVideoDecoderHost::OnHostMsgReset\n"); |
| 290 | 816 |
| 291 reset_reply_context_ = context->MakeReplyMessageContext(); | 817 reset_reply_context_ = context->MakeReplyMessageContext(); |
| 292 decoder_->Reset(); | 818 if (decoder_) |
| 819 decoder_->Reset(); |
| 820 else |
| 821 software_decoder_->Reset(); |
| 293 | 822 |
| 294 return PP_OK_COMPLETIONPENDING; | 823 return PP_OK_COMPLETIONPENDING; |
| 295 } | 824 } |
| 296 | 825 |
| 297 void PepperVideoDecoderHost::ProvidePictureBuffers( | 826 void PepperVideoDecoderHost::ProvidePictureBuffers( |
| 298 uint32 requested_num_of_buffers, | 827 uint32 requested_num_of_buffers, |
| 299 const gfx::Size& dimensions, | 828 const gfx::Size& dimensions, |
| 300 uint32 texture_target) { | 829 uint32 texture_target) { |
| 301 DCHECK(RenderThreadImpl::current()); | 830 RequestTextures(requested_num_of_buffers, |
| 302 host()->SendUnsolicitedReply( | 831 dimensions, |
| 303 pp_resource(), | 832 texture_target, |
| 304 PpapiPluginMsg_VideoDecoder_RequestTextures( | 833 std::vector<gpu::Mailbox>()); |
| 305 requested_num_of_buffers, | |
| 306 PP_MakeSize(dimensions.width(), dimensions.height()), | |
| 307 texture_target)); | |
| 308 } | 834 } |
| 309 | 835 |
| 310 void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) { | 836 void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) { |
| 311 DCHECK(RenderThreadImpl::current()); | 837 DCHECK(RenderThreadImpl::current()); |
| 312 host()->SendUnsolicitedReply( | 838 host()->SendUnsolicitedReply( |
| 313 pp_resource(), | 839 pp_resource(), |
| 314 PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(), | 840 PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(), |
| 315 picture.picture_buffer_id())); | 841 picture.picture_buffer_id())); |
| 316 } | 842 } |
| 317 | 843 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 336 case media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM: | 862 case media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM: |
| 337 pp_error = PP_ERROR_RESOURCE_FAILED; | 863 pp_error = PP_ERROR_RESOURCE_FAILED; |
| 338 break; | 864 break; |
| 339 // No default case, to catch unhandled enum values. | 865 // No default case, to catch unhandled enum values. |
| 340 } | 866 } |
| 341 host()->SendUnsolicitedReply( | 867 host()->SendUnsolicitedReply( |
| 342 pp_resource(), PpapiPluginMsg_VideoDecoder_NotifyError(pp_error)); | 868 pp_resource(), PpapiPluginMsg_VideoDecoder_NotifyError(pp_error)); |
| 343 } | 869 } |
| 344 | 870 |
| 345 void PepperVideoDecoderHost::NotifyResetDone() { | 871 void PepperVideoDecoderHost::NotifyResetDone() { |
| 872 printf("PepperVideoDecoderHost::NotifyResetDone:pending=%i\n", (int)pending_de
codes_.size()); |
| 346 DCHECK(RenderThreadImpl::current()); | 873 DCHECK(RenderThreadImpl::current()); |
| 347 host()->SendReply(reset_reply_context_, | 874 host()->SendReply(reset_reply_context_, |
| 348 PpapiPluginMsg_VideoDecoder_ResetReply()); | 875 PpapiPluginMsg_VideoDecoder_ResetReply()); |
| 349 reset_reply_context_ = ppapi::host::ReplyMessageContext(); | 876 reset_reply_context_ = ppapi::host::ReplyMessageContext(); |
| 350 } | 877 } |
| 351 | 878 |
| 352 void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer( | 879 void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer( |
| 353 int32 bitstream_buffer_id) { | 880 int32 bitstream_buffer_id) { |
| 354 DCHECK(RenderThreadImpl::current()); | 881 DCHECK(RenderThreadImpl::current()); |
| 355 PendingDecodeMap::iterator it = pending_decodes_.find(bitstream_buffer_id); | 882 PendingDecodeMap::iterator it = pending_decodes_.find(bitstream_buffer_id); |
| 356 if (it == pending_decodes_.end()) { | 883 if (it == pending_decodes_.end()) { |
| 357 NOTREACHED(); | 884 NOTREACHED(); |
| 358 return; | 885 return; |
| 359 } | 886 } |
| 360 const PendingDecode& pending_decode = it->second; | 887 const PendingDecode& pending_decode = it->second; |
| 361 host()->SendReply( | 888 host()->SendReply( |
| 362 pending_decode.reply_context, | 889 pending_decode.reply_context, |
| 363 PpapiPluginMsg_VideoDecoder_DecodeReply(pending_decode.shm_id)); | 890 PpapiPluginMsg_VideoDecoder_DecodeReply(pending_decode.shm_id)); |
| 364 shm_buffer_busy_[pending_decode.shm_id] = false; | 891 shm_buffer_busy_[pending_decode.shm_id] = false; |
| 365 pending_decodes_.erase(it); | 892 pending_decodes_.erase(it); |
| 366 } | 893 } |
| 367 | 894 |
| 368 void PepperVideoDecoderHost::NotifyFlushDone() { | 895 void PepperVideoDecoderHost::NotifyFlushDone() { |
| 369 DCHECK(RenderThreadImpl::current()); | 896 DCHECK(RenderThreadImpl::current()); |
| 370 host()->SendReply(flush_reply_context_, | 897 host()->SendReply(flush_reply_context_, |
| 371 PpapiPluginMsg_VideoDecoder_FlushReply()); | 898 PpapiPluginMsg_VideoDecoder_FlushReply()); |
| 372 flush_reply_context_ = ppapi::host::ReplyMessageContext(); | 899 flush_reply_context_ = ppapi::host::ReplyMessageContext(); |
| 373 } | 900 } |
| 374 | 901 |
| 902 void PepperVideoDecoderHost::OnInitializeComplete( |
| 903 media::PipelineStatus status) { |
| 904 if (!initialized_) { |
| 905 initialized_ = true; |
| 906 int32_t result = MediaPipelineStatusToPepper(status); |
| 907 initialize_reply_context_.params.set_result(result); |
| 908 host()->SendReply(initialize_reply_context_, |
| 909 PpapiPluginMsg_VideoDecoder_InitializeReply()); |
| 910 } |
| 911 } |
| 912 |
| 913 void PepperVideoDecoderHost::RequestTextures( |
| 914 uint32 requested_num_of_buffers, |
| 915 const gfx::Size& dimensions, |
| 916 uint32 texture_target, |
| 917 const std::vector<gpu::Mailbox>& mailboxes) { |
| 918 DCHECK(RenderThreadImpl::current()); |
| 919 host()->SendUnsolicitedReply( |
| 920 pp_resource(), |
| 921 PpapiPluginMsg_VideoDecoder_RequestTextures( |
| 922 requested_num_of_buffers, |
| 923 PP_MakeSize(dimensions.width(), dimensions.height()), |
| 924 texture_target, |
| 925 mailboxes)); |
| 926 } |
| 927 |
| 375 } // namespace content | 928 } // namespace content |
| OLD | NEW |