对于无SDT的特殊码流需要构造一个假的SDT数据交给下面的PSI/SI解析模块。代码如下:
#ifdef FAKE_SDT
static bool isWaitingForSdt = false; //is waiting for sdt on scanning
static int waitingCounter = 0;
static int waitingCounter = 0;
#define SDT_TIMEOUT_VALUE 15000 //ms
#define WAIT_INTERVAL 1000 //ms
#define MAX_PROGRAM_NUMBERS 256
#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;
{
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 PAT_Data patData;
static void timeoutThread(void * params);
static void ConvertPat(unsigned char * buf);
static unsigned char * GetSdtSection(int * len);
#endif
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
if(isWaitingForSdt && fd_handle->pid == 0 && buf[0] == 0) //pat available
{
ConvertPat(buf);
}
#endif
static void ConvertPat(unsigned char * buf)
{
int section_len;
{
int section_len;
section_len = (buf[1]&0x0f) * 256 + buf[2];
patData.transport_stream_id = buf[3] * 256 + buf[4];
patData.total_programs = 0;
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
}
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
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);
}
}
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;
}
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;
}