summaryrefslogtreecommitdiff
authorYan Yan <yan.yan@amlogic.com>2017-10-26 07:48:22 (GMT)
committer Yan Yan <yan.yan@amlogic.com>2017-11-08 13:29:39 (GMT)
commit04b4df76a6298c2c36de520ae6daebb0f993e390 (patch)
tree536156d9a75503e0e3dc90ff7b3bd4e721f83a6e
parentc48191389000939ccf179776e14958d3bba304c8 (diff)
downloadlibzvbi-04b4df76a6298c2c36de520ae6daebb0f993e390.zip
libzvbi-04b4df76a6298c2c36de520ae6daebb0f993e390.tar.gz
libzvbi-04b4df76a6298c2c36de520ae6daebb0f993e390.tar.bz2
cc: new cc implementation [1/1]
PD# 152764 Change-Id: I3abdb8b8f4bdf55741eae29ae4acd35aad6d4f30
Diffstat
-rwxr-xr-xsrc/dtvcc.c266
-rw-r--r--src/dtvcc.h12
2 files changed, 223 insertions, 55 deletions
diff --git a/src/dtvcc.c b/src/dtvcc.c
index 64ec5a9..05c0789 100755
--- a/src/dtvcc.c
+++ b/src/dtvcc.c
@@ -33,7 +33,6 @@
#include "libzvbi.h"
#include "dtvcc.h"
-#include <android/log.h>
#define elements(array) (sizeof(array) / sizeof(array[0]))
@@ -84,6 +83,10 @@ do { \
_member)) : (_type *) 0; \
})
+#define VBI_RGBA(r, g, b) \
+ ((((r) & 0xFF) << 0) | (((g) & 0xFF) << 8) \
+ | (((b) & 0xFF) << 16) | (0xFF << 24))
+
/* These should be defined in inttypes.h. */
#ifndef PRId64
# define PRId64 "lld"
@@ -99,8 +102,6 @@ extern void
vbi_transp_colormap(vbi_decoder *vbi, vbi_rgba *d, vbi_rgba *s, int entries);
extern void
vbi_send_event(vbi_decoder *vbi, vbi_event *ev);
-extern void
-vbi_decode_caption(vbi_decoder *vbi, int line, uint8_t *buf);
static void
dtvcc_get_visible_windows(struct dtvcc_service *ds, int *cnt, struct dtvcc_window **windows);
@@ -2145,7 +2146,7 @@ dtvcc_g2 [96] = {
0x2019, /* 0x1032 Right single quotation mark */
0x201C, /* 0x1033 Left double quotation mark */
0x201D, /* 0x1034 Right double quotation mark */
- 0,
+ 0x2022,
0,
0,
0x2122, /* 0x1039 Trademark sign */
@@ -2230,7 +2231,7 @@ dtvcc_map_color(dtvcc_color c)
return ret;
}
-static unsigned int
+unsigned int
dtvcc_unicode (unsigned int c)
{
if (unlikely (0 == (c & 0x60))) {
@@ -2251,17 +2252,77 @@ dtvcc_unicode (unsigned int c)
/* We map all G2/G3 characters which are not
representable in Unicode to private code U+E900
... U+E9FF. */
- return 0xE9A0; /* caption icon */
+ return 0xf101; /* caption icon */
}
return 0;
}
static void
-dtvcc_event(struct dtvcc_decoder *dc, struct dtvcc_service *ds)
+dtvcc_render(struct dtvcc_decoder * dc, struct dtvcc_service * ds)
{
+#if 0
vbi_event event;
struct tvcc_decoder *td = PARENT(dc, struct tvcc_decoder, dtvcc);
+ struct dtvcc_window *win[8];
+ int i, cnt;
+
+ //printf("render check\n");
+
+ cnt = 8;
+ dtvcc_get_visible_windows(ds, &cnt, win);
+ //if (!cnt)
+ // return;
+
+ if (cnt != ds->old_win_cnt) {
+ //printf("cnt changed\n");
+ goto changed;
+ }
+
+ for (i = 0; i < cnt; i ++) {
+ struct dtvcc_window *w1 = win[i];
+ struct dtvcc_window *w2 = &ds->old_window[i];
+
+ if (memcmp(w1->buffer, w2->buffer, sizeof(w1->buffer))) {
+ //printf("text changed\n");
+ goto changed;
+ }
+
+ if (memcmp(&w1->style, &w2->style, sizeof(w1->style))) {
+ //printf("style changed\n");
+ goto changed;
+ }
+
+ if (memcmp(&w1->curr_pen, &w2->curr_pen, sizeof(w1->curr_pen))) {
+ //printf("pen changed\n");
+ goto changed;
+ }
+
+ if (w1->row_count != w2->row_count) {
+ //printf("row changed\n");
+ goto changed;
+ }
+
+ if (w1->column_count != w2->column_count) {
+ //printf("col changed\n");
+ goto changed;
+ }
+
+ if (w1->visible != w2->visible) {
+ //printf("vis changed\n");
+ goto changed;
+ }
+ }
+
+ return;
+changed:
+ for (i = 0; i < cnt; i ++) {
+ ds->old_window[i] = *win[i];
+ }
+ ds->old_win_cnt = cnt;
+#endif
+ ds->update = 1;
+#if 0
event.type = VBI_EVENT_CAPTION;
event.ev.caption.pgno = ds - dc->service + 1 + 8/*after 8 cc channels*/;
@@ -2272,12 +2333,7 @@ dtvcc_event(struct dtvcc_decoder *dc, struct dtvcc_service *ds)
vbi_send_event(td->vbi, &event);
pthread_mutex_lock(&td->mutex);
-}
-
-static void
-dtvcc_render(struct dtvcc_decoder *dc, struct dtvcc_service *ds)
-{
- ds->update = 1;
+#endif
}
static void
@@ -2395,6 +2451,9 @@ dtvcc_put_char (struct dtvcc_decoder * dc,
dc = dc; /* unused */
dw = ds->curr_window;
+
+ //printf("putchar %c\n", c);
+
if (NULL == dw) {
ds->error_line = __LINE__;
return FALSE;
@@ -2406,6 +2465,7 @@ dtvcc_put_char (struct dtvcc_decoder * dc,
/* FIXME how should we handle TEXT_TAG_NOT_DISPLAYABLE? */
dw->buffer[row][column] = c;
+ dw->pen[row][column] = dw->curr_pen.style;
switch (dw->style.print_direction) {
case DIR_LEFT_RIGHT:
@@ -2631,10 +2691,11 @@ dtvcc_clear_windows (struct dtvcc_decoder * dc,
dtvcc_stream_event (dc, ds, dw, dw->curr_row);
memset (dw->buffer, 0, sizeof (dw->buffer));
+ memset (dw->pen, 0, sizeof(dw->pen));
dw->streamed = 0;
- if(dw->visible)
+ if (dw->visible)
dtvcc_render(dc, ds);
/* FIXME CEA 708-C Section 7.1.4 (Form Feed)
@@ -2727,6 +2788,8 @@ dtvcc_define_window (struct dtvcc_decoder * dc,
unsigned int pen_style_id;
unsigned int c;
+ //printf("define window\n");
+
if (0 != ((buf[1] | buf[6]) & 0xC0)) {
ds->error_line = __LINE__;
return FALSE;
@@ -2757,12 +2820,15 @@ dtvcc_define_window (struct dtvcc_decoder * dc,
return FALSE;
}
+ //printf("define window %d\n", column_count_m1);
+
column_count_m1 = buf[5];
/* We also check the top two zero bits. */
if (unlikely (column_count_m1 >= 42)) {
ds->error_line = __LINE__;
return FALSE;
}
+ //printf("define windowa\n");
window_id = buf[0] & 7;
dw = &ds->window[window_id];
@@ -2816,6 +2882,8 @@ dtvcc_define_window (struct dtvcc_decoder * dc,
ds->created |= window_map;
+ //printf("define %x %x\n", ds->curr_window, ds->created);
+
return dtvcc_clear_windows (dc, ds, window_map);
}
@@ -2828,9 +2896,12 @@ dtvcc_display_windows (struct dtvcc_decoder * dc,
unsigned int i;
window_map &= ds->created;
+
+ //printf("display %02x %p %02x\n", c, ds->curr_window, ds->created);
+
if(ds->curr_window == NULL && ds->created == 0) {
- LOGI("display windows error: cur win is NULL");
return FALSE;
+ //return TRUE;
}
for (i = 0; i < 8; ++i) {
@@ -2905,8 +2976,11 @@ dtvcc_carriage_return (struct dtvcc_decoder * dc,
column > 0; --column) {
dw->buffer[row][column] =
dw->buffer[row][column - 1];
+ dw->pen[row][column] =
+ dw->pen[row][column - 1];
}
dw->buffer[row][column] = 0;
+ memset(&dw->pen[row][column], 0, sizeof(dw->pen[0][0]));
}
break;
@@ -2922,8 +2996,11 @@ dtvcc_carriage_return (struct dtvcc_decoder * dc,
column < dw->column_count - 1; ++column) {
dw->buffer[row][column] =
dw->buffer[row][column + 1];
+ dw->pen[row][column] =
+ dw->pen[row][column + 1];
}
dw->buffer[row][column] = 0;
+ memset(&dw->pen[row][column], 0, sizeof(dw->pen[0][0]));
}
break;
@@ -2937,7 +3014,10 @@ dtvcc_carriage_return (struct dtvcc_decoder * dc,
& ~(1 << dw->row_count);
memmove (&dw->buffer[1], &dw->buffer[0],
sizeof (dw->buffer[0]) * (dw->row_count - 1));
+ memmove (&dw->pen[1], &dw->pen[0],
+ sizeof (dw->pen[0]) * (dw->row_count - 1));
memset (&dw->buffer[0], 0, sizeof (dw->buffer[0]));
+ memset (&dw->pen[0], 0, sizeof(dw->pen[0]));
break;
case DIR_BOTTOM_TOP:
@@ -2949,7 +3029,10 @@ dtvcc_carriage_return (struct dtvcc_decoder * dc,
dw->streamed >>= 1;
memmove (&dw->buffer[0], &dw->buffer[1],
sizeof (dw->buffer[0]) * (dw->row_count - 1));
+ memmove (&dw->pen[0], &dw->pen[1],
+ sizeof (dw->pen[0]) * (dw->row_count - 1));
memset (&dw->buffer[row], 0, sizeof (dw->buffer[0]));
+ memset (&dw->pen[row], 0, sizeof (dw->pen[0]));
break;
}
@@ -3029,6 +3112,7 @@ dtvcc_backspace (struct dtvcc_decoder * dc,
if (0 != dw->buffer[row][column]) {
dw->streamed &= ~mask;
dw->buffer[row][column] = 0;
+ memset(&dw->pen[row][column], 0, sizeof(dw->pen[0][0]));
}
dw->curr_row = row;
@@ -3063,6 +3147,8 @@ dtvcc_hor_carriage_return (struct dtvcc_decoder * dc,
mask = 1 << row;
memset (&dw->buffer[row][0], 0,
sizeof (dw->buffer[0]));
+ memset (&dw->pen[row][0], 0,
+ sizeof (dw->pen[0]));
if (DIR_LEFT_RIGHT == dw->style.print_direction)
dw->curr_column = 0;
else
@@ -3072,8 +3158,10 @@ dtvcc_hor_carriage_return (struct dtvcc_decoder * dc,
case DIR_TOP_BOTTOM:
case DIR_BOTTOM_TOP:
mask = 1 << column;
- for (row = 0; row < dw->column_count; ++row)
+ for (row = 0; row < dw->column_count; ++row) {
dw->buffer[row][column] = 0;
+ memset(&dw->pen[row][column], 0, sizeof(dw->pen[0][0]));
+ }
if (DIR_TOP_BOTTOM == dw->style.print_direction)
dw->curr_row = 0;
else
@@ -3093,20 +3181,33 @@ dtvcc_delete_windows (struct dtvcc_decoder * dc,
{
struct dtvcc_window *dw;
int i;
+ int changed = 0;
for (i = 0; i < N_ELEMENTS(ds->window); i ++) {
dw = &ds->window[i];
- if (window_map & (1 << i)) {
- dtvcc_stream_event (dc, ds, dw, dw->curr_row);
- if (ds->curr_window == dw)
- ds->curr_window = NULL;
+ if (NULL != dw) {
+ unsigned int window_id;
+
+ window_id = dtvcc_window_id (ds, dw);
+ if (ds->created & (1 << window_id)) {
+ if (window_map & (1 << window_id)) {
+ //printf("delete window %d\n", window_id);
+ dtvcc_stream_event (dc, ds, dw, dw->curr_row);
- if (dw->visible)
- dtvcc_render(dc, ds);
+ if (dw == ds->curr_window)
+ ds->curr_window = NULL;
- dw->visible = 0;
- memset(dw->buffer, 0, sizeof(dw->buffer));
+ if (dw->visible)
+ dtvcc_render(dc, ds);
+
+ memset (dw->buffer, 0, sizeof (dw->buffer));
+ memset (dw->pen, 0, sizeof(dw->pen));
+ dw->visible = 0;
+
+ changed = 1;
+ }
+ }
}
}
@@ -3134,7 +3235,8 @@ dtvcc_command (struct dtvcc_decoder * dc,
if (*se_length > n_bytes) {
ds->error_line = __LINE__;
- return FALSE;
+ //return FALSE;
+ return TRUE;
}
switch (c) {
@@ -3154,10 +3256,7 @@ dtvcc_command (struct dtvcc_decoder * dc,
window_id = c & 7;
if (0 == (ds->created & (1 << window_id))) {
ds->error_line = __LINE__;
- LOGI("cc cmd:%02x, set window_id:%d, not create?%d",
- c, window_id, ds->created);
- return TRUE;
- //return FALSE;
+ return FALSE;
}
ds->curr_window = &ds->window[window_id];
return TRUE;
@@ -3272,6 +3371,16 @@ dtvcc_decode_syntactic_elements (struct dtvcc_decoder * dc,
{
ds->timestamp = dc->timestamp;
+#if 0
+ printf("servie %d\n", n_bytes);
+ {
+ int i;
+
+ for (i = 0; i < n_bytes; i ++)
+ printf("%02x ", buf[i]);
+ printf("\n");
+ }
+#endif
while (n_bytes > 0) {
unsigned int se_length;
@@ -3283,9 +3392,12 @@ dtvcc_decode_syntactic_elements (struct dtvcc_decoder * dc,
continue;
}
+ //printf("dec se %02x\n", buf[0]);
+
if (!dtvcc_decode_se (dc, ds,
&se_length,
buf, n_bytes)) {
+ //printf("decode se error\n");
return FALSE;
}
@@ -3305,6 +3417,14 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
unsigned int packet_size;
unsigned int i;
+#if 0
+ printf("%d dtvcc decode packet %d: ", get_input_offset(), dc->packet_size);
+
+ for (i = 0; i < dc->packet_size; i ++) {
+ printf("%02x ", dc->packet[i]);
+ }
+ printf("\n");
+#endif
dc->timestamp.sys = *tv;
dc->timestamp.pts = pts;
@@ -3315,6 +3435,7 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
if (dc->next_sequence_number >= 0
&& 0 != ((dc->packet[0] ^ dc->next_sequence_number) & 0xC0)) {
+ printf("seq reset\n");
dtvcc_reset (dc);
return;
}
@@ -3329,8 +3450,10 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
/* CEA 708-C Section 5: Apparently packet_size need not be
equal to the actually transmitted amount of data. */
if (packet_size > dc->packet_size) {
+ /*
dtvcc_reset (dc);
- return;
+ return;*/
+ packet_size = dc->packet_size;
}
/* Service Layer. */
@@ -3354,6 +3477,8 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
c = dc->packet[i];
service_number = (c & 0xE0) >> 5;
+ //printf("srv %d\n", service_number);
+
/* CEA 708-C Section 6.3: Ignore block_size if
service_number is zero. */
if (0 == service_number) {
@@ -3369,20 +3494,25 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
if (7 == service_number) {
if (i + 1 > packet_size)
- goto service_block_incomplete;
+ break;
+ //goto service_block_incomplete;
header_size = 2;
c = dc->packet[i + 1];
/* We also check the null_fill bits. */
if (c < 7 || c > 63)
- goto invalid_service_block;
+ break;
+ //goto invalid_service_block;
service_number = c;
}
+ //printf("srv %d %d %d %d\n", service_number, header_size, block_size, packet_size);
+
if (i + header_size + block_size > packet_size)
- goto service_block_incomplete;
+ break;
+ //goto service_block_incomplete;
if (service_number <= 6) {
struct dtvcc_service *ds;
@@ -3399,6 +3529,7 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
i += header_size + block_size;
}
+ //printf("check\n");
for (i = 0; i < 6; ++i) {
struct dtvcc_service *ds;
struct program *pr;
@@ -3461,24 +3592,17 @@ dtvcc_try_decode_packet (struct dtvcc_decoder * dc,
static void
dtvcc_reset_service (struct dtvcc_service * ds)
{
- int i = 0;
ds->curr_window = NULL;
ds->created = 0;
- for(i=0; i<8; i++)
- {
- memset(&ds->window[i], 0, sizeof(struct dtvcc_window));
- memset(ds->window[i].buffer, 0, sizeof(ds->window[i].buffer));
- }
+
cc_timestamp_reset (&ds->timestamp);
}
void
dtvcc_reset (struct dtvcc_decoder * dc)
{
- int i;
- for(i=0; i<6; i++){
- dtvcc_reset_service (&dc->service[i]);
- }
+ dtvcc_reset_service (&dc->service[0]);
+ dtvcc_reset_service (&dc->service[1]);
dc->packet_size = 0;
dc->next_sequence_number = -1;
@@ -3488,9 +3612,7 @@ void
dtvcc_init (struct dtvcc_decoder * dc)
{
memset(dc, 0, sizeof(struct dtvcc_decoder));
-
dtvcc_reset (dc);
-
cc_timestamp_reset (&dc->timestamp);
}
@@ -3511,8 +3633,9 @@ static void dtvcc_window_to_page(vbi_decoder *vbi, struct dtvcc_window *dw, stru
#if 1
pg->rows = dw->row_count;
pg->columns = dw->column_count;
-
+
dtvcc_set_page_color_map(vbi, pg);
+ memset(dw->row_start, 0, sizeof(dw->row_start));
for (i=0; i<pg->rows; i++)
{
@@ -3540,13 +3663,14 @@ static void dtvcc_window_to_page(vbi_decoder *vbi, struct dtvcc_window *dw, stru
if (0 == c) {
ac.unicode = 0x20;
ac.opacity = VBI_TRANSPARENT_SPACE;
+ dw->row_start[i] ++;
} else {
ac.unicode = dtvcc_unicode (c);
if (0 == ac.unicode) {
ac.unicode = 0x20;
+ dw->row_start[i] ++;
}
}
-
pg->text[i*pg->columns + j] = ac;
}
}
@@ -3664,7 +3788,23 @@ tvcc_decode_data (struct tvcc_decoder *td,
cc_count = buf[1] & 0x1F;
dtvcc = FALSE;
+#if 0
+ printf("tvcc decode %d:\n", n_bytes);
+ {
+ int i;
+
+ for (i = 0; i < n_bytes; i ++) {
+ printf("%02x ", buf[i]);
+ if ((i + 1) % 16 == 0)
+ printf("\n");
+ }
+ printf("\n");
+ }
+#endif
pthread_mutex_lock(&td->mutex);
+
+ //printf("cc count %d\n", cc_count);
+
for (i = 0; i < cc_count; ++i) {
unsigned int b0;
unsigned int cc_valid;
@@ -3679,9 +3819,12 @@ tvcc_decode_data (struct tvcc_decoder *td,
cc_data_1 = buf[4 + i * 3];
cc_data_2 = buf[5 + i * 3];
+ //printf("cc type %02x %02x %02x %02x\n", cc_type, cc_valid, cc_data_1, cc_data_2);
+
switch (cc_type) {
case NTSC_F1:
case NTSC_F2:
+ //printf("ntsc cc\n");
/* Note CEA 708-C Table 4: Only one NTSC pair
will be present in field picture user_data
or in progressive video pictures, and up to
@@ -3701,6 +3844,7 @@ tvcc_decode_data (struct tvcc_decoder *td,
case DTVCC_DATA:
j = td->dtvcc.packet_size;
+ //printf("atsc data %d %d %02x %02x\n", j, cc_valid, cc_data_1, cc_data_2);
if (j <= 0) {
/* Missed packet start. */
break;
@@ -3722,6 +3866,7 @@ tvcc_decode_data (struct tvcc_decoder *td,
case DTVCC_START:
dtvcc = TRUE;
j = td->dtvcc.packet_size;
+ //printf("atsc start %d %d %02x %02x\n", j, cc_valid, cc_data_1, cc_data_2);
if (j > 0) {
/* End of DTVCC packet. */
dtvcc_decode_packet (&td->dtvcc,
@@ -3734,20 +3879,33 @@ tvcc_decode_data (struct tvcc_decoder *td,
td->dtvcc.packet[0] = cc_data_1;
td->dtvcc.packet[1] = cc_data_2;
td->dtvcc.packet_size = 2;
-
- dtvcc_try_decode_packet (&td->dtvcc, &now, pts);
+ dtvcc_try_decode_packet(&td->dtvcc, &now, pts);
}
break;
}
}
- for (i = 0; i < N_ELEMENTS(td->dtvcc.service); i ++) {
- struct dtvcc_service *ds = &td->dtvcc.service[i];
+ {
+ int i;
+
+ for (i = 0; i < N_ELEMENTS(td->dtvcc.service); i ++) {
+ struct dtvcc_service *ds = &td->dtvcc.service[i];
+
+ if (ds->update) {
+ struct vbi_event event;
+
+ event.type = VBI_EVENT_CAPTION;
+ event.ev.caption.pgno = i + 1 + 8/*after 8 cc channels*/;
- if (ds->update) {
- dtvcc_event(&td->dtvcc, ds);
+ /* Permits calling tvcc_fetch_page from handler */
+ pthread_mutex_unlock(&td->mutex);
- ds->update = 0;
+ vbi_send_event(td->vbi, &event);
+
+ pthread_mutex_lock(&td->mutex);
+
+ ds->update = 0;
+ }
}
}
diff --git a/src/dtvcc.h b/src/dtvcc.h
index 2557a36..78a5c17 100644
--- a/src/dtvcc.h
+++ b/src/dtvcc.h
@@ -336,6 +336,8 @@ struct dtvcc_window {
/* EIA 708-C window state. */
uint16_t buffer[16][42];
+ struct dtvcc_pen_style pen[16][42];
+ int row_start[16];
vbi_bool visible;
@@ -381,6 +383,9 @@ struct dtvcc_service {
/* Interpretation Layer. */
struct dtvcc_window window[8];
+ struct dtvcc_window old_window[8];
+
+ int old_win_cnt;
int update;
struct dtvcc_window * curr_window;
@@ -474,6 +479,7 @@ struct tvcc_decoder {
struct cc_decoder cc;
struct dtvcc_decoder dtvcc;
};
+unsigned int dtvcc_unicode (unsigned int c);
extern void tvcc_init(struct tvcc_decoder *td);
@@ -483,7 +489,7 @@ extern void tvcc_reset(struct tvcc_decoder *td);
extern void tvcc_destroy(struct tvcc_decoder *td);
-extern void tvcc_fetch_page(struct tvcc_decoder *td, int pgno, int *sub_cnt, struct vbi_page *sub_pages);
+extern void tvcc_fetch_page(struct tvcc_decoder *td, int pgno, int *cnt, struct vbi_page *sub_pages);
static void dtvcc_init(struct dtvcc_decoder * dc);
@@ -497,5 +503,9 @@ extern vbi_bool cc_feed(struct cc_decoder *cd, const uint8_t buffer[2], unsigned
extern void cc_reset(struct cc_decoder *cd);
+extern void vbi_decode_caption(vbi_decoder *vbi, int line, const uint8_t *buf);
+
+extern int get_input_offset();
+
#endif