Skip to content

Commit

Permalink
media: dvb: update buffer mmaped flags and frame counter
Browse files Browse the repository at this point in the history
Now that we have support for a buffer counter and for
error flags, update them at DMX_DQBUF.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
mchehab committed Feb 23, 2018
1 parent 9c171cd commit fdbeb96
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 76 deletions.
24 changes: 15 additions & 9 deletions drivers/media/dvb-core/dmxdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)

static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter)
struct dmx_section_filter *filter,
u32 *buffer_flags)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret;
Expand All @@ -404,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
dprintk("section callback %*ph\n", 6, buffer1);
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
buffer1, buffer1_len);
buffer1, buffer1_len,
buffer_flags);
if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
buffer2, buffer2_len);
buffer2, buffer2_len,
buffer_flags);
} else {
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
buffer1, buffer1_len);
Expand All @@ -427,7 +430,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,

static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed)
struct dmx_ts_feed *feed,
u32 *buffer_flags)
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
Expand Down Expand Up @@ -456,9 +460,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
}

if (dvb_vb2_is_streaming(ctx)) {
ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len,
buffer_flags);
if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len,
buffer_flags);
} else {
if (buffer->error) {
spin_unlock(&dmxdevfilter->dev->lock);
Expand Down Expand Up @@ -1218,7 +1224,7 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
int ret;

if (!dmxdev->may_do_mmap)
return -EOPNOTSUPP;
return -ENOTTY;

if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
Expand Down Expand Up @@ -1318,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
break;
#endif
default:
ret = -EINVAL;
ret = -ENOTTY;
break;
}
mutex_unlock(&dmxdev->mutex);
Expand Down Expand Up @@ -1367,7 +1373,7 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
int ret;

if (!dmxdev->may_do_mmap)
return -EOPNOTSUPP;
return -ENOTTY;

if (dmxdev->exit)
return -ENODEV;
Expand Down
112 changes: 73 additions & 39 deletions drivers/media/dvb-core/dvb_demux.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
dprintk(x); \
} while (0)

#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
# define dprintk_sect_loss(x...) dprintk(x)
#else
# define dprintk_sect_loss(x...)
#endif

#define set_buf_flags(__feed, __flag) \
do { \
(__feed)->buffer_flags |= (__flag); \
} while (0)

/******************************************************************************
* static inlined helper functions
******************************************************************************/
Expand Down Expand Up @@ -104,31 +115,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
{
int count = payload(buf);
int p;
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
int ccok;
u8 cc;
#endif

if (count == 0)
return -1;

p = 188 - count;

#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
if (!ccok)
dprintk("missed packet: %d instead of %d!\n",
cc, (feed->cc + 1) & 0x0f);
#endif
if (!ccok) {
set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("missed packet: %d instead of %d!\n",
cc, (feed->cc + 1) & 0x0f);
}

if (buf[1] & 0x40) // PUSI ?
feed->peslen = 0xfffa;

feed->peslen += count;

return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts);
return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts,
&feed->buffer_flags);
}

static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
Expand All @@ -150,7 +160,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
return 0;

return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
NULL, 0, &f->filter);
NULL, 0, &f->filter, &feed->buffer_flags);
}

static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
Expand All @@ -169,8 +179,10 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
if (sec->check_crc) {
section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
if (section_syntax_indicator &&
demux->check_crc32(feed, sec->secbuf, sec->seclen))
demux->check_crc32(feed, sec->secbuf, sec->seclen)) {
set_buf_flags(feed, DMX_BUFFER_FLAG_HAD_CRC32_DISCARD);
return -1;
}
}

do {
Expand All @@ -187,7 +199,6 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
{
struct dmx_section_feed *sec = &feed->feed.sec;

#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
if (sec->secbufp < sec->tsfeedp) {
int n = sec->tsfeedp - sec->secbufp;

Expand All @@ -197,12 +208,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
* but just first and last.
*/
if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
dprintk("section ts padding loss: %d/%d\n",
n, sec->tsfeedp);
dprintk("pad data: %*ph\n", n, sec->secbuf);
set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("section ts padding loss: %d/%d\n",
n, sec->tsfeedp);
dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf);
}
}
#endif

sec->tsfeedp = sec->secbufp = sec->seclen = 0;
sec->secbuf = sec->secbuf_base;
Expand Down Expand Up @@ -237,11 +249,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
return 0;

if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
dprintk("section buffer full loss: %d/%d\n",
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
DMX_MAX_SECFEED_SIZE);
#endif
set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("section buffer full loss: %d/%d\n",
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
DMX_MAX_SECFEED_SIZE);
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
}

