1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/pepper/pepper_video_source_host.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/renderer/renderer_ppapi_host.h"
10bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/ppb_image_data_impl.h"
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/renderer/render_thread_impl.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/host/dispatch_host_message.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/host/ppapi_host.h"
155b892326406927b709cdaf6c384d4ababf456332Ben Murdoch#include "ppapi/proxy/host_dispatcher.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/proxy/ppb_image_data_proxy.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/scoped_pp_resource.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/thunk/enter.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/thunk/ppb_image_data_api.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/libyuv/include/libyuv/convert.h"
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ppapi::host::HostMessageContext;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ppapi::host::ReplyMessageContext;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content {
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)PepperVideoSourceHost::FrameReceiver::FrameReceiver(
30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const base::WeakPtr<PepperVideoSourceHost>& host)
31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    : host_(host),
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      main_message_loop_proxy_(base::MessageLoopProxy::current()) {}
33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
34a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochPepperVideoSourceHost::FrameReceiver::~FrameReceiver() {}
35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool PepperVideoSourceHost::FrameReceiver::GotFrame(
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const scoped_refptr<media::VideoFrame>& frame) {
38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // It's not safe to access the host from this thread, so post a task to our
39a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // main thread to transfer the new frame.
40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  main_message_loop_proxy_->PostTask(
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      FROM_HERE, base::Bind(&FrameReceiver::OnGotFrame, this, frame));
42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return true;
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void PepperVideoSourceHost::FrameReceiver::OnGotFrame(
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const scoped_refptr<media::VideoFrame>& frame) {
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (host_.get()) {
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Hold a reference to the new frame and release the previous.
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    host_->last_frame_ = frame;
51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (host_->get_frame_pending_)
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      host_->SendGetFrameReply();
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
57a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochPepperVideoSourceHost::PepperVideoSourceHost(RendererPpapiHost* host,
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             PP_Instance instance,
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             PP_Resource resource)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : ResourceHost(host->GetPpapiHost(), instance, resource),
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      renderer_ppapi_host_(host),
6258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      source_handler_(new VideoSourceHandler(NULL)),
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      get_frame_pending_(false),
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      weak_factory_(this) {
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  frame_receiver_ = new FrameReceiver(weak_factory_.GetWeakPtr());
665b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  memset(&shared_image_desc_, 0, sizeof(shared_image_desc_));
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochPepperVideoSourceHost::~PepperVideoSourceHost() { Close(); }
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int32_t PepperVideoSourceHost::OnResourceMessageReceived(
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPC::Message& msg,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    HostMessageContext* context) {
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(PepperVideoSourceHost, msg)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoSource_Open,
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnHostMsgOpen)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoSource_GetFrame,
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        OnHostMsgGetFrame)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoSource_Close,
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        OnHostMsgClose)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return PP_ERROR_FAILED;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int32_t PepperVideoSourceHost::OnHostMsgOpen(HostMessageContext* context,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             const std::string& stream_url) {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL gurl(stream_url);
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!gurl.is_valid())
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return PP_ERROR_BADARGUMENT;
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!source_handler_->Open(gurl.spec(), frame_receiver_.get()))
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return PP_ERROR_BADARGUMENT;
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  stream_url_ = gurl.spec();
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ReplyMessageContext reply_context = context->MakeReplyMessageContext();
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  reply_context.params.set_result(PP_OK);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  host()->SendReply(reply_context, PpapiPluginMsg_VideoSource_OpenReply());
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint32_t PepperVideoSourceHost::OnHostMsgGetFrame(HostMessageContext* context) {
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!source_handler_.get())
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return PP_ERROR_FAILED;
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (get_frame_pending_)
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  reply_context_ = context->MakeReplyMessageContext();
109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  get_frame_pending_ = true;
110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // If a frame is ready, try to convert it and send the reply.
112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (last_frame_.get())
113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    SendGetFrameReply();
114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int32_t PepperVideoSourceHost::OnHostMsgClose(HostMessageContext* context) {
119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  Close();
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return PP_OK;
121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void PepperVideoSourceHost::SendGetFrameReply() {
124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(get_frame_pending_);
125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  get_frame_pending_ = false;
126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(last_frame_.get());
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<media::VideoFrame> frame(last_frame_);
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  last_frame_ = NULL;
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int dst_width = frame->visible_rect().width();
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int dst_height = frame->visible_rect().height();
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1345b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  // Note: We try to reuse the shared memory for the previous frame here. This
1355b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  // means that the previous frame may be overwritten and is no longer valid
1365b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  // after calling this function again.
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC::PlatformFileForTransit image_handle;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32_t byte_count;
1395b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  if (shared_image_.get() && dst_width == shared_image_->width() &&
1405b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      dst_height == shared_image_->height()) {
1415b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    // We have already allocated the correct size in shared memory. We need to
1425b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    // duplicate the handle for IPC however, which will close down the
1435b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    // duplicated handle when it's done.
1445b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    int local_fd = 0;
1455b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (shared_image_->GetSharedMemory(&local_fd, &byte_count) != PP_OK) {
1465b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      SendGetFrameErrorReply(PP_ERROR_FAILED);
1475b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      return;
1485b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    }
1495b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
1505b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    ppapi::proxy::HostDispatcher* dispatcher =
1515b892326406927b709cdaf6c384d4ababf456332Ben Murdoch        ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
1525b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (!dispatcher) {
1535b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      SendGetFrameErrorReply(PP_ERROR_FAILED);
1545b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      return;
1555b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    }
1565b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
1575b892326406927b709cdaf6c384d4ababf456332Ben Murdoch#if defined(OS_WIN)
1585b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    image_handle = dispatcher->ShareHandleWithRemote(
1595b892326406927b709cdaf6c384d4ababf456332Ben Murdoch        reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false);
1605b892326406927b709cdaf6c384d4ababf456332Ben Murdoch#elif defined(OS_POSIX)
1615b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    image_handle = dispatcher->ShareHandleWithRemote(local_fd, false);
1625b892326406927b709cdaf6c384d4ababf456332Ben Murdoch#else
1635b892326406927b709cdaf6c384d4ababf456332Ben Murdoch#error Not implemented.
1645b892326406927b709cdaf6c384d4ababf456332Ben Murdoch#endif
1655b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  } else {
1665b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    // We need to allocate new shared memory.
1675b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    shared_image_ = NULL;  // Release any previous image.
1685b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
1695b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    ppapi::ScopedPPResource resource(
1705b892326406927b709cdaf6c384d4ababf456332Ben Murdoch        ppapi::ScopedPPResource::PassRef(),
1715b892326406927b709cdaf6c384d4ababf456332Ben Murdoch        ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
1725b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            pp_instance(),
1735b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            ppapi::PPB_ImageData_Shared::SIMPLE,
1745b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            PP_IMAGEDATAFORMAT_BGRA_PREMUL,
1755b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            PP_MakeSize(dst_width, dst_height),
1765b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            false /* init_to_zero */,
1775b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            &shared_image_desc_,
1785b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            &image_handle,
1795b892326406927b709cdaf6c384d4ababf456332Ben Murdoch            &byte_count));
1805b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (!resource) {
1815b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      SendGetFrameErrorReply(PP_ERROR_FAILED);
1825b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      return;
1835b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    }
1845b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
1855b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
1865b892326406927b709cdaf6c384d4ababf456332Ben Murdoch        enter_resource(resource, false);
1875b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (enter_resource.failed()) {
1885b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      SendGetFrameErrorReply(PP_ERROR_FAILED);
1895b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      return;
1905b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    }
1915b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
1925b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    shared_image_ = static_cast<PPB_ImageData_Impl*>(enter_resource.object());
1935b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (!shared_image_.get()) {
1945b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      SendGetFrameErrorReply(PP_ERROR_FAILED);
1955b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      return;
1965b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    }
1975b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
1985b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    DCHECK(!shared_image_->IsMapped());  // New memory should not be mapped.
1995b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (!shared_image_->Map() || !shared_image_->GetMappedBitmap() ||
2005b892326406927b709cdaf6c384d4ababf456332Ben Murdoch        !shared_image_->GetMappedBitmap()->getPixels()) {
2015b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      shared_image_ = NULL;
2025b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      SendGetFrameErrorReply(PP_ERROR_FAILED);
2035b892326406927b709cdaf6c384d4ababf456332Ben Murdoch      return;
2045b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    }
205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2075b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  const SkBitmap* bitmap = shared_image_->GetMappedBitmap();
208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!bitmap) {
209a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    SendGetFrameErrorReply(PP_ERROR_FAILED);
210a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
211a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
2125b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  uint8_t* bitmap_pixels = static_cast<uint8_t*>(bitmap->getPixels());
214a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!bitmap_pixels) {
215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    SendGetFrameErrorReply(PP_ERROR_FAILED);
216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Calculate that portion of the |frame| that should be copied into
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // |bitmap|. If |frame| has been cropped,
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // frame->coded_size() != frame->visible_rect().
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int src_width = frame->coded_size().width();
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int src_height = frame->coded_size().height();
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(src_width >= dst_width && src_height >= dst_height);
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int horiz_crop = frame->visible_rect().x();
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int vert_crop = frame->visible_rect().y();
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const uint8* src_y = frame->data(media::VideoFrame::kYPlane) +
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       (src_width * vert_crop + horiz_crop);
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int center = (src_width + 1) / 2;
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const uint8* src_u = frame->data(media::VideoFrame::kUPlane) +
233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       (center * vert_crop + horiz_crop) / 2;
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const uint8* src_v = frame->data(media::VideoFrame::kVPlane) +
235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                       (center * vert_crop + horiz_crop) / 2;
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  libyuv::I420ToBGRA(src_y,
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     frame->stride(media::VideoFrame::kYPlane),
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     src_u,
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     frame->stride(media::VideoFrame::kUPlane),
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     src_v,
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     frame->stride(media::VideoFrame::kVPlane),
243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                     bitmap_pixels,
244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                     bitmap->rowBytes(),
245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                     dst_width,
246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                     dst_height);
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ppapi::HostResource host_resource;
2495b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  host_resource.SetHostResource(pp_instance(), shared_image_->GetReference());
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Convert a video timestamp to a PP_TimeTicks (a double, in seconds).
2525b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  const PP_TimeTicks timestamp = frame->timestamp().InSecondsF();
253a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ppapi::proxy::SerializedHandle serialized_handle;
255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  serialized_handle.set_shmem(image_handle, byte_count);
256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  reply_context_.params.AppendHandle(serialized_handle);
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  host()->SendReply(reply_context_,
259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    PpapiPluginMsg_VideoSource_GetFrameReply(
2605b892326406927b709cdaf6c384d4ababf456332Ben Murdoch                        host_resource, shared_image_desc_, timestamp));
261a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
262a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  reply_context_ = ppapi::host::ReplyMessageContext();
263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
265a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void PepperVideoSourceHost::SendGetFrameErrorReply(int32_t error) {
266a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  reply_context_.params.set_result(error);
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  host()->SendReply(
268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      reply_context_,
269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      PpapiPluginMsg_VideoSource_GetFrameReply(
270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          ppapi::HostResource(), PP_ImageDataDesc(), 0.0 /* timestamp */));
271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  reply_context_ = ppapi::host::ReplyMessageContext();
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void PepperVideoSourceHost::Close() {
275a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (source_handler_.get() && !stream_url_.empty())
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    source_handler_->Close(frame_receiver_.get());
277a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
278a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  source_handler_.reset(NULL);
279a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  stream_url_.clear();
2805b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
2815b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  shared_image_ = NULL;
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace content
285