diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c index e65848ac..6a2395ae 100755 --- a/src/descrambler/descrambler.c +++ b/src/descrambler/descrambler.c @@ -347,6 +347,22 @@ key_late( th_descrambler_runtime_t *dr, uint8_t ki ) return dr->dr_ecm_key_time + 2 < dr->dr_key_start; } +static int +ecm_reset( service_t *t, th_descrambler_runtime_t *dr ) +{ + th_descrambler_t *td; + int ret = 0; + + /* reset the reader ECM state */ + LIST_FOREACH(td, &t->s_descramblers, td_service_link) { + if (!td->td_ecm_reset(td)) { + dr->dr_key_valid = 0; + ret = 1; + } + } + return ret; +} + int descrambler_descramble ( service_t *t, elementary_stream_t *st, @@ -354,7 +370,7 @@ descrambler_descramble ( service_t *t, { th_descrambler_t *td; th_descrambler_runtime_t *dr = t->s_descramble; - int count, failed, off, size, flush_data = 0; + int count, failed, resolved, off, size, flush_data = 0; uint8_t *tsb2, ki; lock_assert(&t->s_stream_mutex); @@ -362,18 +378,21 @@ descrambler_descramble ( service_t *t, if (dr == NULL) return -1; - count = failed = 0; + count = failed = resolved = 0; LIST_FOREACH(td, &t->s_descramblers, td_service_link) { count++; - if (td->td_keystate == DS_FORBIDDEN) { - failed++; - continue; + switch (td->td_keystate) { + case DS_FORBIDDEN: failed++; break; + case DS_RESOLVED : resolved++; break; + default: break; } - if (td->td_keystate != DS_RESOLVED) - continue; + } + if (resolved) { + + /* update the keys */ if (dr->dr_key_changed) { - dr->dr_csa.csa_flush(&dr->dr_csa, (mpegts_service_t *)td->td_service); + dr->dr_csa.csa_flush(&dr->dr_csa, (mpegts_service_t *)t); if (dr->dr_key_changed & 1) tvhcsa_set_key_even(&dr->dr_csa, dr->dr_key_even); if (dr->dr_key_changed & 2) @@ -381,6 +400,7 @@ descrambler_descramble ( service_t *t, dr->dr_key_changed = 0; } + /* process the queued TS packets */ if (dr->dr_buf.sb_ptr > 0) { for (off = 0, size = dr->dr_buf.sb_ptr; off < size; off += 188) { tsb2 = dr->dr_buf.sb_data + off; @@ -388,7 +408,8 @@ descrambler_descramble ( service_t *t, if ((ki & 0x80) != 0x00) { if (key_valid(dr, ki) == 0) { sbuf_cut(&dr->dr_buf, off); - goto next2; + flush_data = 1; + goto next; } if (dr->dr_key_index != (ki & 0x40) && dr->dr_key_start + 2 < dispatch_clock) { @@ -397,23 +418,22 @@ descrambler_descramble ( service_t *t, ((mpegts_service_t *)t)->s_dvb_svcname); if (key_late(dr, ki)) { sbuf_cut(&dr->dr_buf, off); - if (!td->td_ecm_reset(td)) { - dr->dr_key_valid = 0; + if (ecm_reset(t, dr)) { + flush_data = 1; goto next; } } key_update(dr, ki); } } - dr->dr_csa.csa_descramble(&dr->dr_csa, - (mpegts_service_t *)td->td_service, - tsb2); + dr->dr_csa.csa_descramble(&dr->dr_csa, (mpegts_service_t *)t, tsb2); } if (off > 0) service_reset_streaming_status_flags(t, TSS_NO_ACCESS); sbuf_free(&dr->dr_buf); } + /* check for key change */ ki = tsb[3]; if ((ki & 0x80) != 0x00) { if (key_valid(dr, ki) == 0) { @@ -422,7 +442,7 @@ descrambler_descramble ( service_t *t, ((mpegts_service_t *)t)->s_dvb_svcname, (ki & 0x40) ? "odd stream key is not valid" : "even stream key is not valid"); - continue; + goto next; } if (dr->dr_key_index != (ki & 0x40) && dr->dr_key_start + 2 < dispatch_clock) { @@ -433,24 +453,19 @@ descrambler_descramble ( service_t *t, tvhtrace("descrambler", "ECM late (%ld seconds) for service \"%s\"", dispatch_clock - dr->dr_ecm_key_time, ((mpegts_service_t *)t)->s_dvb_svcname); - if (!td->td_ecm_reset(td)) { - dr->dr_key_valid = 0; + if (ecm_reset(t, dr)) { + flush_data = 1; goto next; } } key_update(dr, ki); } } - dr->dr_csa.csa_descramble(&dr->dr_csa, - (mpegts_service_t *)td->td_service, - tsb); + dr->dr_csa.csa_descramble(&dr->dr_csa, (mpegts_service_t *)t, tsb); service_reset_streaming_status_flags(t, TSS_NO_ACCESS); return 1; -next: - flush_data = 1; -next2: - continue; } +next: if (dr->dr_ecm_start) { /* ECM sent */ ki = tsb[3]; if ((ki & 0x80) != 0x00) {