| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/renderer/gpu_video_decoder_host.h" | 5 #include "chrome/renderer/gpu_video_decoder_host.h" |
| 6 | 6 |
| 7 #include "chrome/common/gpu_messages.h" | 7 #include "chrome/common/gpu_messages.h" |
| 8 #include "chrome/renderer/gpu_video_service_host.h" | 8 #include "chrome/renderer/gpu_video_service_host.h" |
| 9 #include "chrome/renderer/render_thread.h" | 9 #include "chrome/renderer/render_thread.h" |
| 10 | 10 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 } | 99 } |
| 100 | 100 |
| 101 void GpuVideoDecoderHost::FillThisBuffer(scoped_refptr<VideoFrame> frame) { | 101 void GpuVideoDecoderHost::FillThisBuffer(scoped_refptr<VideoFrame> frame) { |
| 102 DCHECK_NE(state_, kStateUninitialized); | 102 DCHECK_NE(state_, kStateUninitialized); |
| 103 | 103 |
| 104 // Depends on who provides buffer. client could return buffer to | 104 // Depends on who provides buffer. client could return buffer to |
| 105 // us while flushing. | 105 // us while flushing. |
| 106 if (state_ == kStateError) | 106 if (state_ == kStateError) |
| 107 return; | 107 return; |
| 108 | 108 |
| 109 // TODO(hclam): We should keep an IDMap to convert between a frame a buffer |
| 110 // ID so that we can signal GpuVideoDecoder in GPU process to use the buffer. |
| 111 // This eliminates one conversion step. |
| 109 GpuVideoDecoderOutputBufferParam param; | 112 GpuVideoDecoderOutputBufferParam param; |
| 113 |
| 114 // TODO(hclam): This is a hack to pass the texture id to the hardware video |
| 115 // decoder. We should have created a mapping between VideoFrame and buffer id |
| 116 // and we pass the buffer id to the GPU process. |
| 117 param.texture = frame->gl_texture(VideoFrame::kRGBPlane); |
| 110 if (!channel_host_ || !channel_host_->Send( | 118 if (!channel_host_ || !channel_host_->Send( |
| 111 new GpuVideoDecoderMsg_FillThisBuffer(route_id(), param))) { | 119 new GpuVideoDecoderMsg_FillThisBuffer(route_id(), param))) { |
| 112 LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBuffer failed"; | 120 LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBuffer failed"; |
| 113 } | 121 } |
| 114 } | 122 } |
| 115 | 123 |
| 116 bool GpuVideoDecoderHost::Flush() { | 124 bool GpuVideoDecoderHost::Flush() { |
| 117 state_ = kStateFlushing; | 125 state_ = kStateFlushing; |
| 118 if (!channel_host_ || !channel_host_->Send( | 126 if (!channel_host_ || !channel_host_->Send( |
| 119 new GpuVideoDecoderMsg_Flush(route_id()))) { | 127 new GpuVideoDecoderMsg_Flush(route_id()))) { |
| 120 LOG(ERROR) << "GpuVideoDecoderMsg_Flush failed"; | 128 LOG(ERROR) << "GpuVideoDecoderMsg_Flush failed"; |
| 121 return false; | 129 return false; |
| 122 } | 130 } |
| 123 input_buffer_queue_.clear(); | 131 input_buffer_queue_.clear(); |
| 124 // TODO(jiesun): because GpuVideoDeocder/GpuVideoDecoder are asynchronously. | 132 // TODO(jiesun): because GpuVideoDeocder/GpuVideoDecoder are asynchronously. |
| 125 // We need a way to make flush logic more clear. but I think ring buffer | 133 // We need a way to make flush logic more clear. but I think ring buffer |
| 126 // should make the busy flag obsolete, therefore I will leave it for now. | 134 // should make the busy flag obsolete, therefore I will leave it for now. |
| 127 input_buffer_busy_ = false; | 135 input_buffer_busy_ = false; |
| 128 return true; | 136 return true; |
| 129 } | 137 } |
| 130 | 138 |
| 131 void GpuVideoDecoderHost::OnInitializeDone( | 139 void GpuVideoDecoderHost::OnInitializeDone( |
| 132 const GpuVideoDecoderInitDoneParam& param) { | 140 const GpuVideoDecoderInitDoneParam& param) { |
| 133 done_param_ = param; | 141 done_param_ = param; |
| 134 bool success = false; | 142 bool success = false; |
| 135 | 143 |
| 136 do { | 144 do { |
| 137 if (!param.success_) | 145 if (!param.success) |
| 138 break; | 146 break; |
| 139 | 147 |
| 140 if (!base::SharedMemory::IsHandleValid(param.input_buffer_handle_)) | 148 if (!base::SharedMemory::IsHandleValid(param.input_buffer_handle)) |
| 141 break; | 149 break; |
| 142 input_transfer_buffer_.reset( | 150 input_transfer_buffer_.reset( |
| 143 new base::SharedMemory(param.input_buffer_handle_, false)); | 151 new base::SharedMemory(param.input_buffer_handle, false)); |
| 144 if (!input_transfer_buffer_->Map(param.input_buffer_size_)) | 152 if (!input_transfer_buffer_->Map(param.input_buffer_size)) |
| 145 break; | 153 break; |
| 146 | 154 |
| 147 if (!base::SharedMemory::IsHandleValid(param.output_buffer_handle_)) | 155 if (!base::SharedMemory::IsHandleValid(param.output_buffer_handle)) |
| 148 break; | 156 break; |
| 149 output_transfer_buffer_.reset( | 157 output_transfer_buffer_.reset( |
| 150 new base::SharedMemory(param.output_buffer_handle_, false)); | 158 new base::SharedMemory(param.output_buffer_handle, false)); |
| 151 if (!output_transfer_buffer_->Map(param.output_buffer_size_)) | 159 if (!output_transfer_buffer_->Map(param.output_buffer_size)) |
| 152 break; | 160 break; |
| 153 | 161 |
| 154 success = true; | 162 success = true; |
| 155 } while (0); | 163 } while (0); |
| 156 | 164 |
| 157 state_ = success ? kStateNormal : kStateError; | 165 state_ = success ? kStateNormal : kStateError; |
| 158 event_handler_->OnInitializeDone(success, param); | 166 event_handler_->OnInitializeDone(success, param); |
| 159 } | 167 } |
| 160 | 168 |
| 161 void GpuVideoDecoderHost::OnUninitializeDone() { | 169 void GpuVideoDecoderHost::OnUninitializeDone() { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 172 | 180 |
| 173 void GpuVideoDecoderHost::OnEmptyThisBufferDone() { | 181 void GpuVideoDecoderHost::OnEmptyThisBufferDone() { |
| 174 scoped_refptr<Buffer> buffer; | 182 scoped_refptr<Buffer> buffer; |
| 175 event_handler_->OnEmptyBufferDone(buffer); | 183 event_handler_->OnEmptyBufferDone(buffer); |
| 176 } | 184 } |
| 177 | 185 |
| 178 void GpuVideoDecoderHost::OnFillThisBufferDone( | 186 void GpuVideoDecoderHost::OnFillThisBufferDone( |
| 179 const GpuVideoDecoderOutputBufferParam& param) { | 187 const GpuVideoDecoderOutputBufferParam& param) { |
| 180 scoped_refptr<VideoFrame> frame; | 188 scoped_refptr<VideoFrame> frame; |
| 181 | 189 |
| 182 if (param.flags_ & GpuVideoDecoderOutputBufferParam::kFlagsEndOfStream) { | 190 if (param.flags & GpuVideoDecoderOutputBufferParam::kFlagsEndOfStream) { |
| 183 VideoFrame::CreateEmptyFrame(&frame); | 191 VideoFrame::CreateEmptyFrame(&frame); |
| 184 } else { | 192 } else if (done_param_.surface_type == |
| 193 GpuVideoDecoderInitDoneParam::SurfaceTypeSystemMemory) { |
| 185 VideoFrame::CreateFrame(VideoFrame::YV12, | 194 VideoFrame::CreateFrame(VideoFrame::YV12, |
| 186 init_param_.width_, | 195 init_param_.width, |
| 187 init_param_.height_, | 196 init_param_.height, |
| 188 base::TimeDelta::FromMicroseconds(param.timestamp_), | 197 base::TimeDelta::FromMicroseconds(param.timestamp), |
| 189 base::TimeDelta::FromMicroseconds(param.duration_), | 198 base::TimeDelta::FromMicroseconds(param.duration), |
| 190 &frame); | 199 &frame); |
| 191 | |
| 192 uint8* src = static_cast<uint8*>(output_transfer_buffer_->memory()); | 200 uint8* src = static_cast<uint8*>(output_transfer_buffer_->memory()); |
| 193 uint8* data0 = frame->data(0); | 201 uint8* data0 = frame->data(0); |
| 194 uint8* data1 = frame->data(1); | 202 uint8* data1 = frame->data(1); |
| 195 uint8* data2 = frame->data(2); | 203 uint8* data2 = frame->data(2); |
| 196 int32 size = init_param_.width_ * init_param_.height_; | 204 int32 size = init_param_.width * init_param_.height; |
| 197 memcpy(data0, src, size); | 205 memcpy(data0, src, size); |
| 198 memcpy(data1, src + size, size / 4); | 206 memcpy(data1, src + size, size / 4); |
| 199 memcpy(data2, src + size + size / 4, size / 4); | 207 memcpy(data2, src + size + size / 4, size / 4); |
| 208 } else if (done_param_.surface_type == |
| 209 GpuVideoDecoderInitDoneParam::SurfaceTypeGlTexture) { |
| 210 // TODO(hclam): The logic in buffer allocation is pretty much around |
| 211 // using shared memory for output buffer which needs to be adjusted. For |
| 212 // now we have to add this hack to get the texture id. |
| 213 VideoFrame::GlTexture textures[3] = { param.texture, 0, 0 }; |
| 214 media::VideoFrame::CreateFrameGlTexture( |
| 215 media::VideoFrame::RGBA, init_param_.width, init_param_.height, |
| 216 textures, |
| 217 base::TimeDelta::FromMicroseconds(param.timestamp), |
| 218 base::TimeDelta::FromMicroseconds(param.duration), |
| 219 &frame); |
| 200 } | 220 } |
| 201 | 221 |
| 202 event_handler_->OnFillBufferDone(frame); | 222 event_handler_->OnFillBufferDone(frame); |
| 203 if (!channel_host_ || !channel_host_->Send( | 223 if (!channel_host_ || !channel_host_->Send( |
| 204 new GpuVideoDecoderMsg_FillThisBufferDoneACK(route_id()))) { | 224 new GpuVideoDecoderMsg_FillThisBufferDoneACK(route_id()))) { |
| 205 LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBufferDoneACK failed"; | 225 LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBufferDoneACK failed"; |
| 206 } | 226 } |
| 207 } | 227 } |
| 208 | 228 |
| 209 void GpuVideoDecoderHost::OnEmptyThisBufferACK() { | 229 void GpuVideoDecoderHost::OnEmptyThisBufferACK() { |
| 210 input_buffer_busy_ = false; | 230 input_buffer_busy_ = false; |
| 211 SendInputBufferToGpu(); | 231 SendInputBufferToGpu(); |
| 212 } | 232 } |
| 213 | 233 |
| 214 void GpuVideoDecoderHost::SendInputBufferToGpu() { | 234 void GpuVideoDecoderHost::SendInputBufferToGpu() { |
| 215 if (input_buffer_busy_) return; | 235 if (input_buffer_busy_) return; |
| 216 if (input_buffer_queue_.empty()) return; | 236 if (input_buffer_queue_.empty()) return; |
| 217 | 237 |
| 218 input_buffer_busy_ = true; | 238 input_buffer_busy_ = true; |
| 219 | 239 |
| 220 scoped_refptr<Buffer> buffer; | 240 scoped_refptr<Buffer> buffer; |
| 221 buffer = input_buffer_queue_.front(); | 241 buffer = input_buffer_queue_.front(); |
| 222 input_buffer_queue_.pop_front(); | 242 input_buffer_queue_.pop_front(); |
| 223 | 243 |
| 224 // Send input data to GPU process. | 244 // Send input data to GPU process. |
| 225 GpuVideoDecoderInputBufferParam param; | 245 GpuVideoDecoderInputBufferParam param; |
| 226 param.offset_ = 0; | 246 param.offset = 0; |
| 227 param.size_ = buffer->GetDataSize(); | 247 param.size = buffer->GetDataSize(); |
| 228 param.timestamp_ = buffer->GetTimestamp().InMicroseconds(); | 248 param.timestamp = buffer->GetTimestamp().InMicroseconds(); |
| 229 memcpy(input_transfer_buffer_->memory(), buffer->GetData(), param.size_); | 249 memcpy(input_transfer_buffer_->memory(), buffer->GetData(), param.size); |
| 230 if (!channel_host_ || !channel_host_->Send( | 250 if (!channel_host_ || !channel_host_->Send( |
| 231 new GpuVideoDecoderMsg_EmptyThisBuffer(route_id(), param))) { | 251 new GpuVideoDecoderMsg_EmptyThisBuffer(route_id(), param))) { |
| 232 LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBuffer failed"; | 252 LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBuffer failed"; |
| 233 } | 253 } |
| 234 } | 254 } |
| OLD | NEW |