summaryrefslogtreecommitdiff
path: root/tvapi/libtv/tv/CTvSubtitle.cpp (plain)
blob: 2b9505e254476d24627d03aa00092d5bf654451e
1//
2//
3// amlogic 2013
4//
5// @ Project : tv
6// @ Date : 2013-11
7// @ Author :
8//
9#define LOG_TAG "CTvSubtitle"
10
11#include "CTvSubtitle.h"
12#include "am_misc.h"
13#include "am_dmx.h"
14
15CTvSubtitle::CTvSubtitle()
16{
17 mpObser = NULL;
18}
19
20CTvSubtitle::~CTvSubtitle()
21{
22}
23
24void CTvSubtitle::setObserver(IObserver *pObser)
25{
26 isSubOpen = false;
27 mpObser = pObser;
28}
29
30void CTvSubtitle::setBuffer(char *share_mem)
31{
32 pthread_mutex_lock(&lock);
33 buffer = (unsigned char *)share_mem;
34 pthread_mutex_unlock(&lock);
35}
36
37void CTvSubtitle::stopDecoder()
38{
39}
40
41/**
42 * 开始字幕信息解析showboz sync
43 */
44void CTvSubtitle::startSub()
45{
46}
47
48/**
49 * 停止图文/字幕信息解析
50 */
51void CTvSubtitle::stop()
52{
53}
54
55/**
56 * 停止图文/字幕信息解析并清除缓存数据
57 */
58void CTvSubtitle::clear()
59{
60}
61
62/**
63 * 在图文模式下进入下一页
64 */
65void CTvSubtitle::nextPage()
66{
67}
68
69/**
70 * 在图文模式下进入上一页
71 */
72void CTvSubtitle::previousPage()
73{
74}
75
76/**
77 * 在图文模式下跳转到指定页
78 * @param page 要跳转到的页号
79 */
80void CTvSubtitle::gotoPage(int page __unused)
81{
82}
83
84/**
85 * 在图文模式下跳转到home页
86 */
87void CTvSubtitle::goHome()
88{
89}
90
91/**
92 * 在图文模式下根据颜色跳转到指定链接
93 * @param color 颜色,COLOR_RED/COLOR_GREEN/COLOR_YELLOW/COLOR_BLUE
94 */
95void CTvSubtitle::colorLink(int color __unused)
96{
97}
98
99/**
100 * 在图文模式下设定搜索字符串
101 * @param pattern 搜索匹配字符串
102 * @param casefold 是否区分大小写
103 */
104void CTvSubtitle::setSearchPattern(char *pattern __unused, bool casefold __unused)
105{
106}
107
108/**
109 * 搜索下一页
110 */
111void CTvSubtitle::searchNext()
112{
113}
114
115/**
116 * 搜索上一页
117 */
118void CTvSubtitle::searchPrevious()
119{
120}
121
122int CTvSubtitle::sub_init(int bmp_width, int bmp_height)
123{
124 pthread_mutex_init(&lock, NULL);
125 bmp_w = bmp_width;
126 bmp_h = bmp_height;
127 sub_w = 720;
128 sub_h = 576;
129 bmp_pitch = bmp_w * 4;
130 return 0;
131}
132
133int CTvSubtitle::sub_destroy()
134{
135 return 0;
136}
137
138int CTvSubtitle::sub_lock()
139{
140 pthread_mutex_lock(&lock);
141 return 0;
142}
143
144int CTvSubtitle::sub_unlock()
145{
146 pthread_mutex_unlock(&lock);
147 return 0;
148}
149
150int CTvSubtitle::sub_clear()
151{
152 return 0;
153}
154
155static void clear_bitmap(CTvSubtitle *pSub)
156{
157 unsigned char *ptr = pSub->buffer;
158 int y = pSub->bmp_h;
159
160 while (y--) {
161 memset(ptr, 0, pSub->bmp_pitch);
162 ptr += pSub->bmp_pitch;
163 }
164}
165
166static void show_sub_cb(AM_SUB2_Handle_t handle, AM_SUB2_Picture_t *pic)
167{
168 LOGD("dvb callback-----------");
169
170 CTvSubtitle *pSub = ((CTvSubtitle *) AM_SUB2_GetUserData(handle));
171 pthread_mutex_lock(&pSub->lock);
172 clear_bitmap(pSub);
173
174 if (pic) {
175 AM_SUB2_Region_t *rgn = pic->p_region;
176 pSub->sub_w = pic->original_width;
177 pSub->sub_h = pic->original_height;
178 while (rgn) {
179 int sx, sy, dx, dy, rw, rh;
180
181 // ensure we have a valid buffer
182 if (! rgn->p_buf) {
183 rgn = rgn->p_next;
184 continue;
185 }
186
187 sx = 0;
188 sy = 0;
189 dx = pic->original_x + rgn->left;
190 dy = pic->original_y + rgn->top;
191 rw = rgn->width;
192 rh = rgn->height;
193
194 if (dx < 0) {
195 sx = -dx;
196 dx = 0;
197 rw += dx;
198 }
199
200 if (dx + rw > pSub->bmp_w) {
201 rw = pSub->bmp_w - dx;
202 }
203
204 if (dy < 0) {
205 sy = -dy;
206 dy = 0;
207 rh += dy;
208 }
209
210 if (dy + rh > pSub->bmp_h) {
211 rh = pSub->bmp_h - dy;
212 }
213
214 if ((rw > 0) && (rh > 0)) {
215 unsigned char *sbegin = (unsigned char *)rgn->p_buf + sy * rgn->width + sx;
216 unsigned char *dbegin = pSub->buffer + dy * pSub->bmp_pitch + dx * 4;
217 unsigned char *src, *dst;
218 int size;
219
220 while (rh) {
221 src = sbegin;
222 dst = dbegin;
223 size = rw;
224 while (size--) {
225 int c = src[0];
226
227 if (c < (int)rgn->entry) {
228 if (rgn->clut[c].a) {
229 *dst++ = rgn->clut[c].r;
230 *dst++ = rgn->clut[c].g;
231 *dst++ = rgn->clut[c].b;
232 } else {
233 dst += 3;
234 }
235 *dst++ = rgn->clut[c].a;
236 } else {
237 dst += 4;
238 }
239 src ++;
240 }
241 sbegin += rgn->width;
242 dbegin += pSub->bmp_pitch;
243 rh--;
244 }
245 }
246
247 rgn = rgn->p_next;
248 }
249 pSub->mpObser->updateSubtitle(pic->original_width, pic->original_height);
250 }
251 pthread_mutex_unlock(&pSub->lock);
252
253}
254
255static uint64_t get_pts_cb(void *handle __unused, uint64_t pts __unused)
256{
257 char buf[32];
258 AM_ErrorCode_t ret;
259 uint32_t v;
260 uint64_t r;
261
262 ret = AM_FileRead("/sys/class/tsync/pts_pcrscr", buf, sizeof(buf));
263 if (!ret) {
264 v = strtoul(buf, 0, 16);
265 if (pts & (1LL << 32)) {
266 r = ((uint64_t)v) | (1LL << 32);
267 } else {
268 r = (uint64_t)v;
269 }
270 } else {
271 r = 0LL;
272 }
273
274 return r;
275}
276
277static void pes_data_cb(int dev_no __unused, int fhandle __unused,
278 const uint8_t *data, int len, void *user_data)
279{
280 CTvSubtitle *pSub = ((CTvSubtitle *) user_data);
281 AM_PES_Decode(pSub->pes_handle, (uint8_t *)data, len);
282}
283
284static int close_dmx(CTvSubtitle *pSub)
285{
286 AM_DMX_FreeFilter(pSub->dmx_id, pSub->filter_handle);
287 AM_DMX_Close(pSub->dmx_id);
288 pSub->dmx_id = -1;
289 pSub->filter_handle = -1;
290
291 return 0;
292}
293
294static int open_dmx(CTvSubtitle *pSub, int dmx_id, int pid)
295{
296 close_dmx(pSub);
297 AM_DMX_OpenPara_t op;
298 struct dmx_pes_filter_params pesp;
299 AM_ErrorCode_t ret;
300
301 pSub->dmx_id = -1;
302 pSub->filter_handle = -1;
303 memset(&op, 0, sizeof(op));
304
305 ret = AM_DMX_Open(dmx_id, &op);
306 if (ret != AM_SUCCESS) {
307 LOGD("error AM_DMX_Open != AM_SUCCESS");
308 goto error;
309 }
310 pSub->dmx_id = dmx_id;
311
312 ret = AM_DMX_AllocateFilter(dmx_id, &pSub->filter_handle);
313 if (ret != AM_SUCCESS) {
314 LOGD("error AM_DMX_AllocateFilter != AM_SUCCESS");
315 goto error;
316 }
317
318 ret = AM_DMX_SetBufferSize(dmx_id, pSub->filter_handle, 0x80000);
319 if (ret != AM_SUCCESS) {
320 LOGD("error AM_DMX_SetBufferSize != AM_SUCCESS");
321 goto error;
322 }
323
324 memset(&pesp, 0, sizeof(pesp));
325 pesp.pid = pid;
326 pesp.output = DMX_OUT_TAP;
327 pesp.pes_type = DMX_PES_TELETEXT0;
328
329 ret = AM_DMX_SetPesFilter(dmx_id, pSub->filter_handle, &pesp);
330 if (ret != AM_SUCCESS) {
331 LOGD("error AM_DMX_SetPesFilter != AM_SUCCESS, err = %s", strerror(errno));
332 goto error;
333 }
334
335 ret = AM_DMX_SetCallback(dmx_id, pSub->filter_handle, pes_data_cb, pSub);
336 if (ret != AM_SUCCESS) {
337 LOGD("error AM_DMX_SetCallback != AM_SUCCESS");
338 goto error;
339 }
340
341 ret = AM_DMX_StartFilter(dmx_id, pSub->filter_handle);
342 if (ret != AM_SUCCESS) {
343 LOGD("error AM_DMX_StartFilter != AM_SUCCESS,dmx_id=%d,filter_handle=%d, ret = %d", dmx_id, pSub->filter_handle, ret);
344 goto error;
345 }
346
347 return 0;
348error:
349 if (pSub->filter_handle != -1) {
350 AM_DMX_FreeFilter(dmx_id, pSub->filter_handle);
351 }
352 if (pSub->dmx_id != -1) {
353 AM_DMX_Close(dmx_id);
354 }
355
356 return -1;
357}
358
359static void pes_sub_cb(AM_PES_Handle_t handle, uint8_t *buf, int size)
360{
361 CTvSubtitle *pSub = ((CTvSubtitle *) AM_SUB2_GetUserData(handle));
362 AM_SUB2_Decode(pSub->sub_handle, buf, size);
363}
364
365int CTvSubtitle::sub_switch_status()
366{
367 return isSubOpen ? 1 : 0;
368}
369int CTvSubtitle::sub_start_dvb_sub(int dmx_id, int pid, int page_id, int anc_page_id)
370{
371 LOGD("start dvb subtitle=----------------");
372
373 AM_PES_Para_t pesp;
374 AM_SUB2_Para_t subp;
375 int ret;
376
377 memset(&pesp, 0, sizeof(pesp));
378 pesp.packet = pes_sub_cb;
379 pesp.user_data = this;
380 ret = AM_PES_Create(&pes_handle, &pesp);
381 if (ret != AM_SUCCESS) {
382 LOGD("error AM_PES_Create != AM_SUCCESS");
383 goto error;
384 }
385
386 memset(&subp, 0, sizeof(subp));
387 subp.show = show_sub_cb;
388 subp.get_pts = get_pts_cb;
389 subp.composition_id = page_id;
390 subp.ancillary_id = anc_page_id;
391 subp.user_data = this;
392 ret = AM_SUB2_Create(&sub_handle, &subp);
393 if (ret != AM_SUCCESS) {
394 LOGD("error AM_SUB2_Create != AM_SUCCESS");
395 goto error;
396 }
397
398 ret = AM_SUB2_Start(sub_handle);
399 if (ret != AM_SUCCESS) {
400 LOGD("error AM_SUB2_Start != AM_SUCCESS");
401 goto error;
402 }
403
404 ret = open_dmx(this, dmx_id, pid);
405 if (ret < 0) {
406 LOGD("error open_dmx != AM_SUCCESS");
407 goto error;
408 }
409 isSubOpen = true;
410 return 0;
411error:
412 if (sub_handle) {
413 AM_SUB2_Destroy(sub_handle);
414 sub_handle = NULL;
415 }
416 if (pes_handle) {
417 AM_PES_Destroy(pes_handle);
418 pes_handle = NULL;
419 }
420 return -1;
421}
422
423int CTvSubtitle::sub_start_dtv_tt(int dmx_id __unused, int region_id __unused, int pid __unused,
424 int page __unused, int sub_page __unused, bool is_sub __unused)
425{
426 return 0;
427}
428
429int CTvSubtitle::sub_stop_dvb_sub()
430{
431 pthread_mutex_lock(&lock);
432 close_dmx(this);
433 AM_SUB2_Destroy(sub_handle);
434 AM_PES_Destroy(pes_handle);
435
436 clear_bitmap(this);
437 mpObser->updateSubtitle(0, 0);
438
439 sub_handle = NULL;
440 pes_handle = NULL;
441 isSubOpen = false;
442 pthread_mutex_unlock(&lock);
443 return 0;
444}
445
446int CTvSubtitle::sub_stop_dtv_tt()
447{
448 return 0;
449}
450
451int CTvSubtitle::sub_tt_goto(int page __unused)
452{
453 return 0;
454}
455
456int CTvSubtitle::sub_tt_color_link(int color __unused)
457{
458 return 0;
459}
460
461int CTvSubtitle::sub_tt_home_link()
462{
463 return 0;
464}
465
466int CTvSubtitle::sub_tt_next(int dir __unused)
467{
468 return 0;
469}
470
471int CTvSubtitle::sub_tt_set_search_pattern(char *pattern __unused, bool casefold __unused)
472{
473 return 0;
474}
475
476int CTvSubtitle::sub_tt_search(int dir __unused)
477{
478 return 0;
479}
480
481/*
482 * 1, Set the country first and parameters should be either USA or KOREA
483#define CMD_SET_COUNTRY_USA 0x5001
484#define CMD_SET_COUNTRY_KOREA 0x5002
485
4862, Set the source type which including
487 a)VBI data(for analog program only)
488 b)USER data(for AIR or Cable service)
489CMD_CC_SET_VBIDATA = 0x7001,
490CMD_CC_SET_USERDATA = 0x7002,
4912.1 If the frontend type is Analog we must set the channel Index
492 with command 'CMD_CC_SET_CHAN_NUM' and the parameter is like 57M
493 we set 0x20000, this should according to USA standard frequency
494 table.
495
4963, Next is to set the CC service type
497
498#define CMD_CC_1 0x3001
499#define CMD_CC_2 0x3002
500#define CMD_CC_3 0x3003
501#define CMD_CC_4 0x3004
502
503//this doesn't support currently
504#define CMD_TT_1 0x3005
505#define CMD_TT_2 0x3006
506#define CMD_TT_3 0x3007
507#define CMD_TT_4 0x3008
508
509#define CMD_SERVICE_1 0x4001
510#define CMD_SERVICE_2 0x4002
511#define CMD_SERVICE_3 0x4003
512#define CMD_SERVICE_4 0x4004
513#define CMD_SERVICE_5 0x4005
514#define CMD_SERVICE_6 0x4006
515
5164, Then set CMD_CC_START to start the CC service, and you needn't to stop
517
518CC service while switching services
519
5205, CMD_CC_STOP should be called in some cases like switch source, change
521
522program, no signal, blocked...*/
523
524//channel_num == 0 ,if frontend is dtv
525//else != 0
526int CTvSubtitle::sub_start_atsc_cc(enum cc_param_country country, enum cc_param_source_type src_type, int channel_num, enum cc_param_caption_type caption_type)
527{
528 LOGD("----sub_start_atsc_cc-1--- country=%d,src=%d,ctype=%d", country, src_type, caption_type);
529 switch (country) {
530 case CC_PARAM_COUNTRY_USA:
531 AM_CC_Cmd(CMD_SET_COUNTRY_USA);
532 break;
533 case CC_PARAM_COUNTRY_KOREA:
534 AM_CC_Cmd(CMD_SET_COUNTRY_KOREA);
535 break;
536 default:
537 AM_CC_Cmd(CMD_SET_COUNTRY_USA);
538 break;
539 }
540
541 switch (src_type) {
542 case CC_PARAM_SOURCE_VBIDATA:
543 AM_CC_Cmd(CMD_CC_SET_VBIDATA);
544 break;
545 case CC_PARAM_SOURCE_USERDATA:
546 AM_CC_Cmd(CMD_CC_SET_USERDATA);
547 break;
548 default:
549 AM_CC_Cmd(CMD_CC_SET_USERDATA);
550 break;
551 }
552
553 //just for test
554 if (channel_num == 0) {
555 } else {
556 //AM_CC_Cmd(CMD_CC_SET_CHAN_NUM);
557 }
558
559 AM_CLOSECAPTION_cmd_t cc_t_cmd;
560 switch (caption_type) {
561 case CC_PARAM_ANALOG_CAPTION_TYPE_CC1:
562 cc_t_cmd = CMD_CC_1;
563 break;
564 case CC_PARAM_ANALOG_CAPTION_TYPE_CC2:
565 cc_t_cmd = CMD_CC_2;
566 break;
567 case CC_PARAM_ANALOG_CAPTION_TYPE_CC3:
568 cc_t_cmd = CMD_CC_3;
569 break;
570 case CC_PARAM_ANALOG_CAPTION_TYPE_CC4:
571 cc_t_cmd = CMD_CC_4;
572 break;
573 case CC_PARAM_DIGITAL_CAPTION_TYPE_SERVICE1:
574 cc_t_cmd = CMD_SERVICE_1;
575 break;
576 case CC_PARAM_DIGITAL_CAPTION_TYPE_SERVICE2:
577 cc_t_cmd = CMD_SERVICE_2;
578 break;
579 case CC_PARAM_DIGITAL_CAPTION_TYPE_SERVICE3:
580 cc_t_cmd = CMD_SERVICE_3;
581 break;
582 case CC_PARAM_DIGITAL_CAPTION_TYPE_SERVICE4:
583 cc_t_cmd = CMD_SERVICE_4;
584 break;
585 default:
586 cc_t_cmd = CMD_SERVICE_1;
587 break;
588 }
589 AM_CC_Cmd(cc_t_cmd);
590
591 AM_CC_Set_CallBack(close_caption_callback, this);
592 AM_VCHIP_Set_CallBack(atv_vchip_callback, this);
593 //start
594 AM_CC_Cmd(CMD_CC_START);
595 LOGD("----sub_start_atsc_cc-2--- country=%d,src=%d,ctype=%d", country, src_type, caption_type);
596 return 0;
597}
598
599int CTvSubtitle::sub_stop_atsc_cc()
600{
601 LOGD("----sub_stop_atsc_cc----");
602 AM_CC_Cmd(CMD_CC_STOP);
603 return 0;
604}
605
606int CTvSubtitle::ResetVchipChgStat()
607{
608 avchip_chg = 0;
609 AM_CC_Cmd(CMD_VCHIP_RST_CHGSTAT);
610 return 0;
611}
612
613int CTvSubtitle::IsVchipChange()
614{
615 return avchip_chg;
616}
617
618//cnt :data buf len
619//databuf len is max 512
620//cmdbuf len is max 128
621void CTvSubtitle::close_caption_callback(char *str, int cnt, int data_buf[], int cmd_buf[], void *user_data)
622{
623 /*
624 CTvSubtitle *pSub = (CTvSubtitle *)user_data;
625
626 if (pSub == NULL)
627 {
628 LOGD("sub cc callback is null user data for this");
629 return;
630 }
631
632 if (pSub->mpObser == NULL) return;
633
634 pSub->mCurCCEv.mDataBufSize = cnt;
635 pSub->mCurCCEv.mpDataBuffer = data_buf;
636 pSub->mCurCCEv.mCmdBufSize = 128;//max
637 pSub->mCurCCEv.mpCmdBuffer = cmd_buf;
638
639 pSub->mpObser->onEvent(pSub->mCurCCEv);
640 */
641
642 str = str;
643 cnt = cnt;
644 data_buf = data_buf;
645 cmd_buf = cmd_buf;
646 user_data = user_data;
647}
648
649void CTvSubtitle::atv_vchip_callback(int Is_chg, void *user_data)
650{
651 CTvSubtitle *pSub = (CTvSubtitle *)user_data;
652 pSub->avchip_chg = Is_chg;
653}
654
655