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