libdvbpsi源码分析(三)PSI decocder详细分析
生活随笔
收集整理的這篇文章主要介紹了
libdvbpsi源码分析(三)PSI decocder详细分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
????????由上一篇 libdvbpsi源碼分析(二)main函數,簡單分析了demo程序中main函數的執行流程?,F在將對具體的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
- 下一篇: ubuntu snmp Error: u