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; #endif ts_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 */ /*创建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设计)
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 to specific 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 data from caller. Do not use from inside libdvbpsi. It will 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 a PAT 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 of the 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.