#include <asm/uaccess.h>
#include "dvb_demux.h"
-#include "dvb_functions.h"
#define NOBUFS
/*
feed->peslen += count;
- return feed->cb.ts (&buf[p], count, 0, 0, &feed->feed.ts, DMX_OK);
+ return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
}
neq |= f->maskandnotmode[i] & xor;
}
- if (f->doneq & !neq)
+ if (f->doneq && !neq)
return 0;
return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen,
- 0, 0, &f->filter, DMX_OK);
+ NULL, 0, &f->filter, DMX_OK);
}
}
/*
-** Losless Section Demux 1.4 by Emard
+** Losless Section Demux 1.4.1 by Emard
+** Valsecchi Patrick:
+** - middle of section A (no PUSI)
+** - end of section A and start of section B
+** (with PUSI pointing to the start of the second section)
+**
+** In this case, without feed->pusi_seen you'll receive a garbage section
+** consisting of the end of section A. Basically because tsfeedp
+** is incemented and the use=0 condition is not raised
+** when the second packet arrives.
+**
+** Fix:
+** when demux is started, let feed->pusi_seen = 0 to
+** prevent initial feeding of garbage from the end of
+** previous section. When you for the first time see PUSI=1
+** then set feed->pusi_seen = 1
*/
static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
{
sec->seclen = seclen;
sec->crc_val = ~0;
/* dump [secbuf .. secbuf+seclen) */
+ if(feed->pusi_seen)
dvb_dmx_swfilter_section_feed(feed);
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+ else
+ printk("dvb_demux.c pusi not seen, discarding section data\n");
+#endif
sec->secbufp += seclen; /* secbufp and secbuf moving together is */
sec->secbuf += seclen; /* redundand but saves pointer arithmetic */
}
static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf)
{
u8 p, count;
- int ccok;
+ int ccok, dc_i = 0;
u8 cc;
count = payload(buf);
p = 188-count; /* payload start */
cc = buf[3] & 0x0f;
- ccok = ((feed->cc+1) & 0x0f) == cc ? 1 : 0;
+ ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
- if(ccok == 0)
- {
+
+ if (buf[3] & 0x20) {
+ /* adaption field present, check for discontinuity_indicator */
+ if ((buf[4] > 0) && (buf[5] & 0x80))
+ dc_i = 1;
+ }
+
+ if (!ccok || dc_i) {
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
printk("dvb_demux.c discontinuity detected %d bytes lost\n", count);
/* those bytes under sume circumstances will again be reported
** in the following dvb_dmx_swfilter_section_new
*/
#endif
+ /* Discontinuity detected. Reset pusi_seen = 0 to
+ ** stop feeding of suspicious data until next PUSI=1 arrives
+ */
+ feed->pusi_seen = 0;
dvb_dmx_swfilter_section_new(feed);
return 0;
}
- if(buf[1] & 0x40)
- {
+ if (buf[1] & 0x40) {
// PUSI=1 (is set), section boundary is here
- if(count > 1 && buf[p] < count)
- {
+ if (count > 1 && buf[p] < count) {
const u8 *before = buf+p+1;
u8 before_len = buf[p];
const u8 *after = before+before_len;
u8 after_len = count-1-before_len;
dvb_dmx_swfilter_section_copy_dump(feed, before, before_len);
+ /* before start of new section, set pusi_seen = 1 */
+ feed->pusi_seen = 1;
dvb_dmx_swfilter_section_new(feed);
dvb_dmx_swfilter_section_copy_dump(feed, after, after_len);
}
if(count > 0)
printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
#endif
- }
- else
- {
+ } else {
// PUSI=0 (is not set), no section boundary
const u8 *entire = buf+p;
u8 entire_len = count;
if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf);
else
- feed->cb.ts(buf, 188, 0, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
}
if (feed->ts_type & TS_DECODER)
if (feed->demux->write_to_decoder)
}
if (feed->pid == 0x2000)
- feed->cb.ts(buf, 188, 0, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
}
}
-
+EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)
{
spin_unlock(&demux->lock);
}
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
bailout:
spin_unlock(&demux->lock);
}
+EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
bailout:
spin_unlock(&demux->lock);
}
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
{
+ spin_lock_irq(&feed->demux->lock);
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
- return;
+ goto out;
}
list_add(&feed->list_head, &feed->demux->feed_list);
+out:
+ spin_unlock_irq(&feed->demux->lock);
}
static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
{
+ spin_lock_irq(&feed->demux->lock);
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
- return;
+ goto out;
}
list_del(&feed->list_head);
+out:
+ spin_unlock_irq(&feed->demux->lock);
}
static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
if (feed->buffer_size) {
#ifdef NOBUFS
- feed->buffer=0;
+ feed->buffer=NULL;
#else
feed->buffer = vmalloc(feed->buffer_size);
if (!feed->buffer) {
feed->demux = demux;
feed->pid = 0xffff;
feed->peslen = 0xfffa;
- feed->buffer = 0;
+ feed->buffer = NULL;
(*ts_feed) = &feed->feed.ts;
(*ts_feed)->parent = dmx;
- (*ts_feed)->priv = 0;
+ (*ts_feed)->priv = NULL;
(*ts_feed)->is_filtering = 0;
(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering;
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
}
#ifndef NOBUFS
- if (feed->buffer) {
vfree(feed->buffer);
feed->buffer=0;
- }
#endif
feed->state = DMX_STATE_FREE;
feed->pid = 0xffff;
- if (feed->ts_type & TS_DECODER)
+ if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
demux->pesfilter[feed->pes_type] = NULL;
up(&demux->mutex);
spin_lock_irq(&dvbdemux->lock);
*filter=&dvbdmxfilter->filter;
(*filter)->parent=feed;
- (*filter)->priv=0;
+ (*filter)->priv=NULL;
dvbdmxfilter->feed=dvbdmxfeed;
dvbdmxfilter->type=DMX_TYPE_SEC;
dvbdmxfilter->state=DMX_STATE_READY;
dvbdmxfeed->feed.sec.check_crc=check_crc;
#ifdef NOBUFS
- dvbdmxfeed->buffer=0;
+ dvbdmxfeed->buffer=NULL;
#else
dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
if (!dvbdmxfeed->buffer) {
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
dvbdmxfeed->feed.sec.tsfeedp = 0;
- dvbdmxfeed->filter=0;
- dvbdmxfeed->buffer=0;
+ dvbdmxfeed->filter=NULL;
+ dvbdmxfeed->buffer=NULL;
(*feed)=&dvbdmxfeed->feed.sec;
(*feed)->is_filtering=0;
(*feed)->parent=demux;
- (*feed)->priv=0;
+ (*feed)->priv=NULL;
(*feed)->set=dmx_section_feed_set;
(*feed)->allocate_filter=dmx_section_feed_allocate_filter;
return -EINVAL;
}
#ifndef NOBUFS
- if (dvbdmxfeed->buffer) {
vfree(dvbdmxfeed->buffer);
dvbdmxfeed->buffer=0;
- }
#endif
dvbdmxfeed->state=DMX_STATE_FREE;
up(&dvbdemux->mutex);
return 0;
}
+EXPORT_SYMBOL(dvbdmx_connect_frontend);
int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
up(&dvbdemux->mutex);
return 0;
}
+EXPORT_SYMBOL(dvbdmx_disconnect_frontend);
static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
if (!dvbdemux->memcopy)
dvbdemux->memcopy = dvb_dmx_memcopy;
- dmx->frontend=0;
+ dmx->frontend=NULL;
dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list;
dmx->priv=(void *) dvbdemux;
dmx->open=dvbdmx_open;
return 0;
}
+EXPORT_SYMBOL(dvb_dmx_init);
int dvb_dmx_release(struct dvb_demux *dvbdemux)
struct dmx_demux *dmx = &dvbdemux->dmx;
dmx_unregister_demux(dmx);
- if (dvbdemux->filter)
vfree(dvbdemux->filter);
- if (dvbdemux->feed)
vfree(dvbdemux->feed);
return 0;
}
+EXPORT_SYMBOL(dvb_dmx_release);
+