📄 dvb_demux.c
字号:
return -ENOMEM; }#endif } feed->state = DMX_STATE_READY; up(&demux->mutex); return 0;}static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed){ struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; struct dvb_demux *demux = feed->demux; int ret; if (down_interruptible (&demux->mutex)) return -ERESTARTSYS; if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { up(&demux->mutex); return -EINVAL; } if (!demux->start_feed) { up(&demux->mutex); return -ENODEV; } if ((ret = demux->start_feed(feed)) < 0) { up(&demux->mutex); return ret; } spin_lock_irq(&demux->lock); ts_feed->is_filtering = 1; feed->state = DMX_STATE_GO; spin_unlock_irq(&demux->lock); up(&demux->mutex); return 0;} static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed){ struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; struct dvb_demux *demux = feed->demux; int ret; if (down_interruptible (&demux->mutex)) return -ERESTARTSYS; if (feed->state < DMX_STATE_GO) { up(&demux->mutex); return -EINVAL; } if (!demux->stop_feed) { up(&demux->mutex); return -ENODEV; } ret = demux->stop_feed(feed); spin_lock_irq(&demux->lock); ts_feed->is_filtering = 0; feed->state = DMX_STATE_ALLOCATED; spin_unlock_irq(&demux->lock); up(&demux->mutex); return ret;}static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed, dmx_ts_cb callback){ struct dvb_demux *demux = (struct dvb_demux *) dmx; struct dvb_demux_feed *feed; if (down_interruptible (&demux->mutex)) return -ERESTARTSYS; if (!(feed = dvb_dmx_feed_alloc(demux))) { up(&demux->mutex); return -EBUSY; } feed->type = DMX_TYPE_TS; feed->cb.ts = callback; feed->demux = demux; feed->pid = 0xffff; feed->peslen = 0xfffa; feed->buffer = 0; (*ts_feed) = &feed->feed.ts; (*ts_feed)->parent = dmx; (*ts_feed)->priv = 0; (*ts_feed)->is_filtering = 0; (*ts_feed)->start_filtering = dmx_ts_feed_start_filtering; (*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering; (*ts_feed)->set = dmx_ts_feed_set; if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { feed->state = DMX_STATE_FREE; up(&demux->mutex); return -EBUSY; } feed->filter->type = DMX_TYPE_TS; feed->filter->feed = feed; feed->filter->state = DMX_STATE_READY; up(&demux->mutex); return 0;}static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_feed){ struct dvb_demux *demux = (struct dvb_demux *) dmx; struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; if (down_interruptible (&demux->mutex)) return -ERESTARTSYS; if (feed->state == DMX_STATE_FREE) { up(&demux->mutex); return -EINVAL; }#ifndef NOBUFS if (feed->buffer) { vfree(feed->buffer); feed->buffer=0; }#endif feed->state = DMX_STATE_FREE; feed->filter->state = DMX_STATE_FREE; dvb_demux_feed_del(feed); feed->pid = 0xffff; if (feed->ts_type & TS_DECODER) demux->pesfilter[feed->pes_type] = NULL; up(&demux->mutex); return 0;}/****************************************************************************** * dmx_section_feed API calls ******************************************************************************/static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed, struct dmx_section_filter** filter) { struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; struct dvb_demux *dvbdemux = dvbdmxfeed->demux; struct dvb_demux_filter *dvbdmxfilter; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { up(&dvbdemux->mutex); return -EBUSY; } spin_lock_irq(&dvbdemux->lock); *filter = &dvbdmxfilter->filter; (*filter)->parent = feed; (*filter)->priv = 0; dvbdmxfilter->feed = dvbdmxfeed; dvbdmxfilter->type = DMX_TYPE_SEC; dvbdmxfilter->state = DMX_STATE_READY; dvbdmxfilter->next = dvbdmxfeed->filter; dvbdmxfeed->filter = dvbdmxfilter; spin_unlock_irq(&dvbdemux->lock); up(&dvbdemux->mutex); return 0;}static int dmx_section_feed_set(struct dmx_section_feed* feed, u16 pid, size_t circular_buffer_size, int descramble, int check_crc) { struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; if (pid > 0x1fff) return -EINVAL; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; dvb_demux_feed_add(dvbdmxfeed); dvbdmxfeed->pid = pid; dvbdmxfeed->buffer_size = circular_buffer_size; dvbdmxfeed->descramble = descramble; if (dvbdmxfeed->descramble) { up(&dvbdmx->mutex); return -ENOSYS; } dvbdmxfeed->feed.sec.check_crc = check_crc;#ifdef NOBUFS dvbdmxfeed->buffer = 0;#else dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size); if (!dvbdmxfeed->buffer) { up(&dvbdmx->mutex); return -ENOMEM; }#endif dvbdmxfeed->state = DMX_STATE_READY; up(&dvbdmx->mutex); return 0;}static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed){ int i; struct dvb_demux_filter *f; struct dmx_section_filter *sf; u8 mask, mode, doneq; if (!(f=dvbdmxfeed->filter)) return; do { sf = &f->filter; doneq = 0; for (i=0; i<DVB_DEMUX_MASK_MAX; i++) { mode = sf->filter_mode[i]; mask = sf->filter_mask[i]; f->maskandmode[i] = mask & mode; doneq |= f->maskandnotmode[i] = mask & ~mode; } f->doneq = doneq ? 1 : 0; } while ((f = f->next));}static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed){ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; if (feed->is_filtering) { up(&dvbdmx->mutex); return -EBUSY; } if (!dvbdmxfeed->filter) { up(&dvbdmx->mutex); return -EINVAL; } dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = 0; dvbdmxfeed->feed.sec.seclen = 0; if (!dvbdmx->start_feed) { up(&dvbdmx->mutex); return -ENODEV; } prepare_secfilters(dvbdmxfeed); if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { up(&dvbdmx->mutex); return ret; } spin_lock_irq(&dvbdmx->lock); feed->is_filtering = 1; dvbdmxfeed->state = DMX_STATE_GO; spin_unlock_irq(&dvbdmx->lock); up(&dvbdmx->mutex); return 0;}static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed){ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; if (!dvbdmx->stop_feed) { up(&dvbdmx->mutex); return -ENODEV; } ret = dvbdmx->stop_feed(dvbdmxfeed); spin_lock_irq(&dvbdmx->lock); dvbdmxfeed->state = DMX_STATE_READY; feed->is_filtering = 0; spin_unlock_irq(&dvbdmx->lock); up(&dvbdmx->mutex); return ret;}static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, struct dmx_section_filter* filter){ struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *) filter, *f; struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; if (dvbdmxfilter->feed != dvbdmxfeed) { up(&dvbdmx->mutex); return -EINVAL; } if (feed->is_filtering) feed->stop_filtering(feed); spin_lock_irq(&dvbdmx->lock); f = dvbdmxfeed->filter; if (f == dvbdmxfilter) { dvbdmxfeed->filter = dvbdmxfilter->next; } else { while(f->next != dvbdmxfilter) f = f->next; f->next = f->next->next; } dvbdmxfilter->state = DMX_STATE_FREE; spin_unlock_irq(&dvbdmx->lock); up(&dvbdmx->mutex); return 0;}static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, struct dmx_section_feed **feed, dmx_section_cb callback){ struct dvb_demux *dvbdmx = (struct dvb_demux *) demux; struct dvb_demux_feed *dvbdmxfeed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { up(&dvbdmx->mutex); return -EBUSY; } dvbdmxfeed->type = DMX_TYPE_SEC; dvbdmxfeed->cb.sec = callback; dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->pid = 0xffff; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->filter = 0; dvbdmxfeed->buffer = 0; (*feed)=&dvbdmxfeed->feed.sec; (*feed)->is_filtering = 0; (*feed)->parent = demux; (*feed)->priv = 0; (*feed)->set = dmx_section_feed_set; (*feed)->allocate_filter = dmx_section_feed_allocate_filter; (*feed)->start_filtering = dmx_section_feed_start_filtering; (*feed)->stop_filtering = dmx_section_feed_stop_filtering; (*feed)->release_filter = dmx_section_feed_release_filter; up(&dvbdmx->mutex); return 0;}static int dvbdmx_release_section_feed(struct dmx_demux *demux, struct dmx_section_feed *feed){ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx = (struct dvb_demux *) demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; if (dvbdmxfeed->state==DMX_STATE_FREE) { up(&dvbdmx->mutex); return -EINVAL; }#ifndef NOBUFS if (dvbdmxfeed->buffer) { vfree(dvbdmxfeed->buffer); dvbdmxfeed->buffer=0; }#endif dvbdmxfeed->state=DMX_STATE_FREE; dvb_demux_feed_del(dvbdmxfeed); dvbdmxfeed->pid = 0xffff; up(&dvbdmx->mutex); return 0;}/****************************************************************************** * dvb_demux kernel data API calls ******************************************************************************/static int dvbdmx_open(struct dmx_demux *demux){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (dvbdemux->users >= MAX_DVB_DEMUX_USERS) return -EUSERS; dvbdemux->users++; return 0;}static int dvbdmx_close(struct dmx_demux *demux){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (dvbdemux->users == 0) return -ENODEV; dvbdemux->users--; //FIXME: release any unneeded resources if users==0 return 0;}static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count){ struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) return -EINVAL; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; dvb_dmx_swfilter(dvbdemux, buf, count); up(&dvbdemux->mutex); if (signal_pending(current)) return -EINTR; return count;}static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; struct list_head *head = &dvbdemux->frontend_list; list_add(&(frontend->connectivity_list), head); return 0;}static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; struct list_head *pos, *n, *head = &dvbdemux->frontend_list; list_for_each_safe (pos, n, head) { if (DMX_FE_ENTRY(pos) == frontend) { list_del(pos); return 0; } } return -ENODEV;}static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (list_empty(&dvbdemux->frontend_list)) return NULL; return &dvbdemux->frontend_list;}int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (demux->frontend) return -EINVAL; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; demux->frontend = frontend; up(&dvbdemux->mutex); return 0;}int dvbdmx_disconnect_frontend(struct dmx_demux *demux){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; demux->frontend = NULL; up(&dvbdemux->mutex); return 0;}static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids){ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; memcpy(pids, dvbdemux->pids, 5*sizeof(u16)); return 0;}int dvb_dmx_init(struct dvb_demux *dvbdemux){ int i, err; struct dmx_demux *dmx = &dvbdemux->dmx; dvbdemux->users = 0; dvbdemux->filter = vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter)); if (!dvbdemux->filter) return -ENOMEM; dvbdemux->feed = vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed)); if (!dvbdemux->feed) { vfree(dvbdemux->filter); return -ENOMEM; } for (i=0; i<dvbdemux->filternum; i++) { dvbdemux->filter[i].state = DMX_STATE_FREE; dvbdemux->filter[i].index = i; } for (i=0; i<dvbdemux->feednum; i++) dvbdemux->feed[i].state = DMX_STATE_FREE; dvbdemux->frontend_list.next= dvbdemux->frontend_list.prev= &dvbdemux->frontend_list; for (i=0; i<DMX_TS_PES_OTHER; i++) { dvbdemux->pesfilter[i] = NULL; dvbdemux->pids[i] = 0xffff; } INIT_LIST_HEAD(&dvbdemux->feed_list); dvbdemux->playing = 0; dvbdemux->recording = 0; dvbdemux->tsbufp = 0; if (!dvbdemux->check_crc32) dvbdemux->check_crc32 = dvb_dmx_crc32; if (!dvbdemux->memcopy) dvbdemux->memcopy = dvb_dmx_memcopy; dmx->frontend = 0; dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list; dmx->priv = (void *) dvbdemux; dmx->open = dvbdmx_open; dmx->close = dvbdmx_close; dmx->write = dvbdmx_write; dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed; dmx->release_ts_feed = dvbdmx_release_ts_feed; dmx->allocate_section_feed = dvbdmx_allocate_section_feed; dmx->release_section_feed = dvbdmx_release_section_feed; dmx->descramble_mac_address = NULL; dmx->descramble_section_payload = NULL; dmx->add_frontend = dvbdmx_add_frontend; dmx->remove_frontend = dvbdmx_remove_frontend; dmx->get_frontends = dvbdmx_get_frontends; dmx->connect_frontend = dvbdmx_connect_frontend; dmx->disconnect_frontend = dvbdmx_disconnect_frontend; dmx->get_pes_pids = dvbdmx_get_pes_pids; sema_init(&dvbdemux->mutex, 1); spin_lock_init(&dvbdemux->lock); if ((err = dmx_register_demux(dmx)) < 0) return err; return 0;}int dvb_dmx_release(struct dvb_demux *dvbdemux){ struct dmx_demux *dmx = &dvbdemux->dmx; dmx_unregister_demux(dmx); if (dvbdemux->filter) vfree(dvbdemux->filter); if (dvbdemux->feed) vfree(dvbdemux->feed); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -