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;
#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。
/* 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 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.