summaryrefslogtreecommitdiff
authoryan yan <yan.yan@amlogic.com>2017-12-13 03:35:28 (GMT)
committer yan yan <yan.yan@amlogic.com>2017-12-13 03:35:28 (GMT)
commit3a91f6b913bc1469231472fc7bfd882e5f4f68a7 (patch)
tree21dc0a2bb656c511581edcc5c2f5b17afc2ab84f
parent517cd69d54b05d5382940f38cb284c301fc89603 (diff)
downloadlibzvbi-3a91f6b913bc1469231472fc7bfd882e5f4f68a7.zip
libzvbi-3a91f6b913bc1469231472fc7bfd882e5f4f68a7.tar.gz
libzvbi-3a91f6b913bc1469231472fc7bfd882e5f4f68a7.tar.bz2
ATVCC: 1. fix color mismatch issue
DTVCC: 1. Start decoding when more than 2 bytes received, instead of 2. Ignore sub sequence mismatch, no reset action now. PD# NONE whole packet decode. Change-Id: I83b88c578c1a53d9adf8b4cf931114138c4b4800
Diffstat
-rw-r--r--src/caption.c2
-rw-r--r--src/dtvcc.c227
2 files changed, 191 insertions, 38 deletions
diff --git a/src/caption.c b/src/caption.c
index 27de703..d9d9fbe 100644
--- a/src/caption.c
+++ b/src/caption.c
@@ -1008,7 +1008,7 @@ caption_command(vbi_decoder *vbi, struct caption *cc,
ch->attr.foreground = palette_mapping[c2];
} else {
ch->attr.italic = TRUE;
- //ch->attr.foreground = VBI_WHITE;
+ ch->attr.foreground = VBI_WHITE;
}
}
diff --git a/src/dtvcc.c b/src/dtvcc.c
index d7b6de5..1b1a36a 100644
--- a/src/dtvcc.c
+++ b/src/dtvcc.c
@@ -3450,6 +3450,40 @@ dtvcc_decode_syntactic_elements (struct dtvcc_decoder * dc,
return TRUE;
}
+static void
+dtvcc_try_decode_channels (struct dtvcc_decoder *dc)
+{
+ int i;
+
+ for (i = 0; i < 6; ++i) {
+ struct dtvcc_service *ds;
+ struct program *pr;
+ vbi_bool success;
+
+ ds = &dc->service[i];
+ if (0 == ds->service_data_in)
+ continue;
+ if (!ds->delay ||
+ (ds->delay && ds->service_data_in>=128))
+ {
+ //AM_DEBUG(1, "service datain %d", ds->service_data_in);
+ success = dtvcc_decode_syntactic_elements
+ (dc, ds, ds->service_data, ds->service_data_in);
+ if (ds->service_data_in >= 128)
+ {
+ ds->delay = 0;
+ ds->delay_cancel = 0;
+ }
+ ds->service_data_in = 0;
+
+ if (success)
+ continue;
+ }
+ //dtvcc_reset_service (ds);
+ //dc->next_sequence_number = -1;
+ }
+}
+
void
dtvcc_decode_packet (struct dtvcc_decoder * dc,
const struct timeval * tv,
@@ -3474,7 +3508,7 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
/* sequence_number [2], packet_size_code [6],
packet_data [n * 8] */
-#if 1
+#if 0
if (dc->next_sequence_number >= 0
&& 0 != ((dc->packet[0] ^ dc->next_sequence_number) & 0xC0)) {
dtvcc_reset (dc);
@@ -3536,7 +3570,6 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
if (7 == service_number) {
if (i + 1 > packet_size)
break;
- //goto service_block_incomplete;
header_size = 2;
c = dc->packet[i + 1];
@@ -3544,7 +3577,6 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
/* We also check the null_fill bits. */
if (c < 7 || c > 63)
break;
- //goto invalid_service_block;
service_number = c;
}
@@ -3555,7 +3587,6 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
{
break;
}
- //goto service_block_incomplete;
if (service_number <= 6) {
struct dtvcc_service *ds;
@@ -3572,48 +3603,62 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
i += header_size + block_size;
}
- for (i = 0; i < 6; ++i) {
- struct dtvcc_service *ds;
- struct program *pr;
- vbi_bool success;
+ dtvcc_try_decode_channels(dc);
+ return;
+}
- ds = &dc->service[i];
- if (0 == ds->service_data_in)
- continue;
- if (!ds->delay ||
- (ds->delay && ds->service_data_in>=128))
- {
- //AM_DEBUG(1, "service datain %d", ds->service_data_in);
- success = dtvcc_decode_syntactic_elements
- (dc, ds, ds->service_data, ds->service_data_in);
- if (ds->service_data_in >= 128)
- {
- ds->delay = 0;
- ds->delay_cancel = 0;
- }
- ds->service_data_in = 0;
+static int
+dtvcc_get_se_len (unsigned char *p, int left)
+{
+ unsigned char c;
+ int se_length;
- if (success)
- continue;
+ if (left < 1)
+ return 0;
+
+ c = p[0];
+
+ if ((c == 0x8d) && (c == 0x8e))
+ return 1;
+
+ if (0 != (c & 0x60))
+ return 1;
+
+ if (0x10 != c) {
+ if ((int8_t) c < 0) {
+ se_length = dtvcc_c1_length[c - 0x80];
+ } else {
+ se_length = dtvcc_c0_length[c >> 3];
}
- //dtvcc_reset_service (ds);
- dc->next_sequence_number = -1;
- }
- return;
+ if (left < se_length)
+ return 0;
- invalid_service_block:
- {
- dtvcc_reset (dc);
- return;
+ return se_length;
}
- service_block_incomplete:
- {
- dtvcc_reset (dc);
- return;
+ if (left < 2)
+ return 0;
+
+ c = p[1];
+ if (0 != (c & 0x60))
+ return 2;
+
+ if ((int8_t) c >= 0) {
+ se_length = (c >> 3) + 2;
+ } else if (c < 0x90) {
+ se_length = (c >> 3) - 10;
+ } else {
+ if (left < 3)
+ return 0;
+
+ se_length = (p[2] & 0x1F) + 3;
}
+ if (left < se_length)
+ return 0;
+
+ return se_length;
}
void
@@ -3623,6 +3668,8 @@ dtvcc_try_decode_packet (struct dtvcc_decoder * dc,
{
unsigned int packet_size_code;
unsigned int packet_size;
+ unsigned char *p;
+ int left;
if (dc->packet_size < 1)
return;
@@ -3636,6 +3683,112 @@ dtvcc_try_decode_packet (struct dtvcc_decoder * dc,
if (packet_size <= dc->packet_size) {
dtvcc_decode_packet(dc, tv, pts);
dc->packet_size = 0;
+ return;
+ }
+
+ p = dc->packet + 1;
+ left = dc->packet_size - 1;
+ while (left > 0) {
+ unsigned int service_number;
+ unsigned int block_size;
+ unsigned int header_size;
+ unsigned int c;
+
+ header_size = 1;
+
+ c = p[0];
+ service_number = (c & 0xE0) >> 5;
+ if (0 == service_number)
+ break;
+
+ block_size = c & 0x1F;
+
+ if (7 == service_number) {
+ if (left < 2)
+ break;
+
+ header_size = 2;
+ c = p[1];
+
+ if (c < 7 || c > 63)
+ break;
+
+ service_number = c;
+ }
+
+ if (left >= header_size + block_size) {
+ if (service_number <= 6) {
+ struct dtvcc_service *ds;
+ unsigned int in;
+
+ ds = &dc->service[service_number - 1];
+ in = ds->service_data_in;
+ memcpy (ds->service_data + in,
+ p + header_size,
+ block_size);
+
+ ds->service_data_in = in + block_size;
+ }
+ } else {
+ unsigned char *s = p + header_size;
+ int sleft = left - header_size;
+
+ while (sleft > 0) {
+ int se_len;
+
+ se_len = dtvcc_get_se_len(s, sleft);
+ if (se_len <= 0)
+ break;
+
+ s += se_len;
+ sleft -= se_len;
+ }
+
+ if (sleft != left - header_size) {
+ int parsed = left - header_size - sleft;
+
+ if (service_number <= 6) {
+ struct dtvcc_service *ds;
+ unsigned int in;
+
+ ds = &dc->service[service_number - 1];
+ in = ds->service_data_in;
+ memcpy (ds->service_data + in,
+ p + header_size,
+ parsed);
+
+ ds->service_data_in = in + parsed;
+ }
+
+ memmove(p + header_size, s, sleft);
+ block_size -= parsed;
+ left -= parsed;
+
+ p[0] &= ~0x1f;
+ p[0] |= block_size;
+ }
+ break;
+ }
+
+ p += header_size + block_size;
+ left -= header_size + block_size;
+ }
+
+ if (left != dc->packet_size - 1) {
+ int parsed = dc->packet_size - 1 - left;
+
+ memmove(dc->packet + 1, p, left);
+
+ packet_size_code = ((dc->packet[0] & 0x3f) << 1) - parsed;
+ if (packet_size_code & 1)
+ packet_size_code ++;
+ packet_size_code >>= 1;
+
+ dc->packet[0] &= ~0x3f;
+ dc->packet[0] |= packet_size_code;
+ dc->packet_size = left + 1;
+
+ dtvcc_try_decode_channels(dc);
}
}