⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 av7110_av.c

📁 linux环境下的dvb驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			if (wait_event_interruptible(av7110->aout.queue,					(dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)))				return count-todo;		}		n = todo;		if (n > IPACKS * 2)			n = IPACKS * 2;		if (copy_from_user(av7110->kbuf[type], buf, n))			return -EFAULT;		av7110_ipack_instant_repack(av7110->kbuf[type], n,					    &av7110->ipack[type]);		todo -= n;		buf += n;	}	return count - todo;}void av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed){	memset(p->pes, 0, TS_SIZE);	p->counter = 0;	p->pos = 0;	p->frags = 0;	if (feed)		p->feed = feed;}static void clear_p2t(struct av7110_p2t *p){	memset(p->pes, 0, TS_SIZE);//	p->counter = 0;	p->pos = 0;	p->frags = 0;}static int find_pes_header(u8 const *buf, long int length, int *frags){	int c = 0;	int found = 0;	*frags = 0;	while (c < length - 3 && !found) {		if (buf[c] == 0x00 && buf[c + 1] == 0x00 &&		    buf[c + 2] == 0x01) {			switch ( buf[c + 3] ) {			case PROG_STREAM_MAP:			case PRIVATE_STREAM2:			case PROG_STREAM_DIR:			case ECM_STREAM     :			case EMM_STREAM     :			case PADDING_STREAM :			case DSM_CC_STREAM  :			case ISO13522_STREAM:			case PRIVATE_STREAM1:			case AUDIO_STREAM_S ... AUDIO_STREAM_E:			case VIDEO_STREAM_S ... VIDEO_STREAM_E:				found = 1;				break;			default:				c++;				break;			}		} else			c++;	}	if (c == length - 3 && !found) {		if (buf[length - 1] == 0x00)			*frags = 1;		if (buf[length - 2] == 0x00 &&		    buf[length - 1] == 0x00)			*frags = 2;		if (buf[length - 3] == 0x00 &&		    buf[length - 2] == 0x00 &&		    buf[length - 1] == 0x01)			*frags = 3;		return -1;	}	return c;}void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p){	int c, c2, l, add;	int check, rest;	c = 0;	c2 = 0;	if (p->frags){		check = 0;		switch(p->frags) {		case 1:			if (buf[c] == 0x00 && buf[c + 1] == 0x01) {				check = 1;				c += 2;			}			break;		case 2:			if (buf[c] == 0x01) {				check = 1;				c++;			}			break;		case 3:			check = 1;		}		if (check) {			switch (buf[c]) {			case PROG_STREAM_MAP:			case PRIVATE_STREAM2:			case PROG_STREAM_DIR:			case ECM_STREAM     :			case EMM_STREAM     :			case PADDING_STREAM :			case DSM_CC_STREAM  :			case ISO13522_STREAM:			case PRIVATE_STREAM1:			case AUDIO_STREAM_S ... AUDIO_STREAM_E:			case VIDEO_STREAM_S ... VIDEO_STREAM_E:				p->pes[0] = 0x00;				p->pes[1] = 0x00;				p->pes[2] = 0x01;				p->pes[3] = buf[c];				p->pos = 4;				memcpy(p->pes + p->pos, buf + c, (TS_SIZE - 4) - p->pos);				c += (TS_SIZE - 4) - p->pos;				p_to_t(p->pes, (TS_SIZE - 4), pid, &p->counter, p->feed);				clear_p2t(p);				break;			default:				c = 0;				break;			}		}		p->frags = 0;	}	if (p->pos) {		c2 = find_pes_header(buf + c, length - c, &p->frags);		if (c2 >= 0 && c2 < (TS_SIZE - 4) - p->pos)			l = c2+c;		else			l = (TS_SIZE - 4) - p->pos;		memcpy(p->pes + p->pos, buf, l);		c += l;		p->pos += l;		p_to_t(p->pes, p->pos, pid, &p->counter, p->feed);		clear_p2t(p);	}	add = 0;	while (c < length) {		c2 = find_pes_header(buf + c + add, length - c - add, &p->frags);		if (c2 >= 0) {			c2 += c + add;			if (c2 > c){				p_to_t(buf + c, c2 - c, pid, &p->counter, p->feed);				c = c2;				clear_p2t(p);				add = 0;			} else				add = 1;		} else {			l = length - c;			rest = l % (TS_SIZE - 4);			l -= rest;			p_to_t(buf + c, l, pid, &p->counter, p->feed);			memcpy(p->pes, buf + c + l, rest);			p->pos = rest;			c = length;		}	}}int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length){	int i;	int c = 0;	int fill;	u8 tshead[4] = { 0x47, 0x00, 0x00, 0x10 };	fill = (TS_SIZE - 4) - length;	if (pes_start)		tshead[1] = 0x40;	if (fill)		tshead[3] = 0x30;	tshead[1] |= (u8)((pid & 0x1F00) >> 8);	tshead[2] |= (u8)(pid & 0x00FF);	tshead[3] |= ((*counter)++ & 0x0F);	memcpy(buf, tshead, 4);	c += 4;	if (fill) {		buf[4] = fill - 1;		c++;		if (fill > 1) {			buf[5] = 0x00;			c++;		}		for (i = 6; i < fill + 4; i++) {			buf[i] = 0xFF;			c++;		}	}	return c;}static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,		   struct dvb_demux_feed *feed){	int l, pes_start;	u8 obuf[TS_SIZE];	long c = 0;	pes_start = 0;	if (length > 3 &&	     buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)		switch (buf[3]) {			case PROG_STREAM_MAP:			case PRIVATE_STREAM2:			case PROG_STREAM_DIR:			case ECM_STREAM     :			case EMM_STREAM     :			case PADDING_STREAM :			case DSM_CC_STREAM  :			case ISO13522_STREAM:			case PRIVATE_STREAM1:			case AUDIO_STREAM_S ... AUDIO_STREAM_E:			case VIDEO_STREAM_S ... VIDEO_STREAM_E:				pes_start = 1;				break;			default:				break;		}	while (c < length) {		memset(obuf, 0, TS_SIZE);		if (length - c >= (TS_SIZE - 4)){			l = write_ts_header2(pid, counter, pes_start,					     obuf, (TS_SIZE - 4));			memcpy(obuf + l, buf + c, TS_SIZE - l);			c += TS_SIZE - l;		} else {			l = write_ts_header2(pid, counter, pes_start,					     obuf, length - c);			memcpy(obuf + l, buf + c, TS_SIZE - l);			c = length;		}		feed->cb.ts(obuf, 188, 0, 0, &feed->feed.ts, DMX_OK);		pes_start = 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];	DEB_EE(("av7110: %p\n", av7110));	switch (feed->pes_type) {	case 0:		if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)			return -EINVAL;		break;	case 1:		if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)			return -EINVAL;		break;	default:		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;}/****************************************************************************** * Video MPEG decoder events ******************************************************************************/void dvb_video_add_event(struct av7110 *av7110, struct video_event *event){	struct dvb_video_events *events = &av7110->video_events;	int wp;	DEB_D(("\n"));	spin_lock_bh(&events->lock);	wp = (events->eventw + 1) % MAX_VIDEO_EVENT;	if (wp == events->eventr) {		events->overflow = 1;		events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;	}	//FIXME: timestamp?	memcpy(&events->events[events->eventw], event, sizeof(struct video_event));	events->eventw = wp;	spin_unlock_bh(&events->lock);	wake_up_interruptible(&events->wait_queue);}static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event, int flags){	struct dvb_video_events *events = &av7110->video_events;	DEB_D(("\n"));	if (events->overflow) {		events->overflow = 0;		return -EOVERFLOW;	}	if (events->eventw == events->eventr) {		int ret;		if (flags & O_NONBLOCK)			return -EWOULDBLOCK;		ret = wait_event_interruptible(events->wait_queue,					       events->eventw != events->eventr);		if (ret < 0)			return ret;	}	spin_lock_bh(&events->lock);	memcpy(event, &events->events[events->eventr],	       sizeof(struct video_event));	events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;	spin_unlock_bh(&events->lock);	return 0;}/****************************************************************************** * DVB device file operations ******************************************************************************/static unsigned int dvb_video_poll(struct file *file, poll_table *wait){	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;	unsigned int mask = 0;	DEB_EE(("av7110: %p\n", av7110));	if ((file->f_flags & O_ACCMODE) != O_RDONLY)		poll_wait(file, &av7110->avout.queue, wait);	poll_wait(file, &av7110->video_events.wait_queue, wait);	if (av7110->video_events.eventw != av7110->video_events.eventr)		mask = POLLPRI;	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {		if (av7110->playing) {			if (FREE_COND)				mask |= (POLLOUT | POLLWRNORM);			} else /* if not playing: may play if asked for */				mask |= (POLLOUT | POLLWRNORM);	}	return mask;}static ssize_t dvb_video_write(struct file *file, const char *buf,			       size_t count, loff_t *ppos){	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;	DEB_EE(("av7110: %p\n", av7110));	if ((file->f_flags & O_ACCMODE) == O_RDONLY)		return -EPERM;	if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY)		return -EPERM;	return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1, 1);}static unsigned int dvb_audio_poll(struct file *file, poll_table *wait){	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;	unsigned int mask = 0;	DEB_EE(("av7110: %p\n", av7110));	poll_wait(file, &av7110->aout.queue, wait);	if (av7110->playing) {		if (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)			mask |= (POLLOUT | POLLWRNORM);	} else /* if not playing: may play if asked for */		mask = (POLLOUT | POLLWRNORM);	return mask;}static ssize_t dvb_audio_write(struct file *file, const char *buf,			       size_t count, loff_t *ppos){	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;	DEB_EE(("av7110: %p\n", av7110));	if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) {		printk(KERN_ERR "not audio source memory\n");		return -EPERM;	}	return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);}u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };#define MIN_IFRAME 400000static int play_iframe(struct av7110 *av7110, u8 *buf, unsigned int len, int nonblock){	int i, n;	DEB_EE(("av7110: %p\n", av7110));	if (!(av7110->playing & RP_VIDEO)) {		if (av7110_av_start_play(av7110, RP_VIDEO) < 0)			return -EBUSY;	}	/* setting n always > 1, fixes problems when playing stillframes	   consisting of I- and P-Frames */	n = MIN_IFRAME / len + 1;	/* FIXME: nonblock? */	dvb_play(av7110, iframe_header, sizeof(iframe_header), 0, 1, 0);	for (i = 0; i < n; i++)		dvb_play(av7110, buf, len, 0, 1, 1);	av7110_ipack_flush(&av7110->ipack[1]);	return 0;}static int dvb_video_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, void *parg){	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -