OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/common/gpu/media/gl_surface_capturer.h" |
| 6 |
| 7 #include "base/message_loop/message_loop_proxy.h" |
| 8 #include "content/common/gpu/gpu_channel.h" |
| 9 #include "content/common/gpu/gpu_messages.h" |
| 10 #include "ipc/ipc_message_macros.h" |
| 11 |
| 12 namespace content { |
| 13 |
| 14 GLSurfaceCapturer::GLSurfaceCapturer(int32 route_id, GpuCommandBufferStub* stub) |
| 15 : weak_this_factory_(this), |
| 16 route_id_(route_id), |
| 17 stub_(stub), |
| 18 output_format_(media::VideoFrame::INVALID) { |
| 19 DCHECK(thread_checker_.CalledOnValidThread()); |
| 20 stub_->AddDestructionObserver(this); |
| 21 stub_->channel()->AddRoute(route_id_, this); |
| 22 } |
| 23 |
| 24 GLSurfaceCapturer::~GLSurfaceCapturer() { |
| 25 DCHECK(thread_checker_.CalledOnValidThread()); |
| 26 if (surface_capturer_) |
| 27 surface_capturer_.release()->Destroy(); |
| 28 |
| 29 stub_->channel()->RemoveRoute(route_id_); |
| 30 stub_->RemoveDestructionObserver(this); |
| 31 } |
| 32 |
| 33 bool GLSurfaceCapturer::OnMessageReceived(const IPC::Message& message) { |
| 34 if (!surface_capturer_) |
| 35 return false; |
| 36 bool handled = true; |
| 37 IPC_BEGIN_MESSAGE_MAP(GLSurfaceCapturer, message) |
| 38 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Initialize, OnInitialize) |
| 39 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Capture, OnCapture) |
| 40 IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Destroy, OnDestroy) |
| 41 IPC_MESSAGE_UNHANDLED(handled = false) |
| 42 IPC_END_MESSAGE_MAP() |
| 43 return handled; |
| 44 } |
| 45 |
| 46 void GLSurfaceCapturer::NotifyCaptureParameters(const gfx::Size& buffer_size, |
| 47 const gfx::Rect& visible_rect) { |
| 48 DCHECK(thread_checker_.CalledOnValidThread()); |
| 49 output_buffer_size_ = buffer_size; |
| 50 output_visible_rect_ = visible_rect; |
| 51 Send(new SurfaceCapturerHostMsg_NotifyCaptureParameters( |
| 52 route_id_, buffer_size, visible_rect)); |
| 53 } |
| 54 |
| 55 void GLSurfaceCapturer::NotifyError(SurfaceCapturer::Error error) { |
| 56 DCHECK(thread_checker_.CalledOnValidThread()); |
| 57 Send(new SurfaceCapturerHostMsg_NotifyError(route_id_, error)); |
| 58 } |
| 59 |
| 60 void GLSurfaceCapturer::OnWillDestroyStub() { |
| 61 DCHECK(thread_checker_.CalledOnValidThread()); |
| 62 delete this; |
| 63 } |
| 64 |
| 65 void GLSurfaceCapturer::OnInitialize(media::VideoFrame::Format format) { |
| 66 DVLOG(2) << "OnInitialize(): format=" << format; |
| 67 DCHECK(thread_checker_.CalledOnValidThread()); |
| 68 DCHECK(!surface_capturer_); |
| 69 |
| 70 // TODO(sheu): actually create a capturer. |
| 71 |
| 72 if (!surface_capturer_) { |
| 73 NOTIMPLEMENTED() << "OnInitialize(): GL surface capturing not available."; |
| 74 NotifyError(SurfaceCapturer::kPlatformFailureError); |
| 75 return; |
| 76 } |
| 77 |
| 78 output_format_ = format; |
| 79 surface_capturer_->Initialize(output_format_); |
| 80 } |
| 81 |
| 82 void GLSurfaceCapturer::OnCapture(int32 frame_id, |
| 83 base::SharedMemoryHandle buffer_shm, |
| 84 uint32_t buffer_size) { |
| 85 DVLOG(3) << "OnCapture(): frame_id=" << frame_id |
| 86 << ", buffer_size=" << buffer_size; |
| 87 DCHECK(thread_checker_.CalledOnValidThread()); |
| 88 if (!surface_capturer_) |
| 89 return; |
| 90 if (frame_id < 0) { |
| 91 DLOG(ERROR) << "OnCapture(): invalid frame_id=" << frame_id; |
| 92 NotifyError(SurfaceCapturer::kPlatformFailureError); |
| 93 return; |
| 94 } |
| 95 |
| 96 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(buffer_shm, true)); |
| 97 if (!shm->Map(buffer_size)) { |
| 98 DLOG(ERROR) << "OnCapture(): could not map frame_id=" << frame_id; |
| 99 NotifyError(SurfaceCapturer::kPlatformFailureError); |
| 100 return; |
| 101 } |
| 102 scoped_refptr<media::VideoFrame> frame = |
| 103 media::VideoFrame::WrapExternalSharedMemory( |
| 104 output_format_, |
| 105 output_buffer_size_, |
| 106 output_visible_rect_, |
| 107 output_visible_rect_.size(), |
| 108 reinterpret_cast<uint8*>(shm->memory()), |
| 109 buffer_size, |
| 110 buffer_shm, |
| 111 base::TimeDelta(), |
| 112 base::Bind(base::IgnoreResult(&base::MessageLoopProxy::PostTask), |
| 113 base::MessageLoopProxy::current(), |
| 114 FROM_HERE, |
| 115 base::Bind(&GLSurfaceCapturer::CaptureFrameFinished, |
| 116 weak_this_factory_.GetWeakPtr(), |
| 117 frame_id, |
| 118 base::Passed(&shm)))); |
| 119 if (!frame) { |
| 120 DLOG(ERROR) << "OnCapture(): could not create frame for" |
| 121 "frame_id=" << frame_id; |
| 122 NotifyError(SurfaceCapturer::kPlatformFailureError); |
| 123 return; |
| 124 } |
| 125 surface_capturer_->Capture(frame); |
| 126 } |
| 127 |
| 128 void GLSurfaceCapturer::OnDestroy() { |
| 129 DVLOG(2) << "OnDestroy()"; |
| 130 DCHECK(thread_checker_.CalledOnValidThread()); |
| 131 delete this; |
| 132 } |
| 133 |
| 134 void GLSurfaceCapturer::CaptureFrameFinished( |
| 135 int32 frame_id, |
| 136 scoped_ptr<base::SharedMemory> shm) { |
| 137 DCHECK(thread_checker_.CalledOnValidThread()); |
| 138 Send(new SurfaceCapturerHostMsg_NotifyCaptureDone(route_id_, frame_id)); |
| 139 // Let shm fall out of scope. |
| 140 } |
| 141 |
| 142 void GLSurfaceCapturer::Send(IPC::Message* message) { |
| 143 DCHECK(thread_checker_.CalledOnValidThread()); |
| 144 uint32 type = message->type(); |
| 145 if (!stub_->channel()->Send(message)) { |
| 146 DLOG(ERROR) << "Send(): sending failed: message->type()=" << type; |
| 147 NotifyError(SurfaceCapturer::kPlatformFailureError); |
| 148 } |
| 149 } |
| 150 |
| 151 } // namespace content |
OLD | NEW |