Loading drivers/media/dvb-core/demux.h +3 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * Copyright (c) 2000 Nokia Research Center * Tampere, FINLAND * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License Loading Loading @@ -38,6 +38,8 @@ /* Common definitions */ /*--------------------------------------------------------------------------*/ #define DMX_EVENT_QUEUE_SIZE 500 /* number of events */ /* * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter. */ Loading drivers/media/dvb-core/dmxdev.h +2 −3 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ * Copyright (C) 2000 Ralph Metzler & Marcus Metzler * for convergence integrated media GmbH * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License Loading Loading @@ -70,11 +70,10 @@ struct dmxdev_sec_feed { struct dmx_cipher_operations cipher_ops; }; #define DMX_EVENT_QUEUE_SIZE 500 /* number of events */ struct dmxdev_events_queue { /* * indices used to manage events queue. * read_index advanced when relevent data is read * read_index advanced when relevant data is read * from the buffer. * notified_index is the index from which next events * are returned. Loading drivers/media/dvb-core/dvb_demux.h +3 −2 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler * for convergence integrated media GmbH * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License Loading Loading @@ -75,7 +75,8 @@ struct dmx_index_entry { struct list_head next; }; #define DMX_IDX_EVENT_QUEUE_SIZE 100 #define DMX_IDX_EVENT_QUEUE_SIZE DMX_EVENT_QUEUE_SIZE struct dvb_demux_rec_info { /* Reference counter for number of feeds using this information */ int ref_count; Loading drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c +217 −107 Original line number Diff line number Diff line Loading @@ -3451,33 +3451,171 @@ static int mpq_dmx_tspp2_calc_tsp_num_delta( return tsp_num / (int)packet_size; } /** * mpq_dmx_tspp2_offset_in_range() - return whether some buffer offset is in * the given offsets range, taking wrap-around into consideration. * * @offset: offset to check * @from: range "left" boundary * @to: range "right"boundary * * Return true if offset is in range, false otherwise */ static bool mpq_dmx_tspp2_offset_in_range(u32 offset, u32 from, u32 to) { if (from <= to) return (offset >= from && offset < to); return !(offset >= to && offset < from); } /** * mpq_dmx_tspp2_match_after_pusi() - check if PUSI offset precedes the * TSP match offset in the recording chunk. * * @pusi: pusi tsp offset * @match: match tsp offset * @chunk_start: recording chunk start offset * @chunk_size: recording chunk size * @buffer_size: recording buffer size * * Return true if PUSI offset precedes match offset, false otherwise */ static bool mpq_dmx_tspp2_match_after_pusi(u32 pusi, u32 match, u32 chunk_start, size_t chunk_size, size_t buffer_size) { u32 end_offset = (chunk_start + chunk_size) % buffer_size; if ((chunk_start + chunk_size) >= buffer_size) { if ((pusi >= chunk_start && match >= chunk_start) || (pusi < end_offset && match < end_offset)) return (pusi <= match); return (pusi > match); } return (pusi <= match); } /** * mpq_dmx_tspp2_process_index_desc() - process one indexing descriptor * (descriptor might be partial) * * @feed: dvb_demux feed object * @rec_pipe: recording pipe info * @idx_desc: indexing descriptor to process * @rec_data_size: recording chunk size * @ts_pkt_size: TS packet size */ static void mpq_dmx_tspp2_process_index_desc(struct dvb_demux_feed *feed, struct pipe_info *rec_pipe, struct mpq_tspp2_index_desc *idx_desc, size_t rec_data_size, size_t ts_pkt_size) { struct dmx_index_event_info idx_event; struct mpq_tspp2_index_table *index_table; struct dvb_dmx_video_patterns_results pattern; u8 pattern_id; u8 table_id; int tsp_delta; u32 match_tsp_offset; u32 pusi_tsp_offset; u32 from = rec_pipe->tspp_write_offset; u32 to = (rec_pipe->tspp_write_offset + rec_data_size) % rec_pipe->buffer.size; /* Convert addresses in the indexing desc. from big-endian */ idx_desc->matched_tsp_addr = be32_to_cpu(idx_desc->matched_tsp_addr); idx_desc->pusi_tsp_addr = be32_to_cpu(idx_desc->pusi_tsp_addr); idx_desc->last_tsp_addr = 0; /* unused */ idx_event.pid = feed->pid; idx_event.stc = mpq_dmx_tspp2_get_stc(idx_desc->stc, 7); pattern_id = idx_desc->pattern_id & INDEX_DESC_PATTERN_ID_MASK; table_id = (idx_desc->pattern_id & INDEX_DESC_TABLE_ID_MASK) >> 5; index_table = &mpq_dmx_tspp2_info.index_tables[table_id]; idx_event.type = index_table->patterns[pattern_id].type; MPQ_DVB_DBG_PRINT( "%s: Index info: pattern_id=0x%x, pusi=0x%x, match=0x%x\n", __func__, idx_desc->pattern_id, idx_desc->pusi_tsp_addr, idx_desc->matched_tsp_addr); if (idx_desc->matched_tsp_addr && idx_desc->matched_tsp_addr != ULONG_MAX) { match_tsp_offset = idx_desc->matched_tsp_addr - ts_pkt_size + 1 - rec_pipe->buffer.iova; pusi_tsp_offset = idx_desc->pusi_tsp_addr - rec_pipe->buffer.iova; tsp_delta = mpq_dmx_tspp2_calc_tsp_num_delta( pusi_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_pkt_size); /* * PUSI address and match address are both in the chunk, * but if PUSI address is after the match address then * it is really from previous chunk. */ if (mpq_dmx_tspp2_offset_in_range(pusi_tsp_offset, from, to) && !mpq_dmx_tspp2_match_after_pusi(pusi_tsp_offset, match_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size)) idx_event.last_pusi_tsp_num = feed->rec_info->ts_output_count - ((rec_pipe->buffer.size / ts_pkt_size) - tsp_delta); else idx_event.last_pusi_tsp_num = feed->rec_info->ts_output_count + tsp_delta; idx_event.match_tsp_num = feed->rec_info->ts_output_count + mpq_dmx_tspp2_calc_tsp_num_delta( match_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_pkt_size); feed->last_pattern_tsp_num = idx_event.match_tsp_num; MPQ_DVB_DBG_PRINT( "%s: PUSI tsp num=%llu, Match tsp num=%llu (tsp_delta=%d)\n", __func__, idx_event.last_pusi_tsp_num, idx_event.match_tsp_num, tsp_delta); pattern.info[0].type = index_table->patterns[pattern_id].type; pattern.info[0].offset = 0; pattern.info[0].used_prefix_size = 0; dvb_dmx_process_idx_pattern(feed, &pattern, 0, idx_event.stc, 0, idx_event.match_tsp_num, 0, idx_event.last_pusi_tsp_num, 0); } } /** * mpq_dmx_tspp2_index_pipe_handler() - Handler for index pipe notifications * * @index_pipe: pipe_info for the indexing pipe * @rec_pipe: pipe_info for the recording payload pipe * @index_pipe: pipe_info for the indexing pipe * @ts_packet_size: Recording TS packet size * @event: Notification event type * @rec_data_size: Recording chunk size * @tspp_index_last_addr: Index pipe last write address sampled * * Return error status */ static int mpq_dmx_tspp2_index_pipe_handler(struct pipe_info *rec_pipe, struct pipe_info *index_pipe, u32 tspp_index_last_addr, size_t ts_packet_size, enum mpq_dmx_tspp2_pipe_event event, size_t rec_data_size) struct pipe_info *index_pipe, size_t ts_packet_size, enum mpq_dmx_tspp2_pipe_event event, size_t rec_data_size, u32 tspp_index_last_addr) { int i; struct dvb_demux_feed *feed; u32 num_desc; u32 desc_offset; struct dmx_index_event_info idx_event; u32 desc_leftover = 0; struct mpq_tspp2_feed *tspp2_feed; struct mpq_tspp2_index_desc index_desc; struct mpq_tspp2_index_table *index_table; struct dvb_dmx_video_patterns_results pattern; size_t data_size; u8 pattern_id; u8 table_id; if (!index_pipe->ref_count) { MPQ_DVB_ERR_PRINT( Loading @@ -3504,97 +3642,69 @@ static int mpq_dmx_tspp2_index_pipe_handler(struct pipe_info *rec_pipe, tspp2_feed = index_pipe->parent; feed = tspp2_feed->mpq_feed->dvb_demux_feed; /* Calculate new data in indexing pipe */ data_size = mpq_dmx_tspp2_calc_pipe_data(index_pipe, tspp_index_last_addr); index_pipe->tspp_last_addr = tspp_index_last_addr; index_pipe->tspp_write_offset += data_size; if (index_pipe->tspp_write_offset >= index_pipe->buffer.size) index_pipe->tspp_write_offset -= index_pipe->buffer.size; /* * Calculate total data to process, disregarding leftover from previous * partial descriptor that was processed. */ if (index_pipe->tspp_read_offset % TSPP2_DMX_SPS_INDEXING_DESC_SIZE) { desc_leftover = TSPP2_DMX_SPS_INDEXING_DESC_SIZE - index_pipe->tspp_read_offset % TSPP2_DMX_SPS_INDEXING_DESC_SIZE; if (desc_leftover <= data_size) mpq_dmx_release_data(index_pipe, desc_leftover); else return 0; } data_size = mpq_dmx_calc_fullness(index_pipe->tspp_write_offset, index_pipe->tspp_read_offset, index_pipe->buffer.size); if (data_size == 0) return 0; num_desc = data_size / TSPP2_DMX_SPS_INDEXING_DESC_SIZE; idx_event.pid = feed->pid; MPQ_DVB_DBG_PRINT("%s: TS output count=%llu, last_pusi_addr=0x%X\n", __func__, feed->rec_info->ts_output_count, tspp2_feed->last_pusi_addr); for (i = 0; i < num_desc; i++) { desc_offset = index_pipe->tspp_write_offset + i * TSPP2_DMX_SPS_INDEXING_DESC_SIZE; if (desc_offset >= index_pipe->buffer.size) desc_offset -= index_pipe->buffer.size; memcpy(&index_desc, index_pipe->buffer.mem + desc_offset, sizeof(index_desc)); /* Convert addresses in the indexing desc. from big-endian */ index_desc.matched_tsp_addr = be32_to_cpu(index_desc.matched_tsp_addr); index_desc.pusi_tsp_addr = be32_to_cpu(index_desc.pusi_tsp_addr); index_desc.last_tsp_addr = be32_to_cpu(index_desc.last_tsp_addr); idx_event.pid = feed->pid; idx_event.stc = mpq_dmx_tspp2_get_stc(index_desc.stc, 7); pattern_id = index_desc.pattern_id & INDEX_DESC_PATTERN_ID_MASK; table_id = (index_desc.pattern_id & INDEX_DESC_TABLE_ID_MASK) >> 5; index_table = &mpq_dmx_tspp2_info.index_tables[table_id]; idx_event.type = index_table->patterns[pattern_id].type; MPQ_DVB_DBG_PRINT( "%s: Index desc(#%d, offset=%u): id=0x%X(0x%llx), match TSP=0x%X, PUSI=0x%X, last TSP=0x%X\n", __func__, i, desc_offset, index_desc.pattern_id, idx_event.type, index_desc.matched_tsp_addr, index_desc.pusi_tsp_addr, index_desc.last_tsp_addr); if (index_desc.matched_tsp_addr) { u32 match_tsp_offset = index_desc.matched_tsp_addr - ts_packet_size + 1 - rec_pipe->buffer.iova; pattern_id = index_desc.pattern_id & INDEX_DESC_PATTERN_ID_MASK; idx_event.last_pusi_tsp_num = feed->rec_info->ts_output_count + mpq_dmx_tspp2_calc_tsp_num_delta( index_desc.pusi_tsp_addr - rec_pipe->buffer.iova, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_packet_size); idx_event.match_tsp_num = feed->rec_info->ts_output_count + mpq_dmx_tspp2_calc_tsp_num_delta( match_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_packet_size); feed->last_pattern_tsp_num = idx_event.match_tsp_num; "\n%s: TS output count=%llu, desc_data=%u, desc_leftover=%u\n", __func__, feed->rec_info->ts_output_count, data_size, desc_leftover); MPQ_DVB_DBG_PRINT( "%s: PUSI tsp num=%llu, Match tsp num=%llu\n", __func__, idx_event.last_pusi_tsp_num, idx_event.match_tsp_num); "%s: Recording chunk: from=%u, to=%u, size=%u\n\n", __func__, rec_pipe->tspp_write_offset, (rec_pipe->tspp_write_offset + rec_data_size) % rec_pipe->buffer.size, rec_data_size); pattern.info[0].type = index_table->patterns[pattern_id].type; pattern.info[0].offset = 0; pattern.info[0].used_prefix_size = 0; /* * Loop over the indexing descriptors and process each one. * The last descriptor might be a partial descriptor (24 bytes out of * 28 total) which does not contain the information where the frame/PES * ends, but we don't use this field anyway so we process it too. */ while (data_size >= TSPP2_DMX_MIN_INDEXING_DESC_SIZE) { memcpy(&index_desc, index_pipe->buffer.mem + index_pipe->tspp_read_offset, sizeof(index_desc)); dvb_dmx_process_idx_pattern(feed, &pattern, 0, idx_event.stc, 0, idx_event.match_tsp_num, 0, idx_event.last_pusi_tsp_num, 0); mpq_dmx_tspp2_process_index_desc(feed, rec_pipe, &index_desc, rec_data_size, ts_packet_size); /* * Descriptor was processed - advance the index pipe read offset */ if (data_size >= TSPP2_DMX_SPS_INDEXING_DESC_SIZE) { mpq_dmx_release_data(index_pipe, TSPP2_DMX_SPS_INDEXING_DESC_SIZE); data_size -= TSPP2_DMX_SPS_INDEXING_DESC_SIZE; } else { mpq_dmx_release_data(index_pipe, data_size); data_size = 0; } } index_pipe->tspp_last_addr = tspp_index_last_addr; index_pipe->tspp_write_offset += num_desc * TSPP2_DMX_SPS_INDEXING_DESC_SIZE; if (index_pipe->tspp_write_offset >= index_pipe->buffer.size) index_pipe->tspp_write_offset -= index_pipe->buffer.size; mpq_dmx_release_data(index_pipe, num_desc * TSPP2_DMX_SPS_INDEXING_DESC_SIZE); return 0; } Loading Loading @@ -3710,7 +3820,7 @@ static int mpq_dmx_tspp2_rec_pipe_handler(struct pipe_info *pipe_info, u32 tspp_last_addr; u32 tspp_index_last_addr; struct dmx_data_ready data; struct pipe_info *index_pipe = NULL; struct pipe_info *index_pipe = pipe_info->parent->secondary_pipe; int ret = 0; if (!pipe_info->ref_count || pipe_info->type != REC_PIPE) { Loading Loading @@ -3739,15 +3849,15 @@ static int mpq_dmx_tspp2_rec_pipe_handler(struct pipe_info *pipe_info, } /* * Sample indexing pipe before the recording pipe, to prevent indexing * reported on recorded data that will be sampled only in the next * iteration. * Sample indexing pipe before sampling the recording pipe. * This ensures indexing data refers to the current recording chunk, * or the previous recording chunk (as we might still miss indexing * descriptor that was written immediately after we sampled the pipe, * which will be processed in the next iteration). */ if (pipe_info->parent->secondary_pipe != NULL) { index_pipe = pipe_info->parent->secondary_pipe; if (index_pipe) tspp2_pipe_last_address_used_get(index_pipe->handle, &tspp_index_last_addr); } tspp2_pipe_last_address_used_get(pipe_info->handle, &tspp_last_addr); data_size = mpq_dmx_tspp2_calc_pipe_data(pipe_info, tspp_last_addr); Loading Loading @@ -3782,10 +3892,10 @@ static int mpq_dmx_tspp2_rec_pipe_handler(struct pipe_info *pipe_info, mpq_dmx_tspp2_index(feed, pipe_info, data_size, ts_packet_size); /* Handle HW indexing results */ if (index_pipe != NULL) if (index_pipe) mpq_dmx_tspp2_index_pipe_handler(pipe_info, index_pipe, tspp_index_last_addr, ts_packet_size, event, data_size); ts_packet_size, event, data_size, tspp_index_last_addr); /* * Limit indexing notification to the last TS packet in the Loading Loading @@ -4353,7 +4463,7 @@ static int mpq_dmx_tspp2_allocate_index_pipe(struct dvb_demux_feed *feed) } ret = mpq_dmx_init_out_pipe(mpq_demux, pipe_info, TSPP2_DMX_SPS_INDEXING_MAX_BUFF_SIZE, &sps_cfg, TSPP2_DMX_INDEX_PIPE_BUFFER_SIZE, &sps_cfg, &pull_cfg, 1, ION_HEAP(tspp2_buff_heap), 0); if (ret) { Loading drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.h +8 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ #define TSPP2_DMX_SPS_SECTION_DESC_SIZE 188 /* size of TS packet */ #define TSPP2_DMX_SPS_PCR_DESC_SIZE 195 /* size of PCR packet */ #define TSPP2_DMX_SPS_INDEXING_DESC_SIZE 28 /* index entry size */ #define TSPP2_DMX_MIN_INDEXING_DESC_SIZE 24 /* partial index desc */ #define TSPP2_DMX_SPS_VPES_HEADER_DESC_SIZE (1 + 2*VPES_HEADER_DATA_SIZE) #define TSPP2_DMX_SPS_VPES_PAYLOAD_DESC_SIZE 2048 /* Video PES payload */ #define TSPP2_DMX_SPS_NON_VID_PES_DESC_SIZE 256 /* Non-Video PES */ Loading Loading @@ -130,6 +131,13 @@ #define PES_ASM_STATUS_SIZE_MISMATCH 0x04 #define PES_ASM_STATUS_TX_FAILED 0x08 /* * Indexing header pipe should contain no more headers than is possible * to report. */ #define TSPP2_DMX_INDEX_PIPE_BUFFER_SIZE \ (TSPP2_DMX_SPS_INDEXING_DESC_SIZE * DMX_EVENT_QUEUE_SIZE) #define INDEX_TABLE_PREFIX_LENGTH 3 #define INDEX_TABLE_PREFIX_VALUE 0x00000001 #define INDEX_TABLE_PREFIX_MASK 0x00FFFFFF Loading Loading
drivers/media/dvb-core/demux.h +3 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * Copyright (c) 2000 Nokia Research Center * Tampere, FINLAND * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License Loading Loading @@ -38,6 +38,8 @@ /* Common definitions */ /*--------------------------------------------------------------------------*/ #define DMX_EVENT_QUEUE_SIZE 500 /* number of events */ /* * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter. */ Loading
drivers/media/dvb-core/dmxdev.h +2 −3 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ * Copyright (C) 2000 Ralph Metzler & Marcus Metzler * for convergence integrated media GmbH * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License Loading Loading @@ -70,11 +70,10 @@ struct dmxdev_sec_feed { struct dmx_cipher_operations cipher_ops; }; #define DMX_EVENT_QUEUE_SIZE 500 /* number of events */ struct dmxdev_events_queue { /* * indices used to manage events queue. * read_index advanced when relevent data is read * read_index advanced when relevant data is read * from the buffer. * notified_index is the index from which next events * are returned. Loading
drivers/media/dvb-core/dvb_demux.h +3 −2 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler * for convergence integrated media GmbH * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License Loading Loading @@ -75,7 +75,8 @@ struct dmx_index_entry { struct list_head next; }; #define DMX_IDX_EVENT_QUEUE_SIZE 100 #define DMX_IDX_EVENT_QUEUE_SIZE DMX_EVENT_QUEUE_SIZE struct dvb_demux_rec_info { /* Reference counter for number of feeds using this information */ int ref_count; Loading
drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c +217 −107 Original line number Diff line number Diff line Loading @@ -3451,33 +3451,171 @@ static int mpq_dmx_tspp2_calc_tsp_num_delta( return tsp_num / (int)packet_size; } /** * mpq_dmx_tspp2_offset_in_range() - return whether some buffer offset is in * the given offsets range, taking wrap-around into consideration. * * @offset: offset to check * @from: range "left" boundary * @to: range "right"boundary * * Return true if offset is in range, false otherwise */ static bool mpq_dmx_tspp2_offset_in_range(u32 offset, u32 from, u32 to) { if (from <= to) return (offset >= from && offset < to); return !(offset >= to && offset < from); } /** * mpq_dmx_tspp2_match_after_pusi() - check if PUSI offset precedes the * TSP match offset in the recording chunk. * * @pusi: pusi tsp offset * @match: match tsp offset * @chunk_start: recording chunk start offset * @chunk_size: recording chunk size * @buffer_size: recording buffer size * * Return true if PUSI offset precedes match offset, false otherwise */ static bool mpq_dmx_tspp2_match_after_pusi(u32 pusi, u32 match, u32 chunk_start, size_t chunk_size, size_t buffer_size) { u32 end_offset = (chunk_start + chunk_size) % buffer_size; if ((chunk_start + chunk_size) >= buffer_size) { if ((pusi >= chunk_start && match >= chunk_start) || (pusi < end_offset && match < end_offset)) return (pusi <= match); return (pusi > match); } return (pusi <= match); } /** * mpq_dmx_tspp2_process_index_desc() - process one indexing descriptor * (descriptor might be partial) * * @feed: dvb_demux feed object * @rec_pipe: recording pipe info * @idx_desc: indexing descriptor to process * @rec_data_size: recording chunk size * @ts_pkt_size: TS packet size */ static void mpq_dmx_tspp2_process_index_desc(struct dvb_demux_feed *feed, struct pipe_info *rec_pipe, struct mpq_tspp2_index_desc *idx_desc, size_t rec_data_size, size_t ts_pkt_size) { struct dmx_index_event_info idx_event; struct mpq_tspp2_index_table *index_table; struct dvb_dmx_video_patterns_results pattern; u8 pattern_id; u8 table_id; int tsp_delta; u32 match_tsp_offset; u32 pusi_tsp_offset; u32 from = rec_pipe->tspp_write_offset; u32 to = (rec_pipe->tspp_write_offset + rec_data_size) % rec_pipe->buffer.size; /* Convert addresses in the indexing desc. from big-endian */ idx_desc->matched_tsp_addr = be32_to_cpu(idx_desc->matched_tsp_addr); idx_desc->pusi_tsp_addr = be32_to_cpu(idx_desc->pusi_tsp_addr); idx_desc->last_tsp_addr = 0; /* unused */ idx_event.pid = feed->pid; idx_event.stc = mpq_dmx_tspp2_get_stc(idx_desc->stc, 7); pattern_id = idx_desc->pattern_id & INDEX_DESC_PATTERN_ID_MASK; table_id = (idx_desc->pattern_id & INDEX_DESC_TABLE_ID_MASK) >> 5; index_table = &mpq_dmx_tspp2_info.index_tables[table_id]; idx_event.type = index_table->patterns[pattern_id].type; MPQ_DVB_DBG_PRINT( "%s: Index info: pattern_id=0x%x, pusi=0x%x, match=0x%x\n", __func__, idx_desc->pattern_id, idx_desc->pusi_tsp_addr, idx_desc->matched_tsp_addr); if (idx_desc->matched_tsp_addr && idx_desc->matched_tsp_addr != ULONG_MAX) { match_tsp_offset = idx_desc->matched_tsp_addr - ts_pkt_size + 1 - rec_pipe->buffer.iova; pusi_tsp_offset = idx_desc->pusi_tsp_addr - rec_pipe->buffer.iova; tsp_delta = mpq_dmx_tspp2_calc_tsp_num_delta( pusi_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_pkt_size); /* * PUSI address and match address are both in the chunk, * but if PUSI address is after the match address then * it is really from previous chunk. */ if (mpq_dmx_tspp2_offset_in_range(pusi_tsp_offset, from, to) && !mpq_dmx_tspp2_match_after_pusi(pusi_tsp_offset, match_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size)) idx_event.last_pusi_tsp_num = feed->rec_info->ts_output_count - ((rec_pipe->buffer.size / ts_pkt_size) - tsp_delta); else idx_event.last_pusi_tsp_num = feed->rec_info->ts_output_count + tsp_delta; idx_event.match_tsp_num = feed->rec_info->ts_output_count + mpq_dmx_tspp2_calc_tsp_num_delta( match_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_pkt_size); feed->last_pattern_tsp_num = idx_event.match_tsp_num; MPQ_DVB_DBG_PRINT( "%s: PUSI tsp num=%llu, Match tsp num=%llu (tsp_delta=%d)\n", __func__, idx_event.last_pusi_tsp_num, idx_event.match_tsp_num, tsp_delta); pattern.info[0].type = index_table->patterns[pattern_id].type; pattern.info[0].offset = 0; pattern.info[0].used_prefix_size = 0; dvb_dmx_process_idx_pattern(feed, &pattern, 0, idx_event.stc, 0, idx_event.match_tsp_num, 0, idx_event.last_pusi_tsp_num, 0); } } /** * mpq_dmx_tspp2_index_pipe_handler() - Handler for index pipe notifications * * @index_pipe: pipe_info for the indexing pipe * @rec_pipe: pipe_info for the recording payload pipe * @index_pipe: pipe_info for the indexing pipe * @ts_packet_size: Recording TS packet size * @event: Notification event type * @rec_data_size: Recording chunk size * @tspp_index_last_addr: Index pipe last write address sampled * * Return error status */ static int mpq_dmx_tspp2_index_pipe_handler(struct pipe_info *rec_pipe, struct pipe_info *index_pipe, u32 tspp_index_last_addr, size_t ts_packet_size, enum mpq_dmx_tspp2_pipe_event event, size_t rec_data_size) struct pipe_info *index_pipe, size_t ts_packet_size, enum mpq_dmx_tspp2_pipe_event event, size_t rec_data_size, u32 tspp_index_last_addr) { int i; struct dvb_demux_feed *feed; u32 num_desc; u32 desc_offset; struct dmx_index_event_info idx_event; u32 desc_leftover = 0; struct mpq_tspp2_feed *tspp2_feed; struct mpq_tspp2_index_desc index_desc; struct mpq_tspp2_index_table *index_table; struct dvb_dmx_video_patterns_results pattern; size_t data_size; u8 pattern_id; u8 table_id; if (!index_pipe->ref_count) { MPQ_DVB_ERR_PRINT( Loading @@ -3504,97 +3642,69 @@ static int mpq_dmx_tspp2_index_pipe_handler(struct pipe_info *rec_pipe, tspp2_feed = index_pipe->parent; feed = tspp2_feed->mpq_feed->dvb_demux_feed; /* Calculate new data in indexing pipe */ data_size = mpq_dmx_tspp2_calc_pipe_data(index_pipe, tspp_index_last_addr); index_pipe->tspp_last_addr = tspp_index_last_addr; index_pipe->tspp_write_offset += data_size; if (index_pipe->tspp_write_offset >= index_pipe->buffer.size) index_pipe->tspp_write_offset -= index_pipe->buffer.size; /* * Calculate total data to process, disregarding leftover from previous * partial descriptor that was processed. */ if (index_pipe->tspp_read_offset % TSPP2_DMX_SPS_INDEXING_DESC_SIZE) { desc_leftover = TSPP2_DMX_SPS_INDEXING_DESC_SIZE - index_pipe->tspp_read_offset % TSPP2_DMX_SPS_INDEXING_DESC_SIZE; if (desc_leftover <= data_size) mpq_dmx_release_data(index_pipe, desc_leftover); else return 0; } data_size = mpq_dmx_calc_fullness(index_pipe->tspp_write_offset, index_pipe->tspp_read_offset, index_pipe->buffer.size); if (data_size == 0) return 0; num_desc = data_size / TSPP2_DMX_SPS_INDEXING_DESC_SIZE; idx_event.pid = feed->pid; MPQ_DVB_DBG_PRINT("%s: TS output count=%llu, last_pusi_addr=0x%X\n", __func__, feed->rec_info->ts_output_count, tspp2_feed->last_pusi_addr); for (i = 0; i < num_desc; i++) { desc_offset = index_pipe->tspp_write_offset + i * TSPP2_DMX_SPS_INDEXING_DESC_SIZE; if (desc_offset >= index_pipe->buffer.size) desc_offset -= index_pipe->buffer.size; memcpy(&index_desc, index_pipe->buffer.mem + desc_offset, sizeof(index_desc)); /* Convert addresses in the indexing desc. from big-endian */ index_desc.matched_tsp_addr = be32_to_cpu(index_desc.matched_tsp_addr); index_desc.pusi_tsp_addr = be32_to_cpu(index_desc.pusi_tsp_addr); index_desc.last_tsp_addr = be32_to_cpu(index_desc.last_tsp_addr); idx_event.pid = feed->pid; idx_event.stc = mpq_dmx_tspp2_get_stc(index_desc.stc, 7); pattern_id = index_desc.pattern_id & INDEX_DESC_PATTERN_ID_MASK; table_id = (index_desc.pattern_id & INDEX_DESC_TABLE_ID_MASK) >> 5; index_table = &mpq_dmx_tspp2_info.index_tables[table_id]; idx_event.type = index_table->patterns[pattern_id].type; MPQ_DVB_DBG_PRINT( "%s: Index desc(#%d, offset=%u): id=0x%X(0x%llx), match TSP=0x%X, PUSI=0x%X, last TSP=0x%X\n", __func__, i, desc_offset, index_desc.pattern_id, idx_event.type, index_desc.matched_tsp_addr, index_desc.pusi_tsp_addr, index_desc.last_tsp_addr); if (index_desc.matched_tsp_addr) { u32 match_tsp_offset = index_desc.matched_tsp_addr - ts_packet_size + 1 - rec_pipe->buffer.iova; pattern_id = index_desc.pattern_id & INDEX_DESC_PATTERN_ID_MASK; idx_event.last_pusi_tsp_num = feed->rec_info->ts_output_count + mpq_dmx_tspp2_calc_tsp_num_delta( index_desc.pusi_tsp_addr - rec_pipe->buffer.iova, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_packet_size); idx_event.match_tsp_num = feed->rec_info->ts_output_count + mpq_dmx_tspp2_calc_tsp_num_delta( match_tsp_offset, rec_pipe->tspp_write_offset, rec_data_size, rec_pipe->buffer.size, ts_packet_size); feed->last_pattern_tsp_num = idx_event.match_tsp_num; "\n%s: TS output count=%llu, desc_data=%u, desc_leftover=%u\n", __func__, feed->rec_info->ts_output_count, data_size, desc_leftover); MPQ_DVB_DBG_PRINT( "%s: PUSI tsp num=%llu, Match tsp num=%llu\n", __func__, idx_event.last_pusi_tsp_num, idx_event.match_tsp_num); "%s: Recording chunk: from=%u, to=%u, size=%u\n\n", __func__, rec_pipe->tspp_write_offset, (rec_pipe->tspp_write_offset + rec_data_size) % rec_pipe->buffer.size, rec_data_size); pattern.info[0].type = index_table->patterns[pattern_id].type; pattern.info[0].offset = 0; pattern.info[0].used_prefix_size = 0; /* * Loop over the indexing descriptors and process each one. * The last descriptor might be a partial descriptor (24 bytes out of * 28 total) which does not contain the information where the frame/PES * ends, but we don't use this field anyway so we process it too. */ while (data_size >= TSPP2_DMX_MIN_INDEXING_DESC_SIZE) { memcpy(&index_desc, index_pipe->buffer.mem + index_pipe->tspp_read_offset, sizeof(index_desc)); dvb_dmx_process_idx_pattern(feed, &pattern, 0, idx_event.stc, 0, idx_event.match_tsp_num, 0, idx_event.last_pusi_tsp_num, 0); mpq_dmx_tspp2_process_index_desc(feed, rec_pipe, &index_desc, rec_data_size, ts_packet_size); /* * Descriptor was processed - advance the index pipe read offset */ if (data_size >= TSPP2_DMX_SPS_INDEXING_DESC_SIZE) { mpq_dmx_release_data(index_pipe, TSPP2_DMX_SPS_INDEXING_DESC_SIZE); data_size -= TSPP2_DMX_SPS_INDEXING_DESC_SIZE; } else { mpq_dmx_release_data(index_pipe, data_size); data_size = 0; } } index_pipe->tspp_last_addr = tspp_index_last_addr; index_pipe->tspp_write_offset += num_desc * TSPP2_DMX_SPS_INDEXING_DESC_SIZE; if (index_pipe->tspp_write_offset >= index_pipe->buffer.size) index_pipe->tspp_write_offset -= index_pipe->buffer.size; mpq_dmx_release_data(index_pipe, num_desc * TSPP2_DMX_SPS_INDEXING_DESC_SIZE); return 0; } Loading Loading @@ -3710,7 +3820,7 @@ static int mpq_dmx_tspp2_rec_pipe_handler(struct pipe_info *pipe_info, u32 tspp_last_addr; u32 tspp_index_last_addr; struct dmx_data_ready data; struct pipe_info *index_pipe = NULL; struct pipe_info *index_pipe = pipe_info->parent->secondary_pipe; int ret = 0; if (!pipe_info->ref_count || pipe_info->type != REC_PIPE) { Loading Loading @@ -3739,15 +3849,15 @@ static int mpq_dmx_tspp2_rec_pipe_handler(struct pipe_info *pipe_info, } /* * Sample indexing pipe before the recording pipe, to prevent indexing * reported on recorded data that will be sampled only in the next * iteration. * Sample indexing pipe before sampling the recording pipe. * This ensures indexing data refers to the current recording chunk, * or the previous recording chunk (as we might still miss indexing * descriptor that was written immediately after we sampled the pipe, * which will be processed in the next iteration). */ if (pipe_info->parent->secondary_pipe != NULL) { index_pipe = pipe_info->parent->secondary_pipe; if (index_pipe) tspp2_pipe_last_address_used_get(index_pipe->handle, &tspp_index_last_addr); } tspp2_pipe_last_address_used_get(pipe_info->handle, &tspp_last_addr); data_size = mpq_dmx_tspp2_calc_pipe_data(pipe_info, tspp_last_addr); Loading Loading @@ -3782,10 +3892,10 @@ static int mpq_dmx_tspp2_rec_pipe_handler(struct pipe_info *pipe_info, mpq_dmx_tspp2_index(feed, pipe_info, data_size, ts_packet_size); /* Handle HW indexing results */ if (index_pipe != NULL) if (index_pipe) mpq_dmx_tspp2_index_pipe_handler(pipe_info, index_pipe, tspp_index_last_addr, ts_packet_size, event, data_size); ts_packet_size, event, data_size, tspp_index_last_addr); /* * Limit indexing notification to the last TS packet in the Loading Loading @@ -4353,7 +4463,7 @@ static int mpq_dmx_tspp2_allocate_index_pipe(struct dvb_demux_feed *feed) } ret = mpq_dmx_init_out_pipe(mpq_demux, pipe_info, TSPP2_DMX_SPS_INDEXING_MAX_BUFF_SIZE, &sps_cfg, TSPP2_DMX_INDEX_PIPE_BUFFER_SIZE, &sps_cfg, &pull_cfg, 1, ION_HEAP(tspp2_buff_heap), 0); if (ret) { Loading
drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.h +8 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ #define TSPP2_DMX_SPS_SECTION_DESC_SIZE 188 /* size of TS packet */ #define TSPP2_DMX_SPS_PCR_DESC_SIZE 195 /* size of PCR packet */ #define TSPP2_DMX_SPS_INDEXING_DESC_SIZE 28 /* index entry size */ #define TSPP2_DMX_MIN_INDEXING_DESC_SIZE 24 /* partial index desc */ #define TSPP2_DMX_SPS_VPES_HEADER_DESC_SIZE (1 + 2*VPES_HEADER_DATA_SIZE) #define TSPP2_DMX_SPS_VPES_PAYLOAD_DESC_SIZE 2048 /* Video PES payload */ #define TSPP2_DMX_SPS_NON_VID_PES_DESC_SIZE 256 /* Non-Video PES */ Loading Loading @@ -130,6 +131,13 @@ #define PES_ASM_STATUS_SIZE_MISMATCH 0x04 #define PES_ASM_STATUS_TX_FAILED 0x08 /* * Indexing header pipe should contain no more headers than is possible * to report. */ #define TSPP2_DMX_INDEX_PIPE_BUFFER_SIZE \ (TSPP2_DMX_SPS_INDEXING_DESC_SIZE * DMX_EVENT_QUEUE_SIZE) #define INDEX_TABLE_PREFIX_LENGTH 3 #define INDEX_TABLE_PREFIX_VALUE 0x00000001 #define INDEX_TABLE_PREFIX_MASK 0x00FFFFFF Loading