| 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 |