summaryrefslogtreecommitdiff
path: root/tv_input.cpp (plain)
blob: 4431ef720dbf6d08eebd37ea41736c65e910055d
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
47struct sideband_handle_t {
48 native_handle_t nativeHandle;
49 int identflag;
50 int usage;
51};
52
53typedef 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
62enum hdmi_port_id {
63 PORT_HDMI1 = 1,
64 PORT_HDMI3,
65 PORT_HDMI2,
66};
67
68static 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
87void TvIputHal_ChannelConl(tv_input_private_t *priv, int ops_type, int device_id)
88{
89 if (priv->mpTv) {
90 if (ops_type) {
91 LOGD ( "%s, OpenSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
92 priv->mpTv->StartTv();
93 priv->mpTv->SwitchSourceInput((tv_source_input_t) device_id);
94 } else if (priv->mpTv->GetCurrentSourceInput() == device_id) {
95 LOGD ( "%s, StopSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
96 priv->mpTv->StopTv();
97 }
98 }
99}
100
101static int notify_tv_device_status(tv_input_private_t *priv, tv_source_input_t source_input, int type)
102{
103 tv_input_event_t event;
104 event.device_info.device_id = source_input;
105 event.device_info.audio_type = AUDIO_DEVICE_NONE;
106 event.device_info.audio_address = NULL;
107 event.type = type;
108 switch (source_input) {
109 case SOURCE_TV:
110 case SOURCE_DTV:
111 event.device_info.type = TV_INPUT_TYPE_TUNER;
112 break;
113 case SOURCE_AV1:
114 case SOURCE_AV2:
115 event.device_info.type = TV_INPUT_TYPE_COMPONENT;
116 break;
117 case SOURCE_HDMI1:
118 case SOURCE_HDMI2:
119 case SOURCE_HDMI3:
120 event.device_info.type = TV_INPUT_TYPE_HDMI;
121 event.device_info.hdmi.port_id = getHdmiPort(source_input);
122 break;
123 case SOURCE_SPDIF:
124 event.device_info.type = TV_INPUT_TYPE_OTHER_HARDWARE;
125 break;
126 default:
127 break;
128 }
129 priv->callback->notify(&priv->device, &event, priv->callback_data);
130 return 0;
131}
132
133static int notify_TV_Input_Capture_Succeeded(tv_input_private_t *priv, int device_id, int stream_id, uint32_t seq)
134{
135 tv_input_event_t event;
136 event.type = TV_INPUT_EVENT_CAPTURE_SUCCEEDED;
137 event.capture_result.device_id = device_id;
138 event.capture_result.stream_id = stream_id;
139 event.capture_result.seq = seq;
140 priv->callback->notify(&priv->device, &event, priv->callback_data);
141 return 0;
142}
143
144static int notify_TV_Input_Capture_Fail(tv_input_private_t *priv, int device_id, int stream_id, uint32_t seq)
145{
146 tv_input_event_t event;
147 event.type = TV_INPUT_EVENT_CAPTURE_FAILED;
148 event.capture_result.device_id = device_id;
149 event.capture_result.stream_id = stream_id;
150 event.capture_result.seq = seq;
151 priv->callback->notify(&priv->device, &event, priv->callback_data);
152 return 0;
153}
154void TvCallback::onTvEvent (int32_t msgType, const Parcel &p)
155{
156 tv_input_private_t *priv = (tv_input_private_t *)(mPri);
157 switch (msgType) {
158 case SOURCE_CONNECT_CALLBACK: {
159 tv_source_input_t source = (tv_source_input_t)p.readInt32();
160 int connectState = p.readInt32();
161 LOGD("TvCallback::onTvEvent source = %d, status = %d", source, connectState);
162
163 if (source != SOURCE_HDMI1 && source != SOURCE_HDMI2 && source != SOURCE_HDMI3
164 && source != SOURCE_AV1 && source != SOURCE_AV2)
165 break;
166
167 if (connectState == 1) {
168 notify_tv_device_status(priv, source, TV_INPUT_EVENT_DEVICE_AVAILABLE);
169 notify_tv_device_status(priv, source, TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED);
170 } else {
171 notify_tv_device_status(priv, source, TV_INPUT_EVENT_DEVICE_UNAVAILABLE);
172 }
173 break;
174 }
175 default:
176 break;
177 }
178}
179
180#define NORMAL_STREAM_ID 1
181#define FRAME_CAPTURE_STREAM_ID 2
182static tv_stream_config_t mconfig[2];
183static int get_stream_configs(int dev_id, int *num_configurations, const tv_stream_config_t **configs)
184{
185 switch (dev_id) {
186 case SOURCE_TV:
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_DTV:
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_AV1:
211 case SOURCE_AV2:
212 mconfig[0].stream_id = NORMAL_STREAM_ID;
213 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
214 mconfig[0].max_video_width = 1920;
215 mconfig[0].max_video_height = 1080;
216 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
217 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
218 mconfig[1].max_video_width = 1920;
219 mconfig[1].max_video_height = 1080;
220 *num_configurations = 2;
221 *configs = mconfig;
222 break;
223 case SOURCE_HDMI1:
224 mconfig[0].stream_id = NORMAL_STREAM_ID;
225 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
226 mconfig[0].max_video_width = 1920;
227 mconfig[0].max_video_height = 1080;
228 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
229 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
230 mconfig[1].max_video_width = 1920;
231 mconfig[1].max_video_height = 1080;
232 *num_configurations = 2;
233 *configs = mconfig;
234 break;
235 case SOURCE_HDMI2:
236 mconfig[0].stream_id = NORMAL_STREAM_ID;
237 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
238 mconfig[0].max_video_width = 1920;
239 mconfig[0].max_video_height = 1080;
240 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
241 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
242 mconfig[1].max_video_width = 1920;
243 mconfig[1].max_video_height = 1080;
244 *num_configurations = 2;
245 *configs = mconfig;
246 break;
247 case SOURCE_HDMI3:
248 mconfig[0].stream_id = NORMAL_STREAM_ID;
249 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
250 mconfig[0].max_video_width = 1920;
251 mconfig[0].max_video_height = 1080;
252 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
253 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
254 mconfig[1].max_video_width = 1920;
255 mconfig[1].max_video_height = 1080;
256 *num_configurations = 2;
257 *configs = mconfig;
258 break;
259 case SOURCE_SPDIF:
260 mconfig[0].stream_id = NORMAL_STREAM_ID;
261 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
262 mconfig[0].max_video_width = 1920;
263 mconfig[0].max_video_height = 1080;
264 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
265 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
266 mconfig[1].max_video_width = 1920;
267 mconfig[1].max_video_height = 1080;
268 *num_configurations = 2;
269 *configs = mconfig;
270 break;
271 default:
272 break;
273 }
274 return 0;
275}
276
277static int get_tv_stream(tv_stream_t *stream)
278{
279 static struct sideband_handle_t *tvstream = NULL;
280 if (stream->stream_id == NORMAL_STREAM_ID) {
281 if ( !tvstream ) {
282 tvstream = (struct sideband_handle_t *)native_handle_create(0, 2);
283 if ( !tvstream ) {
284 return -EINVAL;
285 }
286 }
287 tvstream->identflag = 0xabcdcdef; //magic word
288 tvstream->usage = GRALLOC_USAGE_AML_VIDEO_OVERLAY;
289 stream->type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE;
290 stream->sideband_stream_source_handle = (native_handle_t *)tvstream;
291 } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) {
292 stream->type = TV_STREAM_TYPE_BUFFER_PRODUCER;
293 }
294 return 0;
295}
296
297static void available_all_tv_device(tv_input_private_t *priv)
298{
299 int tv_devices[15];
300 int count = 0;
301 priv->mpTv->getAllTvDevices(tv_devices, &count);
302
303 if (count == 0) {
304 ALOGE("tv.source.input.ids.default is not set.");
305 return;
306 }
307
308 notify_tv_device_status(priv, SOURCE_TV, TV_INPUT_EVENT_DEVICE_AVAILABLE);
309 notify_tv_device_status(priv, SOURCE_TV, TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED);
310
311 notify_tv_device_status(priv, SOURCE_DTV, TV_INPUT_EVENT_DEVICE_AVAILABLE);
312 notify_tv_device_status(priv, SOURCE_DTV, TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED);
313
314 if (priv->mpTv->GetHdmiAvHotplugDetectOnoff()) {
315 for (int i=0; i < count; i++) {
316 tv_source_input_t source_input = (tv_source_input_t)tv_devices[i];
317 if (source_input == SOURCE_TV || source_input == SOURCE_DTV)
318 continue;
319
320 int status = priv->mpTv->GetSourceConnectStatus(source_input);
321 if (status == 1) {
322 notify_tv_device_status(priv, source_input, TV_INPUT_EVENT_DEVICE_AVAILABLE);
323 notify_tv_device_status(priv, source_input, TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED);
324 }
325 }
326 priv->mpTv->setTvObserver(priv->tvcallback);
327 } else {
328 for (int i=0; i < count; i++) {
329 tv_source_input_t source_input = (tv_source_input_t)tv_devices[i];
330 if (source_input == SOURCE_TV || source_input == SOURCE_DTV)
331 continue;
332 notify_tv_device_status(priv, source_input, TV_INPUT_EVENT_DEVICE_AVAILABLE);
333 notify_tv_device_status(priv, source_input, TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED);
334 }
335 }
336}
337
338static int tv_input_device_open(const struct hw_module_t *module,
339 const char *name, struct hw_device_t **device);
340
341static struct hw_module_methods_t tv_input_module_methods = {
342open:
343 tv_input_device_open
344};
345
346tv_input_module_t HAL_MODULE_INFO_SYM = {
347common:
348 {
349tag:
350 HARDWARE_MODULE_TAG,
351 version_major: 0,
352 version_minor: 1,
353id:
354 TV_INPUT_HARDWARE_MODULE_ID,
355name: "TVInput module"
356 ,
357author: "Amlogic"
358 ,
359methods:
360 &tv_input_module_methods,
361dso: NULL,
362reserved: {0},
363 }
364};
365
366/*****************************************************************************/
367static int tv_input_initialize(struct tv_input_device *dev,
368 const tv_input_callback_ops_t *callback, void *data)
369{
370 if (dev == NULL || callback == NULL) {
371 return -EINVAL;
372 }
373 tv_input_private_t *priv = (tv_input_private_t *)dev;
374 if (priv->callback != NULL) {
375 return -EEXIST;
376 }
377 priv->callback = callback;
378 priv->callback_data = data;
379
380 available_all_tv_device(priv);
381 return 0;
382}
383
384static int tv_input_get_stream_configurations(const struct tv_input_device *dev __unused,
385 int device_id, int *num_configurations,
386 const tv_stream_config_t **configs)
387{
388 if (get_stream_configs(device_id, num_configurations, configs) == 0) {
389 return 0;
390 }
391 return -EINVAL;
392}
393
394static int tv_input_open_stream(struct tv_input_device *dev, int device_id,
395 tv_stream_t *stream)
396{
397 tv_input_private_t *priv = (tv_input_private_t *)dev;
398 if (priv) {
399 if (get_tv_stream(stream) != 0) {
400 return -EINVAL;
401 }
402 if (stream->stream_id == NORMAL_STREAM_ID) {
403 TvIputHal_ChannelConl(priv, 1, device_id);
404 return 0;
405 } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) {
406 aml_screen_module_t* mModule;
407 if (hw_get_module(AML_SCREEN_HARDWARE_MODULE_ID,
408 (const hw_module_t **)&mModule) < 0) {
409 ALOGE("can not get screen source module");
410 } else {
411 mModule->common.methods->open((const hw_module_t *)mModule,
412 AML_SCREEN_SOURCE, (struct hw_device_t**)&(priv->mDev));
413 //do test here, we can use ops of mDev to operate vdin source
414 }
415
416 if (priv->mDev) {
417 int mCustomW = stream->buffer_producer.width;
418 int mCustomH = stream->buffer_producer.height;
419 mBufferSize = mCustomW * mCustomH * 3/2;
420
421 priv->mDev->ops.set_format(priv->mDev, mCustomW, mCustomH, V4L2_PIX_FMT_NV21);
422 priv->mDev->ops.set_port_type(priv->mDev, (int)0x4000); //TVIN_PORT_HDMI0 = 0x4000
423 priv->mDev->ops.start_v4l2_device(priv->mDev);
424 }
425 return 0;
426 }
427 }
428 return -EINVAL;
429}
430
431static int tv_input_close_stream(struct tv_input_device *dev, int device_id,
432 int stream_id)
433{
434 tv_input_private_t *priv = (tv_input_private_t *)dev;
435 if (stream_id == NORMAL_STREAM_ID) {
436 TvIputHal_ChannelConl(priv, 0, device_id);
437 return 0;
438 } else if (stream_id == FRAME_CAPTURE_STREAM_ID) {
439 if (priv->mDev) {
440 priv->mDev->ops.stop_v4l2_device(priv->mDev);
441 }
442 return 0;
443 }
444 return -EINVAL;
445}
446
447static int tv_input_request_capture(
448 struct tv_input_device *dev __unused, int device_id __unused,
449 int stream_id __unused, buffer_handle_t* buffer __unused, uint32_t seq __unused)
450{
451 tv_input_private_t *priv = (tv_input_private_t *)dev;
452 int index;
453 aml_screen_buffer_info_t buff_info;
454 int mFrameWidth , mFrameHeight ;
455 int ret;
456 long *src = NULL;
457 unsigned char *dest = NULL;
458 ANativeWindowBuffer *buf;
459 if (priv->mDev) {
460 ret = priv->mDev->ops.aquire_buffer(priv->mDev, &buff_info);
461 if (ret != 0 || (buff_info.buffer_mem == 0)) {
462 LOGD("Get V4l2 buffer failed");
463 notify_TV_Input_Capture_Fail(priv,device_id,stream_id,--seq);
464 return -EWOULDBLOCK;
465 }
466 src = (long *)buff_info.buffer_mem;
467 buf = container_of(buffer, ANativeWindowBuffer, handle);
468 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
469 graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest);
470 if (dest == NULL) {
471 LOGD("Invalid Gralloc Handle");
472 return -EWOULDBLOCK;
473 }
474 memcpy(dest, src, mBufferSize);
475 graphicBuffer->unlock();
476 graphicBuffer.clear();
477 priv->mDev->ops.release_buffer(priv->mDev, src);
478
479 notify_TV_Input_Capture_Succeeded(priv,device_id,stream_id,seq);
480 return 0;
481 }
482 return -EWOULDBLOCK;
483}
484
485static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t)
486{
487 return -EINVAL;
488}
489
490/*****************************************************************************/
491
492static int tv_input_device_close(struct hw_device_t *dev)
493{
494 tv_input_private_t *priv = (tv_input_private_t *)dev;
495 if (priv) {
496 if (priv->mpTv) {
497 delete priv->mpTv;
498 }
499 if (priv->mDev) {
500 delete priv->mDev;
501 }
502 free(priv);
503 }
504 return 0;
505}
506
507/*****************************************************************************/
508
509static int tv_input_device_open(const struct hw_module_t *module,
510 const char *name, struct hw_device_t **device)
511{
512 int status = -EINVAL;
513 if (!strcmp(name, TV_INPUT_DEFAULT_DEVICE)) {
514 tv_input_private_t *dev = (tv_input_private_t *)malloc(sizeof(*dev));
515
516 /* initialize our state here */
517 memset(dev, 0, sizeof(*dev));
518 dev->mpTv = new TvPlay();
519 dev->tvcallback = new TvCallback(dev);
520 /* initialize the procs */
521 dev->device.common.tag = HARDWARE_DEVICE_TAG;
522 dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1;
523 dev->device.common.module = const_cast<hw_module_t *>(module);
524 dev->device.common.close = tv_input_device_close;
525
526 dev->device.initialize = tv_input_initialize;
527 dev->device.get_stream_configurations =
528 tv_input_get_stream_configurations;
529 dev->device.open_stream = tv_input_open_stream;
530 dev->device.close_stream = tv_input_close_stream;
531 dev->device.request_capture = tv_input_request_capture;
532 dev->device.cancel_capture = tv_input_cancel_capture;
533
534 *device = &dev->device.common;
535 status = 0;
536 }
537 return status;
538}
539