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

Commit fd46d16d authored by Oliver Endriss's avatar Oliver Endriss Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (11759): dvb-ttpci: Add TS replay capability



Implemented TS replay capability.
audio/video devices are able to process PES and TS data now.

Signed-off-by: default avatarOliver Endriss <o.endriss@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent b7fd6067
Loading
Loading
Loading
Loading
+78 −17
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@

static void p_to_t(u8 const *buf, long int length, u16 pid,
		   u8 *counter, struct dvb_demux_feed *feed);
static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len);


int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
@@ -437,6 +438,45 @@ static void play_audio_cb(u8 *buf, int count, void *priv)
	aux_ring_buffer_write(&av7110->aout, buf, count);
}


#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096)

static ssize_t ts_play(struct av7110 *av7110, const char __user *buf,
		       unsigned long count, int nonblock, int type)
{
	struct dvb_ringbuffer *rb;
	u8 *kb;
	unsigned long todo = count;

	dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count);

	rb = (type) ? &av7110->avout : &av7110->aout;
	kb = av7110->kbuf[type];

	if (!kb)
		return -ENOBUFS;

	if (nonblock && !FREE_COND_TS)
		return -EWOULDBLOCK;

	while (todo >= TS_SIZE) {
		if (!FREE_COND_TS) {
			if (nonblock)
				return count - todo;
			if (wait_event_interruptible(rb->queue, FREE_COND_TS))
				return count - todo;
		}
		if (copy_from_user(kb, buf, TS_SIZE))
			return -EFAULT;
		write_ts_to_decoder(av7110, type, kb, TS_SIZE);
		todo -= TS_SIZE;
		buf += TS_SIZE;
	}

	return count - todo;
}


#define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \
		   dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)

@@ -780,11 +820,32 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
}


static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len)
{
	struct ipack *ipack = &av7110->ipack[type];

	if (!(buf[3] & PAYLOAD))
		return -1;

	if (buf[1] & PAY_START)
		av7110_ipack_flush(ipack);

	if (buf[3] & ADAPT_FIELD) {
		len -= buf[4] + 1;
		buf += buf[4] + 1;
		if (!len)
			return 0;
	}

	av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
	return 0;
}


int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len)
{
	struct dvb_demux *demux = feed->demux;
	struct av7110 *av7110 = (struct av7110 *) demux->priv;
	struct ipack *ipack = &av7110->ipack[feed->pes_type];

	dprintk(2, "av7110:%p, \n", av7110);

@@ -804,20 +865,7 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l
		return -1;
	}

	if (!(buf[3] & 0x10)) /* no payload? */
		return -1;
	if (buf[1] & 0x40)
		av7110_ipack_flush(ipack);

	if (buf[3] & 0x20) {  /* adaptation field? */
		len -= buf[4] + 1;
		buf += buf[4] + 1;
		if (!len)
			return 0;
	}

	av7110_ipack_instant_repack(buf + 4, len - 4, &av7110->ipack[feed->pes_type]);
	return 0;
	return write_ts_to_decoder(av7110, feed->pes_type, buf, len);
}


@@ -916,6 +964,7 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf,
{
	struct dvb_device *dvbdev = file->private_data;
	struct av7110 *av7110 = dvbdev->priv;
	unsigned char c;

	dprintk(2, "av7110:%p, \n", av7110);

@@ -925,6 +974,11 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf,
	if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY)
		return -EPERM;

	if (get_user(c, buf))
		return -EFAULT;
	if (c == 0x47 && count % TS_SIZE == 0)
		return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
	else
		return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
}

@@ -952,6 +1006,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
{
	struct dvb_device *dvbdev = file->private_data;
	struct av7110 *av7110 = dvbdev->priv;
	unsigned char c;

	dprintk(2, "av7110:%p, \n", av7110);

@@ -959,6 +1014,12 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
		printk(KERN_ERR "not audio source memory\n");
		return -EPERM;
	}

	if (get_user(c, buf))
		return -EFAULT;
	if (c == 0x47 && count % TS_SIZE == 0)
		return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
	else
		return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
}