blob: 8c8a22499fa63c00d7057075b00992a4ac67a504
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 <tv/CTv.h> |
26 | #include <tvin/CTvin.h> |
27 | #include <tvserver/TvService.h> |
28 | #include <screen_source/v4l2_vdin.h> |
29 | #include <ui/GraphicBufferMapper.h> |
30 | #include <ui/GraphicBuffer.h> |
31 | /*****************************************************************************/ |
32 | |
33 | #define LOGD(...) \ |
34 | { \ |
35 | __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__); } |
36 | |
37 | #ifndef container_of |
38 | #define container_of(ptr, type, member) ({ \ |
39 | const typeof(((type *) 0)->member) *__mptr = (ptr); \ |
40 | (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); }) |
41 | #endif |
42 | |
43 | typedef struct tv_input_private { |
44 | tv_input_device_t device; |
45 | |
46 | // Callback related data |
47 | const tv_input_callback_ops_t *callback; |
48 | void *callback_data; |
49 | //TvService* pTvService; |
50 | CTv *pTv; |
51 | vdin_screen_source *pScreen; |
52 | } tv_input_private_t; |
53 | |
54 | static int notify_ATV_device_available(tv_input_private_t *priv) |
55 | { |
56 | tv_input_event_t event; |
57 | event.device_info.device_id = SOURCE_TV; |
58 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
59 | event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE; |
60 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
61 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
62 | return 0; |
63 | } |
64 | |
65 | static int notify_ATV_stream_configurations_change(tv_input_private_t *priv) |
66 | { |
67 | tv_input_event_t event; |
68 | event.device_info.device_id = SOURCE_TV; |
69 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
70 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
71 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
72 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
73 | return 0; |
74 | } |
75 | |
76 | static int notify_DTV_device_available(tv_input_private_t *priv) |
77 | { |
78 | tv_input_event_t event; |
79 | event.device_info.device_id = SOURCE_DTV; |
80 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
81 | event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE; |
82 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
83 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
84 | return 0; |
85 | } |
86 | |
87 | static int notify_DTV_stream_configurations_change(tv_input_private_t *priv) |
88 | { |
89 | tv_input_event_t event; |
90 | event.device_info.device_id = SOURCE_DTV; |
91 | event.device_info.type = TV_INPUT_TYPE_TUNER; |
92 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
93 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
94 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
95 | return 0; |
96 | } |
97 | |
98 | static int notify_AV_device_available(tv_input_private_t *priv) |
99 | { |
100 | tv_input_event_t event; |
101 | event.device_info.device_id = SOURCE_AV1; |
102 | event.device_info.type = TV_INPUT_TYPE_COMPONENT; |
103 | event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE; |
104 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
105 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
106 | return 0; |
107 | } |
108 | |
109 | static int notify_AV_stream_configurations_change(tv_input_private_t *priv) |
110 | { |
111 | tv_input_event_t event; |
112 | event.device_info.device_id = SOURCE_AV1; |
113 | event.device_info.type = TV_INPUT_TYPE_COMPONENT; |
114 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
115 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
116 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
117 | return 0; |
118 | } |
119 | |
120 | static int notify_HDMI_device_available(tv_input_private_t *priv, int dev_id, uint32_t port_id) |
121 | { |
122 | tv_input_event_t event; |
123 | event.device_info.device_id = dev_id; |
124 | event.device_info.type = TV_INPUT_TYPE_HDMI; |
125 | event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE; |
126 | event.device_info.hdmi.port_id = port_id; |
127 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
128 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
129 | return 0; |
130 | } |
131 | |
132 | static int notify_HDMI_stream_configurations_change(tv_input_private_t *priv, int dev_id, uint32_t port_id) |
133 | { |
134 | tv_input_event_t event; |
135 | event.device_info.device_id = dev_id; |
136 | event.device_info.type = TV_INPUT_TYPE_HDMI; |
137 | event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED; |
138 | event.device_info.hdmi.port_id = port_id; |
139 | event.device_info.audio_type = AUDIO_DEVICE_NONE; |
140 | priv->callback->notify(&priv->device, &event, priv->callback_data); |
141 | return 0; |
142 | } |
143 | |
144 | #define NORMAL_STREAM_ID 1 |
145 | #define FRAME_CAPTURE_STREAM_ID 2 |
146 | static tv_stream_config_t mconfig[2]; |
147 | static int get_stream_configs(int dev_id, int *num_configurations, const tv_stream_config_t **configs) |
148 | { |
149 | switch (dev_id) { |
150 | case SOURCE_TV: |
151 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
152 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
153 | mconfig[0].max_video_width = 1920; |
154 | mconfig[0].max_video_height = 1080; |
155 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
156 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
157 | mconfig[1].max_video_width = 1920; |
158 | mconfig[1].max_video_height = 1080; |
159 | *num_configurations = 2; |
160 | *configs = mconfig; |
161 | break; |
162 | case SOURCE_DTV: |
163 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
164 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
165 | mconfig[0].max_video_width = 1920; |
166 | mconfig[0].max_video_height = 1080; |
167 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
168 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
169 | mconfig[1].max_video_width = 1920; |
170 | mconfig[1].max_video_height = 1080; |
171 | *num_configurations = 2; |
172 | *configs = mconfig; |
173 | break; |
174 | case SOURCE_AV1: |
175 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
176 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
177 | mconfig[0].max_video_width = 1920; |
178 | mconfig[0].max_video_height = 1080; |
179 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
180 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
181 | mconfig[1].max_video_width = 1920; |
182 | mconfig[1].max_video_height = 1080; |
183 | *num_configurations = 2; |
184 | *configs = mconfig; |
185 | break; |
186 | case SOURCE_HDMI1: |
187 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
188 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
189 | mconfig[0].max_video_width = 1920; |
190 | mconfig[0].max_video_height = 1080; |
191 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
192 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
193 | mconfig[1].max_video_width = 1920; |
194 | mconfig[1].max_video_height = 1080; |
195 | *num_configurations = 2; |
196 | *configs = mconfig; |
197 | break; |
198 | case SOURCE_HDMI2: |
199 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
200 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
201 | mconfig[0].max_video_width = 1920; |
202 | mconfig[0].max_video_height = 1080; |
203 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
204 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
205 | mconfig[1].max_video_width = 1920; |
206 | mconfig[1].max_video_height = 1080; |
207 | *num_configurations = 2; |
208 | *configs = mconfig; |
209 | break; |
210 | case SOURCE_HDMI3: |
211 | mconfig[0].stream_id = NORMAL_STREAM_ID; |
212 | mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ; |
213 | mconfig[0].max_video_width = 1920; |
214 | mconfig[0].max_video_height = 1080; |
215 | mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID; |
216 | mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ; |
217 | mconfig[1].max_video_width = 1920; |
218 | mconfig[1].max_video_height = 1080; |
219 | *num_configurations = 2; |
220 | *configs = mconfig; |
221 | break; |
222 | default: |
223 | break; |
224 | } |
225 | return 0; |
226 | } |
227 | |
228 | static int get_tv_stream(tv_stream_t *stream) |
229 | { |
230 | if (stream->stream_id == NORMAL_STREAM_ID) { |
231 | native_handle *h = native_handle_create(0, 0); |
232 | if (!h) { |
233 | return -EINVAL; |
234 | } |
235 | stream->type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE; |
236 | stream->sideband_stream_source_handle = h; |
237 | } else if (stream->stream_id == NORMAL_STREAM_ID) { |
238 | stream->type = TV_STREAM_TYPE_BUFFER_PRODUCER; |
239 | } |
240 | return 0; |
241 | } |
242 | |
243 | static int tv_input_device_open(const struct hw_module_t *module, |
244 | const char *name, struct hw_device_t **device); |
245 | |
246 | static struct hw_module_methods_t tv_input_module_methods = { |
247 | open: |
248 | tv_input_device_open |
249 | }; |
250 | |
251 | tv_input_module_t HAL_MODULE_INFO_SYM = { |
252 | common: |
253 | { |
254 | tag: |
255 | HARDWARE_MODULE_TAG, |
256 | version_major: 0, |
257 | version_minor: 1, |
258 | id: |
259 | TV_INPUT_HARDWARE_MODULE_ID, |
260 | name: "TVInput module" |
261 | , |
262 | author: "Amlogic" |
263 | , |
264 | methods: |
265 | &tv_input_module_methods, |
266 | } |
267 | }; |
268 | |
269 | /*****************************************************************************/ |
270 | |
271 | static int tv_input_initialize(struct tv_input_device *dev, |
272 | const tv_input_callback_ops_t *callback, void *data) |
273 | { |
274 | if (dev == NULL || callback == NULL) { |
275 | return -EINVAL; |
276 | } |
277 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
278 | if (priv->callback != NULL) { |
279 | return -EEXIST; |
280 | } |
281 | |
282 | priv->callback = callback; |
283 | priv->callback_data = data; |
284 | /* ATV_DEVICE_AVAILABLE */ |
285 | notify_ATV_device_available(priv); |
286 | notify_ATV_stream_configurations_change(priv); |
287 | /* DTV_DEVICE_AVAILABLE */ |
288 | notify_DTV_device_available(priv); |
289 | notify_DTV_stream_configurations_change(priv); |
290 | /* AV_DEVICE_AVAILABLE */ |
291 | notify_AV_device_available(priv); |
292 | notify_AV_stream_configurations_change(priv); |
293 | /* HDMI1_DEVICE_AVAILABLE */ |
294 | notify_HDMI_device_available(priv, SOURCE_HDMI1, 1); |
295 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI1, 1); |
296 | /* HDMI2_DEVICE_AVAILABLE */ |
297 | notify_HDMI_device_available(priv, SOURCE_HDMI2, 1); |
298 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, 1); |
299 | /* HDMI3_DEVICE_AVAILABLE */ |
300 | notify_HDMI_device_available(priv, SOURCE_HDMI3, 1); |
301 | notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, 1); |
302 | // |
303 | return 0; |
304 | } |
305 | |
306 | static int tv_input_get_stream_configurations(const struct tv_input_device *dev, |
307 | int device_id, int *num_configurations, |
308 | const tv_stream_config_t **configs) |
309 | { |
310 | if (get_stream_configs(device_id, num_configurations, configs) == 0) { |
311 | return 0; |
312 | } |
313 | return -EINVAL; |
314 | } |
315 | |
316 | static int tv_input_open_stream(struct tv_input_device *dev, int device_id, |
317 | tv_stream_t *stream) |
318 | { |
319 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
320 | if (priv) { |
321 | if (get_tv_stream(stream) != 0) { |
322 | return -EINVAL; |
323 | } |
324 | if (stream->stream_id == NORMAL_STREAM_ID) { |
325 | LOGD ( "%s, SetSourceSwitchInput id = %d\n", __FUNCTION__, device_id ); |
326 | priv->pTv->StartTvLock(); |
327 | priv->pTv->SetSourceSwitchInput((tv_source_input_t) device_id); |
328 | return 0; |
329 | } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) { |
330 | priv->pScreen->set_format(1920, 1080, V4L2_PIX_FMT_NV21); |
331 | priv->pScreen->start_v4l2_device(); |
332 | return 0; |
333 | } |
334 | } |
335 | return -EINVAL; |
336 | } |
337 | |
338 | static int tv_input_close_stream(struct tv_input_device *dev, int device_id, |
339 | int stream_id) |
340 | { |
341 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
342 | if (stream_id == NORMAL_STREAM_ID) { |
343 | LOGD ( "%s, SetSourceSwitchInput id = %d\n", __FUNCTION__, device_id ); |
344 | priv->pTv->StopTvLock(); |
345 | return 0; |
346 | } else if (stream_id == FRAME_CAPTURE_STREAM_ID) { |
347 | priv->pScreen->stop_v4l2_device(); |
348 | return 0; |
349 | } |
350 | return -EINVAL; |
351 | } |
352 | |
353 | static int tv_input_request_capture( |
354 | struct tv_input_device *dev, int device_id, int stream_id, buffer_handle_t buffer, uint32_t seq) |
355 | { |
356 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
357 | int index; |
358 | aml_screen_buffer_info_t buff_info; |
359 | int mFrameWidth , mFrameHeight ; |
360 | int ret; |
361 | long *src = NULL; |
362 | unsigned char *dest = NULL; |
363 | ANativeWindowBuffer *buf; |
364 | ret = priv->pScreen->aquire_buffer(&buff_info); |
365 | if (ret != 0 || (buff_info.buffer_mem == 0)) { |
366 | LOGD("Get V4l2 buffer failed"); |
367 | return -EWOULDBLOCK; |
368 | } |
369 | src = (long *)buff_info.buffer_mem; |
370 | |
371 | buf = container_of(&buffer, ANativeWindowBuffer, handle); |
372 | |
373 | sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); |
374 | graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest); |
375 | if (dest == NULL) { |
376 | LOGD("Invalid Gralloc Handle"); |
377 | return -EWOULDBLOCK; |
378 | } |
379 | memcpy(dest, src, mFrameWidth * mFrameHeight * 3 / 2); |
380 | graphicBuffer->unlock(); |
381 | graphicBuffer.clear(); |
382 | LOGD("queue one buffer to native window"); |
383 | priv->pScreen->release_buffer(src); |
384 | return 0; |
385 | } |
386 | |
387 | static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t) |
388 | { |
389 | return -EINVAL; |
390 | } |
391 | |
392 | /*****************************************************************************/ |
393 | |
394 | static int tv_input_device_close(struct hw_device_t *dev) |
395 | { |
396 | tv_input_private_t *priv = (tv_input_private_t *)dev; |
397 | if (priv->pTv != NULL) { |
398 | delete priv->pTv; |
399 | } |
400 | if (priv) { |
401 | free(priv); |
402 | } |
403 | return 0; |
404 | } |
405 | |
406 | /*****************************************************************************/ |
407 | |
408 | static int tv_input_device_open(const struct hw_module_t *module, |
409 | const char *name, struct hw_device_t **device) |
410 | { |
411 | int status = -EINVAL; |
412 | if (!strcmp(name, TV_INPUT_DEFAULT_DEVICE)) { |
413 | tv_input_private_t *dev = (tv_input_private_t *)malloc(sizeof(*dev)); |
414 | |
415 | /* initialize our state here */ |
416 | memset(dev, 0, sizeof(*dev)); |
417 | /*intialize tv*/ |
418 | dev->pTv = new CTv(); |
419 | TvService::instantiate(dev->pTv); |
420 | dev->pTv->OpenTv(); |
421 | dev->pScreen = new vdin_screen_source(); |
422 | if (dev->pScreen->init() != 0 ) { |
423 | LOGD("init screen source not ok!"); |
424 | } |
425 | /* initialize the procs */ |
426 | dev->device.common.tag = HARDWARE_DEVICE_TAG; |
427 | dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1; |
428 | dev->device.common.module = const_cast<hw_module_t *>(module); |
429 | dev->device.common.close = tv_input_device_close; |
430 | |
431 | dev->device.initialize = tv_input_initialize; |
432 | dev->device.get_stream_configurations = |
433 | tv_input_get_stream_configurations; |
434 | dev->device.open_stream = tv_input_open_stream; |
435 | dev->device.close_stream = tv_input_close_stream; |
436 | dev->device.request_capture = tv_input_request_capture; |
437 | dev->device.cancel_capture = tv_input_cancel_capture; |
438 | |
439 | *device = &dev->device.common; |
440 | status = 0; |
441 | } |
442 | return status; |
443 | } |
444 |