Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fdbeb962 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

media: dvb: update buffer mmaped flags and frame counter



Now that we have support for a buffer counter and for
error flags, update them at DMX_DQBUF.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 9c171cdf
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;
@@ -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);
@@ -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;
@@ -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);
@@ -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;
+73 −39
Original line number Diff line number Diff line
@@ -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
 ******************************************************************************/
@@ -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",
	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);
#endif
	}

	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,
@@ -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)
@@ -169,9 +179,11 @@ 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 {
		if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
@@ -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;

@@ -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",
			set_buf_flags(feed,
				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
			dprintk_sect_loss("section ts padding loss: %d/%d\n",
					  n, sec->tsfeedp);
			dprintk("pad data: %*ph\n", n, sec->secbuf);
			dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf);
		}
	}
#endif

	sec->tsfeedp = sec->secbufp = sec->seclen = 0;
	sec->secbuf = sec->secbuf_base;
@@ -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",
		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);
#endif
		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
	}

@@ -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 */
	}
@@ -307,18 +319,22 @@ 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
@@ -326,6 +342,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
		 * FIXME: does it make sense if the MPEG-TS is the one
		 *	reporting discontinuity?
		 */

		feed->pusi_seen = false;
		dvb_dmx_swfilter_section_new(feed);
	}
@@ -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);
@@ -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)
@@ -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
@@ -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);
@@ -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);
	}
}

@@ -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);
}
@@ -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;
@@ -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;
+3 −2
Original line number Diff line number Diff line
@@ -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;

@@ -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;

+22 −9
Original line number Diff line number Diff line
@@ -256,7 +256,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
}

int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
			const unsigned char *src, int len)
			const unsigned char *src, int len,
			enum dmx_buffer_flags *buffer_flags)
{
	unsigned long flags = 0;
	void *vbuf = NULL;
@@ -264,15 +265,17 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
	unsigned char *psrc = (unsigned char *)src;
	int ll = 0;

	dprintk(3, "[%s] %d bytes are rcvd\n", ctx->name, len);
	if (!src) {
		dprintk(3, "[%s]:NULL pointer src\n", ctx->name);
		/**normal case: This func is called twice from demux driver
		 * once with valid src pointer, second time with NULL pointer
	/*
	 * normal case: This func is called twice from demux driver
	 * one with valid src pointer, second time with NULL pointer
	 */
	if (!src || !len)
		return 0;
	}
	spin_lock_irqsave(&ctx->slock, flags);
	if (buffer_flags && *buffer_flags) {
		ctx->flags |= *buffer_flags;
		*buffer_flags = 0;
	}
	while (todo) {
		if (!ctx->buf) {
			if (list_empty(&ctx->dvb_q)) {
@@ -395,6 +398,7 @@ int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)

int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
	unsigned long flags;
	int ret;

	ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking);
@@ -402,7 +406,16 @@ int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
		return ret;
	}
	dprintk(5, "[%s] index=%d\n", ctx->name, b->index);

	spin_lock_irqsave(&ctx->slock, flags);
	b->count = ctx->count++;
	b->flags = ctx->flags;
	ctx->flags = 0;
	spin_unlock_irqrestore(&ctx->slock, flags);

	dprintk(5, "[%s] index=%d, count=%d, flags=%d\n",
		ctx->name, b->index, ctx->count, b->flags);


	return 0;
}
+3 −2
Original line number Diff line number Diff line
@@ -324,14 +324,15 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
		}
		return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
						  buffer2, buffer2_len,
						  &dvbdmxfilter->filter);
						  &dvbdmxfilter->filter, NULL);
	case DMX_TYPE_TS:
		if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
			return 0;
		if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
			return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
							 buffer2, buffer2_len,
							 &dvbdmxfilter->feed->feed.ts);
							 &dvbdmxfilter->feed->feed.ts,
							 NULL);
		else
			av7110_p2t_write(buffer1, buffer1_len,
					 dvbdmxfilter->feed->pid,
Loading