summaryrefslogtreecommitdiff
path: root/ntsc_decode/am_vbi.c (plain)
blob: 85d82fb7bb241be04d8e01955423f8ddfe3d457a
1#undef NDEBUG
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <pthread.h>
6#include <unistd.h>
7#include <string.h>
8#include "vbi.h"
9#include "exp-gfx.h"
10#include "hamm.h"
11#include "dvb_demux.h"
12#include "sliced.h"
13#include "sliced_vbi.h"
14#include "am_vbi.h"
15#include "vbi_dmx.h"
16
17/********************define variable***************************/
18
19
20typedef struct
21{
22 vbi_decoder *dec;
23 vbi_bool cc_status;
24 AM_VBI_CC_Para_t cc_para;
25 AM_VBI_XDS_Para_t xds_para;
26 int page_no;
27 int sub_page_no;
28 vbi_bool disp_update;
29 vbi_bool running;
30 uint64_t pts;
31 pthread_mutex_t lock;
32 pthread_cond_t cond;
33 pthread_t thread;
34}AM_VBI_Parser_t;
35
36vbi_pgno pgno = -1;
37
38//AM_VBI_Parser_t *parser = NULL;
39
40#if 0
41static void
42reset (AM_VBI_Parser_t *parser)
43{
44 vbi_page page;
45 vbi_bool success;
46 int row;
47
48 success = vbi_fetch_cc_page (parser->dec, &page, pgno, TRUE);
49 assert (success);
50
51 for (row = 0; row <= page.rows; ++row)
52 render (parser,&page, row);
53
54 vbi_unref_page (&page);
55}
56#endif
57/**********************************************************/
58
59
60 void vbi_cc_show(AM_VBI_Parser_t *parser)
61{
62
63 vbi_page page;
64 vbi_bool success;
65 int row;
66 //user_data = user_data;
67
68 //if (pgno != -1 && parser->page_no != pgno)
69 // return;
70
71 /* Fetching & rendering in the handler
72 is a bad idea, but this is only a test */
73 AM_DEBUG("NTSC-------------------- vbi_cc_show****************\n");
74 success = vbi_fetch_cc_page (parser->dec, &page, parser->page_no, TRUE);
75 AM_DEBUG("NTSC--------------1212------vbi_fetch_cc_page success****************\n");
76 assert (success);
77
78 int i ,j;
79 if(parser->cc_para.draw_begin)
80 parser->cc_para.draw_begin(parser);
81
82 vbi_draw_cc_page_region (&page, VBI_PIXFMT_RGBA32_LE, parser->cc_para.bitmap,
83 parser->cc_para.pitch, 0, 0, page.columns, page.rows);
84
85 if(parser->cc_para.draw_end)
86 parser->cc_para.draw_end(parser);
87 vbi_unref_page (&page);
88}
89
90
91static void* vbi_cc_thread(void *arg)
92{
93 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)arg;
94
95 pthread_mutex_lock(&parser->lock);
96 AM_DEBUG("NTSC***************________________ vbi_cc_thread parser->running = %d\n",parser->running);
97 while(parser->running)
98 {
99 AM_DEBUG("NTSC***************________________ vbi_cc_thread disp_update = %d\n",parser->disp_update);
100 while(parser->running && !parser->disp_update){
101 pthread_cond_wait(&parser->cond, &parser->lock);
102 }
103 AM_DEBUG("NTSC***************________________ vbi_cc_thread disp_update = %d\n",parser->disp_update);
104 if(parser->disp_update){
105 vbi_cc_show(parser);
106 parser->disp_update = FALSE;
107 }
108 }
109 pthread_mutex_unlock(&parser->lock);
110
111 return NULL;
112}
113
114static void vbi_cc_handler(vbi_event * ev,void * user_data)
115{
116 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)user_data;
117
118 if(parser->page_no == 0)
119 return;
120 //***************************************************temp add cc status
121 if(parser->cc_status == AM_TRUE)
122 if(parser->page_no == ev->ev.caption.pgno){
123 //parser->page_no = ev->ev.caption.pgno;
124 parser->disp_update = AM_TRUE;
125 pthread_cond_signal(&parser->cond);
126
127 //vbi_cc_show(parser);
128 }
129}
130
131
132
133
134
135
136
137
138
139static void vbi_xds_handler (vbi_event * ev, void * user_data)
140{
141 AM_DEBUG("xds-------------------- xds_handler****************");
142 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)user_data;
143
144
145 if(ev == NULL)
146 return;
147 vbi_program_info * prog_info = ev->ev.prog_info;
148
149 vbi_xds_subclass_program xds_program = 0;
150 switch(ev->type)
151 {
152 case VBI_EVENT_ASPECT :
153 /* program identification number */
154 if(!(prog_info->month == -1 && prog_info->day == -1
155 && prog_info->hour == -1 && prog_info->min == -1 ))
156 {
157 xds_program = VBI_XDS_PROGRAM_ID;
158 AM_DEBUG("xds*********VBI_XDS_PROGRAM_ID \n");
159 break;
160 }
161 /* program name */
162 if(!(prog_info->title[0] == 0))
163 {
164 xds_program = VBI_XDS_PROGRAM_NAME;
165 AM_DEBUG("xds*********VBI_XDS_PROGRAM_NAME \n");
166 break;
167 }
168 /* program aspect ratio */
169 if(!(prog_info->aspect.first_line == prog_info->aspect.last_line == -1 && prog_info->aspect.ratio == 0.0))
170 {
171 xds_program = VBI_XDS_PROGRAM_ASPECT_RATIO;
172 AM_DEBUG("xds*********VBI_XDS_PROGRAM_ASPECT_RATIO \n");
173 break;
174 }
175
176 break;
177 case VBI_EVENT_PROG_INFO :
178 /* 02 Program Length */
179 if(!(prog_info->length_hour == -1 && prog_info->length_min == -1 &&prog_info->elapsed_hour == -1 &&
180 prog_info->elapsed_min == -1 &&prog_info->elapsed_sec == -1 ))
181 {
182 xds_program = VBI_XDS_PROGRAM_LENGTH;
183 AM_DEBUG("xds*********VBI_XDS_PROGRAM_LENGTH \n");
184 break;
185 }
186
187 /* 04 Program type */
188 /*
189 * If unknown type_classf == VBI_PROG_CLASSF_NONE.
190 * VBI_PROG_CLASSF_EIA_608 can have up to 32 tags
191 * identifying 96 keywords. Their numerical value
192 * is given here instead of composing a string for
193 * easier filtering. Use vbi_prog_type_str_by_id to
194 * get the keywords. A zero marks the end.
195 */
196 if(!(prog_info->type_classf == VBI_PROG_CLASSF_NONE))
197 {
198 xds_program = VBI_XDS_PROGRAM_TYPE;
199 AM_DEBUG("xds*********VBI_XDS_PROGRAM_TYPE \n");
200 break;
201 }
202
203 /* 05 Program rating */
204 /*
205 * For details STFW for "v-chip"
206 * If unknown rating_auth == VBI_RATING_NONE
207 */
208 if(!(prog_info->rating_auth == VBI_RATING_AUTH_NONE))
209 {
210 xds_program = VBI_XDS_PROGRAM_RATING;
211 AM_DEBUG("xds*********VBI_XDS_PROGRAM_RATING \n");
212 break;
213 }
214
215 /* 06 Program Audio Services */
216 /*
217 * BTSC audio (two independent tracks) is flagged according to XDS,
218 * Zweiton/NICAM/EIA-J audio is flagged mono/none, stereo/none or
219 * mono/mono for bilingual transmissions.
220 */
221 if((prog_info->audio[0].mode != VBI_AUDIO_MODE_UNKNOWN) ||
222 (prog_info->audio[1].mode != VBI_AUDIO_MODE_UNKNOWN))
223 {
224 xds_program = VBI_XDS_PROGRAM_AUDIO_SERVICES;
225 AM_DEBUG("xds*********VBI_XDS_PROGRAM_AUDIO_SERVICES \n");
226 break;
227 }
228
229 /* 07 Program Caption Services */
230 /*
231 * Bits 0...7 corresponding to Caption page 1...8.
232 * Note for the current program this information is also
233 * available via vbi_classify_page().
234 *
235 * If unknown caption_services == -1, _language[] = NULL
236 */
237 if(!(prog_info->caption_services == -1))
238 {
239 xds_program = VBI_XDS_PROGRAM_CAPTION_SERVICES;
240 AM_DEBUG("xds*********VBI_XDS_PROGRAM_CAPTION_SERVICES \n");
241 break;
242 }
243 break;
244
245 }
246
247 if(prog_info->rating_auth != VBI_RATING_AUTH_NONE)
248 {
249 AM_DEBUG("xds**********prog_info->rating_auth = %d\n",prog_info->rating_auth );
250
251 if(prog_info->rating_auth == VBI_RATING_AUTH_MPAA)
252 AM_DEBUG("xds**********result*******************VBI_RATING_AUTH_MPAA\n");
253 if(prog_info->rating_auth == VBI_RATING_AUTH_TV_US)
254 AM_DEBUG("xds**********result*******************VBI_RATING_AUTH_TV_US\n");
255 if(prog_info->rating_auth == VBI_RATING_AUTH_TV_CA_EN)
256 AM_DEBUG("xds**********result*******************VBI_RATING_AUTH_TV_CA_EN\n");
257 if(prog_info->rating_auth == VBI_RATING_AUTH_TV_CA_FR)
258 AM_DEBUG("xds**********result*******************VBI_RATING_AUTH_TV_CA_FR\n");
259 if(prog_info->rating_auth == VBI_RATING_AUTH_NONE)
260 AM_DEBUG("result*******************VBI_RATING_AUTH_NONE\n");
261
262 if (prog_info->rating_dlsv == VBI_RATING_D)
263 AM_DEBUG("xds**********result*******************VBI_RATING_D\n");
264 if (prog_info->rating_dlsv == VBI_RATING_L)
265 AM_DEBUG("xds**********result*******************VBI_RATING_L\n");
266 if (prog_info->rating_dlsv == VBI_RATING_S)
267 AM_DEBUG("xds**********result*******************VBI_RATING_S\n");
268 if (prog_info->rating_dlsv == VBI_RATING_V)
269 AM_DEBUG("xds**********result*******************VBI_RATING_V\n");
270 AM_DEBUG("xds**********result*******************prog_info->rating_id = %d\n",prog_info->rating_id );
271
272 }
273
274 parser->xds_para.xds_callback(parser,xds_program,*prog_info);
275
276}
277
278/**********************************************************/
279
280static vbi_bool
281decode_frame (const vbi_sliced * sliced,
282 unsigned int n_lines,
283 const uint8_t * raw,
284 const vbi_sampling_par *sp,
285 double sample_time,
286 int64_t stream_time,
287 void * user_data)
288{
289 AM_DEBUG("NTSC-------------------- decode_frame\n");
290 if(user_data == NULL) return FALSE;
291 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)user_data;
292 raw = raw;
293 sp = sp;
294 stream_time = stream_time; /* unused */
295
296 vbi_decode (parser->dec, sliced, n_lines, sample_time);
297 return TRUE;
298}
299
300
301
302 vbi_bool
303decode_vbi (int dev_no, int fid, const uint8_t *data, int len, void *user_data){
304
305 AM_DEBUG("NTSC-------------------- decode_vbi len = %d\n",len);
306 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)user_data;
307 if(user_data == NULL)
308 AM_DEBUG("NTSC-------------------- decode_vbi NOT user_data ");
309
310 int length = len;
311 struct stream *st;
312 if(len < 0 || data == NULL)
313 goto error;
314 st = read_stream_new (data,length,FILE_FORMAT_SLICED,
315 0,decode_frame,parser);
316
317 stream_loop (st);
318 stream_delete (st);
319 return AM_SUCCESS;
320
321 error:
322 return AM_FAILURE;
323
324}
325
326 void init_vbi_decoder( AM_VBI_Parser_t* parser)
327 {
328 memset(parser, 0, sizeof(AM_VBI_Parser_t));
329 parser->dec = vbi_decoder_new ();
330 assert (NULL != parser->dec);
331 pthread_mutex_init(&parser->lock, NULL);
332 pthread_cond_init(&parser->cond, NULL);
333 }
334
335
336
337
338vbi_bool AM_VBI_CC_Create(AM_VBI_Handle_t *handle, AM_VBI_CC_Para_t *para)
339{
340 AM_VBI_Parser_t* parser = NULL;
341 if(*handle == NULL)
342 {
343
344 parser = (AM_VBI_Parser_t*)malloc(sizeof(AM_VBI_Parser_t));
345 if(!parser)
346 {
347 return AM_VBI_DMX_ERR_NOT_ALLOCATED;
348 }
349 init_vbi_decoder(parser);
350 }else
351 parser = (AM_VBI_Parser_t*)handle;
352
353 vbi_bool success;
354 success = vbi_event_handler_add (parser->dec, VBI_EVENT_CAPTION,
355 vbi_cc_handler, parser);
356
357 //******************************************************
358 //success = vbi_event_handler_add (parser->dec, VBI_EVENT_ASPECT | VBI_EVENT_PROG_INFO,
359 // vbi_xds_handler, parser);
360 //************************************************
361 assert (success);
362 parser->cc_para = *para;
363 *handle = parser;
364 return AM_SUCCESS;
365}
366
367
368 AM_ErrorCode_t AM_VBI_CC_Start(AM_VBI_Handle_t handle)
369{
370 AM_DEBUG("NTSC-------------------- ******************AM_NTSC_CC_Start \n");
371 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)handle;
372 vbi_bool ret = AM_SUCCESS;
373
374 //*******************************************************temp
375 parser->cc_status = AM_TRUE;
376 //*******************************************************temp
377 if(!parser)
378 {
379 AM_DEBUG("NTSC-------------------- ******************AM_CC_ERR_INVALID_HANDLE \n");
380 return AM_CC_ERR_INVALID_HANDLE;
381 }
382
383 pthread_mutex_lock(&parser->lock);
384
385 if(!parser->running)
386 {
387 parser->running = AM_TRUE;
388 if(pthread_create(&parser->thread, NULL, vbi_cc_thread, parser))
389 {
390 parser->running = AM_FALSE;
391 ret = AM_CC_ERR_CANNOT_CREATE_THREAD;
392 }
393 }
394 pthread_mutex_unlock(&parser->lock);
395
396 return AM_SUCCESS;
397}
398
399
400
401
402
403/********************************************************/
404AM_ErrorCode_t AM_VBI_CC_Stop(AM_VBI_Handle_t handle)
405{
406 AM_DEBUG("NTSC-------------------- ******************AM_VBI_CC_Stop \n");
407 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)handle;
408 vbi_bool ret = AM_SUCCESS;
409
410 pthread_t th;
411 vbi_bool wait = AM_FALSE;
412
413 if(!parser)
414 {
415 AM_DEBUG("NTSC-------------------- ******************AM_CC_ERR_INVALID_HANDLE \n");
416 return AM_CC_ERR_INVALID_HANDLE;
417 }
418
419 pthread_mutex_lock(&parser->lock);
420
421 if(parser->running)
422 {
423 parser->running = AM_FALSE;
424 wait = AM_TRUE;
425 th = parser->thread;
426 }
427
428 pthread_mutex_unlock(&parser->lock);
429 pthread_cond_signal(&parser->cond);
430
431 if(wait)
432 {
433 pthread_join(th, NULL);
434 }
435
436 return AM_SUCCESS;
437}
438
439
440void* AM_VBI_CC_GetUserData(AM_VBI_Handle_t handle)
441{
442 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)handle;
443 if(!parser)
444 {
445 return NULL;
446 }
447 return parser->cc_para.user_data;
448}
449
450vbi_bool AM_VBI_XDS_Create(AM_VBI_Handle_t *handle,AM_VBI_XDS_Para_t *para)
451{
452 vbi_bool ret = AM_SUCCESS;
453 AM_VBI_Parser_t* parser;
454 if(*handle == NULL)
455 {
456 AM_DEBUG("NTSC-------------------- ******************AM_XDS_Create handle is null \n");
457 parser = (AM_VBI_Parser_t*)malloc(sizeof(AM_VBI_Parser_t));
458 if(!parser)
459 {
460 return AM_VBI_DMX_ERR_NOT_ALLOCATED;
461 }
462 init_vbi_decoder(parser);
463 *handle = parser;
464 }else
465 parser = (AM_VBI_Parser_t*)*handle;
466 parser->xds_para = *para;
467 AM_DEBUG("NTSC--------------- ******************vbi_event_handler_add xds_handle \n");
468 ret = vbi_event_handler_add (parser->dec, VBI_EVENT_ASPECT | VBI_EVENT_PROG_INFO,
469 vbi_xds_handler, parser);
470
471 assert (ret);
472 return AM_SUCCESS;
473
474}
475
476
477vbi_bool AM_VBI_CC_set_type(AM_VBI_Handle_t handle,VBI_CC_TYPE cc_type)
478{
479 AM_DEBUG("NTSC-------------------- ******************AM_VBI_CC_set_type ===%d\n",cc_type);
480 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)handle;
481
482 if(cc_type < 1 || cc_type >8)
483 return AM_FAILURE;
484 else
485 parser->page_no = cc_type;
486 return AM_SUCCESS;
487}
488
489vbi_bool AM_VBI_CC_set_status(AM_VBI_Handle_t handle,vbi_bool flag)
490{
491 AM_DEBUG("NTSC-------------------- ******************AM_VBI_CC_set_status ===%d\n");
492 AM_VBI_Parser_t *parser = (AM_VBI_Parser_t*)handle;
493 if(flag == AM_TRUE)
494 parser->cc_status = AM_TRUE;
495 else
496 if(flag == AM_FAILURE)
497 parser->cc_status = AM_FAILURE;
498 return AM_SUCCESS;
499
500}
501
502