对于无SDT的特殊码流需要构造一个假的SDT数据交给下面的PSI/SI解析模块。代码如下:
 
#ifdef FAKE_SDT
static bool isWaitingForSdt = false; //is waiting for sdt on scanning
static int  waitingCounter = 0;
#define SDT_TIMEOUT_VALUE 15000  //ms
#define WAIT_INTERVAL   1000   //ms
#define MAX_PROGRAM_NUMBERS     256
typedef struct
{
    int transport_stream_id;
    int total_programs;
    int program_numbers[MAX_PROGRAM_NUMBERS];
}PAT_Data;
static FROST_Thread *timeout_thread_id;
static PAT_Data  patData;
static void timeoutThread(void * params);
static void ConvertPat(unsigned char * buf);
static unsigned char * GetSdtSection(int * len);
#endif
 
 
在PAT拿到后,先解析它:
#ifdef FAKE_SDT
    if(isWaitingForSdt && fd_handle->pid == 0 && buf[0] == 0) //pat available
    {
        ConvertPat(buf);
    }
#endif
 
static void ConvertPat(unsigned char * buf)
{
    int section_len;
    section_len = (buf[1]&0x0f) * 256 + buf[2];
    patData.transport_stream_id = buf[3] * 256 + buf[4];
    patData.total_programs = 0;
    section_len -= 9; //length of valid data
    buf += 8;
    while(section_len > 0)
    {
        patData.program_numbers[patData.total_programs] = buf[0] * 256 + buf[1];
        if(patData.program_numbers[patData.total_programs] != 0) //not nit pid
        {
            patData.total_programs ++;
        }
        section_len -= 4;
        buf += 4;
    }
#if 0
    int i;
    for(i = 0; i < patData.total_programs; i ++)
    {
        printf("%d: %d\n", i + 1, patData.program_numbers[i]);
    }
#endif
}
 
isWaitingForSdt 是一个表示有没有真正的SDT的标志位,初始化为1,如果检测到有SDT表,那么它会被赋为0
 
#ifdef FAKE_SDT
    if(fd_handle->pid == 0x11)
    {
        isWaitingForSdt = false;
    }
#endif
 
为了不影响其他表的接受,我们另外创建了一个线程来做如下的事情:
#ifdef FAKE_SDT
static void timeoutThread(void * params)
{
    int i, len;
    ICE_FilterHandle * fd_handle;
    unsigned char * psect;
    for(;;)
    {
        if(isWaitingForSdt)
        {
            waitingCounter ++;
            if(waitingCounter >= SDT_TIMEOUT_VALUE/WAIT_INTERVAL)
            {
                 if(patData.total_programs > 0 && patData.total_programs < 200)
                 {
                    isWaitingForSdt = false;
                    psect = GetSdtSection(&len);
                    for (i=0; i < filter_number * NUMBER_OF_DEMUXES; i++)
                    {
                        if(i < filter_number)
                        {
                            fd_handle = &(filter_handle[0].fd_handle[i]);
                        }
                        else
                        {
                            fd_handle = &(filter_handle[1].fd_handle[i - filter_number]);
                        }
                        if(fd_handle->pid == 0x11) break;
                    }
                    if(i < filter_number * NUMBER_OF_DEMUXES)
                    {
                        FROST_MutexLock(fd_handle->callback_mutex);
                        if(fd_handle->allocated_bit)
                        {
                            frost_uint8 * buf = fd_handle->request_buffer(fd_handle->user_data, len);
                            if (!buf)
                            {
                                FROST_MutexUnlock(fd_handle->callback_mutex);
                                TRACE_ERROR(("Error: request buffer callback failed at time fake sdt\n"));
                                return;
                            }
                            memcpy(buf, psect, len);
                            nxpdvr_section_hook(fd_handle->pid, buf);
                            printf("fake sdt\n");
                            fd_handle->section_ready(fd_handle->user_data, fd_handle->pid, buf);
                        }
                        FROST_MutexUnlock(fd_handle->callback_mutex);
                    }
                 }
            }
        }
        FROST_Sleep(WAIT_INTERVAL);
    }
}
#endif
 
以下是构建SDT的函数:
#define original_network_id 0
static unsigned char * GetSdtSection(int * len)
{
 unsigned char * pc;
 int i;
 int section_length;
 char buf[10];
 int j;
 int descriptor_length;
 int descriptors_loop_length;
 unsigned char _sdt_section[4096];
 
 _sdt_section[0] = 0x42; //table_id
 section_length = 0;  //[1] [2] - section_length
 _sdt_section[3] = (unsigned char)(patData.transport_stream_id >> 8);
 _sdt_section[4] = (unsigned char)patData.transport_stream_id;
 _sdt_section[5] = 0xc1; // 11 00000 1
 _sdt_section[6] = 0; //section_number
 _sdt_section[7] = 0; //last_section_number
 //original_network_id
 _sdt_section[8] = (unsigned char)(original_network_id >> 8);
 _sdt_section[9] = (unsigned char)original_network_id;
 _sdt_section[10] = 0xff; //reserved future use
 pc = _sdt_section + 11;
 section_length += 8;
 for(i = 0; i < patData.total_programs; i ++)
 {
  int service_id;
  service_id = i + 1; //to adapt to program_number in pat
  pc[0] = (unsigned char)(service_id >> 8);
  pc[1] = (unsigned char)(service_id);
  pc[2] = 0xfc; //eit flag
  descriptors_loop_length = 13; //see below
  pc[3] = (unsigned char)(descriptors_loop_length >> 8);//[3] [4] descriptors_loop_length
  pc[3] |= 0x80;
  pc[4] = (unsigned char)descriptors_loop_length;
  
  pc += 5;
  section_length += 5;
  
  //service_descriptor
  pc[0] = 0x48; //descriptor_tag
   //[1] descriptor_length
  pc[2] = 0x01; //service_type
  pc[3] = 0; //service_provider_name_length
  pc[4] = 8; //service_name_length
  sprintf(buf, "noname%02d", (i + 1));
  for(j = 0; j < 8; j ++)
  {
   pc[5 + j] = buf[j];
  }
  descriptor_length = 11;
  pc[1] = (unsigned char)descriptor_length;
  pc += (descriptor_length + 2);
  section_length += (descriptor_length + 2);
 }
 section_length += 4; //for CRC32
 // printf("section_length = %d\n", section_length);
 _sdt_section[1] = (unsigned char)(section_length >> 8);
 _sdt_section[1] |= 0xB0;
 _sdt_section[2] = (unsigned char)section_length;
 *len = (section_length + 3);
 return _sdt_section;
}