OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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 "chrome/renderer/gpu_video_decoder_host.h" |
| 6 |
| 7 #include "chrome/common/gpu_messages.h" |
| 8 #include "chrome/renderer/gpu_video_service_host.h" |
| 9 #include "chrome/renderer/render_thread.h" |
| 10 |
| 11 void GpuVideoDecoderHost::OnChannelError() { |
| 12 channel_host_.release(); |
| 13 } |
| 14 |
| 15 void GpuVideoDecoderHost::OnMessageReceived(const IPC::Message& msg) { |
| 16 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoderHost, msg) |
| 17 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_InitializeACK, |
| 18 OnInitializeDone) |
| 19 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_DestroyACK, |
| 20 OnUninitializeDone) |
| 21 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_FlushACK, |
| 22 OnFlushDone) |
| 23 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferACK, |
| 24 OnEmptyThisBufferACK) |
| 25 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferDone, |
| 26 OnEmptyThisBufferDone) |
| 27 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_FillThisBufferDone, |
| 28 OnFillThisBufferDone) |
| 29 IPC_MESSAGE_UNHANDLED_ERROR() |
| 30 IPC_END_MESSAGE_MAP() |
| 31 } |
| 32 |
| 33 bool GpuVideoDecoderHost::Initialize(const GpuVideoDecoderInitParam& param) { |
| 34 DCHECK_EQ(state_, kStateUninitialized); |
| 35 |
| 36 init_param_ = param; |
| 37 if (!channel_host_->Send( |
| 38 new GpuVideoDecoderMsg_Initialize(route_id(), param))) { |
| 39 LOG(ERROR) << "GpuVideoDecoderMsg_Initialize failed"; |
| 40 return false; |
| 41 } |
| 42 return true; |
| 43 } |
| 44 |
| 45 bool GpuVideoDecoderHost::Uninitialize() { |
| 46 if (!channel_host_->Send(new GpuVideoDecoderMsg_Destroy(route_id()))) { |
| 47 LOG(ERROR) << "GpuVideoDecoderMsg_Destroy failed"; |
| 48 return false; |
| 49 } |
| 50 return true; |
| 51 } |
| 52 |
| 53 void GpuVideoDecoderHost::EmptyThisBuffer(scoped_refptr<Buffer> buffer) { |
| 54 DCHECK_NE(state_, kStateUninitialized); |
| 55 DCHECK_NE(state_, kStateFlushing); |
| 56 |
| 57 // We never own input buffers, therefore when client in flush state, it |
| 58 // never call us with EmptyThisBuffer. |
| 59 if (state_ != kStateNormal) |
| 60 return; |
| 61 |
| 62 input_buffer_queue_.push_back(buffer); |
| 63 SendInputBufferToGpu(); |
| 64 } |
| 65 |
| 66 void GpuVideoDecoderHost::FillThisBuffer(scoped_refptr<VideoFrame> frame) { |
| 67 DCHECK_NE(state_, kStateUninitialized); |
| 68 |
| 69 // Depends on who provides buffer. client could return buffer to |
| 70 // us while flushing. |
| 71 if (state_ == kStateError) |
| 72 return; |
| 73 |
| 74 GpuVideoDecoderOutputBufferParam param; |
| 75 if (!channel_host_->Send( |
| 76 new GpuVideoDecoderMsg_FillThisBuffer(route_id(), param))) { |
| 77 LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBuffer failed"; |
| 78 } |
| 79 } |
| 80 |
| 81 bool GpuVideoDecoderHost::Flush() { |
| 82 state_ = kStateFlushing; |
| 83 if (!channel_host_->Send(new GpuVideoDecoderMsg_Flush(route_id()))) { |
| 84 LOG(ERROR) << "GpuVideoDecoderMsg_Flush failed"; |
| 85 return false; |
| 86 } |
| 87 input_buffer_queue_.clear(); |
| 88 // TODO(jiesun): because GpuVideoDeocder/GpuVideoDecoder are asynchronously. |
| 89 // We need a way to make flush logic more clear. but I think ring buffer |
| 90 // should make the busy flag obsolete, therefore I will leave it for now. |
| 91 input_buffer_busy_ = false; |
| 92 return true; |
| 93 } |
| 94 |
| 95 void GpuVideoDecoderHost::OnInitializeDone( |
| 96 const GpuVideoDecoderInitDoneParam& param) { |
| 97 done_param_ = param; |
| 98 bool success = false; |
| 99 |
| 100 do { |
| 101 if (!param.success_) |
| 102 break; |
| 103 |
| 104 if (!base::SharedMemory::IsHandleValid(param.input_buffer_handle_)) |
| 105 break; |
| 106 input_transfer_buffer_.reset( |
| 107 new base::SharedMemory(param.input_buffer_handle_, false)); |
| 108 if (!input_transfer_buffer_->Map(param.input_buffer_size_)) |
| 109 break; |
| 110 |
| 111 if (!base::SharedMemory::IsHandleValid(param.output_buffer_handle_)) |
| 112 break; |
| 113 output_transfer_buffer_.reset( |
| 114 new base::SharedMemory(param.output_buffer_handle_, false)); |
| 115 if (!output_transfer_buffer_->Map(param.output_buffer_size_)) |
| 116 break; |
| 117 |
| 118 success = true; |
| 119 } while (0); |
| 120 |
| 121 state_ = success ? kStateNormal : kStateError; |
| 122 event_handler_->OnInitializeDone(success, param); |
| 123 } |
| 124 |
| 125 void GpuVideoDecoderHost::OnUninitializeDone() { |
| 126 input_transfer_buffer_.reset(); |
| 127 output_transfer_buffer_.reset(); |
| 128 |
| 129 event_handler_->OnUninitializeDone(); |
| 130 } |
| 131 |
| 132 void GpuVideoDecoderHost::OnFlushDone() { |
| 133 state_ = kStateNormal; |
| 134 event_handler_->OnFlushDone(); |
| 135 } |
| 136 |
| 137 void GpuVideoDecoderHost::OnEmptyThisBufferDone() { |
| 138 scoped_refptr<Buffer> buffer; |
| 139 event_handler_->OnEmptyBufferDone(buffer); |
| 140 } |
| 141 |
| 142 void GpuVideoDecoderHost::OnFillThisBufferDone( |
| 143 const GpuVideoDecoderOutputBufferParam& param) { |
| 144 scoped_refptr<VideoFrame> frame; |
| 145 |
| 146 if (param.flags_ & GpuVideoDecoderOutputBufferParam::kFlagsEndOfStream) { |
| 147 VideoFrame::CreateEmptyFrame(&frame); |
| 148 } else { |
| 149 VideoFrame::CreateFrame(VideoFrame::YV12, |
| 150 init_param_.width_, |
| 151 init_param_.height_, |
| 152 base::TimeDelta::FromMicroseconds(param.timestamp_), |
| 153 base::TimeDelta::FromMicroseconds(param.duration_), |
| 154 &frame); |
| 155 |
| 156 uint8* src = static_cast<uint8*>(output_transfer_buffer_->memory()); |
| 157 uint8* data0 = frame->data(0); |
| 158 uint8* data1 = frame->data(1); |
| 159 uint8* data2 = frame->data(2); |
| 160 int32 size = init_param_.width_ * init_param_.height_; |
| 161 memcpy(data0, src, size); |
| 162 memcpy(data1, src + size, size / 4); |
| 163 memcpy(data2, src + size + size / 4, size / 4); |
| 164 } |
| 165 |
| 166 event_handler_->OnFillBufferDone(frame); |
| 167 if (!channel_host_->Send( |
| 168 new GpuVideoDecoderMsg_FillThisBufferDoneACK(route_id()))) { |
| 169 LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBufferDoneACK failed"; |
| 170 } |
| 171 } |
| 172 |
| 173 void GpuVideoDecoderHost::OnEmptyThisBufferACK() { |
| 174 input_buffer_busy_ = false; |
| 175 SendInputBufferToGpu(); |
| 176 } |
| 177 |
| 178 void GpuVideoDecoderHost::SendInputBufferToGpu() { |
| 179 if (input_buffer_busy_) return; |
| 180 if (input_buffer_queue_.empty()) return; |
| 181 |
| 182 input_buffer_busy_ = true; |
| 183 |
| 184 scoped_refptr<Buffer> buffer; |
| 185 buffer = input_buffer_queue_.front(); |
| 186 input_buffer_queue_.pop_front(); |
| 187 |
| 188 // Send input data to GPU process. |
| 189 GpuVideoDecoderInputBufferParam param; |
| 190 param.offset_ = 0; |
| 191 param.size_ = buffer->GetDataSize(); |
| 192 param.timestamp_ = buffer->GetTimestamp().InMicroseconds(); |
| 193 memcpy(input_transfer_buffer_->memory(), buffer->GetData(), param.size_); |
| 194 if (!channel_host_->Send( |
| 195 new GpuVideoDecoderMsg_EmptyThisBuffer(route_id(), param))) { |
| 196 LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBuffer failed"; |
| 197 } |
| 198 } |
| 199 |
OLD | NEW |