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