blob: 7da87107cb95ae44079ce2be3641ac8e6b1da8b6
1 | /* |
2 | * Copyright 2014 The Android Open Source Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #define LOG_TAG "TvInput" |
18 | #include <fcntl.h> |
19 | #include <errno.h> |
20 | |
21 | #include <cutils/log.h> |
22 | #include <cutils/native_handle.h> |
23 | |
24 | #include <hardware/tv_input.h> |
25 | #include "TvPlay.h" |
26 | #include "tv_callback.h" |
27 | #include <tvcmd.h> |
28 | #include <ui/GraphicBufferMapper.h> |
29 | #include <ui/GraphicBuffer.h> |
30 | #include <gralloc_priv.h> |
31 | #include <gralloc_helper.h> |
32 | #include <hardware/hardware.h> |
33 | #include <hardware/aml_screen.h> |
34 | #include <linux/videodev2.h> |
35 | #include <android/native_window.h> |
36 | /*****************************************************************************/ |
37 | |
38 | #define LOGD(...) \ |
39 | { \ |
40 | __android_log_print(ANDROID_LOG_DEBUG, "tv_input", __VA_ARGS__); } |
41 | |
42 | #ifndef container_of |
43 | #define container_of(ptr, type, member) \ |
44 | (type *)((char*)(ptr) - offsetof(type, member)) |
45 | #endif |
46 | |
47 | struct sideband_handle_t { |
48 | native_handle_t nativeHandle; |
49 | int identflag; |
50 | int usage; |
51 | }; |
52 | |
53 | typedef struct tv_input_private { |
54 | tv_input_device_t device; |
55 | const tv_input_callback_ops_t *callback; |
56 | void *callback_data; |
57 | aml_screen_device_t *mDev; |
58 | TvPlay *mpTv; |
59 | TvCallback *tvcallback; |
60 | } tv_input_private_t; |
61 | |
62 | enum hdmi_port_id { |
63 | PORT_HDMI1 = 1, |
64 | PORT_HDMI3, |
65 | PORT_HDMI2, |
66 | }; |
67 | |
68 | static int getHdmiPort(tv_source_input_t source_input) |
69 | { |
70 | int port = PORT_HDMI1; |
71 | switch (source_input) { |
72 | case SOURCE_HDMI1: |
73 | port = PORT_HDMI1; |
74 | break; |
75 | case SOURCE_HDMI2: |
76 | port = PORT_HDMI2; |
77 | break; |
78 | case SOURCE_HDMI3: |
79 | port = PORT_HDMI3; |
80 | break; |
81 | default: |
82 | break; |
83 | } |
84 | return port; |
85 | } |
86 | |
87 | static int notify_ATV_device_available(tv_input_private_t *priv) |
88 | { |
89 | tv_input_event_t event; |
90 | event.device_info.device_id = SOURCE_TV; |
91 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
92 | event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE; |
93 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
94 | event.device_info.audio_address = NULL; |
95 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
96 | return 0; |
97 | } |
98 | |
99 | static int notify_ATV_stream_configurations_change(tv_input_private_t *priv) |
100 | { |
101 | tv_input_event_t event; |
102 | event.device_info.device_id = SOURCE_TV; |
103 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
104 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
105 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
106 | event.device_info.audio_address = NULL; |
107 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
108 | return 0; |
109 | } |
110 | |
111 | static int notify_DTV_device_available(tv_input_private_t *priv) |
112 | { |
113 | tv_input_event_t event; |
114 | event.device_info.device_id = SOURCE_DTV; |
115 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
116 | event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE; |
117 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
118 | event.device_info.audio_address = NULL; |
119 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
120 | return 0; |
121 | } |
122 | |
123 | static int notify_DTV_stream_configurations_change(tv_input_private_t *priv) |
124 | { |
125 | tv_input_event_t event; |
126 | event.device_info.device_id = SOURCE_DTV; |
127 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
128 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
129 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
130 | event.device_info.audio_address = NULL; |
131 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
132 | return 0; |
133 | } |
134 | |
135 | void TvIputHal_ChannelConl(tv_input_private_t *priv, int ops_type, int device_id) |
136 | { |
137 | if (priv->mpTv) { |
138 | if (ops_type) { |
139 | LOGD ( "%s, OpenSourceSwitchInput id = %d\n", __FUNCTION__, device_id ); |
140 | priv->mpTv->StartTv(); |
141 | priv->mpTv->SwitchSourceInput((tv_source_input_t) device_id); |
142 | } else if (priv->mpTv->GetCurrentSourceInput() == device_id) { |
143 | LOGD ( "%s, StopSourceSwitchInput id = %d\n", __FUNCTION__, device_id ); |
144 | priv->mpTv->StopTv(); |
145 | } |
146 | } |
147 | } |
148 | |
149 | static int notify_AV_device_available(tv_input_private_t *priv, tv_source_input_t source_input, int type) |
150 | { |
151 | tv_input_event_t event; |
152 | event.device_info.device_id = source_input; |
153 | event.device_info.type = TV_INPUT_TYPE_COMPONENT; |
154 | event.type = type; |
155 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
156 | event.device_info.audio_address = NULL; |
157 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
158 | return 0; |
159 | } |
160 | |
161 | static int notify_AV_stream_configurations_change(tv_input_private_t *priv, tv_source_input_t source_input) |
162 | { |
163 | tv_input_event_t event; |
164 | event.device_info.device_id = source_input; |
165 | event.device_info.type = TV_INPUT_TYPE_COMPONENT; |
166 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
167 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
168 | event.device_info.audio_address = NULL; |
169 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
170 | return 0; |
171 | } |
172 | |
173 | static int notify_HDMI_device_available(tv_input_private_t *priv, tv_source_input_t source_input, uint32_t port_id, int type) |
174 | { |
175 | tv_input_event_t event; |
176 | event.device_info.device_id = source_input; |
177 | event.device_info.type = TV_INPUT_TYPE_HDMI; |
178 | event.type = type; |
179 | event.device_info.hdmi.port_id = port_id; |
180 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
181 | event.device_info.audio_address = NULL; |
182 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
183 | return 0; |
184 | } |
185 | |
186 | static int notify_HDMI_stream_configurations_change(tv_input_private_t *priv, tv_source_input_t source_input, uint32_t port_id) |
187 | { |
188 | tv_input_event_t event; |
189 | event.device_info.device_id = source_input; |
190 | event.device_info.type = TV_INPUT_TYPE_HDMI; |
191 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
192 | event.device_info.hdmi.port_id = port_id; |
193 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
194 | event.device_info.audio_address = NULL; |
195 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
196 | return 0; |
197 | } |
198 | |
199 | static int notify_TV_Input_Capture_Succeeded(tv_input_private_t *priv, int device_id, int stream_id, uint32_t seq) |
200 | { |
201 | tv_input_event_t event; |
202 | event.type = TV_INPUT_EVENT_CAPTURE_SUCCEEDED; |
203 | event.capture_result.device_id = device_id; |
204 | event.capture_result.stream_id = stream_id; |
205 | event.capture_result.seq = seq; |
206 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
207 | return 0; |
208 | } |
209 | |
210 | static int notify_TV_Input_Capture_Fail(tv_input_private_t *priv, int device_id, int stream_id, uint32_t seq) |
211 | { |
212 | tv_input_event_t event; |
213 | event.type = TV_INPUT_EVENT_CAPTURE_FAILED; |
214 | event.capture_result.device_id = device_id; |
215 | event.capture_result.stream_id = stream_id; |
216 | event.capture_result.seq = seq; |
217 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
218 | return 0; |
219 | } |
220 | void TvCallback::onTvEvent (int32_t msgType, const Parcel &p) |
221 | { |
222 | tv_input_private_t *priv = (tv_input_private_t *)(mPri); |
223 | switch (msgType) { |
224 | case SOURCE_CONNECT_CALLBACK: { |
225 | int source = p.readInt32(); |
226 | int connectState = p.readInt32(); |
227 | LOGD("TvCallback::onTvEvent source = %d, status = %d", source, connectState) |
228 | |
229 | switch (source) { |
230 | case SOURCE_HDMI1: |
231 | case SOURCE_HDMI2: |
232 | case SOURCE_HDMI3: { |
233 | if (connectState == 1) { |
234 | notify_HDMI_device_available(priv, (tv_source_input_t)source, getHdmiPort((tv_source_input_t)source), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
235 | notify_HDMI_stream_configurations_change(priv, (tv_source_input_t)source, getHdmiPort((tv_source_input_t)source)); |
236 | } else { |
237 | notify_HDMI_device_available(priv, (tv_source_input_t)source, getHdmiPort((tv_source_input_t)source), TV_INPUT_EVENT_DEVICE_UNAVAILABLE); |
238 | } |
239 | } |
240 | break; |
241 | |
242 | case SOURCE_AV1: |
243 | case SOURCE_AV2: { |
244 | if (connectState == 1) { |
245 | notify_AV_device_available(priv, (tv_source_input_t)source, TV_INPUT_EVENT_DEVICE_AVAILABLE); |
246 | notify_AV_stream_configurations_change(priv, (tv_source_input_t)source); |
247 | } else { |
248 | notify_AV_device_available(priv, (tv_source_input_t)source, TV_INPUT_EVENT_DEVICE_UNAVAILABLE); |
249 | } |
250 | } |
251 | break; |
252 | |
253 | default: |
254 | break; |
255 | } |
256 | } |
257 | break; |
258 | |
259 | default: |
260 | break; |
261 | } |
262 | } |
263 | |
264 | #define NORMAL_STREAM_ID 1 |
265 | #define FRAME_CAPTURE_STREAM_ID 2 |
266 | static tv_stream_config_t mconfig[2]; |
267 | static int get_stream_configs(int dev_id, int *num_configurations, const tv_stream_config_t **configs) |
268 | { |
269 | switch (dev_id) { |
270 | case SOURCE_TV: |
271 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
272 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
273 | mconfig[0].max_video_width = 1920; |
274 | mconfig[0].max_video_height = 1080; |
275 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
276 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
277 | mconfig[1].max_video_width = 1920; |
278 | mconfig[1].max_video_height = 1080; |
279 | *num_configurations = 2; |
280 | *configs = mconfig; |
281 | break; |
282 | case SOURCE_DTV: |
283 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
284 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
285 | mconfig[0].max_video_width = 1920; |
286 | mconfig[0].max_video_height = 1080; |
287 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
288 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
289 | mconfig[1].max_video_width = 1920; |
290 | mconfig[1].max_video_height = 1080; |
291 | *num_configurations = 2; |
292 | *configs = mconfig; |
293 | break; |
294 | case SOURCE_AV1: |
295 | case SOURCE_AV2: |
296 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
297 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
298 | mconfig[0].max_video_width = 1920; |
299 | mconfig[0].max_video_height = 1080; |
300 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
301 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
302 | mconfig[1].max_video_width = 1920; |
303 | mconfig[1].max_video_height = 1080; |
304 | *num_configurations = 2; |
305 | *configs = mconfig; |
306 | break; |
307 | case SOURCE_HDMI1: |
308 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
309 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
310 | mconfig[0].max_video_width = 1920; |
311 | mconfig[0].max_video_height = 1080; |
312 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
313 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
314 | mconfig[1].max_video_width = 1920; |
315 | mconfig[1].max_video_height = 1080; |
316 | *num_configurations = 2; |
317 | *configs = mconfig; |
318 | break; |
319 | case SOURCE_HDMI2: |
320 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
321 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
322 | mconfig[0].max_video_width = 1920; |
323 | mconfig[0].max_video_height = 1080; |
324 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
325 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
326 | mconfig[1].max_video_width = 1920; |
327 | mconfig[1].max_video_height = 1080; |
328 | *num_configurations = 2; |
329 | *configs = mconfig; |
330 | break; |
331 | case SOURCE_HDMI3: |
332 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
333 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
334 | mconfig[0].max_video_width = 1920; |
335 | mconfig[0].max_video_height = 1080; |
336 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
337 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
338 | mconfig[1].max_video_width = 1920; |
339 | mconfig[1].max_video_height = 1080; |
340 | *num_configurations = 2; |
341 | *configs = mconfig; |
342 | break; |
343 | default: |
344 | break; |
345 | } |
346 | return 0; |
347 | } |
348 | |
349 | static int get_tv_stream(tv_stream_t *stream) |
350 | { |
351 | static struct sideband_handle_t *tvstream = NULL; |
352 | if (stream->stream_id == NORMAL_STREAM_ID) { |
353 | if ( !tvstream ) { |
354 | tvstream = (struct sideband_handle_t *)native_handle_create(0, 2); |
355 | if ( !tvstream ) { |
356 | return -EINVAL; |
357 | } |
358 | } |
359 | tvstream->identflag = 0xabcdcdef; //magic word |
360 | tvstream->usage = GRALLOC_USAGE_AML_VIDEO_OVERLAY; |
361 | stream->type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE; |
362 | stream->sideband_stream_source_handle = (native_handle_t *)tvstream; |
363 | } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) { |
364 | stream->type = TV_STREAM_TYPE_BUFFER_PRODUCER; |
365 | } |
366 | return 0; |
367 | } |
368 | |
369 | static int tv_input_device_open(const struct hw_module_t *module, |
370 | const char *name, struct hw_device_t **device); |
371 | |
372 | static struct hw_module_methods_t tv_input_module_methods = { |
373 | open: |
374 | tv_input_device_open |
375 | }; |
376 | |
377 | tv_input_module_t HAL_MODULE_INFO_SYM = { |
378 | common: |
379 | { |
380 | tag: |
381 | HARDWARE_MODULE_TAG, |
382 | version_major: 0, |
383 | version_minor: 1, |
384 | id: |
385 | TV_INPUT_HARDWARE_MODULE_ID, |
386 | name: "TVInput module" |
387 | , |
388 | author: "Amlogic" |
389 | , |
390 | methods: |
391 | &tv_input_module_methods, |
392 | dso: NULL, |
393 | reserved: {0}, |
394 | } |
395 | }; |
396 | |
397 | /*****************************************************************************/ |
398 | static int tv_input_initialize(struct tv_input_device *dev, |
399 | const tv_input_callback_ops_t *callback, void *data) |
400 | { |
401 | if (dev == NULL || callback == NULL) { |
402 | return -EINVAL; |
403 | } |
404 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
405 | if (priv->callback != NULL) { |
406 | return -EEXIST; |
407 | } |
408 | priv->callback = callback; |
409 | priv->callback_data = data; |
410 | /* ATV_DEVICE_AVAILABLE */ |
411 | notify_ATV_device_available(priv); |
412 | notify_ATV_stream_configurations_change(priv); |
413 | /* DTV_DEVICE_AVAILABLE */ |
414 | notify_DTV_device_available(priv); |
415 | notify_DTV_stream_configurations_change(priv); |
416 | |
417 | if (priv->mpTv->GetHdmiAvHotplugDetectOnoff()) { |
418 | /* AV1_DEVICE_AVAILABLE */ |
419 | int status = priv->mpTv->GetSourceConnectStatus(SOURCE_AV1); |
420 | if (status == 1) { //IN |
421 | notify_AV_device_available(priv, SOURCE_AV1, TV_INPUT_EVENT_DEVICE_AVAILABLE); |
422 | notify_AV_stream_configurations_change(priv, SOURCE_AV1); |
423 | } |
424 | |
425 | /* AV2_DEVICE_AVAILABLE */ |
426 | status = priv->mpTv->GetSourceConnectStatus(SOURCE_AV2); |
427 | if (status == 1) { //IN |
428 | notify_AV_device_available(priv, SOURCE_AV2, TV_INPUT_EVENT_DEVICE_AVAILABLE); |
429 | notify_AV_stream_configurations_change(priv, SOURCE_AV2); |
430 | } |
431 | |
432 | /* HDMI1_DEVICE_AVAILABLE */ |
433 | status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI1); |
434 | if (status == 1) { //IN |
435 | notify_HDMI_device_available(priv, SOURCE_HDMI1, getHdmiPort(SOURCE_HDMI1), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
436 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI1, getHdmiPort(SOURCE_HDMI1)); |
437 | } |
438 | |
439 | /* HDMI2_DEVICE_AVAILABLE */ |
440 | status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI2); |
441 | if (status == 1) { //IN |
442 | notify_HDMI_device_available(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
443 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2)); |
444 | } |
445 | |
446 | /* HDMI3_DEVICE_AVAILABLE */ |
447 | status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI3); |
448 | if (status == 1) { //IN |
449 | notify_HDMI_device_available(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
450 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3)); |
451 | } |
452 | |
453 | priv->mpTv->setTvObserver(priv->tvcallback); |
454 | } else { |
455 | /* AV1_DEVICE_AVAILABLE */ |
456 | notify_AV_device_available(priv, SOURCE_AV1, TV_INPUT_EVENT_DEVICE_AVAILABLE); |
457 | notify_AV_stream_configurations_change(priv, SOURCE_AV1); |
458 | /* AV2_DEVICE_AVAILABLE */ |
459 | notify_AV_device_available(priv, SOURCE_AV2, TV_INPUT_EVENT_DEVICE_AVAILABLE); |
460 | notify_AV_stream_configurations_change(priv, SOURCE_AV2); |
461 | /* HDMI1_DEVICE_AVAILABLE */ |
462 | notify_HDMI_device_available(priv, SOURCE_HDMI1, getHdmiPort(SOURCE_HDMI1), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
463 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI1, getHdmiPort(SOURCE_HDMI1)); |
464 | /* HDMI2_DEVICE_AVAILABLE */ |
465 | notify_HDMI_device_available(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
466 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2)); |
467 | /* HDMI3_DEVICE_AVAILABLE */ |
468 | notify_HDMI_device_available(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3), TV_INPUT_EVENT_DEVICE_AVAILABLE); |
469 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3)); |
470 | } |
471 | return 0; |
472 | } |
473 | |
474 | static int tv_input_get_stream_configurations(const struct tv_input_device *dev __unused, |
475 | int device_id, int *num_configurations, |
476 | const tv_stream_config_t **configs) |
477 | { |
478 | if (get_stream_configs(device_id, num_configurations, configs) == 0) { |
479 | return 0; |
480 | } |
481 | return -EINVAL; |
482 | } |
483 | |
484 | static int tv_input_open_stream(struct tv_input_device *dev, int device_id, |
485 | tv_stream_t *stream) |
486 | { |
487 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
488 | if (priv) { |
489 | if (get_tv_stream(stream) != 0) { |
490 | return -EINVAL; |
491 | } |
492 | if (stream->stream_id == NORMAL_STREAM_ID) { |
493 | TvIputHal_ChannelConl(priv, 1, device_id); |
494 | return 0; |
495 | } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) { |
496 | aml_screen_module_t* mModule; |
497 | if (hw_get_module(AML_SCREEN_HARDWARE_MODULE_ID, |
498 | (const hw_module_t **)&mModule) < 0) { |
499 | ALOGE("can not get screen source module"); |
500 | } else { |
501 | mModule->common.methods->open((const hw_module_t *)mModule, |
502 | AML_SCREEN_SOURCE, (struct hw_device_t**)&(priv->mDev)); |
503 | //do test here, we can use ops of mDev to operate vdin source |
504 | } |
505 | |
506 | if (priv->mDev) { |
507 | int mCustomW = stream->buffer_producer.width; |
508 | int mCustomH = stream->buffer_producer.height; |
509 | mBufferSize = mCustomW * mCustomH * 3/2; |
510 | |
511 | priv->mDev->ops.set_format(priv->mDev, mCustomW, mCustomH, V4L2_PIX_FMT_NV21); |
512 | priv->mDev->ops.set_port_type(priv->mDev, (int)0x4000); //TVIN_PORT_HDMI0 = 0x4000 |
513 | priv->mDev->ops.start_v4l2_device(priv->mDev); |
514 | } |
515 | return 0; |
516 | } |
517 | } |
518 | return -EINVAL; |
519 | } |
520 | |
521 | static int tv_input_close_stream(struct tv_input_device *dev, int device_id, |
522 | int stream_id) |
523 | { |
524 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
525 | if (stream_id == NORMAL_STREAM_ID) { |
526 | TvIputHal_ChannelConl(priv, 0, device_id); |
527 | return 0; |
528 | } else if (stream_id == FRAME_CAPTURE_STREAM_ID) { |
529 | if (priv->mDev) { |
530 | priv->mDev->ops.stop_v4l2_device(priv->mDev); |
531 | } |
532 | return 0; |
533 | } |
534 | return -EINVAL; |
535 | } |
536 | |
537 | static int tv_input_request_capture( |
538 | struct tv_input_device *dev __unused, int device_id __unused, |
539 | int stream_id __unused, buffer_handle_t* buffer __unused, uint32_t seq __unused) |
540 | { |
541 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
542 | int index; |
543 | aml_screen_buffer_info_t buff_info; |
544 | int mFrameWidth , mFrameHeight ; |
545 | int ret; |
546 | long *src = NULL; |
547 | unsigned char *dest = NULL; |
548 | ANativeWindowBuffer *buf; |
549 | if (priv->mDev) { |
550 | ret = priv->mDev->ops.aquire_buffer(priv->mDev, &buff_info); |
551 | if (ret != 0 || (buff_info.buffer_mem == 0)) { |
552 | LOGD("Get V4l2 buffer failed"); |
553 | notify_TV_Input_Capture_Fail(priv,device_id,stream_id,--seq); |
554 | return -EWOULDBLOCK; |
555 | } |
556 | src = (long *)buff_info.buffer_mem; |
557 | buf = container_of(buffer, ANativeWindowBuffer, handle); |
558 | sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); |
559 | graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest); |
560 | if (dest == NULL) { |
561 | LOGD("Invalid Gralloc Handle"); |
562 | return -EWOULDBLOCK; |
563 | } |
564 | memcpy(dest, src, mBufferSize); |
565 | graphicBuffer->unlock(); |
566 | graphicBuffer.clear(); |
567 | priv->mDev->ops.release_buffer(priv->mDev, src); |
568 | |
569 | notify_TV_Input_Capture_Succeeded(priv,device_id,stream_id,seq); |
570 | return 0; |
571 | } |
572 | return -EWOULDBLOCK; |
573 | } |
574 | |
575 | static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t) |
576 | { |
577 | return -EINVAL; |
578 | } |
579 | |
580 | /*****************************************************************************/ |
581 | |
582 | static int tv_input_device_close(struct hw_device_t *dev) |
583 | { |
584 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
585 | if (priv) { |
586 | if (priv->mpTv) { |
587 | delete priv->mpTv; |
588 | } |
589 | if (priv->mDev) { |
590 | delete priv->mDev; |
591 | } |
592 | free(priv); |
593 | } |
594 | return 0; |
595 | } |
596 | |
597 | /*****************************************************************************/ |
598 | |
599 | static int tv_input_device_open(const struct hw_module_t *module, |
600 | const char *name, struct hw_device_t **device) |
601 | { |
602 | int status = -EINVAL; |
603 | if (!strcmp(name, TV_INPUT_DEFAULT_DEVICE)) { |
604 | tv_input_private_t *dev = (tv_input_private_t *)malloc(sizeof(*dev)); |
605 | |
606 | /* initialize our state here */ |
607 | memset(dev, 0, sizeof(*dev)); |
608 | dev->mpTv = new TvPlay(); |
609 | dev->tvcallback = new TvCallback(dev); |
610 | /* initialize the procs */ |
611 | dev->device.common.tag = HARDWARE_DEVICE_TAG; |
612 | dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1; |
613 | dev->device.common.module = const_cast<hw_module_t *>(module); |
614 | dev->device.common.close = tv_input_device_close; |
615 | |
616 | dev->device.initialize = tv_input_initialize; |
617 | dev->device.get_stream_configurations = |
618 | tv_input_get_stream_configurations; |
619 | dev->device.open_stream = tv_input_open_stream; |
620 | dev->device.close_stream = tv_input_close_stream; |
621 | dev->device.request_capture = tv_input_request_capture; |
622 | dev->device.cancel_capture = tv_input_cancel_capture; |
623 | |
624 | *device = &dev->device.common; |
625 | status = 0; |
626 | } |
627 | return status; |
628 | } |
629 |