📄 av7110_av.c
字号:
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 + -