libdvbpsi源码分析(三)PSI decocder详细分析
生活随笔
收集整理的这篇文章主要介绍了
libdvbpsi源码分析(三)PSI decocder详细分析
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
2019独角兽企业重金招聘Python工程师标准>>>
由上一篇 libdvbpsi源码分析(二)main函数,简单分析了demo程序中main函数的执行流程。现在将对具体的PSI表作详细解析。主要是对main函数中的libdvbpsi_init和dvbpsi_new以及相关的dvbpsi_pat_attach作相关分析。1.创建PSI decoders
ts_stream_t *libdvbpsi_init(int debug, ts_stream_log_cb pf_log, void *cb_data) 将每张table表的数据各自抽象成specific decoder(ts_xxx_t),最后封装成通用的universal decoder即:ts_stream_t
struct ts_stream_t {/* Program Association Table */ts_pat_t pat;/* Program Map Table */int i_pmt;ts_pmt_t *pmt;/* Conditional Access Table */ts_cat_t cat;#ifdef TS_USE_SCTE_SIS/* Splice Information Section */ts_sis_t sis; #endifts_rst_t rst;/* Subbtables */ts_sdt_t sdt;ts_eit_t eit;ts_tdt_t tdt;/* pid */ts_pid_t pid[8192];enum dvbpsi_msg_level level;/* statistics */uint64_t i_packets;uint64_t i_null_packets;uint64_t i_lost_bytes;/* logging */ts_stream_log_cb pf_log;void *cb_data; }; 其中,libdvbpsi_init创建了一个整体的decoder,它由各个具体的specific decoder构成。代码展开如下:
ts_stream_t *libdvbpsi_init(int debug, ts_stream_log_cb pf_log, void *cb_data) {ts_stream_t *stream = (ts_stream_t *)calloc(1, sizeof(ts_stream_t));if (stream == NULL)return NULL;if (pf_log){stream->pf_log = pf_log;stream->cb_data = cb_data;}/* print PSI tables debug anyway, unless no debug is wanted at all */switch (debug){case 0: stream->level = DVBPSI_MSG_NONE; break;case 1: stream->level = DVBPSI_MSG_ERROR; break;case 2: stream->level = DVBPSI_MSG_WARN; break;case 3: stream->level = DVBPSI_MSG_DEBUG; break;}/* PAT *//*创建dvbpsi handle structure*/stream->pat.handle = dvbpsi_new(&dvbpsi_message, stream->level);if (stream->pat.handle == NULL)goto error;/*初始化PAT decoder 并且将handle_PAT(callback) 绑定到pat decoder*/if (!dvbpsi_pat_attach(stream->pat.handle, handle_PAT, stream)){dvbpsi_delete(stream->pat.handle);stream->pat.handle = NULL;goto error;}/* CAT */stream->cat.handle = dvbpsi_new(&dvbpsi_message, stream->level);if (stream->cat.handle == NULL)goto error;if (!dvbpsi_cat_attach(stream->cat.handle, handle_CAT, stream)){dvbpsi_delete(stream->cat.handle);stream->cat.handle = NULL;goto error;}/* SDT demuxer */stream->sdt.handle = dvbpsi_new(&dvbpsi_message, stream->level);if (stream->sdt.handle == NULL)goto error;if (!dvbpsi_AttachDemux(stream->sdt.handle, handle_subtable, stream)){dvbpsi_delete(stream->sdt.handle);stream->sdt.handle = NULL;goto error;}/* RST */stream->rst.handle = dvbpsi_new(&dvbpsi_message, stream->level);if (stream->rst.handle == NULL)goto error;if (!dvbpsi_rst_attach(stream->rst.handle, handle_RST, stream)){dvbpsi_delete(stream->rst.handle);stream->rst.handle = NULL;goto error;}/* EIT demuxer */stream->eit.handle = dvbpsi_new(&dvbpsi_message, stream->level);if (stream->eit.handle == NULL)goto error;if (!dvbpsi_AttachDemux(stream->eit.handle, handle_subtable, stream)){dvbpsi_delete(stream->eit.handle);stream->eit.handle = NULL;goto error;}/* TDT demuxer */stream->tdt.handle = dvbpsi_new(&dvbpsi_message, stream->level);if (stream->tdt.handle == NULL)goto error;if (!dvbpsi_AttachDemux(stream->tdt.handle, handle_subtable, stream)){dvbpsi_delete(stream->tdt.handle);stream->tdt.handle = NULL;goto error;}stream->pat.pid = &stream->pid[0x00];stream->cat.pid = &stream->pid[0x01];stream->sdt.pid = &stream->pid[0x11];stream->eit.pid = &stream->pid[0x12];stream->rst.pid = &stream->pid[0x13];stream->tdt.pid = &stream->pid[0x14];return stream;error:if (dvbpsi_decoder_present(stream->pat.handle))dvbpsi_pat_detach(stream->pat.handle);if (dvbpsi_decoder_present(stream->cat.handle))dvbpsi_cat_detach(stream->cat.handle);if (dvbpsi_decoder_present(stream->sdt.handle))dvbpsi_DetachDemux(stream->sdt.handle);if (dvbpsi_decoder_present(stream->eit.handle))dvbpsi_DetachDemux(stream->eit.handle);if (dvbpsi_decoder_present(stream->rst.handle))dvbpsi_rst_detach(stream->rst.handle);if (dvbpsi_decoder_present(stream->tdt.handle))dvbpsi_DetachDemux(stream->tdt.handle);if (stream->pat.handle)dvbpsi_delete(stream->pat.handle);if (stream->cat.handle)dvbpsi_delete(stream->cat.handle);if (stream->sdt.handle)dvbpsi_delete(stream->sdt.handle);if (stream->rst.handle)dvbpsi_delete(stream->rst.handle);if (stream->eit.handle)dvbpsi_delete(stream->eit.handle);if (stream->tdt.handle)dvbpsi_delete(stream->tdt.handle);free(stream);return NULL; } 2.PAT表的解析
由于每个表的具体解析流程都是相似的,所以选取其中一个做典型分析。比如PAT。
/* PAT */ /*创建dvbpsi handle structure*/ stream->pat.handle = dvbpsi_new(&dvbpsi_message, stream->level); if (stream->pat.handle == NULL)goto error;/*初始化PAT decoder 并且将handle_PAT(callback) 绑定到pat decoder*/ if (!dvbpsi_pat_attach(stream->pat.handle, handle_PAT, stream)) {dvbpsi_delete(stream->pat.handle);stream->pat.handle = NULL;goto error; } 2.1.pat表的sepecfic decoder的抽象(也就是它的struct设计)
ts_pat_t:
typedef struct {dvbpsi_t *handle; int i_pat_version;int i_ts_id;ts_pid_t *pid; } ts_pat_t; dvbpsi_t:
struct dvbpsi_s {dvbpsi_decoder_t *p_decoder; /*!< private pointer tospecific decoder *//* Messages callback */dvbpsi_message_cb pf_message; /*!< Log message callback */enum dvbpsi_msg_level i_msg_level; /*!< Log level *//* private data pointer for use by caller, not by libdvbpsi itself ! */void *p_sys; /*!< pointer to private datafrom caller. Do not usefrom inside libdvbpsi. Itwill crash any application. */ }; dvbpsi_decoder_t:
struct dvbpsi_decoder_s {DVBPSI_DECODER_COMMON };/*实质上宏替换展开,则dvbpsi_decoder_t如下所示*/dvbpsi_decoder_t{uint8_t i_magic[3]; /*!< Reserved magic value */ bool b_complete_header; /*!< Flag for header completion */ bool b_discontinuity; /*!< Discontinuity flag */ bool b_current_valid; /*!< Current valid indicator */ uint8_t i_continuity_counter; /*!< Continuity counter */ uint8_t i_last_section_number;/*!< Last received section number */ dvbpsi_psi_section_t *p_current_section; /*!< Current section */ dvbpsi_psi_section_t *p_sections; /*!< List of received PSI sections */ dvbpsi_callback_gather_t pf_gather;/*!< PSI decoder's callback */ int i_section_max_size; /*!< Max size of a section for this decoder */ int i_need; /*!< Bytes needed */ } dvbpsi_psi_section_t:
struct dvbpsi_psi_section_s {/* non-specific section data */uint8_t i_table_id; /*!< table_id */bool b_syntax_indicator; /*!< section_syntax_indicator */bool b_private_indicator; /*!< private_indicator */uint16_t i_length; /*!< section_length *//* used if b_syntax_indicator is true */uint16_t i_extension; /*!< table_id_extension *//*!< transport_stream_id for aPAT section */uint8_t i_version; /*!< version_number */bool b_current_next; /*!< current_next_indicator */uint8_t i_number; /*!< section_number */uint8_t i_last_number; /*!< last_section_number *//* non-specific section data *//* the content is table-specific */uint8_t * p_data; /*!< complete section */uint8_t * p_payload_start; /*!< payload start */uint8_t * p_payload_end; /*!< payload end *//* used if b_syntax_indicator is true */uint32_t i_crc; /*!< CRC_32 *//* list handling */struct dvbpsi_psi_section_s * p_next; /*!< next element ofthe list */ }; dvbpsi_psi_section_t结构体的设计,是根据标准ISO/IEC 13818-1 section 2.4.4.11协议如下表 private section所示:
table1: private section
由上述可知,用面向对象的思想来看,其继承关系是:
dvbpsi_psi_section_t<--dvbpsi_pat_decoder_t<--dvbpsi_decoder_t<--dvbpsi_t<--ts_pat_t<--ts_stream_t.
转载于:https://my.oschina.net/mavericsoung/blog/175574
总结
以上是生活随笔为你收集整理的libdvbpsi源码分析(三)PSI decocder详细分析的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 设计模式学习系列9 外观模式Facade
- 下一篇: Hbase shell 常用命令