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 |