Loading drivers/media/dvb-core/demux.h +5 −3 Original line number Original line Diff line number Diff line Loading @@ -93,7 +93,7 @@ struct dmx_data_ready { /* /* * data_length may be 0 in case of DMX_OK_PES_END or DMX_OK_EOS * data_length may be 0 in case of DMX_OK_PES_END or DMX_OK_EOS * and in non-DMX_OK_XXX events. In DMX_OK_PES_END, * and in non-DMX_OK_XXX events. In DMX_OK_PES_END, * data_length is for data comming after the end of PES. * data_length is for data coming after the end of PES. */ */ int data_length; int data_length; Loading Loading @@ -292,11 +292,13 @@ typedef int (*dmx_section_cb) ( const u8 * buffer1, typedef int (*dmx_ts_fullness) ( typedef int (*dmx_ts_fullness) ( struct dmx_ts_feed *source, struct dmx_ts_feed *source, int required_space); int required_space, int wait); typedef int (*dmx_section_fullness) ( typedef int (*dmx_section_fullness) ( struct dmx_section_filter *source, struct dmx_section_filter *source, int required_space); int required_space, int wait); /*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ /* DVB Front-End */ /* DVB Front-End */ Loading drivers/media/dvb-core/dmxdev.c +183 −23 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,58 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk if (debug) printk #define dprintk if (debug) printk static inline int dvb_dmxdev_verify_buffer_size(u32 size, u32 max_size, u32 size_align) { if (size_align) return size <= max_size && !(size % size_align); else return size <= max_size; } static int dvb_filter_verify_buffer_size(struct dmxdev_filter *filter, size_t size) { struct dmx_caps caps; /* * For backward compatibility, if no demux capabilities can * be retrieved assume size is ok. * Decoder filter buffer size is verified when decoder buffer is set. */ if (filter->dev->demux->get_caps) { filter->dev->demux->get_caps(filter->dev->demux, &caps); if (filter->type == DMXDEV_TYPE_SEC) return dvb_dmxdev_verify_buffer_size( size, caps.section.max_size, caps.section.size_alignment); if (filter->params.pes.output == DMX_OUT_TAP) return dvb_dmxdev_verify_buffer_size( size, caps.pes.max_size, caps.pes.size_alignment); if (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP || filter->params.pes.output == DMX_OUT_TS_TAP) { if (filter->dmx_tsp_format == DMX_TSP_FORMAT_188) return dvb_dmxdev_verify_buffer_size( size, caps.recording_188_tsp.max_size, caps.recording_188_tsp.size_alignment); return dvb_dmxdev_verify_buffer_size( size, caps.recording_192_tsp.max_size, caps.recording_192_tsp.size_alignment); } } return 1; } static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, const u8 *src, size_t len) const u8 *src, size_t len) { { Loading Loading @@ -1115,6 +1167,38 @@ static int dvb_dvr_external_input_only(struct dmxdev *dmxdev) return is_external_only; return is_external_only; } } static int dvb_dvr_verify_buffer_size(struct dmxdev *dmxdev, unsigned int f_flags, unsigned long size) { struct dmx_caps caps; int tsp_size; if (!dmxdev->demux->get_caps) return 1; if (dmxdev->demux->get_tsp_size) tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux); else tsp_size = 188; dmxdev->demux->get_caps(dmxdev->demux, &caps); if ((f_flags & O_ACCMODE) == O_RDONLY) return (tsp_size == 188 && dvb_dmxdev_verify_buffer_size(size, caps.recording_188_tsp.max_size, caps.recording_188_tsp.size_alignment)) || (tsp_size == 192 && dvb_dmxdev_verify_buffer_size(size, caps.recording_192_tsp.max_size, caps.recording_192_tsp.size_alignment)); return (tsp_size == 188 && dvb_dmxdev_verify_buffer_size(size, caps.playback_188_tsp.max_size, caps.playback_188_tsp.size_alignment)) || (tsp_size == 192 && dvb_dmxdev_verify_buffer_size(size, caps.playback_192_tsp.max_size, caps.playback_192_tsp.size_alignment)); } static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) size_t count, loff_t *ppos) { { Loading @@ -1129,7 +1213,8 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, if (!dmxdev->demux->write) if (!dmxdev->demux->write) return -EOPNOTSUPP; return -EOPNOTSUPP; if (((file->f_flags & O_ACCMODE) == O_RDONLY) || if (!dvb_dvr_verify_buffer_size(dmxdev, file->f_flags, src->size) || ((file->f_flags & O_ACCMODE) == O_RDONLY) || !src->data || !cmdbuf->data || !src->data || !cmdbuf->data || (dvb_dvr_external_input_only(dmxdev) && (dvb_dvr_external_input_only(dmxdev) && (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL))) (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL))) Loading Loading @@ -1203,6 +1288,10 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, if (dmxdev->exit) if (dmxdev->exit) return -ENODEV; return -ENODEV; if (!dvb_dvr_verify_buffer_size(dmxdev, file->f_flags, dmxdev->dvr_buffer.size)) return -EINVAL; res = dvb_dmxdev_buffer_read(NULL, &dmxdev->dvr_buffer, res = dvb_dmxdev_buffer_read(NULL, &dmxdev->dvr_buffer, file->f_flags & O_NONBLOCK, file->f_flags & O_NONBLOCK, buf, count, ppos); buf, count, ppos); Loading Loading @@ -1475,12 +1564,14 @@ static int dvb_dvr_get_event(struct dmxdev *dmxdev, */ */ flush_len = dvb_ringbuffer_avail(&dmxdev->dvr_buffer); flush_len = dvb_ringbuffer_avail(&dmxdev->dvr_buffer); dvb_ringbuffer_flush(&dmxdev->dvr_buffer); dvb_ringbuffer_flush(&dmxdev->dvr_buffer); dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); dmxdev->dvr_buffer.error = 0; dmxdev->dvr_buffer.error = 0; } } spin_unlock_irq(&dmxdev->lock); spin_unlock_irq(&dmxdev->lock); if (event->type == DMX_EVENT_BUFFER_OVERFLOW) dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); /* /* * in PULL mode, we might be stalling on * in PULL mode, we might be stalling on * event queue, so need to wake-up waiters * event queue, so need to wake-up waiters Loading Loading @@ -1522,10 +1613,7 @@ static int dvb_dvr_get_buffer_status(struct dmxdev *dmxdev, */ */ flush_len = dvb_ringbuffer_avail(buf); flush_len = dvb_ringbuffer_avail(buf); dvb_ringbuffer_flush(buf); dvb_ringbuffer_flush(buf); dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); } } buf->error = 0; buf->error = 0; } } Loading @@ -1535,6 +1623,9 @@ static int dvb_dvr_get_buffer_status(struct dmxdev *dmxdev, dmx_buffer_status->write_offset = buf->pwrite; dmx_buffer_status->write_offset = buf->pwrite; dmx_buffer_status->size = buf->size; dmx_buffer_status->size = buf->size; if (dmx_buffer_status->error == -EOVERFLOW) dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); spin_unlock_irq(lock); spin_unlock_irq(lock); return 0; return 0; Loading Loading @@ -1738,7 +1829,17 @@ static int dvb_dmxdev_set_decoder_buffer_size( struct dmxdev_filter *dmxdevfilter, struct dmxdev_filter *dmxdevfilter, unsigned long size) unsigned long size) { { if (0 == size) struct dmx_caps caps; struct dmx_demux *demux = dmxdevfilter->dev->demux; if (demux->get_caps) { demux->get_caps(demux, &caps); if (!dvb_dmxdev_verify_buffer_size(size, caps.decoder.max_size, caps.decoder.size_alignment)) return -EINVAL; } if (size == 0) return -EINVAL; return -EINVAL; if (dmxdevfilter->decoder_buffers.buffers_size == size) if (dmxdevfilter->decoder_buffers.buffers_size == size) Loading Loading @@ -1841,6 +1942,7 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter, struct dmxdev_feed *feed; struct dmxdev_feed *feed; struct dmxdev_feed *ts_feed = NULL; struct dmxdev_feed *ts_feed = NULL; struct dmx_caps caps; struct dmx_caps caps; int ret = 0; if (!dmxdevfilter->dev->demux->get_caps) if (!dmxdevfilter->dev->demux->get_caps) return -EINVAL; return -EINVAL; Loading @@ -1866,7 +1968,7 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter, ts_feed->idx_params = *idx_params; ts_feed->idx_params = *idx_params; if ((dmxdevfilter->state == DMXDEV_STATE_GO) && if ((dmxdevfilter->state == DMXDEV_STATE_GO) && ts_feed->ts->set_idx_params) ts_feed->ts->set_idx_params) ts_feed->ts->set_idx_params( ret = ts_feed->ts->set_idx_params( ts_feed->ts, idx_params); ts_feed->ts, idx_params); break; break; } } Loading @@ -1875,7 +1977,7 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter, if (!found_pid) if (!found_pid) return -EINVAL; return -EINVAL; return 0; return ret; } } static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter, static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter, Loading Loading @@ -2108,7 +2210,7 @@ static int dvb_dmxdev_abort_ts_insertion(struct dmxdev_filter *dmxdevfilter, } } static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, int required_space) int required_space, int wait) { { struct dmxdev_filter *dmxdevfilter = filter->priv; struct dmxdev_filter *dmxdevfilter = filter->priv; struct dvb_ringbuffer *src; struct dvb_ringbuffer *src; Loading Loading @@ -2150,6 +2252,9 @@ static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock); if (!wait) return -ENOSPC; ret = wait_event_interruptible(src->queue, ret = wait_event_interruptible(src->queue, (!src->data) || (!src->data) || ((dvb_ringbuffer_free(src) >= required_space) && ((dvb_ringbuffer_free(src) >= required_space) && Loading @@ -2165,7 +2270,7 @@ static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, static int dvb_dmxdev_sec_fullness_callback( static int dvb_dmxdev_sec_fullness_callback( struct dmx_section_filter *filter, struct dmx_section_filter *filter, int required_space) int required_space, int wait) { { struct dmxdev_filter *dmxdevfilter = filter->priv; struct dmxdev_filter *dmxdevfilter = filter->priv; struct dvb_ringbuffer *src = &dmxdevfilter->buffer; struct dvb_ringbuffer *src = &dmxdevfilter->buffer; Loading Loading @@ -2199,6 +2304,9 @@ static int dvb_dmxdev_sec_fullness_callback( spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock); if (!wait) return -ENOSPC; ret = wait_event_interruptible(src->queue, ret = wait_event_interruptible(src->queue, (!src->data) || (!src->data) || ((dvb_ringbuffer_free(src) >= required_space) && ((dvb_ringbuffer_free(src) >= required_space) && Loading Loading @@ -2250,7 +2358,7 @@ static int dvb_dmxdev_get_buffer_status( struct dmx_buffer_status *dmx_buffer_status) struct dmx_buffer_status *dmx_buffer_status) { { struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; ssize_t flush_len; ssize_t flush_len = 0; /* /* * Note: Taking the dmxdevfilter->dev->lock spinlock is required only * Note: Taking the dmxdevfilter->dev->lock spinlock is required only Loading Loading @@ -2298,7 +2406,6 @@ static int dvb_dmxdev_get_buffer_status( */ */ flush_len = dvb_ringbuffer_avail(buf); flush_len = dvb_ringbuffer_avail(buf); dvb_ringbuffer_flush(buf); dvb_ringbuffer_flush(buf); dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); } } buf->error = 0; buf->error = 0; } } Loading @@ -2311,6 +2418,9 @@ static int dvb_dmxdev_get_buffer_status( spin_unlock_irq(&dmxdevfilter->dev->lock); spin_unlock_irq(&dmxdevfilter->dev->lock); if (dmx_buffer_status->error == -EOVERFLOW) dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); return 0; return 0; } } Loading Loading @@ -2366,7 +2476,6 @@ static int dvb_dmxdev_get_event(struct dmxdev_filter *dmxdevfilter, */ */ flush_len = dvb_ringbuffer_avail(&dmxdevfilter->buffer); flush_len = dvb_ringbuffer_avail(&dmxdevfilter->buffer); dvb_ringbuffer_flush(&dmxdevfilter->buffer); dvb_ringbuffer_flush(&dmxdevfilter->buffer); dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); dmxdevfilter->buffer.error = 0; dmxdevfilter->buffer.error = 0; } else if (event->type == DMX_EVENT_SECTION_TIMEOUT) { } else if (event->type == DMX_EVENT_SECTION_TIMEOUT) { /* clear buffer error now that user was notified */ /* clear buffer error now that user was notified */ Loading @@ -2387,6 +2496,9 @@ static int dvb_dmxdev_get_event(struct dmxdev_filter *dmxdevfilter, spin_unlock_irq(&dmxdevfilter->dev->lock); spin_unlock_irq(&dmxdevfilter->dev->lock); if (event->type == DMX_EVENT_BUFFER_OVERFLOW) dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); /* /* * in PULL mode, we might be stalling on * in PULL mode, we might be stalling on * event queue, so need to wake-up waiters * event queue, so need to wake-up waiters Loading Loading @@ -2723,6 +2835,23 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed, } } if (dmx_data_ready->status == DMX_OK_EOS) { if (dmx_data_ready->status == DMX_OK_EOS) { /* Report partial recording chunk */ if ((dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) && events->current_event_data_size) { event.type = DMX_EVENT_NEW_REC_CHUNK; event.params.recording_chunk.offset = events->current_event_start_offset; event.params.recording_chunk.size = events->current_event_data_size; events->current_event_start_offset = (events->current_event_start_offset + events->current_event_data_size) % buffer->size; events->current_event_data_size = 0; dvb_dmxdev_add_event(events, &event); } dmxdevfilter->eos_state = 1; dmxdevfilter->eos_state = 1; dprintk("dmxdev: DMX_OK_EOS - entering EOS state\n"); dprintk("dmxdev: DMX_OK_EOS - entering EOS state\n"); event.type = DMX_EVENT_EOS; event.type = DMX_EVENT_EOS; Loading Loading @@ -2856,8 +2985,9 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed, event.params.pes.base_offset = event.params.pes.base_offset = events->current_event_start_offset; events->current_event_start_offset; event.params.pes.start_offset = event.params.pes.start_offset = events->current_event_start_offset + (events->current_event_start_offset + dmx_data_ready->pes_end.start_gap; dmx_data_ready->pes_end.start_gap) % dmxdevfilter->buffer.size; event.params.pes.actual_length = event.params.pes.actual_length = dmx_data_ready->pes_end.actual_length; dmx_data_ready->pes_end.actual_length; Loading Loading @@ -2895,18 +3025,22 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed, if ((dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP) || if ((dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP) || (dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) { (dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) { if (events->current_event_data_size >= while (events->current_event_data_size >= dmxdevfilter->params.pes.rec_chunk_size) { dmxdevfilter->params.pes.rec_chunk_size) { event.type = DMX_EVENT_NEW_REC_CHUNK; event.type = DMX_EVENT_NEW_REC_CHUNK; event.params.recording_chunk.offset = event.params.recording_chunk.offset = events->current_event_start_offset; events->current_event_start_offset; event.params.recording_chunk.size = event.params.recording_chunk.size = events->current_event_data_size; dmxdevfilter->params.pes.rec_chunk_size; events->current_event_data_size = events->current_event_data_size - dmxdevfilter->params.pes.rec_chunk_size; events->current_event_start_offset = (events->current_event_start_offset + dmxdevfilter->params.pes.rec_chunk_size) % buffer->size; dvb_dmxdev_add_event(events, &event); dvb_dmxdev_add_event(events, &event); events->current_event_data_size = 0; } } } } spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock); Loading Loading @@ -3173,9 +3307,15 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, if ((filter->params.pes.output == DMX_OUT_TS_TAP) || if ((filter->params.pes.output == DMX_OUT_TS_TAP) || (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) if (tsfeed->set_idx_params) if (tsfeed->set_idx_params) { tsfeed->set_idx_params( ret = tsfeed->set_idx_params( tsfeed, &feed->idx_params); tsfeed, &feed->idx_params); if (ret) { dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); return ret; } } ret = tsfeed->start_filtering(tsfeed); ret = tsfeed->start_filtering(tsfeed); if (ret < 0) { if (ret < 0) { Loading Loading @@ -3236,7 +3376,24 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) if (filter->state >= DMXDEV_STATE_GO) if (filter->state >= DMXDEV_STATE_GO) dvb_dmxdev_filter_stop(filter); dvb_dmxdev_filter_stop(filter); if (!dvb_filter_verify_buffer_size(filter, filter->buffer.size)) return -EINVAL; if (!filter->buffer.data) { if (!filter->buffer.data) { /* * dmxdev buffer in decoder filters is not really used * to exchange data with applications. Decoder buffers * can be set using DMX_SET_DECODER_BUFFER, which * would not update the filter->buffer.data at all. * Therefore we should not treat this filter as * other regular filters and should not fail here * even if user sets the buffer in deocder * filter as external buffer. */ if ((filter->type == DMXDEV_TYPE_PES) && (filter->params.pes.output == DMX_OUT_DECODER)) filter->buffer_mode = DMX_BUFFER_MODE_INTERNAL; if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) || if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) || dvb_filter_external_buffer_only(dmxdev, filter)) dvb_filter_external_buffer_only(dmxdev, filter)) return -ENOMEM; return -ENOMEM; Loading Loading @@ -3771,6 +3928,9 @@ static int dvb_dmxdev_set_decoder_buffer(struct dmxdev *dmxdev, return -EINVAL; return -EINVAL; dmxdev->demux->get_caps(dmxdev->demux, &caps); dmxdev->demux->get_caps(dmxdev->demux, &caps); if (!dvb_dmxdev_verify_buffer_size(buffs->buffers_size, caps.decoder.max_size, caps.decoder.size_alignment)) return -EINVAL; if ((buffs->buffers_size == 0) || if ((buffs->buffers_size == 0) || (buffs->is_linear && (buffs->is_linear && Loading drivers/media/dvb-core/dvb_demux.c +110 −71 Original line number Original line Diff line number Diff line Loading @@ -178,12 +178,7 @@ static inline u16 section_length(const u8 *buf) return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; } } static inline u16 ts_pid(const u8 *buf) static inline u8 ts_scrambling_ctrl(const u8 *buf) { return ((buf[1] & 0x1f) << 8) + buf[2]; } static inline u16 ts_scrambling_ctrl(const u8 *buf) { { return (buf[3] >> 6) & 0x3; return (buf[3] >> 6) & 0x3; } } Loading Loading @@ -737,7 +732,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, return 0; return 0; } } static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, static int dvb_dmx_swfilter_section_one_packet(struct dvb_demux_feed *feed, const u8 *buf) const u8 *buf) { { u8 p, count; u8 p, count; Loading Loading @@ -815,6 +810,60 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, return 0; return 0; } } /* * dvb_dmx_swfilter_section_packet - wrapper for section filtering of single * TS packet. * * @feed: dvb demux feed * @buf: buffer containing the TS packet * @should_lock: specifies demux locking semantics: if not set, proper demux * locking is expected to have been done by the caller. * * Return error status */ int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf, int should_lock) { int ret; if (!should_lock && !spin_is_locked(&feed->demux->lock)) { pr_err("%s: demux spinlock should have been locked\n", __func__); return -EINVAL; } if (should_lock) spin_lock(&feed->demux->lock); ret = dvb_dmx_swfilter_section_one_packet(feed, buf); if (should_lock) spin_unlock(&feed->demux->lock); return ret; } EXPORT_SYMBOL(dvb_dmx_swfilter_section_packet); static int dvb_demux_idx_event_sort(struct dmx_index_event_info *curr, struct dmx_index_event_info *new) { if (curr->match_tsp_num > new->match_tsp_num) return 0; if (curr->match_tsp_num < new->match_tsp_num) return 1; /* * In case TSP numbers are equal, sort according to event type giving * priority to PUSI events first, then RAI and finally framing events. */ if ((curr->type & DMX_IDX_RAI && new->type & DMX_IDX_PUSI) || (!(curr->type & DMX_IDX_PUSI) && !(curr->type & DMX_IDX_RAI) && new->type & (DMX_IDX_PUSI | DMX_IDX_RAI))) return 0; return 1; } static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, struct dmx_index_event_info *idx_event, struct dmx_index_event_info *idx_event, int traverse_from_tail) int traverse_from_tail) Loading @@ -839,8 +888,8 @@ static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, if (traverse_from_tail) { if (traverse_from_tail) { list_for_each_entry_reverse(curr_entry, list_for_each_entry_reverse(curr_entry, &feed->rec_info->idx_info.ready_list, next) { &feed->rec_info->idx_info.ready_list, next) { if (curr_entry->event.match_tsp_num <= if (dvb_demux_idx_event_sort(&curr_entry->event, idx_event->match_tsp_num) { idx_event)) { pos = &curr_entry->next; pos = &curr_entry->next; break; break; } } Loading @@ -848,8 +897,8 @@ static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, } else { } else { list_for_each_entry(curr_entry, list_for_each_entry(curr_entry, &feed->rec_info->idx_info.ready_list, next) { &feed->rec_info->idx_info.ready_list, next) { if (curr_entry->event.match_tsp_num > if (!dvb_demux_idx_event_sort(&curr_entry->event, idx_event->match_tsp_num) { idx_event)) { pos = &curr_entry->next; pos = &curr_entry->next; break; break; } } Loading @@ -865,12 +914,17 @@ static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, } } int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, struct dmx_index_event_info *idx_event) struct dmx_index_event_info *idx_event, int should_lock) { { int ret; int ret; if (!should_lock && !spin_is_locked(&feed->demux->lock)) return -EINVAL; if (should_lock) spin_lock(&feed->demux->lock); spin_lock(&feed->demux->lock); ret = dvb_demux_save_idx_event(feed, idx_event, 1); ret = dvb_demux_save_idx_event(feed, idx_event, 1); if (should_lock) spin_unlock(&feed->demux->lock); spin_unlock(&feed->demux->lock); return ret; return ret; Loading Loading @@ -900,10 +954,15 @@ static inline void dvb_dmx_notify_indexing(struct dvb_demux_feed *feed) } } } } void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed) void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed, int should_lock) { { if (!should_lock && !spin_is_locked(&feed->demux->lock)) return; if (should_lock) spin_lock(&feed->demux->lock); spin_lock(&feed->demux->lock); dvb_dmx_notify_indexing(feed); dvb_dmx_notify_indexing(feed); if (should_lock) spin_unlock(&feed->demux->lock); spin_unlock(&feed->demux->lock); } } EXPORT_SYMBOL(dvb_dmx_notify_idx_events); EXPORT_SYMBOL(dvb_dmx_notify_idx_events); Loading Loading @@ -1078,7 +1137,7 @@ static void dvb_dmx_index(struct dvb_demux_feed *feed, /* /* * if we still did not encounter a TS packet with PUSI indication, * if we still did not encounter a TS packet with PUSI indication, * we cannot report index entries yet as we need to provide * we cannot report index entries yet as we need to provide * the TS packet number with PUSI indication preceeding the TS * the TS packet number with PUSI indication preceding the TS * packet pointed by the reported index entry. * packet pointed by the reported index entry. */ */ if (feed->curr_pusi_tsp_num == (u64)-1) { if (feed->curr_pusi_tsp_num == (u64)-1) { Loading Loading @@ -1284,7 +1343,8 @@ static inline int dvb_dmx_swfilter_buffer_check( if (likely(was_locked)) if (likely(was_locked)) spin_unlock(&demux->lock); spin_unlock(&demux->lock); ret = demux->buffer_ctrl.ts(ts, desired_space); ret = demux->buffer_ctrl.ts(ts, desired_space, 1); if (likely(was_locked)) if (likely(was_locked)) spin_lock(&demux->lock); spin_lock(&demux->lock); Loading Loading @@ -1334,7 +1394,8 @@ static inline int dvb_dmx_swfilter_buffer_check( if (likely(was_locked)) if (likely(was_locked)) spin_unlock(&demux->lock); spin_unlock(&demux->lock); ret = demux->buffer_ctrl.sec(&f->filter, desired_space); ret = demux->buffer_ctrl.sec(&f->filter, desired_space, 1); if (likely(was_locked)) if (likely(was_locked)) spin_lock(&demux->lock); spin_lock(&demux->lock); Loading Loading @@ -1398,7 +1459,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, if (!feed->feed.sec.is_filtering || if (!feed->feed.sec.is_filtering || feed->secure_mode.is_secured) feed->secure_mode.is_secured) break; break; if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) if (dvb_dmx_swfilter_section_one_packet(feed, buf) < 0) feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; break; break; Loading Loading @@ -1508,52 +1569,6 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf, } } EXPORT_SYMBOL(dvb_dmx_swfilter_packet); EXPORT_SYMBOL(dvb_dmx_swfilter_packet); void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf, size_t count) { struct dvb_demux_feed *feed; u16 pid = ts_pid(buf); struct timespec pre_time; if (dvb_demux_performancecheck) pre_time = current_kernel_time(); spin_lock(&demux->lock); demux->sw_filter_abort = 0; while (count--) { if (buf[0] != 0x47) { buf += 188; continue; } if (demux->playback_mode == DMX_PB_MODE_PULL) if (dvb_dmx_swfilter_buffer_check(demux, pid) < 0) break; list_for_each_entry(feed, &demux->feed_list, list_head) { if (feed->pid != pid) continue; if (!feed->feed.sec.is_filtering) continue; if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) { feed->feed.sec.seclen = 0; feed->feed.sec.secbufp = 0; } } buf += 188; } spin_unlock(&demux->lock); if (dvb_demux_performancecheck) demux->total_process_time += dvb_dmx_calc_time_delta(pre_time); } EXPORT_SYMBOL(dvb_dmx_swfilter_section_packets); void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count) size_t count) { { Loading Loading @@ -2041,6 +2056,7 @@ static struct dvb_demux_rec_info *dvb_dmx_alloc_rec_info( rec_info->ts_output_count = 0; rec_info->ts_output_count = 0; rec_info->idx_info.min_pattern_tsp_num = (u64)-1; rec_info->idx_info.min_pattern_tsp_num = (u64)-1; rec_info->idx_info.pattern_search_feeds_num = 0; rec_info->idx_info.pattern_search_feeds_num = 0; rec_info->idx_info.indexing_feeds_num = 0; return rec_info; return rec_info; } } Loading Loading @@ -2182,15 +2198,23 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) mutex_unlock(&demux->mutex); mutex_unlock(&demux->mutex); return -ENOMEM; return -ENOMEM; } } if (feed->idx_params.enable) { dvb_dmx_init_idx_state(feed); dvb_dmx_init_idx_state(feed); feed->rec_info->idx_info.indexing_feeds_num++; if (demux->set_indexing) demux->set_indexing(feed); } } else { } else { feed->pattern_num = 0; feed->pattern_num = 0; feed->rec_info = NULL; feed->rec_info = NULL; } } if ((ret = demux->start_feed(feed)) < 0) { if ((ret = demux->start_feed(feed)) < 0) { if ((feed->ts_type & TS_PACKET) && !(feed->ts_type & TS_PAYLOAD_ONLY)) { dvb_dmx_free_rec_info(ts_feed); dvb_dmx_free_rec_info(ts_feed); feed->rec_info = NULL; feed->rec_info = NULL; } mutex_unlock(&demux->mutex); mutex_unlock(&demux->mutex); return ret; return ret; } } Loading Loading @@ -2232,6 +2256,8 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) if (feed->rec_info) { if (feed->rec_info) { if (feed->pattern_num) if (feed->pattern_num) feed->rec_info->idx_info.pattern_search_feeds_num--; feed->rec_info->idx_info.pattern_search_feeds_num--; if (feed->idx_params.enable) feed->rec_info->idx_info.indexing_feeds_num--; dvb_dmx_free_rec_info(ts_feed); dvb_dmx_free_rec_info(ts_feed); feed->rec_info = NULL; feed->rec_info = NULL; } } Loading Loading @@ -2368,6 +2394,8 @@ static int dmx_ts_set_idx_params(struct dmx_ts_feed *ts_feed, { { struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; struct dvb_demux *dvbdmx = feed->demux; struct dvb_demux *dvbdmx = feed->demux; int idx_enabled; int ret = 0; mutex_lock(&dvbdmx->mutex); mutex_lock(&dvbdmx->mutex); Loading @@ -2376,19 +2404,28 @@ static int dmx_ts_set_idx_params(struct dmx_ts_feed *ts_feed, mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex); return -EINVAL; return -EINVAL; } } idx_enabled = feed->idx_params.enable; feed->idx_params = *idx_params; feed->idx_params = *idx_params; if (feed->state == DMX_STATE_GO) { if (feed->state == DMX_STATE_GO) { spin_lock_irq(&dvbdmx->lock); spin_lock_irq(&dvbdmx->lock); if (feed->pattern_num) if (feed->pattern_num) feed->rec_info->idx_info.pattern_search_feeds_num--; feed->rec_info->idx_info.pattern_search_feeds_num--; if (idx_enabled && !idx_params->enable) feed->rec_info->idx_info.indexing_feeds_num--; if (!idx_enabled && idx_params->enable) feed->rec_info->idx_info.indexing_feeds_num++; dvb_dmx_init_idx_state(feed); dvb_dmx_init_idx_state(feed); spin_unlock_irq(&dvbdmx->lock); spin_unlock_irq(&dvbdmx->lock); if (dvbdmx->set_indexing) ret = dvbdmx->set_indexing(feed); } } mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex); return 0; return ret; } } static int dvbdmx_ts_feed_oob_cmd(struct dmx_ts_feed *ts_feed, static int dvbdmx_ts_feed_oob_cmd(struct dmx_ts_feed *ts_feed, Loading Loading @@ -2952,11 +2989,13 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->pid = 0xffff; dvbdmxfeed->pid = 0xffff; dvbdmxfeed->secure_mode.is_secured = 0; dvbdmxfeed->secure_mode.is_secured = 0; dvbdmxfeed->tsp_out_format = DMX_TSP_FORMAT_188; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->filter = NULL; dvbdmxfeed->filter = NULL; dvbdmxfeed->buffer = NULL; dvbdmxfeed->buffer = NULL; dvbdmxfeed->idx_params.enable = 0; (*feed) = &dvbdmxfeed->feed.sec; (*feed) = &dvbdmxfeed->feed.sec; (*feed)->is_filtering = 0; (*feed)->is_filtering = 0; Loading drivers/media/dvb-core/dvb_demux.h +13 −4 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,9 @@ struct dvb_demux_rec_info { */ */ u64 min_pattern_tsp_num; u64 min_pattern_tsp_num; /* Number of indexing-enabled feeds */ u8 indexing_feeds_num; /* Number of feeds with video pattern search request */ /* Number of feeds with video pattern search request */ u8 pattern_search_feeds_num; u8 pattern_search_feeds_num; Loading Loading @@ -245,6 +248,7 @@ struct dvb_demux { void (*convert_ts)(struct dvb_demux_feed *feed, void (*convert_ts)(struct dvb_demux_feed *feed, const u8 timestamp[TIMESTAMP_LEN], const u8 timestamp[TIMESTAMP_LEN], u64 *timestampIn27Mhz); u64 *timestampIn27Mhz); int (*set_indexing)(struct dvb_demux_feed *feed); int users; int users; #define MAX_DVB_DEMUX_USERS 10 #define MAX_DVB_DEMUX_USERS 10 Loading Loading @@ -297,8 +301,8 @@ struct dvb_demux { int dvb_dmx_init(struct dvb_demux *dvbdemux); int dvb_dmx_init(struct dvb_demux *dvbdemux); void dvb_dmx_release(struct dvb_demux *dvbdemux); void dvb_dmx_release(struct dvb_demux *dvbdemux); void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf, int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf, size_t count); int should_lock); void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count); size_t count); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); Loading @@ -321,13 +325,13 @@ int dvb_dmx_video_pattern_search( struct dvb_dmx_video_prefix_size_masks *prefix_size_masks, struct dvb_dmx_video_prefix_size_masks *prefix_size_masks, struct dvb_dmx_video_patterns_results *results); struct dvb_dmx_video_patterns_results *results); int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, struct dmx_index_event_info *idx_event); struct dmx_index_event_info *idx_event, int should_lock); void dvb_dmx_process_idx_pattern(struct dvb_demux_feed *feed, void dvb_dmx_process_idx_pattern(struct dvb_demux_feed *feed, struct dvb_dmx_video_patterns_results *patterns, int pattern, struct dvb_dmx_video_patterns_results *patterns, int pattern, u64 curr_stc, u64 prev_stc, u64 curr_stc, u64 prev_stc, u64 curr_match_tsp, u64 prev_match_tsp, u64 curr_match_tsp, u64 prev_match_tsp, u64 curr_pusi_tsp, u64 prev_pusi_tsp); u64 curr_pusi_tsp, u64 prev_pusi_tsp); void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed); void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed, int should_lock); int dvb_dmx_notify_section_event(struct dvb_demux_feed *feed, int dvb_dmx_notify_section_event(struct dvb_demux_feed *feed, struct dmx_data_ready *event, int should_lock); struct dmx_data_ready *event, int should_lock); Loading Loading @@ -411,5 +415,10 @@ static inline int dvb_dmx_is_rec_feed(struct dvb_demux_feed *feed) return 1; return 1; } } static inline u16 ts_pid(const u8 *buf) { return ((buf[1] & 0x1f) << 8) + buf[2]; } #endif /* _DVB_DEMUX_H_ */ #endif /* _DVB_DEMUX_H_ */ drivers/media/platform/msm/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -5,7 +5,7 @@ obj-$(CONFIG_MSM_VIDC_V4L2) += vidc/ obj-$(CONFIG_MSM_VIDC_V4L2) += vidc/ obj-$(CONFIG_MSM_WFD) += wfd/ obj-$(CONFIG_MSM_WFD) += wfd/ obj-y += broadcast/ obj-$(CONFIG_DVB_MPQ) += dvb/ obj-$(CONFIG_DVB_MPQ) += dvb/ obj-$(CONFIG_MSMB_CAMERA) += camera_v2/ obj-$(CONFIG_MSMB_CAMERA) += camera_v2/ obj-y += vcap/ obj-y += vcap/ obj-y += broadcast/ Loading
drivers/media/dvb-core/demux.h +5 −3 Original line number Original line Diff line number Diff line Loading @@ -93,7 +93,7 @@ struct dmx_data_ready { /* /* * data_length may be 0 in case of DMX_OK_PES_END or DMX_OK_EOS * data_length may be 0 in case of DMX_OK_PES_END or DMX_OK_EOS * and in non-DMX_OK_XXX events. In DMX_OK_PES_END, * and in non-DMX_OK_XXX events. In DMX_OK_PES_END, * data_length is for data comming after the end of PES. * data_length is for data coming after the end of PES. */ */ int data_length; int data_length; Loading Loading @@ -292,11 +292,13 @@ typedef int (*dmx_section_cb) ( const u8 * buffer1, typedef int (*dmx_ts_fullness) ( typedef int (*dmx_ts_fullness) ( struct dmx_ts_feed *source, struct dmx_ts_feed *source, int required_space); int required_space, int wait); typedef int (*dmx_section_fullness) ( typedef int (*dmx_section_fullness) ( struct dmx_section_filter *source, struct dmx_section_filter *source, int required_space); int required_space, int wait); /*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ /* DVB Front-End */ /* DVB Front-End */ Loading
drivers/media/dvb-core/dmxdev.c +183 −23 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,58 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk if (debug) printk #define dprintk if (debug) printk static inline int dvb_dmxdev_verify_buffer_size(u32 size, u32 max_size, u32 size_align) { if (size_align) return size <= max_size && !(size % size_align); else return size <= max_size; } static int dvb_filter_verify_buffer_size(struct dmxdev_filter *filter, size_t size) { struct dmx_caps caps; /* * For backward compatibility, if no demux capabilities can * be retrieved assume size is ok. * Decoder filter buffer size is verified when decoder buffer is set. */ if (filter->dev->demux->get_caps) { filter->dev->demux->get_caps(filter->dev->demux, &caps); if (filter->type == DMXDEV_TYPE_SEC) return dvb_dmxdev_verify_buffer_size( size, caps.section.max_size, caps.section.size_alignment); if (filter->params.pes.output == DMX_OUT_TAP) return dvb_dmxdev_verify_buffer_size( size, caps.pes.max_size, caps.pes.size_alignment); if (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP || filter->params.pes.output == DMX_OUT_TS_TAP) { if (filter->dmx_tsp_format == DMX_TSP_FORMAT_188) return dvb_dmxdev_verify_buffer_size( size, caps.recording_188_tsp.max_size, caps.recording_188_tsp.size_alignment); return dvb_dmxdev_verify_buffer_size( size, caps.recording_192_tsp.max_size, caps.recording_192_tsp.size_alignment); } } return 1; } static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, const u8 *src, size_t len) const u8 *src, size_t len) { { Loading Loading @@ -1115,6 +1167,38 @@ static int dvb_dvr_external_input_only(struct dmxdev *dmxdev) return is_external_only; return is_external_only; } } static int dvb_dvr_verify_buffer_size(struct dmxdev *dmxdev, unsigned int f_flags, unsigned long size) { struct dmx_caps caps; int tsp_size; if (!dmxdev->demux->get_caps) return 1; if (dmxdev->demux->get_tsp_size) tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux); else tsp_size = 188; dmxdev->demux->get_caps(dmxdev->demux, &caps); if ((f_flags & O_ACCMODE) == O_RDONLY) return (tsp_size == 188 && dvb_dmxdev_verify_buffer_size(size, caps.recording_188_tsp.max_size, caps.recording_188_tsp.size_alignment)) || (tsp_size == 192 && dvb_dmxdev_verify_buffer_size(size, caps.recording_192_tsp.max_size, caps.recording_192_tsp.size_alignment)); return (tsp_size == 188 && dvb_dmxdev_verify_buffer_size(size, caps.playback_188_tsp.max_size, caps.playback_188_tsp.size_alignment)) || (tsp_size == 192 && dvb_dmxdev_verify_buffer_size(size, caps.playback_192_tsp.max_size, caps.playback_192_tsp.size_alignment)); } static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) size_t count, loff_t *ppos) { { Loading @@ -1129,7 +1213,8 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, if (!dmxdev->demux->write) if (!dmxdev->demux->write) return -EOPNOTSUPP; return -EOPNOTSUPP; if (((file->f_flags & O_ACCMODE) == O_RDONLY) || if (!dvb_dvr_verify_buffer_size(dmxdev, file->f_flags, src->size) || ((file->f_flags & O_ACCMODE) == O_RDONLY) || !src->data || !cmdbuf->data || !src->data || !cmdbuf->data || (dvb_dvr_external_input_only(dmxdev) && (dvb_dvr_external_input_only(dmxdev) && (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL))) (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL))) Loading Loading @@ -1203,6 +1288,10 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, if (dmxdev->exit) if (dmxdev->exit) return -ENODEV; return -ENODEV; if (!dvb_dvr_verify_buffer_size(dmxdev, file->f_flags, dmxdev->dvr_buffer.size)) return -EINVAL; res = dvb_dmxdev_buffer_read(NULL, &dmxdev->dvr_buffer, res = dvb_dmxdev_buffer_read(NULL, &dmxdev->dvr_buffer, file->f_flags & O_NONBLOCK, file->f_flags & O_NONBLOCK, buf, count, ppos); buf, count, ppos); Loading Loading @@ -1475,12 +1564,14 @@ static int dvb_dvr_get_event(struct dmxdev *dmxdev, */ */ flush_len = dvb_ringbuffer_avail(&dmxdev->dvr_buffer); flush_len = dvb_ringbuffer_avail(&dmxdev->dvr_buffer); dvb_ringbuffer_flush(&dmxdev->dvr_buffer); dvb_ringbuffer_flush(&dmxdev->dvr_buffer); dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); dmxdev->dvr_buffer.error = 0; dmxdev->dvr_buffer.error = 0; } } spin_unlock_irq(&dmxdev->lock); spin_unlock_irq(&dmxdev->lock); if (event->type == DMX_EVENT_BUFFER_OVERFLOW) dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); /* /* * in PULL mode, we might be stalling on * in PULL mode, we might be stalling on * event queue, so need to wake-up waiters * event queue, so need to wake-up waiters Loading Loading @@ -1522,10 +1613,7 @@ static int dvb_dvr_get_buffer_status(struct dmxdev *dmxdev, */ */ flush_len = dvb_ringbuffer_avail(buf); flush_len = dvb_ringbuffer_avail(buf); dvb_ringbuffer_flush(buf); dvb_ringbuffer_flush(buf); dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); } } buf->error = 0; buf->error = 0; } } Loading @@ -1535,6 +1623,9 @@ static int dvb_dvr_get_buffer_status(struct dmxdev *dmxdev, dmx_buffer_status->write_offset = buf->pwrite; dmx_buffer_status->write_offset = buf->pwrite; dmx_buffer_status->size = buf->size; dmx_buffer_status->size = buf->size; if (dmx_buffer_status->error == -EOVERFLOW) dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, flush_len); spin_unlock_irq(lock); spin_unlock_irq(lock); return 0; return 0; Loading Loading @@ -1738,7 +1829,17 @@ static int dvb_dmxdev_set_decoder_buffer_size( struct dmxdev_filter *dmxdevfilter, struct dmxdev_filter *dmxdevfilter, unsigned long size) unsigned long size) { { if (0 == size) struct dmx_caps caps; struct dmx_demux *demux = dmxdevfilter->dev->demux; if (demux->get_caps) { demux->get_caps(demux, &caps); if (!dvb_dmxdev_verify_buffer_size(size, caps.decoder.max_size, caps.decoder.size_alignment)) return -EINVAL; } if (size == 0) return -EINVAL; return -EINVAL; if (dmxdevfilter->decoder_buffers.buffers_size == size) if (dmxdevfilter->decoder_buffers.buffers_size == size) Loading Loading @@ -1841,6 +1942,7 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter, struct dmxdev_feed *feed; struct dmxdev_feed *feed; struct dmxdev_feed *ts_feed = NULL; struct dmxdev_feed *ts_feed = NULL; struct dmx_caps caps; struct dmx_caps caps; int ret = 0; if (!dmxdevfilter->dev->demux->get_caps) if (!dmxdevfilter->dev->demux->get_caps) return -EINVAL; return -EINVAL; Loading @@ -1866,7 +1968,7 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter, ts_feed->idx_params = *idx_params; ts_feed->idx_params = *idx_params; if ((dmxdevfilter->state == DMXDEV_STATE_GO) && if ((dmxdevfilter->state == DMXDEV_STATE_GO) && ts_feed->ts->set_idx_params) ts_feed->ts->set_idx_params) ts_feed->ts->set_idx_params( ret = ts_feed->ts->set_idx_params( ts_feed->ts, idx_params); ts_feed->ts, idx_params); break; break; } } Loading @@ -1875,7 +1977,7 @@ static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter, if (!found_pid) if (!found_pid) return -EINVAL; return -EINVAL; return 0; return ret; } } static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter, static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter, Loading Loading @@ -2108,7 +2210,7 @@ static int dvb_dmxdev_abort_ts_insertion(struct dmxdev_filter *dmxdevfilter, } } static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, int required_space) int required_space, int wait) { { struct dmxdev_filter *dmxdevfilter = filter->priv; struct dmxdev_filter *dmxdevfilter = filter->priv; struct dvb_ringbuffer *src; struct dvb_ringbuffer *src; Loading Loading @@ -2150,6 +2252,9 @@ static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock); if (!wait) return -ENOSPC; ret = wait_event_interruptible(src->queue, ret = wait_event_interruptible(src->queue, (!src->data) || (!src->data) || ((dvb_ringbuffer_free(src) >= required_space) && ((dvb_ringbuffer_free(src) >= required_space) && Loading @@ -2165,7 +2270,7 @@ static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter, static int dvb_dmxdev_sec_fullness_callback( static int dvb_dmxdev_sec_fullness_callback( struct dmx_section_filter *filter, struct dmx_section_filter *filter, int required_space) int required_space, int wait) { { struct dmxdev_filter *dmxdevfilter = filter->priv; struct dmxdev_filter *dmxdevfilter = filter->priv; struct dvb_ringbuffer *src = &dmxdevfilter->buffer; struct dvb_ringbuffer *src = &dmxdevfilter->buffer; Loading Loading @@ -2199,6 +2304,9 @@ static int dvb_dmxdev_sec_fullness_callback( spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock); if (!wait) return -ENOSPC; ret = wait_event_interruptible(src->queue, ret = wait_event_interruptible(src->queue, (!src->data) || (!src->data) || ((dvb_ringbuffer_free(src) >= required_space) && ((dvb_ringbuffer_free(src) >= required_space) && Loading Loading @@ -2250,7 +2358,7 @@ static int dvb_dmxdev_get_buffer_status( struct dmx_buffer_status *dmx_buffer_status) struct dmx_buffer_status *dmx_buffer_status) { { struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; ssize_t flush_len; ssize_t flush_len = 0; /* /* * Note: Taking the dmxdevfilter->dev->lock spinlock is required only * Note: Taking the dmxdevfilter->dev->lock spinlock is required only Loading Loading @@ -2298,7 +2406,6 @@ static int dvb_dmxdev_get_buffer_status( */ */ flush_len = dvb_ringbuffer_avail(buf); flush_len = dvb_ringbuffer_avail(buf); dvb_ringbuffer_flush(buf); dvb_ringbuffer_flush(buf); dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); } } buf->error = 0; buf->error = 0; } } Loading @@ -2311,6 +2418,9 @@ static int dvb_dmxdev_get_buffer_status( spin_unlock_irq(&dmxdevfilter->dev->lock); spin_unlock_irq(&dmxdevfilter->dev->lock); if (dmx_buffer_status->error == -EOVERFLOW) dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); return 0; return 0; } } Loading Loading @@ -2366,7 +2476,6 @@ static int dvb_dmxdev_get_event(struct dmxdev_filter *dmxdevfilter, */ */ flush_len = dvb_ringbuffer_avail(&dmxdevfilter->buffer); flush_len = dvb_ringbuffer_avail(&dmxdevfilter->buffer); dvb_ringbuffer_flush(&dmxdevfilter->buffer); dvb_ringbuffer_flush(&dmxdevfilter->buffer); dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); dmxdevfilter->buffer.error = 0; dmxdevfilter->buffer.error = 0; } else if (event->type == DMX_EVENT_SECTION_TIMEOUT) { } else if (event->type == DMX_EVENT_SECTION_TIMEOUT) { /* clear buffer error now that user was notified */ /* clear buffer error now that user was notified */ Loading @@ -2387,6 +2496,9 @@ static int dvb_dmxdev_get_event(struct dmxdev_filter *dmxdevfilter, spin_unlock_irq(&dmxdevfilter->dev->lock); spin_unlock_irq(&dmxdevfilter->dev->lock); if (event->type == DMX_EVENT_BUFFER_OVERFLOW) dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len); /* /* * in PULL mode, we might be stalling on * in PULL mode, we might be stalling on * event queue, so need to wake-up waiters * event queue, so need to wake-up waiters Loading Loading @@ -2723,6 +2835,23 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed, } } if (dmx_data_ready->status == DMX_OK_EOS) { if (dmx_data_ready->status == DMX_OK_EOS) { /* Report partial recording chunk */ if ((dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) && events->current_event_data_size) { event.type = DMX_EVENT_NEW_REC_CHUNK; event.params.recording_chunk.offset = events->current_event_start_offset; event.params.recording_chunk.size = events->current_event_data_size; events->current_event_start_offset = (events->current_event_start_offset + events->current_event_data_size) % buffer->size; events->current_event_data_size = 0; dvb_dmxdev_add_event(events, &event); } dmxdevfilter->eos_state = 1; dmxdevfilter->eos_state = 1; dprintk("dmxdev: DMX_OK_EOS - entering EOS state\n"); dprintk("dmxdev: DMX_OK_EOS - entering EOS state\n"); event.type = DMX_EVENT_EOS; event.type = DMX_EVENT_EOS; Loading Loading @@ -2856,8 +2985,9 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed, event.params.pes.base_offset = event.params.pes.base_offset = events->current_event_start_offset; events->current_event_start_offset; event.params.pes.start_offset = event.params.pes.start_offset = events->current_event_start_offset + (events->current_event_start_offset + dmx_data_ready->pes_end.start_gap; dmx_data_ready->pes_end.start_gap) % dmxdevfilter->buffer.size; event.params.pes.actual_length = event.params.pes.actual_length = dmx_data_ready->pes_end.actual_length; dmx_data_ready->pes_end.actual_length; Loading Loading @@ -2895,18 +3025,22 @@ static int dvb_dmxdev_ts_event_cb(struct dmx_ts_feed *feed, if ((dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP) || if ((dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP) || (dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) { (dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) { if (events->current_event_data_size >= while (events->current_event_data_size >= dmxdevfilter->params.pes.rec_chunk_size) { dmxdevfilter->params.pes.rec_chunk_size) { event.type = DMX_EVENT_NEW_REC_CHUNK; event.type = DMX_EVENT_NEW_REC_CHUNK; event.params.recording_chunk.offset = event.params.recording_chunk.offset = events->current_event_start_offset; events->current_event_start_offset; event.params.recording_chunk.size = event.params.recording_chunk.size = events->current_event_data_size; dmxdevfilter->params.pes.rec_chunk_size; events->current_event_data_size = events->current_event_data_size - dmxdevfilter->params.pes.rec_chunk_size; events->current_event_start_offset = (events->current_event_start_offset + dmxdevfilter->params.pes.rec_chunk_size) % buffer->size; dvb_dmxdev_add_event(events, &event); dvb_dmxdev_add_event(events, &event); events->current_event_data_size = 0; } } } } spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock); Loading Loading @@ -3173,9 +3307,15 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, if ((filter->params.pes.output == DMX_OUT_TS_TAP) || if ((filter->params.pes.output == DMX_OUT_TS_TAP) || (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP)) if (tsfeed->set_idx_params) if (tsfeed->set_idx_params) { tsfeed->set_idx_params( ret = tsfeed->set_idx_params( tsfeed, &feed->idx_params); tsfeed, &feed->idx_params); if (ret) { dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); return ret; } } ret = tsfeed->start_filtering(tsfeed); ret = tsfeed->start_filtering(tsfeed); if (ret < 0) { if (ret < 0) { Loading Loading @@ -3236,7 +3376,24 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) if (filter->state >= DMXDEV_STATE_GO) if (filter->state >= DMXDEV_STATE_GO) dvb_dmxdev_filter_stop(filter); dvb_dmxdev_filter_stop(filter); if (!dvb_filter_verify_buffer_size(filter, filter->buffer.size)) return -EINVAL; if (!filter->buffer.data) { if (!filter->buffer.data) { /* * dmxdev buffer in decoder filters is not really used * to exchange data with applications. Decoder buffers * can be set using DMX_SET_DECODER_BUFFER, which * would not update the filter->buffer.data at all. * Therefore we should not treat this filter as * other regular filters and should not fail here * even if user sets the buffer in deocder * filter as external buffer. */ if ((filter->type == DMXDEV_TYPE_PES) && (filter->params.pes.output == DMX_OUT_DECODER)) filter->buffer_mode = DMX_BUFFER_MODE_INTERNAL; if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) || if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) || dvb_filter_external_buffer_only(dmxdev, filter)) dvb_filter_external_buffer_only(dmxdev, filter)) return -ENOMEM; return -ENOMEM; Loading Loading @@ -3771,6 +3928,9 @@ static int dvb_dmxdev_set_decoder_buffer(struct dmxdev *dmxdev, return -EINVAL; return -EINVAL; dmxdev->demux->get_caps(dmxdev->demux, &caps); dmxdev->demux->get_caps(dmxdev->demux, &caps); if (!dvb_dmxdev_verify_buffer_size(buffs->buffers_size, caps.decoder.max_size, caps.decoder.size_alignment)) return -EINVAL; if ((buffs->buffers_size == 0) || if ((buffs->buffers_size == 0) || (buffs->is_linear && (buffs->is_linear && Loading
drivers/media/dvb-core/dvb_demux.c +110 −71 Original line number Original line Diff line number Diff line Loading @@ -178,12 +178,7 @@ static inline u16 section_length(const u8 *buf) return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; } } static inline u16 ts_pid(const u8 *buf) static inline u8 ts_scrambling_ctrl(const u8 *buf) { return ((buf[1] & 0x1f) << 8) + buf[2]; } static inline u16 ts_scrambling_ctrl(const u8 *buf) { { return (buf[3] >> 6) & 0x3; return (buf[3] >> 6) & 0x3; } } Loading Loading @@ -737,7 +732,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, return 0; return 0; } } static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, static int dvb_dmx_swfilter_section_one_packet(struct dvb_demux_feed *feed, const u8 *buf) const u8 *buf) { { u8 p, count; u8 p, count; Loading Loading @@ -815,6 +810,60 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, return 0; return 0; } } /* * dvb_dmx_swfilter_section_packet - wrapper for section filtering of single * TS packet. * * @feed: dvb demux feed * @buf: buffer containing the TS packet * @should_lock: specifies demux locking semantics: if not set, proper demux * locking is expected to have been done by the caller. * * Return error status */ int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf, int should_lock) { int ret; if (!should_lock && !spin_is_locked(&feed->demux->lock)) { pr_err("%s: demux spinlock should have been locked\n", __func__); return -EINVAL; } if (should_lock) spin_lock(&feed->demux->lock); ret = dvb_dmx_swfilter_section_one_packet(feed, buf); if (should_lock) spin_unlock(&feed->demux->lock); return ret; } EXPORT_SYMBOL(dvb_dmx_swfilter_section_packet); static int dvb_demux_idx_event_sort(struct dmx_index_event_info *curr, struct dmx_index_event_info *new) { if (curr->match_tsp_num > new->match_tsp_num) return 0; if (curr->match_tsp_num < new->match_tsp_num) return 1; /* * In case TSP numbers are equal, sort according to event type giving * priority to PUSI events first, then RAI and finally framing events. */ if ((curr->type & DMX_IDX_RAI && new->type & DMX_IDX_PUSI) || (!(curr->type & DMX_IDX_PUSI) && !(curr->type & DMX_IDX_RAI) && new->type & (DMX_IDX_PUSI | DMX_IDX_RAI))) return 0; return 1; } static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, struct dmx_index_event_info *idx_event, struct dmx_index_event_info *idx_event, int traverse_from_tail) int traverse_from_tail) Loading @@ -839,8 +888,8 @@ static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, if (traverse_from_tail) { if (traverse_from_tail) { list_for_each_entry_reverse(curr_entry, list_for_each_entry_reverse(curr_entry, &feed->rec_info->idx_info.ready_list, next) { &feed->rec_info->idx_info.ready_list, next) { if (curr_entry->event.match_tsp_num <= if (dvb_demux_idx_event_sort(&curr_entry->event, idx_event->match_tsp_num) { idx_event)) { pos = &curr_entry->next; pos = &curr_entry->next; break; break; } } Loading @@ -848,8 +897,8 @@ static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, } else { } else { list_for_each_entry(curr_entry, list_for_each_entry(curr_entry, &feed->rec_info->idx_info.ready_list, next) { &feed->rec_info->idx_info.ready_list, next) { if (curr_entry->event.match_tsp_num > if (!dvb_demux_idx_event_sort(&curr_entry->event, idx_event->match_tsp_num) { idx_event)) { pos = &curr_entry->next; pos = &curr_entry->next; break; break; } } Loading @@ -865,12 +914,17 @@ static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed, } } int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, struct dmx_index_event_info *idx_event) struct dmx_index_event_info *idx_event, int should_lock) { { int ret; int ret; if (!should_lock && !spin_is_locked(&feed->demux->lock)) return -EINVAL; if (should_lock) spin_lock(&feed->demux->lock); spin_lock(&feed->demux->lock); ret = dvb_demux_save_idx_event(feed, idx_event, 1); ret = dvb_demux_save_idx_event(feed, idx_event, 1); if (should_lock) spin_unlock(&feed->demux->lock); spin_unlock(&feed->demux->lock); return ret; return ret; Loading Loading @@ -900,10 +954,15 @@ static inline void dvb_dmx_notify_indexing(struct dvb_demux_feed *feed) } } } } void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed) void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed, int should_lock) { { if (!should_lock && !spin_is_locked(&feed->demux->lock)) return; if (should_lock) spin_lock(&feed->demux->lock); spin_lock(&feed->demux->lock); dvb_dmx_notify_indexing(feed); dvb_dmx_notify_indexing(feed); if (should_lock) spin_unlock(&feed->demux->lock); spin_unlock(&feed->demux->lock); } } EXPORT_SYMBOL(dvb_dmx_notify_idx_events); EXPORT_SYMBOL(dvb_dmx_notify_idx_events); Loading Loading @@ -1078,7 +1137,7 @@ static void dvb_dmx_index(struct dvb_demux_feed *feed, /* /* * if we still did not encounter a TS packet with PUSI indication, * if we still did not encounter a TS packet with PUSI indication, * we cannot report index entries yet as we need to provide * we cannot report index entries yet as we need to provide * the TS packet number with PUSI indication preceeding the TS * the TS packet number with PUSI indication preceding the TS * packet pointed by the reported index entry. * packet pointed by the reported index entry. */ */ if (feed->curr_pusi_tsp_num == (u64)-1) { if (feed->curr_pusi_tsp_num == (u64)-1) { Loading Loading @@ -1284,7 +1343,8 @@ static inline int dvb_dmx_swfilter_buffer_check( if (likely(was_locked)) if (likely(was_locked)) spin_unlock(&demux->lock); spin_unlock(&demux->lock); ret = demux->buffer_ctrl.ts(ts, desired_space); ret = demux->buffer_ctrl.ts(ts, desired_space, 1); if (likely(was_locked)) if (likely(was_locked)) spin_lock(&demux->lock); spin_lock(&demux->lock); Loading Loading @@ -1334,7 +1394,8 @@ static inline int dvb_dmx_swfilter_buffer_check( if (likely(was_locked)) if (likely(was_locked)) spin_unlock(&demux->lock); spin_unlock(&demux->lock); ret = demux->buffer_ctrl.sec(&f->filter, desired_space); ret = demux->buffer_ctrl.sec(&f->filter, desired_space, 1); if (likely(was_locked)) if (likely(was_locked)) spin_lock(&demux->lock); spin_lock(&demux->lock); Loading Loading @@ -1398,7 +1459,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, if (!feed->feed.sec.is_filtering || if (!feed->feed.sec.is_filtering || feed->secure_mode.is_secured) feed->secure_mode.is_secured) break; break; if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) if (dvb_dmx_swfilter_section_one_packet(feed, buf) < 0) feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; break; break; Loading Loading @@ -1508,52 +1569,6 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf, } } EXPORT_SYMBOL(dvb_dmx_swfilter_packet); EXPORT_SYMBOL(dvb_dmx_swfilter_packet); void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf, size_t count) { struct dvb_demux_feed *feed; u16 pid = ts_pid(buf); struct timespec pre_time; if (dvb_demux_performancecheck) pre_time = current_kernel_time(); spin_lock(&demux->lock); demux->sw_filter_abort = 0; while (count--) { if (buf[0] != 0x47) { buf += 188; continue; } if (demux->playback_mode == DMX_PB_MODE_PULL) if (dvb_dmx_swfilter_buffer_check(demux, pid) < 0) break; list_for_each_entry(feed, &demux->feed_list, list_head) { if (feed->pid != pid) continue; if (!feed->feed.sec.is_filtering) continue; if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) { feed->feed.sec.seclen = 0; feed->feed.sec.secbufp = 0; } } buf += 188; } spin_unlock(&demux->lock); if (dvb_demux_performancecheck) demux->total_process_time += dvb_dmx_calc_time_delta(pre_time); } EXPORT_SYMBOL(dvb_dmx_swfilter_section_packets); void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count) size_t count) { { Loading Loading @@ -2041,6 +2056,7 @@ static struct dvb_demux_rec_info *dvb_dmx_alloc_rec_info( rec_info->ts_output_count = 0; rec_info->ts_output_count = 0; rec_info->idx_info.min_pattern_tsp_num = (u64)-1; rec_info->idx_info.min_pattern_tsp_num = (u64)-1; rec_info->idx_info.pattern_search_feeds_num = 0; rec_info->idx_info.pattern_search_feeds_num = 0; rec_info->idx_info.indexing_feeds_num = 0; return rec_info; return rec_info; } } Loading Loading @@ -2182,15 +2198,23 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) mutex_unlock(&demux->mutex); mutex_unlock(&demux->mutex); return -ENOMEM; return -ENOMEM; } } if (feed->idx_params.enable) { dvb_dmx_init_idx_state(feed); dvb_dmx_init_idx_state(feed); feed->rec_info->idx_info.indexing_feeds_num++; if (demux->set_indexing) demux->set_indexing(feed); } } else { } else { feed->pattern_num = 0; feed->pattern_num = 0; feed->rec_info = NULL; feed->rec_info = NULL; } } if ((ret = demux->start_feed(feed)) < 0) { if ((ret = demux->start_feed(feed)) < 0) { if ((feed->ts_type & TS_PACKET) && !(feed->ts_type & TS_PAYLOAD_ONLY)) { dvb_dmx_free_rec_info(ts_feed); dvb_dmx_free_rec_info(ts_feed); feed->rec_info = NULL; feed->rec_info = NULL; } mutex_unlock(&demux->mutex); mutex_unlock(&demux->mutex); return ret; return ret; } } Loading Loading @@ -2232,6 +2256,8 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) if (feed->rec_info) { if (feed->rec_info) { if (feed->pattern_num) if (feed->pattern_num) feed->rec_info->idx_info.pattern_search_feeds_num--; feed->rec_info->idx_info.pattern_search_feeds_num--; if (feed->idx_params.enable) feed->rec_info->idx_info.indexing_feeds_num--; dvb_dmx_free_rec_info(ts_feed); dvb_dmx_free_rec_info(ts_feed); feed->rec_info = NULL; feed->rec_info = NULL; } } Loading Loading @@ -2368,6 +2394,8 @@ static int dmx_ts_set_idx_params(struct dmx_ts_feed *ts_feed, { { struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; struct dvb_demux *dvbdmx = feed->demux; struct dvb_demux *dvbdmx = feed->demux; int idx_enabled; int ret = 0; mutex_lock(&dvbdmx->mutex); mutex_lock(&dvbdmx->mutex); Loading @@ -2376,19 +2404,28 @@ static int dmx_ts_set_idx_params(struct dmx_ts_feed *ts_feed, mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex); return -EINVAL; return -EINVAL; } } idx_enabled = feed->idx_params.enable; feed->idx_params = *idx_params; feed->idx_params = *idx_params; if (feed->state == DMX_STATE_GO) { if (feed->state == DMX_STATE_GO) { spin_lock_irq(&dvbdmx->lock); spin_lock_irq(&dvbdmx->lock); if (feed->pattern_num) if (feed->pattern_num) feed->rec_info->idx_info.pattern_search_feeds_num--; feed->rec_info->idx_info.pattern_search_feeds_num--; if (idx_enabled && !idx_params->enable) feed->rec_info->idx_info.indexing_feeds_num--; if (!idx_enabled && idx_params->enable) feed->rec_info->idx_info.indexing_feeds_num++; dvb_dmx_init_idx_state(feed); dvb_dmx_init_idx_state(feed); spin_unlock_irq(&dvbdmx->lock); spin_unlock_irq(&dvbdmx->lock); if (dvbdmx->set_indexing) ret = dvbdmx->set_indexing(feed); } } mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex); return 0; return ret; } } static int dvbdmx_ts_feed_oob_cmd(struct dmx_ts_feed *ts_feed, static int dvbdmx_ts_feed_oob_cmd(struct dmx_ts_feed *ts_feed, Loading Loading @@ -2952,11 +2989,13 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->pid = 0xffff; dvbdmxfeed->pid = 0xffff; dvbdmxfeed->secure_mode.is_secured = 0; dvbdmxfeed->secure_mode.is_secured = 0; dvbdmxfeed->tsp_out_format = DMX_TSP_FORMAT_188; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->filter = NULL; dvbdmxfeed->filter = NULL; dvbdmxfeed->buffer = NULL; dvbdmxfeed->buffer = NULL; dvbdmxfeed->idx_params.enable = 0; (*feed) = &dvbdmxfeed->feed.sec; (*feed) = &dvbdmxfeed->feed.sec; (*feed)->is_filtering = 0; (*feed)->is_filtering = 0; Loading
drivers/media/dvb-core/dvb_demux.h +13 −4 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,9 @@ struct dvb_demux_rec_info { */ */ u64 min_pattern_tsp_num; u64 min_pattern_tsp_num; /* Number of indexing-enabled feeds */ u8 indexing_feeds_num; /* Number of feeds with video pattern search request */ /* Number of feeds with video pattern search request */ u8 pattern_search_feeds_num; u8 pattern_search_feeds_num; Loading Loading @@ -245,6 +248,7 @@ struct dvb_demux { void (*convert_ts)(struct dvb_demux_feed *feed, void (*convert_ts)(struct dvb_demux_feed *feed, const u8 timestamp[TIMESTAMP_LEN], const u8 timestamp[TIMESTAMP_LEN], u64 *timestampIn27Mhz); u64 *timestampIn27Mhz); int (*set_indexing)(struct dvb_demux_feed *feed); int users; int users; #define MAX_DVB_DEMUX_USERS 10 #define MAX_DVB_DEMUX_USERS 10 Loading Loading @@ -297,8 +301,8 @@ struct dvb_demux { int dvb_dmx_init(struct dvb_demux *dvbdemux); int dvb_dmx_init(struct dvb_demux *dvbdemux); void dvb_dmx_release(struct dvb_demux *dvbdemux); void dvb_dmx_release(struct dvb_demux *dvbdemux); void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf, int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf, size_t count); int should_lock); void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count); size_t count); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); Loading @@ -321,13 +325,13 @@ int dvb_dmx_video_pattern_search( struct dvb_dmx_video_prefix_size_masks *prefix_size_masks, struct dvb_dmx_video_prefix_size_masks *prefix_size_masks, struct dvb_dmx_video_patterns_results *results); struct dvb_dmx_video_patterns_results *results); int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, int dvb_demux_push_idx_event(struct dvb_demux_feed *feed, struct dmx_index_event_info *idx_event); struct dmx_index_event_info *idx_event, int should_lock); void dvb_dmx_process_idx_pattern(struct dvb_demux_feed *feed, void dvb_dmx_process_idx_pattern(struct dvb_demux_feed *feed, struct dvb_dmx_video_patterns_results *patterns, int pattern, struct dvb_dmx_video_patterns_results *patterns, int pattern, u64 curr_stc, u64 prev_stc, u64 curr_stc, u64 prev_stc, u64 curr_match_tsp, u64 prev_match_tsp, u64 curr_match_tsp, u64 prev_match_tsp, u64 curr_pusi_tsp, u64 prev_pusi_tsp); u64 curr_pusi_tsp, u64 prev_pusi_tsp); void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed); void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed, int should_lock); int dvb_dmx_notify_section_event(struct dvb_demux_feed *feed, int dvb_dmx_notify_section_event(struct dvb_demux_feed *feed, struct dmx_data_ready *event, int should_lock); struct dmx_data_ready *event, int should_lock); Loading Loading @@ -411,5 +415,10 @@ static inline int dvb_dmx_is_rec_feed(struct dvb_demux_feed *feed) return 1; return 1; } } static inline u16 ts_pid(const u8 *buf) { return ((buf[1] & 0x1f) << 8) + buf[2]; } #endif /* _DVB_DEMUX_H_ */ #endif /* _DVB_DEMUX_H_ */
drivers/media/platform/msm/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -5,7 +5,7 @@ obj-$(CONFIG_MSM_VIDC_V4L2) += vidc/ obj-$(CONFIG_MSM_VIDC_V4L2) += vidc/ obj-$(CONFIG_MSM_WFD) += wfd/ obj-$(CONFIG_MSM_WFD) += wfd/ obj-y += broadcast/ obj-$(CONFIG_DVB_MPQ) += dvb/ obj-$(CONFIG_DVB_MPQ) += dvb/ obj-$(CONFIG_MSMB_CAMERA) += camera_v2/ obj-$(CONFIG_MSMB_CAMERA) += camera_v2/ obj-y += vcap/ obj-y += vcap/ obj-y += broadcast/