libdvbpsi源码分析(三)PSI decocder详细分析

        由上一篇 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;
#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所示:
libdvbpsi源码分析(三)PSI decocder详细分析_第1张图片

                                            table1: private section

由上述可知,用面向对象的思想来看,其继承关系是:
dvbpsi_psi_section_t<--dvbpsi_pat_decoder_t<--dvbpsi_decoder_t<--dvbpsi_t<--ts_pat_t<--ts_stream_t.


你可能感兴趣的:(decoder,libdvbpsi,PSI)