Expand Down Expand Up @@ -269,12 +280,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
sec->seclen = seclen;
sec->crc_val = ~0;
/* dump [secbuf .. secbuf+seclen) */
if (feed->pusi_seen)
if (feed->pusi_seen) {
dvb_dmx_swfilter_section_feed(feed);
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
else
dprintk("pusi not seen, discarding section data\n");
#endif
} else {
set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("pusi not seen, discarding section data\n");
}
sec->secbufp += seclen; /* secbufp and secbuf moving together is */
sec->secbuf += seclen; /* redundant but saves pointer arithmetic */
}
Expand Down Expand Up @@ -307,25 +319,30 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
}

if (!ccok || dc_i) {
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
if (dc_i)
dprintk("%d frame with disconnect indicator\n",
if (dc_i) {
set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR);
dprintk_sect_loss("%d frame with disconnect indicator\n",
cc);
else
dprintk("discontinuity: %d instead of %d. %d bytes lost\n",
} else {
set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("discontinuity: %d instead of %d. %d bytes lost\n",
cc, (feed->cc + 1) & 0x0f, count + 4);
}
/*
* those bytes under sume circumstances will again be reported
* those bytes under some circumstances will again be reported
* in the following dvb_dmx_swfilter_section_new
*/
#endif

/*
* Discontinuity detected. Reset pusi_seen to
* stop feeding of suspicious data until next PUSI=1 arrives
*
* FIXME: does it make sense if the MPEG-TS is the one
* reporting discontinuity?
*/

feed->pusi_seen = false;
dvb_dmx_swfilter_section_new(feed);
}
Expand All @@ -345,11 +362,11 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
dvb_dmx_swfilter_section_new(feed);
dvb_dmx_swfilter_section_copy_dump(feed, after,
after_len);
} else if (count > 0) {
set_buf_flags(feed,
DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("PUSI=1 but %d bytes lost\n", count);
}
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
else if (count > 0)
dprintk("PUSI=1 but %d bytes lost\n", count);
#endif
} else {
/* PUSI=0 (is not set), no section boundary */
dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
Expand All @@ -369,7 +386,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf);
else
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
&feed->buffer_flags);
}
/* Used only on full-featured devices */
if (feed->ts_type & TS_DECODER)
Expand Down Expand Up @@ -430,6 +448,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
}

if (buf[1] & 0x80) {
list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
continue;
set_buf_flags(feed, DMX_BUFFER_FLAG_TEI);
}
dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n",
pid, buf[1]);
/* data in this packet can't be trusted - drop it unless
Expand All @@ -445,6 +468,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
(demux->cnt_storage[pid] + 1) & 0xf;

if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
continue;
set_buf_flags(feed,
DMX_BUFFER_PKT_COUNTER_MISMATCH);
}

dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
Expand All @@ -466,7 +496,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
if (feed->pid == pid)
dvb_dmx_swfilter_packet_type(feed, buf);
else if (feed->pid == 0x2000)
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
&feed->buffer_flags);
}
}

Expand Down Expand Up @@ -585,7 +616,8 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)

spin_lock_irqsave(&demux->lock, flags);

demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts);
demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts,
&demux->feed->buffer_flags);

spin_unlock_irqrestore(&demux->lock, flags);
}
Expand Down Expand Up @@ -785,6 +817,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
feed->demux = demux;
feed->pid = 0xffff;
feed->peslen = 0xfffa;
feed->buffer_flags = 0;

(*ts_feed) = &feed->feed.ts;
(*ts_feed)->parent = dmx;
Expand Down Expand Up @@ -1042,6 +1075,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
dvbdmxfeed->cb.sec = callback;
dvbdmxfeed->demux = dvbdmx;
dvbdmxfeed->pid = 0xffff;
dvbdmxfeed->buffer_flags = 0;
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
dvbdmxfeed->feed.sec.tsfeedp = 0;
Expand Down
5 changes: 3 additions & 2 deletions drivers/media/dvb-core/dvb_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)

static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed)
struct dmx_ts_feed *feed,
u32 *buffer_flags)
{
struct net_device *dev = feed->priv;

Expand Down Expand Up @@ -992,7 +993,7 @@ static void dvb_net_sec(struct net_device *dev,

static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter)
struct dmx_section_filter *filter, u32 *buffer_flags)
{
struct net_device *dev = filter->priv;

Expand Down
Loading

0 comments on commit fdbeb96

Please sign in to comment.