summaryrefslogtreecommitdiff
authorYan Yan <yan.yan@amlogic.com>2017-11-29 08:45:58 (GMT)
committer Yan Yan <yan.yan@amlogic.com>2017-11-29 09:14:43 (GMT)
commitec185989ea362a690c4d1e298e89023817ddf2e1 (patch)
tree77bf135f94fadf5930f0188b495f236cd52a3c5a
parentfd22762f7be71ebad5f1b16890f16f5842eb2034 (diff)
downloadlibzvbi-ec185989ea362a690c4d1e298e89023817ddf2e1.zip
libzvbi-ec185989ea362a690c4d1e298e89023817ddf2e1.tar.gz
libzvbi-ec185989ea362a690c4d1e298e89023817ddf2e1.tar.bz2
DTVCC: add delay command support
PD# 154395 Change-Id: Ic196465d343ba433239b85a4d02b668a58853808
Diffstat
-rwxr-xr-xsrc/dtvcc.c159
-rw-r--r--src/dtvcc.h6
2 files changed, 141 insertions, 24 deletions
diff --git a/src/dtvcc.c b/src/dtvcc.c
index 40c79ac..aa538a1 100755
--- a/src/dtvcc.c
+++ b/src/dtvcc.c
@@ -3220,6 +3220,45 @@ dtvcc_delete_windows (struct dtvcc_decoder * dc,
}
static vbi_bool
+dtvcc_delay_cmd (struct dtvcc_decoder * dc,
+ struct dtvcc_service * ds,
+ uint8_t delay_cmd,
+ uint8_t delay_time)
+{
+ struct timespec now_ts;
+ int plus_one_second = 0;
+ clock_gettime(CLOCK_REALTIME, &now_ts);
+ if(delay_cmd == 0x8D)
+ {
+ /* Set trigger time
+ Until that time, sevice stop decoding.
+ */
+ /* Delay time is tenths of second */
+ /* We set the timer a little faster to avoid double delay conflict */
+ if((1000000000 - (delay_time%10) * 100000000) > now_ts.tv_nsec)
+ {
+ ds->delay_timer.tv_nsec = ((delay_time % 10) * 100000000 + now_ts.tv_nsec) % 1000000000;
+ ds->delay_timer.tv_sec = (1 + now_ts.tv_sec + delay_time/10) -1;
+ }
+ else
+ {
+ ds->delay_timer.tv_nsec = (delay_time % 10) * 100000000 + now_ts.tv_nsec;
+ ds->delay_timer.tv_sec = (now_ts.tv_sec + delay_time / 10) -1;
+ }
+ ds->delay_timer.tv_sec = now_ts.tv_sec + 1;
+ ds->delay = 1;
+ ds->delay_cancel = 0;
+ AM_DEBUG(1, "Enter delay cmd, now %d until %d", now_ts.tv_sec, ds->delay_timer.tv_sec);
+ }
+ else if(delay_cmd == 0x8E)
+ {
+ ds->delay = 0;
+ ds->delay_cancel = 1;
+ }
+ return TRUE;
+}
+
+static vbi_bool
dtvcc_command (struct dtvcc_decoder * dc,
struct dtvcc_service * ds,
unsigned int * se_length,
@@ -3268,6 +3307,14 @@ dtvcc_command (struct dtvcc_decoder * dc,
case 0x89: /* DSW DisplayWindows */
return dtvcc_display_windows (dc, ds, c, buf[1]);
+ case 0x8D:
+ dtvcc_delay_cmd(dc, ds, 0x8d, buf[1]);
+ return 0;
+
+ case 0x8E:
+ dtvcc_delay_cmd(dc, ds, 0x8e, buf[1]);
+ return 0;
+
case 0x8A: /* HDW HideWindows */
return dtvcc_display_windows (dc, ds, c, buf[1]);
@@ -3371,6 +3418,7 @@ dtvcc_decode_syntactic_elements (struct dtvcc_decoder * dc,
unsigned int n_bytes)
{
ds->timestamp = dc->timestamp;
+ struct timespec ts_now;
#if 0
AM_DEBUG(1, "+++++++++++++++++++++ servie %d\n", n_bytes);
@@ -3383,15 +3431,7 @@ dtvcc_decode_syntactic_elements (struct dtvcc_decoder * dc,
#endif
while (n_bytes > 0) {
unsigned int se_length;
-
- if (0x8D /* DLY */ == *buf
- || 0x8E /* DLC */ == *buf) {
- /* FIXME ignored for now. */
- ++buf;
- --n_bytes;
- continue;
- }
-
+
//printf("dec se %02x\n", buf[0]);
if (!dtvcc_decode_se (dc, ds,
@@ -3537,15 +3577,22 @@ dtvcc_decode_packet (struct dtvcc_decoder * dc,
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;
- success = dtvcc_decode_syntactic_elements
- (dc, ds, ds->service_data, ds->service_data_in);
-
- ds->service_data_in = 0;
-
- if (success)
- continue;
-
+ if (success)
+ continue;
+ }
//dtvcc_reset_service (ds);
dc->next_sequence_number = -1;
}
@@ -3594,6 +3641,8 @@ dtvcc_reset_service (struct dtvcc_service * ds)
{
ds->curr_window = NULL;
ds->created = 0;
+ ds->delay = 0;
+ ds->delay_cancel = 0;
cc_timestamp_reset (&ds->timestamp);
}
@@ -3899,15 +3948,77 @@ tvcc_decode_data (struct tvcc_decoder *td,
/* Permits calling tvcc_fetch_page from handler */
pthread_mutex_unlock(&td->mutex);
- vbi_send_event(td->vbi, &event);
- pthread_mutex_lock(&td->mutex);
+ vbi_send_event(td->vbi, &event);
+ pthread_mutex_lock(&td->mutex);
- ds->update = 0;
- }
- }
- }
+ ds->update = 0;
+ }
+ }
+ }
- pthread_mutex_unlock(&td->mutex);
+ pthread_mutex_unlock(&td->mutex);
+}
+
+/* Only handle effect */
+void update_service_status(struct tvcc_decoder *td)
+{
+ int i;
+ struct timespec ts_now;
+ struct dtvcc_decoder *decoder;
+ decoder = &td->dtvcc;
+ pthread_mutex_lock(&td->mutex);
+ /* CS1 - CS6 */
+ for (i = 0; i < 6; ++i) {
+ struct dtvcc_service *ds;
+ struct program *pr;
+ vbi_bool success;
+
+ ds = &decoder->service[i];
+ /* Check every effect */
+#if 1
+ if(ds->delay)
+ {
+ struct vbi_event event;
+ /* time is up */
+ clock_gettime(CLOCK_REALTIME, &ts_now);
+ if((ts_now.tv_sec > ds->delay_timer.tv_sec) ||
+ ((ts_now.tv_sec == ds->delay_timer.tv_sec) &&(ts_now.tv_nsec > ds->delay_timer.tv_nsec)) ||
+ ds->delay_cancel)
+ {
+ AM_DEBUG(1, "delay timeup");
+ ds->delay = 0;
+ ds->delay_cancel = 0;
+ dtvcc_decode_syntactic_elements
+ (decoder, ds, ds->service_data, ds->service_data_in);
+
+ ds->service_data_in = 0;
+ }
+ }
+#endif
+ }
+ {
+ 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*/;
+
+ /* Permits calling tvcc_fetch_page from handler */
+ pthread_mutex_unlock(&td->mutex);
+
+ vbi_send_event(td->vbi, &event);
+ pthread_mutex_lock(&td->mutex);
+
+ ds->update = 0;
+ }
+ }
+ }
+ pthread_mutex_unlock(&td->mutex);
}
void tvcc_init(struct tvcc_decoder *td)
diff --git a/src/dtvcc.h b/src/dtvcc.h
index 78a5c17..9697d5c 100644
--- a/src/dtvcc.h
+++ b/src/dtvcc.h
@@ -399,6 +399,12 @@ struct dtvcc_service {
uint8_t service_data[128];
unsigned int service_data_in;
+ /* For 0x8D 0x8E delay command
+ if delay flag is set, decoder stop decoding
+ */
+ struct timespec delay_timer;
+ int delay;
+ int delay_cancel;
/** The time when we last received data for this service. */
struct cc_timestamp timestamp;