#include "DST_Parser.h" #define DHL_FAIL_NULL_POINTER 0x02 #define DHL_FAIL_INVALID_SIZE 0x07 #define DHL_FAIL_INVALID_PARAM 0x08 #define DHL_FAIL_OUT_OF_RESOURCE 0x0A #define DHL_FAIL_INVALID_TABLEID 0x23 #define DHL_FAIL_INVALID_VERSION 0x24 #ifndef SysASSERT #ifdef DTAR #define SysASSERT(cond) do { if (!((cond)) { fprintf(stderr, "|%s:%d| ASSERT failed.\n", __FUNCTION__, __LINE__); } } while(0) #else #define SysASSERT(cond) #endif #endif #define checkMemoryError(p) if (p == 0) {err = DHL_FAIL_OUT_OF_RESOURCE ; goto ParseExit;} #if 0 ____MEM_CHAIN____() #endif typedef struct memElement { void* userData; struct memElement *next; } memElement_t, *memElementPtr_t; typedef struct memChainHead { memElementPtr_t element; } memChainHead_t, *memChainHeadPtr_t; typedef struct memChainHead* memId_t; /* API */ #define memChainCreate(a) _memChainCreate((a), __func__, __LINE__) #define memChainDestroy(a) _memChainDestroy((a), __func__, __LINE__) #define memChainAlloc(a, b) _memChainAlloc((a), (b), __func__, __LINE__) static int _memChainCreate (memId_t *memId, const char *func, int nLine) { if (memId == 0) return DHL_FAIL_INVALID_PARAM; memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)_DST_OS_Calloc(sizeof(memChainHead_t), 1, func, nLine); if (memChainHeadPtr == 0) return DHL_FAIL_OUT_OF_RESOURCE; memChainHeadPtr->element = 0; *memId = memChainHeadPtr; /* set instance */ return 0; } static void _memChainDestroy (memId_t memId, const char *func, int nLine) { if (!memId) return; memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)memId; /* free the memElements */ memElementPtr_t currElem = memChainHeadPtr->element; while (currElem != 0) { memElementPtr_t prevElem = currElem; currElem = currElem->next; _DST_OS_Free(prevElem , func, nLine); } /* lastly, free the memChainHead */ _DST_OS_Free(memChainHeadPtr , func, nLine); } static void* _memChainAlloc (memId_t memId, DS_U32 size, const char *func, int nLine) { memElementPtr_t memElementPtr = (memElementPtr_t)_DST_OS_Calloc(sizeof(memElement_t) + size + 8, 1, func, nLine); if (memElementPtr == 0) return 0; void *p = (void *)(((DS_U8 *)(memElementPtr) + sizeof(memElement_t))); /* align on 64-bit boundary */ memElementPtr->userData = (void *)((DS_U32)(((DS_U8 *)p)+8) & ((~0) << 3)); void *rptr = memElementPtr->userData; /* insert element in list */ memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)memId; memElementPtr->next = memChainHeadPtr->element; memChainHeadPtr->element = memElementPtr; return (rptr); } #if 0 ____PAT____() #endif int DHL_PSI_ParsePAT( DS_U8 **sectionArr, MPEG_PAT **returnPat) { if (sectionArr == 0 || sectionArr[0] == 0 || returnPat == 0) return (DHL_FAIL_NULL_POINTER); int numSections = get_last_section_number(sectionArr[0]) + 1; /* now verify all other sections are present */ int i; for ( i = 1; i < numSections; i++) if (sectionArr[i] == 0) return (DHL_FAIL_NULL_POINTER); int numPrograms = 0; int err = 0; for ( i = 0; i < numSections; ++i) { DS_U8 *p = sectionArr[i]; if (p[SECTION_TID] != PROGRAM_ASSOCIATION_SECTION) { //This thing isn't a PAT. Stop right here. if (0) DST_Printf("PAT: Bad table ID."); err = DHL_FAIL_INVALID_TABLEID; break; } if ((p[SECTION_LEN_HI] & 0x80) != 0x80) { if (0) DST_Printf("PAT: section_syntax_indicator not set"); } if ((p[SECTION_LEN_HI] & 0x40) != 0x00) { if (0) DST_Printf("PAT: private_indicator set"); } if (i > p[SECTION_NUM_LAST]) { if (0) DST_Printf("PAT: last_section_number > section_number"); } /* * The PAT has a fixed number of bytes in its main loop with no * descriptors. We have the standard 8 byte header and the trailing * 4 byte CRC. The rest should be an integral number of programs. */ int len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; if (len < 16 || (len - 12) % 4 != 0) { if (0) DST_Printf("PAT: Inappropriate section length(%d)\n",len); //LEON_20050916 | ADD for add patch // - hangup when input abnormal PAT section. err = DHL_FAIL_INVALID_TABLEID; break; } int slots = (len - 12) / 4; p += SECTION_HEADER_LENGTH; int j; for (j = 0; j < slots; ++j, p += 4) { int program_number = (p[0] << 8) + p[1]; if (program_number != 0) { numPrograms++; } } } if (err) return err; /* create the memChain */ memId_t memId = 0; err = memChainCreate(&memId); if (err) return err; MPEG_PAT *pat = (MPEG_PAT *)((memId_t *)(memChainAlloc(memId,sizeof(MPEG_PAT)+sizeof(memId_t))) + 1); if (pat == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } pat->programs = (MPEG_PAT_program *)memChainAlloc(memId,sizeof(MPEG_PAT_program)*numPrograms); if (pat->programs == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } pat->section_number = 0; pat->last_section_number = 0; pat->isWholePAT = true; /* * Second pass, we fill in the table. * We assume that everything we verified or warned about above is still * true. We already bailed out on fatal errors */ int index = 0; for ( i = 0; i < numSections; ++i) { DS_U8 *p = sectionArr[i]; int len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; int transport_stream_id = ((p[SECTION_TID_EXT_HI] << 8) | p[SECTION_TID_EXT_LO]); int version_number = (p[SECTION_VERSION] & SECTION_VERSION_MASK) >> SECTION_VERSION_SHIFT; bool current_next_indicator = (p[SECTION_VERSION] & SECTION_CNI_MASK) != 0; if (i == 0) { pat->transport_stream_id = transport_stream_id; pat->version_number = version_number; pat->current_next_indicator = current_next_indicator; } else { if (pat->transport_stream_id != transport_stream_id) { if (0) DST_Printf("PAT: Inconsistent transport_stream_id"); } if(pat->version_number != version_number) { if (0) DST_Printf("ParsePAT: inconsistent version_number"); } if(pat->current_next_indicator != current_next_indicator) { if (0) DST_Printf("ParsePAT: inconsistent current_next_indicator"); } } int slots = (len - 12) / 4; p += SECTION_HEADER_LENGTH; int j; for ( j = 0; j < slots; ++j, p += 4) { int program_number = (p[0]<<8) + p[1]; int pid = ((p[2]<<8) + p[3]) & PID_MASK; if (program_number == 0) { if (pat->networkPIDPresent) { if (0) DST_Printf("PAT: More than one network_PID"); } else { pat->networkPIDPresent = true; pat->network_PID = pid; } } else { bool bDuplicate = false; int k; for ( k = 0; k < index; ++k) { if (pat->programs[k].program_number != program_number) continue; if (0) DST_Printf("PAT: Duplicate program number"); bDuplicate = true; break; } if (bDuplicate == false) { pat->programs[index].program_number = program_number; pat->programs[index].program_map_PID = pid; index++; } } } } pat->numPrograms = index; *(((memId_t *)pat)-1) = memId; *returnPat = pat; return(err); } #if 0 ____SDT____() #endif static int GetMpegDescriptor (DS_U8 *descriptors, DS_U16 len, DS_U8 tag, DS_U16 instance, DS_U8 **descriptor) { if (descriptors == 0 || len == 0 || descriptor == 0) return DHL_FAIL_INVALID_PARAM; DS_U16 nCount = 0; int nPos = 0; while (nPos < len) { DS_U8 nTag = descriptors[nPos]; DS_U8 nLen = descriptors[nPos+1]; if (nPos + nLen + 2 > len) break; // ÀԷµȵ¥ÀÌÅÍÀÇ ¹üÀ§¸¦ ¹ù¾î³ª µ¥ÀÌÅͰ¡ Àִ°æ¿ì if (nTag == tag) { if (nCount == instance) { *descriptor = &descriptors[nPos]; return 0; } nCount++; } nPos += (nLen + 2); } return DHL_FAIL_INVALID_PARAM; } static int GetMpegDescriptorCount (DS_U8 *descriptors, DS_U16 len, DS_U8 tag) { if (descriptors == 0 || len == 0) return 0; int nCount = 0; int nPos = 0; while (nPos < len) { DS_U8 nTag = descriptors[nPos]; DS_U8 nLen = descriptors[nPos+1]; if (nPos + nLen + 2 > len) break; // ÀԷµȵ¥ÀÌÅÍÀÇ ¹üÀ§¸¦ ¹ù¾î³ª µ¥ÀÌÅͰ¡ Àִ°æ¿ì if (nTag == tag) nCount++; nPos += (nLen + 2); } return nCount; } static void DHL_PSI_ParseServiceDescriptor(DS_U8 *p_desc, memId_t memId, dvb_service_descriptor_t **pp_service_desc) { if ( !p_desc || !pp_service_desc ) return; dvb_service_descriptor_t *p_service = (dvb_service_descriptor_t *)memChainAlloc(memId, sizeof(dvb_service_descriptor_t)); p_service->service_type = p_desc[2]; p_service->i_provider_name_length = p_desc[3]; p_service->p_provider_name = 0; if (p_service->i_provider_name_length) { p_service->p_provider_name = (DS_U8 *)memChainAlloc(memId, p_service->i_provider_name_length); memcpy( p_service->p_provider_name, &p_desc[4], p_service->i_provider_name_length ); } p_service->i_service_name_length = p_desc[4+p_service->i_provider_name_length]; p_service->p_service_name = 0; if (p_service->i_service_name_length) { p_service->p_service_name = (DS_U8 *)memChainAlloc(memId, p_service->i_service_name_length); memcpy( p_service->p_service_name, &p_desc[5+p_service->i_provider_name_length], p_service->i_service_name_length ); } *pp_service_desc = p_service; } static void DHL_PSI_ParseLogoTransmissionDescriptor( DS_U8 *p, memId_t memId, arib_logo_transmission_descriptor_t **pp_logo_transmission ) { DS_U8 len = p[1]; if (len < 2) return; arib_logo_transmission_descriptor_t *p_logo_transmission = (arib_logo_transmission_descriptor_t *)memChainAlloc(memId, sizeof(arib_logo_transmission_descriptor_t)); p_logo_transmission->logo_transmission_type = p[2]; switch (p_logo_transmission->logo_transmission_type) { case 0x01: p_logo_transmission->logo_id = (( p[3] & 0x1 ) << 8 ) + p[4]; p_logo_transmission->logo_version = (( p[5] & 0x7 ) << 8 ) + p[6]; p_logo_transmission->download_data_id = ( p[7] << 8 ) + p[8]; break; case 0x02: p_logo_transmission->logo_id = (( p[3] & 0x1 ) << 8 ) + p[4]; break; case 0x03: p_logo_transmission->logo_char = (DS_U8 *)memChainAlloc(memId, len-1); memcpy(p_logo_transmission->logo_char, &p[3], len-2); p_logo_transmission->logo_char[len-2] = 0; // make null terminate break; } *pp_logo_transmission = p_logo_transmission; } int DHL_PSI_ParseDvbSdt(DS_U8 **sectionArr, bool b_actual, dvb_sdt_t **pp_sdt) { if (!sectionArr || !pp_sdt || !sectionArr[0]) return DHL_FAIL_NULL_POINTER; int numSections = get_last_section_number(sectionArr[0]) + 1; /* now verify all other sections are present */ int i; for ( i = 1; i < numSections; i++) if (sectionArr[i] == 0) return DHL_FAIL_NULL_POINTER; // First pass, we verify section syntax and count the number of programs int numChannels = 0; for ( i = 0; i < numSections; ++i) { DS_U8 *p = sectionArr[i]; if ( (b_actual && p[SECTION_TID] != DVB_TID_service_description_section_actual) || (!b_actual && p[SECTION_TID] != DVB_TID_service_description_section_other) ) { if (0) DST_Printf("SDT: Bad table ID. (0x%02X)\n", p[SECTION_TID]); return DHL_FAIL_INVALID_TABLEID; } if ((p[SECTION_LEN_HI] & 0x80) != 0x80) if (0) DST_Printf("SDT: section_syntax_indicator not set\n"); int len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3 - 4; // + header - crc int nPos = 11; while (len - nPos >= 5) { numChannels++; DS_U16 descriptor_length = ((p[nPos+3]<<8)+p[nPos+4]) & 0xFFF; nPos += (descriptor_length + 5); } } /* create the memChain */ memId_t memId = 0; if (memChainCreate(&memId)) return DHL_FAIL_OUT_OF_RESOURCE; dvb_sdt_t *p_sdt = (dvb_sdt_t *)((memId_t *)(memChainAlloc(memId,sizeof(dvb_sdt_t)+sizeof(memId_t))) + 1); if (!p_sdt) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } p_sdt->numServices = numChannels; p_sdt->services = 0; if (numChannels) { p_sdt->services = (dvb_sdt_service_t *)memChainAlloc(memId,sizeof(dvb_sdt_service_t)*numChannels); if (!p_sdt->services) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } } // Now fill-out all the remaining fields over the all sections. int index = 0; // int i; for ( i = 0; i < numSections; ++i) { DS_U8 *p = sectionArr[i]; if (i == 0) /* First section */ { p_sdt->transport_stream_id = ((p[SECTION_TID_EXT_HI] << 8) | p[SECTION_TID_EXT_LO]); p_sdt->version_number = (p[SECTION_VERSION] & SECTION_VERSION_MASK) >> SECTION_VERSION_SHIFT; p_sdt->original_network_id = ((p[8]<<8) + p[9]); p_sdt->section_number = p[SECTION_NUM]; p_sdt->last_section_number = p[SECTION_NUM_LAST]; } int len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3 - 4;// + header - crc int nPos = 11; while (len - nPos >= 5) { dvb_sdt_service_t *p_service = &p_sdt->services[index]; p_service->service_id = ((p[nPos+0]<<8)+p[nPos+1]); p_service->EIT_user_defined_flags = (p[nPos+2]>>2) & 0x07; p_service->EIT_schedule_flag = (p[nPos+2] & 0x02) ? true : false; p_service->EIT_present_following_flag = (p[nPos+2] & 0x01) ? true : false; p_service->running_status = (p[nPos+3]>>5) & 0x07; p_service->free_CA_mode = ((p[nPos+3]>>4) & 0x01) ? true : false; p_service->descriptor_length = ((p[nPos+3]<<8)+p[nPos+4]) & 0xFFF; p_service->descriptors = 0; if (p_service->descriptor_length) { p_service->descriptors = (DS_U8 *)memChainAlloc( memId, p_service->descriptor_length); if (!p_service->descriptors) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } memcpy(p_service->descriptors, &p[nPos+5], p_service->descriptor_length); } DS_U8* p_desc = 0; int err=GetMpegDescriptor(p_service->descriptors, p_service->descriptor_length, DVB_TAG_service_descriptor, 0, &p_desc); p_service->p_service_desc = 0; if ( p_desc && err == 0 ) DHL_PSI_ParseServiceDescriptor( p_desc, memId, &(p_service->p_service_desc) ); // Parse service_descriptor if available. p_desc = 0; err=GetMpegDescriptor( p_service->descriptors, p_service->descriptor_length, ARIB_TAG_logo_transmission_descriptor, 0, &p_desc ); p_service->logo_tx_desc = 0; if ( p_desc && err == 0 ) DHL_PSI_ParseLogoTransmissionDescriptor( p_desc, memId, &(p_service->logo_tx_desc) ); index++; nPos += (p_service->descriptor_length + 5); } } *(((memId_t *)p_sdt)-1) = memId; *pp_sdt = p_sdt; return 0; } void DHL_PSI_FreeMpegSection (void *sectionPtr) { if (sectionPtr) memChainDestroy(*(((memId_t *)sectionPtr)-1)); } void DHL_PSI_ParseNetworkNameDescriptor(DS_U8 *p_desc, memId_t memId, DS_U8 **pp_network_name, DS_U8 *p_length) { if (!p_desc || !pp_network_name || !p_length) return; *p_length = p_desc[1]; *pp_network_name = (DS_U8 *)memChainAlloc( memId, *p_length); memcpy(*pp_network_name, &p_desc[2], *p_length); } static int DHL_PSI_ParseSystemManagementDescriptor(DS_U8* p, DS_U16* p_system_management_id) { if (!p_system_management_id || !p || p[1] < 2) return -1; *p_system_management_id = (p[2]<<8) + p[3]; return 0; } static void DHL_PSI_ParseServiceListDescriptor(DS_U8 *p_desc, memId_t memId, dvb_service_list_descriptor_t **pp_service_list) { (*pp_service_list) = 0; if (p_desc[1] < 3) return; (*pp_service_list) = (dvb_service_list_descriptor_t *)memChainAlloc(memId, sizeof(dvb_service_list_descriptor_t)); (*pp_service_list)->numServices = p_desc[1]/3; (*pp_service_list)->p_service = (dvb_service_t *)memChainAlloc(memId, sizeof(dvb_service_t)*((*pp_service_list)->numServices)); int i; for ( i=0; i < (*pp_service_list)->numServices; i++) { (*pp_service_list)->p_service[i].service_id = (p_desc[i*3+2] << 8) + p_desc[i*3+3]; (*pp_service_list)->p_service[i].service_type = p_desc[i*3+4]; } } static int DHL_PSI_ParseTSInformationDescriptor(DS_U8* p, memId_t memId, arib_ts_information_descriptor_t **pp_ts_info) { if (p[1] < 2) return DHL_FAIL_INVALID_SIZE; arib_ts_information_descriptor_t *p_ts_info = *pp_ts_info = (arib_ts_information_descriptor_t *)memChainAlloc(memId,sizeof(arib_ts_information_descriptor_t)); p_ts_info->remote_control_key_id = p[2]; p_ts_info->ts_name_length = (p[3]>>2) & 0x3F; p_ts_info->transmission_type_count = p[3]&0x03; if (p_ts_info->ts_name_length) { p_ts_info->ts_name = (DS_U8 *)memChainAlloc(memId, p_ts_info->ts_name_length); memcpy(p_ts_info->ts_name, &p[4], p_ts_info->ts_name_length); } if (!p_ts_info->transmission_type_count) return 0; arib_transmission_type_t *p_tx_type = p_ts_info->transmission_type = (arib_transmission_type_t *)memChainAlloc(memId, sizeof(arib_transmission_type_t)*p_ts_info->transmission_type_count); int off = 4 + p_ts_info->ts_name_length; int i; for ( i=0; i < p_ts_info->transmission_type_count; i++) { p_tx_type[i].transmission_type_info = p[off]; p_tx_type[i].number_of_service = p[off+1]; p_tx_type[i].service_id = 0; off += 2; if (p_tx_type[i].number_of_service) { DS_U16 *p_service_id = p_tx_type[i].service_id = (DS_U16 *)memChainAlloc(memId, (p_tx_type[i].number_of_service) * sizeof(DS_U16)); int j; for ( j=0; j num_transport_stream = numStreams; if (numStreams) { p_nit->transport_streams = (transport_stream_t *)memChainAlloc(memId,sizeof(transport_stream_t)*numStreams); if (!p_nit->transport_streams) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } } // Now fill-out all the remaining fields over the all sections. transport_stream_t *p_ts = p_nit->transport_streams; for ( i = 0; i < numSections; ++i) { DS_U8* p = sectionArr[i]; int network_id = ((p[SECTION_TID_EXT_HI] << 8) | p[SECTION_TID_EXT_LO]); int version_number = (p[SECTION_VERSION] & SECTION_VERSION_MASK) >> SECTION_VERSION_SHIFT; int network_descriptor_length = ((p[8]<<8) + p[9]) & 0xFFF; int last_section_number = p[SECTION_NUM_LAST]; if (i == 0) /* First section */ { p_nit->network_id = network_id; p_nit->version_number = version_number; p_nit->section_number = p[SECTION_NUM]; p_nit->last_section_number = last_section_number; p_nit->network_descriptor_length = network_descriptor_length; if (network_descriptor_length) { DS_U8 *p_desc = 0; p_nit->network_descriptors = (DS_U8 *)memChainAlloc(memId, network_descriptor_length); memcpy(p_nit->network_descriptors, &p[10], network_descriptor_length); int err=GetMpegDescriptor(p_nit->network_descriptors, network_descriptor_length, DVB_TAG_network_name_descriptor, 0, &p_desc); if (!err) DHL_PSI_ParseNetworkNameDescriptor( p_desc, memId, &(p_nit->p_network_name), &(p_nit->network_name_length) ); err=GetMpegDescriptor( p_nit->network_descriptors, network_descriptor_length, ARIB_TAG_system_management_descriptor, 0, &p_desc ); if (!err) { if (!DHL_PSI_ParseSystemManagementDescriptor( p_desc, &p_nit->system_management_id )) p_nit->b_system_management_id = true; } } } int transport_loop_length = ((p[10+network_descriptor_length]<<8) + p[11+network_descriptor_length]) & 0xFFF; p = §ionArr[i][12+network_descriptor_length]; int k; for( k=0; k < transport_loop_length; ) { int original_network_id = ((p[k+2]<<8)+p[k+3]); int transport_descriptor_length = ((p[k+4]<<8)+p[k+5]) & 0xFFF; if (original_network_id) { p_ts->transport_stream_id = ((p[k+0]<<8)+p[k+1]); p_ts->original_network_id = original_network_id; p_ts->transport_descriptor_length = transport_descriptor_length; if ( transport_descriptor_length ) { p_ts->transport_descriptors = (DS_U8 *)memChainAlloc( memId, transport_descriptor_length); if (!p_ts->transport_descriptors) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } memcpy( p_ts->transport_descriptors, &p[k+6], transport_descriptor_length); DS_U8* p_desc = 0; int err=GetMpegDescriptor( p_ts->transport_descriptors, transport_descriptor_length, DVB_TAG_service_list_descriptor, 0, &p_desc ); if (!err) DHL_PSI_ParseServiceListDescriptor( p_desc, memId, &(p_ts->p_service_list) ); err=GetMpegDescriptor( p_ts->transport_descriptors, transport_descriptor_length, ARIB_TAG_ts_information_descriptor, 0, &p_desc ); if (!err) DHL_PSI_ParseTSInformationDescriptor( p_desc, memId, &(p_ts->p_ts_info) ); } p_ts++; } k += (6+transport_descriptor_length); } } *(((memId_t *)p_nit)-1) = memId; *pp_nit = p_nit; return 0; } static void DHL_PSI_ParseSIParameterDescriptor( DS_U8 *p, memId_t memId, arib_si_parameter_descriptor_t **pp_si_parameter ) { *pp_si_parameter = 0; if ( p[1] < 3 ) return; arib_si_parameter_descriptor_t *p_si_parameter = *pp_si_parameter = (arib_si_parameter_descriptor_t *)memChainAlloc(memId, sizeof(arib_si_parameter_descriptor_t)); p_si_parameter->parameter_version = p[2]; p_si_parameter->update_time = ( p[3] << 8 ) + p[4]; if ( p[1] < 5) return; int numTable = 0; int i; for ( i = 5; i <= p[1];) { int table_id = p[i]; int table_description_length = p[i+1]; if (table_id) numTable++; i += (2+table_description_length); } if (numTable == 0) return; p_si_parameter->numTable = numTable; arib_table_description_t *p_table_description = p_si_parameter->table_description = (arib_table_description_t *)memChainAlloc(memId, numTable*sizeof(arib_table_description_t)); for ( i = 5; i <= p[1];) { int table_id = p[i]; int table_description_length = p[i+1]; if (table_id) { p_table_description->table_id = table_id; p_table_description->table_description_length = table_description_length; if (p_table_description->table_description_length) { p_table_description->table_description_byte = (DS_U8 *)memChainAlloc(memId, p_table_description->table_description_length); memcpy(p_table_description->table_description_byte, &p[i+2], p_table_description->table_description_length); } p_table_description++; } i += (2+table_description_length); } } static void DHL_PSI_ParseExtendedBroadcasterDescriptor(DS_U8 *p_desc, memId_t memId, arib_extended_broadcaster_descriptor_t **pp_ex_broad) { DS_U8 *p = p_desc; arib_extended_broadcaster_descriptor_t *p_ex_broad; int i, j, len, off; int num, numId; if (!p_desc || !pp_ex_broad || !memId) return; len = p_desc[1]; if ( len<4 ) return; p_ex_broad = (arib_extended_broadcaster_descriptor_t *)memChainAlloc(memId, sizeof(arib_extended_broadcaster_descriptor_t)); p_ex_broad->broadcaster_type = (p[2] >> 4) & 0x0F; off = 3; if ( p_ex_broad->broadcaster_type == 0x1 ) { p_ex_broad->terrestrial_broadcaster_id = (p[off+0] << 8) + p[off+1]; p_ex_broad->num_affiliation_id = (p[off+2] & 0xF0) >> 4; p_ex_broad->num_broadcaster_id = p[off+2] & 0xF; off += 3; if ( p_ex_broad->num_affiliation_id ) { num = p_ex_broad->num_affiliation_id; p_ex_broad->affiliation_id = (DS_U8 *)memChainAlloc(memId, num); memcpy(p_ex_broad->affiliation_id, &p[off], num); off += num; } if ( p_ex_broad->num_broadcaster_id ) { numId = p_ex_broad->num_broadcaster_id; p_ex_broad->origin_network_id = (DS_U16 *)memChainAlloc(memId, numId*2); p_ex_broad->broadcaster_id = (DS_U8 *)memChainAlloc(memId, numId); for ( i=0, j=0 ; j < p_ex_broad->num_broadcaster_id ; i++, j+=3 ) { p_ex_broad->origin_network_id[i] = (p[off+0] << 8) + p[off+1]; p_ex_broad->broadcaster_id[i] = p[off+2]; off += 3; p_ex_broad->origin_network_id++; p_ex_broad->broadcaster_id++; } } } else if ( p_ex_broad->broadcaster_type == 0x2 ) { p_ex_broad->terrestrial_broadcaster_id = (p[off+0] << 8) + p[off+1]; p_ex_broad->num_affiliation_id = (p[off+2] >> 4) & 0xF; p_ex_broad->num_broadcaster_id = p[off+2] & 0xF; off += 3; if ( p_ex_broad->num_affiliation_id ) { num = p_ex_broad->num_affiliation_id; p_ex_broad->affiliation_id = (DS_U8 *)memChainAlloc(memId, num); memcpy(p_ex_broad->affiliation_id, &p[off], num); off += num; } if ( p_ex_broad->num_broadcaster_id ) { numId = p_ex_broad->num_broadcaster_id; p_ex_broad->origin_network_id = (DS_U16 *)memChainAlloc(memId, numId*2); p_ex_broad->broadcaster_id = (DS_U8 *)memChainAlloc(memId, numId); for ( i=0, j=0 ; j < p_ex_broad->num_broadcaster_id ; i++, j+=3 ) { p_ex_broad->origin_network_id[i] = (p[off+0] << 8) + p[off+1]; p_ex_broad->broadcaster_id[i] = p[off+2]; off += 3; p_ex_broad->origin_network_id++; p_ex_broad->broadcaster_id++; } } } else { p_ex_broad->affiliation_id = (DS_U8 *)0; p_ex_broad->origin_network_id = (DS_U16 *)0; p_ex_broad->broadcaster_id = (DS_U8 *)0; } *pp_ex_broad = p_ex_broad; } int DHL_PSI_ParseDvbBit(DS_U8 **sectionArr, dvb_bit_t **pp_bit) { int err = 0; int i, k; int len, lenBroadcaster; int numBroadcaster; int numSections; // int index; const DS_U8 *p; dvb_bit_t *p_bit = 0; int version_number; int first_descriptor_length; // bool current_next_indicator; // bool broadcast_view_propriety; memId_t memId = 0; // memChainSetup_t memSetup = {MEM_LIMIT,0,0}; broadcaster_t *p_broadcaster; if ((sectionArr == 0) || (pp_bit == 0)) { return (DHL_FAIL_NULL_POINTER); } if (sectionArr[0] == 0) { return (DHL_FAIL_NULL_POINTER); } else { numSections = get_last_section_number(sectionArr[0]) + 1; } /* now verify all other sections are present */ for (i=1; i> 4) & 0x1); first_descriptor_length = ((p[8]<<8) + p[9]) & 0xFFF; lenBroadcaster = len - (7+first_descriptor_length+4); p = §ionArr[i][10+first_descriptor_length]; for ( k=0 ; k < lenBroadcaster ; ) { int broadcaster_id; int broadcaster_descriptor_length; broadcaster_id = p[k+0]; broadcaster_descriptor_length = ((p[k+1]<<8) + p[k+2]) & 0xFFF; if ( broadcaster_id ) numBroadcaster++; k += 3+broadcaster_descriptor_length; } } /* create the memChain */ err = memChainCreate(&memId); if (err) { goto ParseExit; } p_bit = (dvb_bit_t *)((memId_t *)(memChainAlloc(memId,sizeof(dvb_bit_t)+sizeof(memId_t))) + 1); checkMemoryError(p_bit); p_bit->num_broadcaster = numBroadcaster; if ( numBroadcaster > 0 ) { p_bit->broadcaster = (broadcaster_t *)memChainAlloc(memId,sizeof(broadcaster_t)*numBroadcaster); checkMemoryError(p_bit->broadcaster); } else { p_bit->broadcaster = (broadcaster_t *)0; } /* * Now fill-out all the remaining fields over the all sections. */ // index = 0; p_bit->first_descriptors = (DS_U8 *)0; p_broadcaster = p_bit->broadcaster; for (i = 0 ; i < numSections ; ++i) { DS_U8 last_section_number; int original_network_id; p = §ionArr[i][0]; len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; // lenth + 3 ( p[0] (TID) + p[1] + p[2] ) original_network_id = ((p[SECTION_TID_EXT_HI] << 8) | p[SECTION_TID_EXT_LO]); version_number = (p[SECTION_VERSION] & SECTION_VERSION_MASK) >> SECTION_VERSION_SHIFT; // current_next_indicator = (p[SECTION_VERSION] & SECTION_CNI_MASK) != 0; first_descriptor_length = ((p[8]<<8) + p[9]) & 0xFFF; last_section_number = p[SECTION_NUM_LAST]; if (i == 0) { /* First section */ p_bit->original_network_id = original_network_id; p_bit->version_number = version_number; p_bit->section_number = p[SECTION_NUM]; p_bit->last_section_number = last_section_number; if ( p_bit->first_descriptors == (DS_U8 *)0 && first_descriptor_length ) { DS_U8 *p_desc = (DS_U8 *)0; p_bit->first_descriptor_length = first_descriptor_length; p_bit->first_descriptors = (DS_U8 *)memChainAlloc(memId, first_descriptor_length); memcpy(p_bit->first_descriptors, &p[10], first_descriptor_length); /* * Parse SI Parameter Descriptor */ err = GetMpegDescriptor( p_bit->first_descriptors, first_descriptor_length, ARIB_TAG_si_parameter_descriptor, 0, /* only find first one. */ &p_desc ); if ( p_desc && !err ) { DHL_PSI_ParseSIParameterDescriptor( p_desc, memId, &(p_bit->p_si_parameter)); } else { // if (0) DST_Printf("BIT: cannot find si_parameter descriptor.\n"); p_bit->p_si_parameter = (arib_si_parameter_descriptor_t *)0; } } } else { if (p_bit->original_network_id != original_network_id) if (0) DST_Printf("BIT: Inconsistent original_network_id (0x%x, 0x%x)\n", p_bit->original_network_id, original_network_id); if (p_bit->version_number != version_number) if (0) DST_Printf("BIT: inconsistent version_number (0x%x, 0x%x)\n", p_bit->version_number, version_number); if (p_bit->first_descriptor_length != first_descriptor_length) if (0) DST_Printf("BIT: Inconsistent first_descriptor_length (0x%x, 0x%x)\n", p_bit->first_descriptor_length, first_descriptor_length ); if (p_bit->last_section_number != last_section_number ) if (0) DST_Printf("BIT: Inconsistent last_section_number (0x%x, 0x%x)\n", p_bit->last_section_number, last_section_number); } lenBroadcaster = len - first_descriptor_length - 4 - 3 - 7; if ( !p_broadcaster && lenBroadcaster ) { if (0) DST_Printf("BIT: broadcaster length is not 0, but broadcaster is 0.\n"); err = DHL_FAIL_INVALID_TABLEID; goto ParseExit; } p = §ionArr[i][10+first_descriptor_length]; for ( k = 0 ; k < lenBroadcaster ; ) { int broadcaster_id; int broadcaster_descriptor_length; broadcaster_id = p[k+0]; broadcaster_descriptor_length = ((p[k+1]<<8) + p[k+2]) & 0xFFF; p_broadcaster->broadcaster_id = broadcaster_id; p_broadcaster->broadcaster_descriptor_length = broadcaster_descriptor_length; if ( broadcaster_descriptor_length ) { DS_U8 *p_desc = (DS_U8 *)0; p_broadcaster->broadcaster_descriptors = (DS_U8 *)memChainAlloc(memId, broadcaster_descriptor_length); if ( !(p_broadcaster->broadcaster_descriptors) ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } memcpy(p_broadcaster->broadcaster_descriptors, &p[k+3], broadcaster_descriptor_length); /* * Parse Extended Broadcaster Descriptor */ err = GetMpegDescriptor( p_broadcaster->broadcaster_descriptors, broadcaster_descriptor_length, ARIB_TAG_extended_broadcaster_descriptor, 0, /* only find first one. */ &p_desc ); if ( p_desc && !err ) { DHL_PSI_ParseExtendedBroadcasterDescriptor(p_desc, memId, &(p_broadcaster->p_ex_broad)); } else { // if (0) DST_Printf("BIT: cannot find extended_broadcaster descriptor.\n"); p_broadcaster->p_ex_broad = (arib_extended_broadcaster_descriptor_t *)0; } p_desc = (DS_U8 *)0; /* * Parse SI Parameter Descriptor */ err = GetMpegDescriptor( p_broadcaster->broadcaster_descriptors, broadcaster_descriptor_length, ARIB_TAG_si_parameter_descriptor, 0, /* only find first one. */ &p_desc ); if ( p_desc && !err ) { DHL_PSI_ParseSIParameterDescriptor( p_desc, memId, &(p_broadcaster->p_si_parameter)); } else { // if (0) DST_Printf("BIT: cannot find si_parameter descriptor.\n"); p_broadcaster->p_si_parameter = (arib_si_parameter_descriptor_t *)0; } } else { p_broadcaster->broadcaster_descriptors = (DS_U8 *)0; p_broadcaster->p_ex_broad = (arib_extended_broadcaster_descriptor_t *)0; p_broadcaster->p_si_parameter = (arib_si_parameter_descriptor_t *)0; } k += 3+broadcaster_descriptor_length; p_broadcaster++; } } err = 0; *(((memId_t *)p_bit)-1) = memId; if (0) DST_Printf("p_bit = 0x%x\n",(int)memId); *pp_bit = p_bit; memId = 0; /* Don't delete below */ ParseExit: if (memId) { /* delete the patSection memory */ memChainDestroy(memId); } return(err); } static void DHL_PSI_ParseLocalTimeOffsetDescriptor( DS_U8 *p, int numItems, dvb_local_time_t *p_desc ) { int len, idx; int num_lto; dvb_local_time_t *p_lt; DS_U8 *puc; if ( !p || !p_desc ) return; len = p[1]; num_lto = len / 13; p_lt = p_desc; for (idx=0; idxcountry_code = (puc[2]<<16)+(puc[1]<<8)+puc[0]; p_lt->country_region_id = puc[3]>>2; p_lt->local_time_offset_polarity = puc[3] & 1; p_lt->local_time_offset = (puc[4]<<8)+puc[5]; p_lt->time_of_change_date = (puc[6]<<8)+puc[7]; p_lt->time_of_change_time = (puc[8]<<16)+(puc[9]<<8)+puc[10]; p_lt->next_time_offset = (puc[11]<<8)+puc[12]; p_lt++; } } int DHL_PSI_ParseDvbTot(DS_U8 *sectionArr, dvb_tot_t **pp_tot) { int err = 0; const DS_U8 *p; int len, descriptor_length; dvb_tot_t *p_tot = 0; memId_t memId = 0; // memChainSetup_t memSetup = {MEM_LIMIT,0,0}; if (sectionArr == 0 || (pp_tot == 0)) { return (DHL_FAIL_NULL_POINTER); } p = sectionArr; if ( p[SECTION_TID] != DVB_TID_time_offset_section ) { /* * This thing isn't a TDT. Stop right here. */ if (0) DST_Printf("TOT: Bad table ID. (0x%02X)\n", p[SECTION_TID]); err = DHL_FAIL_INVALID_TABLEID; goto ParseExit; } if ((p[SECTION_LEN_HI] & 0x80) != 0x00) { if (0) DST_Printf("TOT: section_syntax_indicator set\n"); } len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; if ( len < 8 ) { err = DHL_FAIL_INVALID_TABLEID; goto ParseExit; } /* create the memChain */ err = memChainCreate(&memId); if (err) { goto ParseExit; } p_tot = (dvb_tot_t *)((memId_t *)(memChainAlloc(memId,sizeof(dvb_tot_t)+sizeof(memId_t))) + 1); checkMemoryError(p_tot); p_tot->date = (p[3]<<8)+p[4]; p_tot->time = (p[5]<<16)+(p[6]<<8)+p[7]; p_tot->p_lto = (dvb_local_time_offset_descriptor_t *)0; p_tot->descriptor_length = 0; p_tot->descriptors = (DS_U8 *)0; if ( len >= 11 ) { DS_U8 *p_desc = (DS_U8 *)0; dvb_local_time_t *p_lt; int numLocaltime; descriptor_length = ((p[8]<<8)+p[9]) & 0xFFF; if ( descriptor_length > 1024 ) { if (0) DST_Printf("TOT: too long descriptor length %d\n", descriptor_length); goto NoDescExit; } /* * Counts number of local_time. */ err=GetMpegDescriptor( (DS_U8 *)&p[10], descriptor_length, DVB_TAG_local_time_offset_descriptor, 0, &p_desc ); if (err==0 && p_desc) { numLocaltime = p_desc[1] / 13; if (numLocaltime <= 0) goto NoDescExit; p_tot->p_lto = (dvb_local_time_offset_descriptor_t *)memChainAlloc(memId, sizeof(dvb_local_time_offset_descriptor_t)); checkMemoryError(p_tot->p_lto); p_lt = p_tot->p_lto->p_local_time = (dvb_local_time_t *)memChainAlloc(memId, sizeof(dvb_local_time_t)*numLocaltime); checkMemoryError(p_tot->p_lto->p_local_time); p_tot->p_lto->i_num_local_time = numLocaltime; DHL_PSI_ParseLocalTimeOffsetDescriptor( p_desc, numLocaltime, p_lt ); } else { if (0) DST_Printf("TOT: cannot find local_time_offset descriptor.\n"); } } NoDescExit: err = 0; *(((memId_t *)p_tot)-1) = memId; *pp_tot = p_tot; memId = 0; /* Don't delete below */ ParseExit: if (memId) { /* delete the patSection memory */ memChainDestroy(memId); } return(err); } static void DHL_PSI_ParseDataContentDescriptor( DS_U8 *p, memId_t memId, arib_data_content_descriptor_t **pp_data_content ) { int i=0, j=0, k=0, len; int err=0; arib_data_content_descriptor_t *p_data_content; len = p[1]; if ( len < 8 ) return; p_data_content = (arib_data_content_descriptor_t *)memChainAlloc(memId, sizeof(arib_data_content_descriptor_t)); if ( p_data_content == (arib_data_content_descriptor_t *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } p_data_content->data_component_id = ( p[2] << 8 ) + p[3]; p_data_content->entry_component = p[4]; p_data_content->selector_length = p[5]; if ( p_data_content->selector_length > 0 ) { DS_U8 *p_selector_byte; p_selector_byte = p_data_content->selector_byte = (DS_U8 *)memChainAlloc( memId, p_data_content->selector_length ); if ( p_selector_byte == (DS_U8 *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } for ( i = 0 ; i < p_data_content->selector_length ; i++ ) { *p_selector_byte = p[i+6]; p_selector_byte++; } } p_data_content->num_of_component_ref = p[i+6]; if ( p_data_content->num_of_component_ref > 0 ) { DS_U8 *p_component_ref; p_component_ref = p_data_content->component_ref = (DS_U8 *)memChainAlloc( memId, p_data_content->num_of_component_ref ); if ( p_component_ref == (DS_U8 *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } for ( j = 0 ; j < p_data_content->num_of_component_ref ; j++ ) { *p_component_ref = p[i+j+7]; p_component_ref++; } } p_data_content->ISO_639_language_code = ( p[i+j+7] << 16 ) + ( p[i+j+8] << 8 ) + p[i+j+9]; p_data_content->text_length = p[i+j+10]; if ( p_data_content->text_length > 0 ) { p_data_content->text_char = (DS_U8 *)memChainAlloc( memId, p_data_content->text_length+1 ); if ( p_data_content->text_char == (DS_U8 *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } for ( k = 0 ; k < p_data_content->text_length ; k++ ) { p_data_content->text_char[k] = p[i+j+k+11]; } p_data_content->text_char[k] = '\0'; } *pp_data_content = p_data_content; ParseDescriptorExit: if ( err ) { if (0) DST_Printf("ERROR: %s returns %d!\n", __func__, err); } } static void DHL_PSI_ParseShortEventDescriptor(DS_U8 *p_desc, memId_t memId, dvb_short_event_descriptor_t **pp_short_event) { dvb_short_event_descriptor_t *p_short_event; int event_name_length, text_length; DS_U32 ISO_639_language_code; if (!p_desc || !pp_short_event) return; if (p_desc[0] != DVB_TAG_short_event_descriptor || p_desc[1] < 5) { if (0) DST_Printf("%s: invalid tag or length, tag: 0x%x, length: 0x%x\n", __func__, p_desc[0], p_desc[1]); return; } ISO_639_language_code = (p_desc[2]<<16) + (p_desc[3]<<8) + p_desc[4]; p_short_event = (dvb_short_event_descriptor_t *)memChainAlloc(memId, sizeof(dvb_short_event_descriptor_t)); if ( !p_short_event ) return; p_short_event->ISO_639_language_code = ISO_639_language_code; p_short_event->event_name_length = event_name_length = p_desc[5]; p_short_event->p_event_name = (DS_U8 *)0; if (event_name_length) { p_short_event->p_event_name = (DS_U8 *)memChainAlloc(memId, event_name_length+1); SysASSERT(p_short_event->p_event_name); memcpy( p_short_event->p_event_name, &p_desc[6], event_name_length ); p_short_event->p_event_name[event_name_length] = '\0'; } p_short_event->text_length = text_length = p_desc[6+event_name_length]; p_short_event->p_text = (DS_U8 *)0; if (text_length) { p_short_event->p_text = (DS_U8 *)memChainAlloc(memId, text_length+1); SysASSERT(p_short_event->p_event_name); memcpy(p_short_event->p_text, &p_desc[7+event_name_length], text_length); p_short_event->p_text[text_length] = '\0'; } *pp_short_event = p_short_event; return; } static void DHL_PSI_ParseAudioComponentDescriptor( DS_U8 *p, memId_t memId, arib_audio_component_descriptor_t **pp_audio_component ) { int i, len; DS_U8 count; int err=0; arib_audio_component_descriptor_t *p_audio_component; len = p[1]; if ( len < 8 ) return; p_audio_component = (arib_audio_component_descriptor_t *)memChainAlloc(memId, sizeof(arib_audio_component_descriptor_t)); if ( p_audio_component == (arib_audio_component_descriptor_t *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } p_audio_component->stream_content = ( p[2] & 0xF ); p_audio_component->component_type = p[3]; p_audio_component->component_tag = p[4]; p_audio_component->stream_type = p[5]; p_audio_component->simulcast_group_tag = p[6]; p_audio_component->ES_multi_lingual_flag = ( p[7] & 0x80 ) >> 7; p_audio_component->main_component_flag = ( p[7] & 0x40 ) >> 6; p_audio_component->quality_indicator = ( p[7] & 0x30 ) >> 4; p_audio_component->sampling_rate = ( p[7] & 0xE ) >> 1; p_audio_component->ISO_639_language_code = ( p[8] << 16 ) + ( p[9] << 8 ) + p[10]; if ( p_audio_component->ES_multi_lingual_flag == 1 ) { // DS_U8 *p_text_char; p_audio_component->ISO_639_language_code_2 = ( p[11] << 16 ) + ( p[12] << 8 ) + p[13]; count = len - 12; p_audio_component->text_char = (DS_U8 *)memChainAlloc( memId, count+1 ); if ( p_audio_component->text_char == (DS_U8 *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } for ( i = 0 ; i < count ; i++ ) { p_audio_component->text_char[i] = (p[i+14]); } p_audio_component->text_char[i] = '\0'; } else { count = len - 9; p_audio_component->text_char = (DS_U8 *)memChainAlloc( memId, count+1 ); if ( p_audio_component->text_char == (DS_U8 *)0 ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } for ( i = 0 ; i < count ; i++ ) { p_audio_component->text_char[i] = (p[i+11]); } p_audio_component->text_char[i] = '\0'; } *pp_audio_component = p_audio_component; ParseDescriptorExit: if ( err ) { if (0) DST_Printf("ERROR: %s returns %d!\n", __func__, err); } } static void DHL_PSI_ParseExtendedEventDescriptor(DS_U8 *p_desc, memId_t memId, dvb_extended_event_descriptor_t **pp_extended_event) { dvb_extended_event_descriptor_t *p_extended_event; DS_U32 ISO_639_language_code; int length_of_items, text_length; int i, numItems; DS_U8 *p = (DS_U8 *)0; if (!p_desc || !pp_extended_event) return; if (p_desc[0] != DVB_TAG_extended_event_descriptor || p_desc[1] < 6) { if (0) DST_Printf("%s: invalid tag or length, tag: 0x%x, length: 0x%x\n", __func__, p_desc[0], p_desc[1]); return; } ISO_639_language_code = (p_desc[3]<<16) + (p_desc[4]<<8) + (p_desc[5]); p_extended_event = (dvb_extended_event_descriptor_t *)memChainAlloc(memId, sizeof(dvb_extended_event_descriptor_t)); if (!p_extended_event) return; p_extended_event->descriptor_number = (p_desc[2]>>4) & 0x0F; p_extended_event->last_descriptor_number = (p_desc[2]) & 0x0F; p_extended_event->ISO_639_language_code = ISO_639_language_code; length_of_items = p_desc[6]; p_extended_event->numItems = 0; p_extended_event->items = (dvb_ext_event_item_t *)0; if (length_of_items) { int item_description_length; int item_length; dvb_ext_event_item_t *p_item; /* * Calculate number of items. */ numItems = 0; p = &p_desc[7]; for(i=0; inumItems = numItems; p_item = p_extended_event->items = (dvb_ext_event_item_t *)memChainAlloc(memId, sizeof(dvb_ext_event_item_t)*numItems); for(i=0; iitem_description_length = item_description_length; if (item_description_length) { p_item->p_item_description = (DS_U8 *)memChainAlloc(memId, item_description_length+1); memcpy(p_item->p_item_description, &p[i+1], item_description_length); p_item->p_item_description[item_description_length] = '\0'; } p_item->item_length = item_length; if (item_length) { p_item->p_item_char = (DS_U8 *)memChainAlloc(memId, item_length+1); memcpy(p_item->p_item_char, &p[i+2+item_description_length], item_length); p_item->p_item_char[item_length] = '\0'; } i += item_description_length+item_length+2; p_item++; } } text_length = p_desc[7+length_of_items]; p_extended_event->text_length = text_length; p_extended_event->p_text = (DS_U8 *)0; if (text_length) { p_extended_event->p_text = (DS_U8 *)memChainAlloc(memId, text_length); memcpy(p_extended_event->p_text, &p_desc[8+length_of_items], text_length); } *pp_extended_event = p_extended_event; return; } static void DHL_PSI_ParseParentalRatingDescriptorEx (DS_U8* p, memId_t memId, dvb_parental_rating_descriptor_t **pp_desc) { //memId_t memId; //memChainSetup_t memSetup = {MEM_LIMIT,0,0}; DS_U8 length; int err=0; dvb_parental_rating_descriptor_t *p_desc; dvb_parental_rating_entry_t *p_entry; int i, numEntries; DS_U8 *p_data; length = p[1]; #if 0 /* create the memChain */ err = memChainCreate(&memId); if (err != 0) goto ParseDescriptorExit; #endif /* create the descriptor memory */ p_desc = (dvb_parental_rating_descriptor_t *)(memChainAlloc(memId,sizeof(dvb_parental_rating_descriptor_t))); if (p_desc == (dvb_parental_rating_descriptor_t *)0) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } numEntries = length>>2; if (numEntries<=0) goto ParseDescriptorExit; p_entry = (dvb_parental_rating_entry_t *)memChainAlloc(memId, sizeof(dvb_parental_rating_entry_t)*numEntries); if (p_entry == (dvb_parental_rating_entry_t *)0) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseDescriptorExit; } p_desc->i_num_ratings = numEntries; p_desc->p_ratings = p_entry; p_data = &p[2]; for (i=0; icountry_code = (p_data[0]<<16) + (p_data[1]<<8) + (p_data[2]<<0); p_entry->rating_value = p_data[3]; p_data += 4; p_entry++; } *(((memId_t *)(p_desc))-1) = memId; memId = 0; /* so memChain not deleted */ *pp_desc = p_desc; ParseDescriptorExit: if (memId) { /* delete the descriptor memory */ memChainDestroy(memId); } if (err) { if (0) DST_Printf("ERROR: %s returns %d!\n", __func__, err); } } static void DHL_PSI_ParseEventGroupDescriptor(DS_U8 *p_desc, memId_t memId, arib_event_group_descriptor_t **pp_event_grp) { DS_U8 *p = p_desc; arib_event_group_descriptor_t *p_event_grp; arib_event_t *p_event; arib_other_event_t *p_other_event; int i, len, off; // int numEvent; if (!p_desc || !pp_event_grp || !memId) return; len = p_desc[1]; if (len<5) return; p_event_grp = (arib_event_group_descriptor_t *)memChainAlloc(memId, sizeof(arib_event_group_descriptor_t)); p_event_grp->group_type = (p[2] >> 4) & 0x0F; p_event_grp->numEvents = p[2]&0x0F; off = 3 /*3=descriptor_tag+length+group_type + event_cnt*/; if ( p_event_grp->numEvents ) { p_event = p_event_grp->p_event = (arib_event_t *)memChainAlloc(memId, sizeof(arib_event_t) * p_event_grp->numEvents); for (i=0; inumEvents && off <= (len+2); i++) { p_event->service_id = (p[0+off]<<8)+p[1+off]; p_event->event_id = (p[2+off]<<8)+p[3+off]; off += 4; p_event++; } } p_event_grp->numOtherNetworkEvents = 0; if ( p_event_grp->group_type == 4 || p_event_grp->group_type == 5 ) { p_event_grp->numOtherNetworkEvents = (len-off-2)/8; if (p_event_grp->numOtherNetworkEvents) { p_other_event = p_event_grp->p_other_event = (arib_other_event_t *)memChainAlloc(memId, sizeof(arib_other_event_t) * p_event_grp->numOtherNetworkEvents); for (i=0; inumOtherNetworkEvents; i++) { p_other_event->original_network_id = (p[0+off]<<8)+p[1+off]; p_other_event->transport_stream_id = (p[2+off]<<8)+p[3+off]; p_other_event->service_id = (p[4+off]<<8)+p[5+off]; p_other_event->event_id = (p[6+off]<<8)+p[7+off]; off += 8; p_other_event++; } } } *pp_event_grp = p_event_grp; } int DHL_PSI_ParseDvbEit(DS_U8 **sectionArr, DVB_EIT **pp_eit) { if (!sectionArr || !sectionArr[0] || !pp_eit) return DHL_FAIL_NULL_POINTER; *pp_eit = 0; // 2013.10.07 section ¸ðµå·Î EIT¸¦ ¹ÞÀ¸¹Ç·Î Ç×»ó section °¹¼ö´Â 1ÀÌ´Ù. int numSections = 1; //get_last_section_number(sectionArr[0]) + 1; // First pass, we verify section syntax and count the number of events. int numEvents = 0; int i; for ( i = 0; i < numSections; ++i) { if (!sectionArr[i]) break; DS_U8* p = sectionArr[i]; if ((p[SECTION_LEN_HI] & 0x80) != 0x80) if (0) DST_Printf("EIT: section_syntax_indicator not set\n"); int len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; DS_U16 service_id = (p[SECTION_TID_EXT_HI] << 8) + p[SECTION_TID_EXT_LO]; if (service_id == 0) continue; // Counts number of services. int event_length = len - 14/*table_id to last_table_id*/ - 4/*crc_32*/; if ( event_length < 12 ) continue; // No events are available for this section. p = §ionArr[i][14]; int k; for( k=0; (k+12+4)eit_events = (dvb_eit_event_t *)memChainAlloc(memId,sizeof(dvb_eit_event_t)*numEvents); if (p_eit->eit_events == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } p_eit->numEvents = numEvents; // Now fill-out all the remaining fields over the all sections. // int index = 0; for ( i = 0; i < numSections; ++i) { if(!sectionArr[i]) break; DS_U8* p = sectionArr[i]; int len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; DS_U16 service_id = ((p[SECTION_TID_EXT_HI] << 8) | p[SECTION_TID_EXT_LO]); if (service_id == 0) continue; DS_U8 version_number = (p[SECTION_VERSION] & SECTION_VERSION_MASK) >> SECTION_VERSION_SHIFT; DS_U8 last_section_number = p[SECTION_NUM_LAST]; DS_U8 table_id = p[SECTION_TID]; DS_U16 transport_stream_id = ((p[8]<<8) + p[9]); DS_U16 original_network_id = ((p[10]<<8) + p[11]); DS_U8 segment_last_section_number = p[12]; DS_U8 last_table_id = p[13]; if (i == 0) { p_eit->table_id = table_id; p_eit->service_id = service_id; p_eit->version_number = version_number; p_eit->section_number = p[6]; p_eit->last_section_number = last_section_number; p_eit->segment_last_section_number = segment_last_section_number; p_eit->transport_stream_id = transport_stream_id; p_eit->original_network_id = original_network_id; p_eit->last_table_id = last_table_id; } int event_length = len - 14/*table_id to last_table_id*/ - 4/*crc_32*/; if ( event_length < 12 ) continue; // No events are available for this section. p = §ionArr[i][14]; int k; for( k=0; (k+12+4)descriptor_length = ((p[k+10]<<8)+p[k+11]) & 0xFFF; p_event->event_id = (p[k+0]<<8)+p[k+1]; p_event->start_date = (p[k+2]<<8)+p[k+3]; p_event->start_time = (p[k+4]<<16)+(p[k+5]<<8)+p[k+6]; p_event->duration = (p[k+7]<<16)+(p[k+8]<<8)+p[k+9]; p_event->running_status = (p[k+10]>>5) & 0x07; p_event->free_CA_mode = (p[k+10]>>4) & 0x01; if (p_event->descriptor_length) { DS_U8 *p_desc_sect = p_event->descriptors = (DS_U8*)memChainAlloc(memId, p_event->descriptor_length); memcpy(p_event->descriptors, &p[k+12], p_event->descriptor_length); // ShortEventDescriptor°¡ 2°³ ÀÌ»óÀÎ °æ¿ì¸¦ À§ÇÏ¿© ¾øÀ» ¶§ ±îÁö ã¾Æ¼­ Parse. p_event->numShortEvents = GetMpegDescriptorCount(p_desc_sect, descriptor_length, DVB_TAG_short_event_descriptor); p_event->pp_short_event = (dvb_short_event_descriptor_t **)memChainAlloc(memId, sizeof(dvb_short_event_descriptor_t *) * p_event->numShortEvents); int m; for ( m = 0; m < p_event->numShortEvents; m++) { DS_U8* p_desc = 0; if (GetMpegDescriptor( p_desc_sect, descriptor_length, DVB_TAG_short_event_descriptor, m, &p_desc )) continue; DHL_PSI_ParseShortEventDescriptor(p_desc, memId, &p_event->pp_short_event[m]); } // extended_event_descriptor°¡ 2°³ ÀÌ»óÀÎ °æ¿ì¸¦ À§ÇÏ¿© ¾øÀ» ¶§ ±îÁö ã¾Æ¼­ Parse. p_event->numExtendedEvents = GetMpegDescriptorCount(p_desc_sect, descriptor_length, DVB_TAG_extended_event_descriptor); p_event->pp_extended_event = (dvb_extended_event_descriptor_t **)memChainAlloc(memId, sizeof(dvb_extended_event_descriptor_t *) * p_event->numExtendedEvents); for ( m = 0; m < p_event->numExtendedEvents; m++) { DS_U8* p_desc = 0; if (GetMpegDescriptor( p_desc_sect, descriptor_length, DVB_TAG_extended_event_descriptor, m, &p_desc )) continue; DHL_PSI_ParseExtendedEventDescriptor(p_desc, memId, &p_event->pp_extended_event[m]); } // Find Parental_Rating descriptor. p_event->numParentalRating = GetMpegDescriptorCount(p_desc_sect, descriptor_length, DVB_TAG_parental_rating_descriptor); p_event->pp_pr_desc = (dvb_parental_rating_descriptor_t **)memChainAlloc(memId, sizeof(dvb_parental_rating_descriptor_t *) * p_event->numParentalRating); for ( m = 0; m < p_event->numParentalRating; m++) { DS_U8* p_desc = 0; if (GetMpegDescriptor( p_desc_sect, descriptor_length, DVB_TAG_parental_rating_descriptor, m, &p_desc )) continue; DHL_PSI_ParseParentalRatingDescriptorEx(p_desc, memId, &p_event->pp_pr_desc[m]); } // Find Event Group descriptor. DS_U8* p_desc = 0; if (!GetMpegDescriptor( p_desc_sect, descriptor_length, ARIB_TAG_event_group_descriptor, 0, &p_desc )) { DHL_PSI_ParseEventGroupDescriptor( p_desc, memId, &p_event->p_event_group ); } // Find Audio component descriptor. p_event->numAudioComponent = GetMpegDescriptorCount(p_desc_sect, descriptor_length, ARIB_TAG_audio_component_descriptor); p_event->pp_audio_component = (arib_audio_component_descriptor_t **)memChainAlloc(memId, sizeof(arib_audio_component_descriptor_t *) * p_event->numAudioComponent); for ( m = 0; m < p_event->numAudioComponent; m++) { DS_U8* p_desc = 0; if (GetMpegDescriptor( p_desc_sect, descriptor_length, ARIB_TAG_audio_component_descriptor, m, &p_desc )) continue; DHL_PSI_ParseAudioComponentDescriptor(p_desc, memId, &p_event->pp_audio_component[m]); } // Data component descriptor p_event->numDataContent = GetMpegDescriptorCount(p_desc_sect, descriptor_length, ARIB_TAG_data_content_descriptor); p_event->pp_data_content = (arib_data_content_descriptor_t **)memChainAlloc(memId, sizeof(arib_data_content_descriptor_t *) * p_event->numDataContent); for ( m = 0; m < p_event->numDataContent; m++) { DS_U8* p_desc = 0; if (GetMpegDescriptor( p_desc_sect, descriptor_length, ARIB_TAG_data_content_descriptor, m, &p_desc )) continue; DHL_PSI_ParseDataContentDescriptor(p_desc, memId, &p_event->pp_data_content[m]); } } k += 12+descriptor_length; p_event++; } } *(((memId_t *)p_eit)-1) = memId; *pp_eit = p_eit; return 0; } static int DHL_PSI_ParseStreamIdentifierDescriptor(DS_U8 *p, DS_U8 *p_component_tag) { if (p[1] < 1) return -1; *p_component_tag = p[2]; return 0; } int DHL_PSI_ParsePMT( DS_U8 *section, MPEG_PMT **returnPmt) { int err = 0; DS_S32 j, k; // DS_S32 index; DS_S32 numStreams; DS_S32 len, len2; MPEG_PMT *pmt; DS_S32 program_info_length, es_info_length; // memChainSetup_t memSetup = {MEM_LIMIT,0,0}; memId_t memId = 0; const DS_U8 *p; DS_U8 *q; int pmtSize = 0; if( section == 0 || returnPmt == 0 ) return DHL_FAIL_NULL_POINTER; /* * First pass, we verify section syntax and count the number of streams */ p = section; numStreams = 0; if (p[SECTION_TID] != TS_PROGRAM_MAP_SECTION) { /* * This thing isn't a PMT. Stop right here. */ if (0) DST_Printf("PMT: Bad table ID."); err = DHL_FAIL_INVALID_TABLEID; goto ParseExit; } if ((p[SECTION_LEN_HI] & 0x80) != 0x80) { if (0) DST_Printf("PAT: section_syntax_indicator not set"); } if ((p[SECTION_LEN_HI] & 0x40) != 0x00) { if (0) DST_Printf("PAT: private_indicator set"); } len = (((p[SECTION_LEN_HI] & 0x0F) << 8) | p[SECTION_LEN_LO]) + 3; if (p[SECTION_NUM] != 0) { if (0) DST_Printf("PMT: section_number != 0"); } if (p[SECTION_NUM_LAST] != 0) { if (0) DST_Printf("PAT: last_section_number != 0"); } program_info_length = ((p[10]<<8) + p[11]) & 0x0FFF; if (program_info_length & 0x0C00) { if (0) DST_Printf("PMT: first 2 bits of program_info_length not 00"); } len2 = len - program_info_length - 16; if (len2 < 0) { if (0) DST_Printf("PMT: program descriptors extend beyond section"); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } p += program_info_length + 12; while (len2 > 0) { if (len2 < 5) { if (0) DST_Printf("PMT: junk bytes at end of table"); break; } es_info_length = ((p[3]<<8) + p[4]) & 0x0FFF; if (es_info_length & 0x0C00) { if (0) DST_Printf("PMT: first 2 bits of ES_info_length not 00"); } if (len2 - es_info_length < 5) { if (0) DST_Printf("PMT: elementary stream descriptors extend beyond section"); break; } /* * This is a hack to repair corrupted PMT's which we have received */ { DS_S32/*BK2003.11.18 <-DS_U32 by cafrii*/ hlen = es_info_length; DS_U8 *hp = (DS_U8 *)&p[5]; DS_U32 dtype, dlen; while(hlen > 0) { dtype = hp[0]; dlen = hp[1]; if (dtype == 10 && dlen == 3) { hp[1] = 4; es_info_length++; ((DS_U8 *)p)[3] = es_info_length>>8; ((DS_U8 *)p)[4] = es_info_length&255; break; } hp += (dlen+2); hlen -= (dlen+2); } } /* * End corrupted PMT hack */ len2 = len2 - es_info_length - 5; p += es_info_length + 5; numStreams++; } /* * At this point, numStreams has the number of streams, which we can * base the size of the PMT from. */ /* create the memChain */ err = memChainCreate(&memId); if (err) { goto ParseExit; } /* allocate memory for pmtSection */ pmtSize = MPEG_PMTSize(numStreams); pmt = (MPEG_PMT *)((memId_t *)(memChainAlloc(memId, pmtSize + sizeof(memId_t))) + 1); checkMemoryError(pmt); /* * Second pass, we fill in the table. * We assume that everything we verified or warned about above is still * true. We already bailed out on fatal errors */ // index = 0; p = section; /* pmt->PID = desc->pid;*/ pmt->program_number = ((p[SECTION_TID_EXT_HI] << 8) | p[SECTION_TID_EXT_LO]); pmt->version_number = (p[SECTION_VERSION] & SECTION_VERSION_MASK) >> SECTION_VERSION_SHIFT; pmt->current_next_indicator = (p[SECTION_VERSION] & SECTION_CNI_MASK) != 0; pmt->PCR_PID = ((p[8] << 8) | p[9]) & PID_MASK; pmt->numStreams = numStreams; len2 = len - program_info_length - 16; p += 12; pmt->descriptor_length = program_info_length; pmt->descriptors = (DS_U8 *)memChainAlloc(memId,program_info_length*sizeof(DS_U8)); checkMemoryError(pmt->descriptors); for (j=0; jdescriptors[j] = *p++; } for (j = 0; j < numStreams; ++j) { pmt->streams[j].stream_type = p[0]; pmt->streams[j].elementary_PID = ((p[1]<<8) | p[2]) & PID_MASK; es_info_length = ((p[3]<<8) + p[4]) & 0x0FFF; p += 5; pmt->streams[j].descriptor_length = es_info_length; pmt->streams[j].descriptors = (DS_U8 *)memChainAlloc(memId,es_info_length*sizeof(DS_U8)); checkMemoryError(pmt->streams[j].descriptors); for (k=0; kstreams[j].descriptors[k] = *p++; } // if (GetMpegDescriptor(pmt->streams[j].descriptors,es_info_length, // video_stream_tag,0/*instance*/,&q) == 0) { // DHL_PSI_ParseVideoStreamDescriptor(q,memId,&pmt->streams[j].videoStreamDescriptor); // } // if (GetMpegDescriptor(pmt->streams[j].descriptors,es_info_length, // video_decode_control_tag,0/*instance*/,&q) == 0) { // DHL_PSI_ParseVideoDecodeControlDescriptor(q,memId,&pmt->streams[j].videoDecodeControlDescriptor); // } pmt->streams[j].b_component_tag_valid = false; if (GetMpegDescriptor(pmt->streams[j].descriptors,es_info_length, DVB_TAG_stream_identifier_descriptor, 0, &q)==0) { if ( DHL_PSI_ParseStreamIdentifierDescriptor(q,&(pmt->streams[j].component_tag)) == 0 ) pmt->streams[j].b_component_tag_valid = true; } } *(((memId_t *)pmt)-1) = memId; *returnPmt = pmt; memId = 0; /* Don't delete below */ ParseExit: if (memId) { /* delete the patSection memory */ memChainDestroy(memId); } return(err); } /*============================================================================== DHL_RESULT ParseTVCTSection (DS_U8 *section, tvctSectionPtr_t *tvctSectionPtr) *section: Pointer to the first byte of the section. *tvctSectionPtr: Return pointer to a parsed TVCT section. Parses an TVCT section and returns the decoded section via the provided handle. ==============================================================================*/ static int DHL_PSI_ParseTVCTSection (DS_U8 *section, tvctSectionPtr_t *tvctSectionPtr) { // T(); if (get_section_syntax_indicator(section) == 0) { if (0) DST_Printf("TVCT: section_syntax_indicator not set\n"); } if (get_private_indicator(section) == 0) { if (0) DST_Printf("TVCT: private_indicator not set\n"); } int err = 0; DS_U16 section_length = get_section_length(section); if (0) DST_Printf("section_length=%d\n", section_length); if (section_length > 1021) { if (0) DST_Printf("TVCT: section_length=%d\n",section_length); return DHL_FAIL_INVALID_PARAM; } memId_t memId = (memId_t)0; /* create the memChain */ err = memChainCreate(&memId); if (err) { return DHL_FAIL_OUT_OF_RESOURCE; } /* allocate memory for tvctSection */ tvctSectionPtr_t tvctSectPtr = (tvctSectionPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(tvctSection_t)+sizeof(memId_t))) + 1); // checkMemoryError(tvctSectPtr); DS_U8 *p = section+3; /* parse section */ tvctSectPtr->transport_stream_id = p[0] * 256 + p[1]; tvctSectPtr->version_number = (p[2] >> 1) & 0x3F; tvctSectPtr->current_next_indicator = p[2] & 0x01; tvctSectPtr->section_number = p[3]; tvctSectPtr->last_section_number = p[4]; DS_U8 protocol_version = p[5]; if (protocol_version > 0) { if (0) DST_Printf("TVCT : invalid protocol version.(0x%x).\r\n" , protocol_version ); if (memId) memChainDestroy(memId); return DHL_FAIL_INVALID_VERSION; } int count_i = tvctSectPtr->num_channels_in_section = p[6]; if (0) DST_Printf("tvctSectPtr->num_channels_in_section=%d\n" , tvctSectPtr->num_channels_in_section ); if( count_i > 0 ) { tvctSectPtr->channel = (tvctChannelPtr_t)memChainAlloc(memId,count_i*sizeof(tvctChannel_t)); checkMemoryError(tvctSectPtr->channel); } p = p+7; int i; for ( i=0; ichannel[i].short_name[j] = p[j*2] * 256 + p[j*2+1]; } tvctSectPtr->channel[i].major_channel_number = (p[14] & 0x0F) * 64 + ((p[15] >> 2) & 0x3F); tvctSectPtr->channel[i].minor_channel_number = (p[15] & 0x03) * 256 + p[16]; //if (0) DST_Printf("tvctSectPtr->channel[i].major_channel_number == %d\n",tvctSectPtr->channel[i].major_channel_number); //if (0) DST_Printf("tvctSectPtr->channel[i].minor_channel_number == %d\n",tvctSectPtr->channel[i].minor_channel_number); tvctSectPtr->channel[i].modulation_mode = (modulation_mode_k)p[17]; tvctSectPtr->channel[i].carrier_frequency = p[18] * 0x1000000 + p[19] * 0x10000 + p[20] * 0x100 + p[21]; tvctSectPtr->channel[i].channel_TSID = p[22] * 0x100 + p[23]; tvctSectPtr->channel[i].program_number = p[24] * 0x100 + p[25]; tvctSectPtr->channel[i].ETM_location = (ETM_location_k)((p[26] >> 6) & 0x03); tvctSectPtr->channel[i].access_controlled = (p[26] >> 5) & 0x01; tvctSectPtr->channel[i].hidden = (p[26] >> 4) & 0x01; tvctSectPtr->channel[i].show_guide = (p[26] >> 1) & 0x01; tvctSectPtr->channel[i].service_type = (service_type_k)(p[27]& 0x3F); tvctSectPtr->channel[i].source_id = p[28] * 256 + p[29]; int count_j = tvctSectPtr->channel[i].descriptor_length = (p[30]&0x03) * 256 + p[31]; tvctSectPtr->channel[i].descriptors = (DS_U8 *)memChainAlloc(memId,count_j); checkMemoryError(tvctSectPtr->channel[i].descriptors); //if (0) DST_Printf("tvctSectPtr->channel[i].descriptor_lengthr == %d\n",tvctSectPtr->channel[i].descriptor_length); for ( j=0; jchannel[i].descriptors[j] = p[32+j]; } p = p + 32 + count_j; } count_i = tvctSectPtr->additional_descriptor_length = (p[0]&0x03) * 256 + p[1]; tvctSectPtr->additional_descriptors = (DS_U8 *)memChainAlloc(memId,count_i); checkMemoryError(tvctSectPtr->additional_descriptors); for ( i=0; iadditional_descriptors[i] = p[2+i]; } /* parsing complete */ *(((memId_t *)tvctSectPtr)-1) = memId; memId = (memId_t)0; /* so memChain not deleted */ ParseExit: // if (bits) { // /* clean up the bitBuffer */ // bitBufferDestroy(bits); // } if (memId) { /* delete the tvctSection memory */ memChainDestroy(memId); } *tvctSectionPtr = tvctSectPtr; return (err); } /*============================================================================== DHL_RESULT DHL_PSI_ParseTVCT (DS_U8 **sectionArr, tvctPtr_t *tvctPtr) **sectionArr: Array of pointers to all TVCT sections. *tvctPtr: Returned pointer to the parsed TVCT. Parses an TVCT and returns the parsed table via the return pointer. ==============================================================================*/ int DHL_PSI_ParseTVCT (DS_U8 **sectionArr, tvctPtr_t *tvctPtr) { // T(); if (sectionArr == 0) { if (0) DST_Printf("%s|%d|sectionArr == 0\n", __func__, __LINE__); return (DHL_FAIL_NULL_POINTER); } if (sectionArr[0] == 0) { if (0) DST_Printf("%s|%d|sectionArr[0] == 0\n", __func__, __LINE__); return (DHL_FAIL_NULL_POINTER); } if (tvctPtr == 0) { if (0) DST_Printf("%s|%d|tvctPtr == 0\n", __func__, __LINE__); return (DHL_FAIL_NULL_POINTER); } *tvctPtr = 0; DS_U8 numSections = get_last_section_number(sectionArr[0]) + 1; if (0) DST_Printf("numSections = %d\n", numSections); int i; for ( i=1; i < numSections; i++) /* now verify all other sections are present */ { if (sectionArr[i] == 0) { if (0) DST_Printf("%s|%d|null section found.\n", __func__, __LINE__); return (DHL_FAIL_NULL_POINTER); } } for( i=0; i < numSections; i++ ) /*chech the protocol_version of each secion.*/ { if( sectionArr[i][8] != 0x00 ) { if (0) DST_Printf("%s|%d|invalid protocol version\n", __func__, __LINE__); return DHL_FAIL_INVALID_VERSION; } } /* create the memChain */ memId_t memId = (memId_t)0; int err = memChainCreate(&memId); if (err) { if (0) DST_Printf("%s|%d|memChainCreate fail\n", __func__, __LINE__); return DHL_FAIL_OUT_OF_RESOURCE; } /* allocate memory for tvct */ *tvctPtr = (tvctPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(tvct_t)+sizeof(memId_t))) + 1); // checkMemoryError(*tvctPtr); /* Get the total number of channels in all sections */ DS_U16 numChannels = 0; for ( i=0; inumChannels = numChannels; /* allocate space in tvct for channels */ (*tvctPtr)->channel = (tvctChannelPtr_t)memChainAlloc(memId,numChannels*sizeof(tvctChannel_t)); checkMemoryError((*tvctPtr)->channel); // #ifdef PSI_DBG // if (0) DST_Printf("DHL_PSI_ParseTVCT, numSection = %d\r\n", numSections); // #endif /* Parse each section and copy channels */ numChannels = 0; for ( i=0; itransport_stream_id = tvctSectPtr->transport_stream_id; (*tvctPtr)->version_number = tvctSectPtr->version_number; /* allocate space for descriptors and copy (if any) */ if (tvctSectPtr->additional_descriptor_length > 0) { (*tvctPtr)->additional_descriptors = (DS_U8 *)memChainAlloc(memId,tvctSectPtr->additional_descriptor_length); if ((*tvctPtr)->additional_descriptors == 0) { DHL_PSI_FreeMpegSection(tvctSectPtr); err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } (*tvctPtr)->additional_descriptor_length = tvctSectPtr->additional_descriptor_length; memcpy((*tvctPtr)->additional_descriptors, tvctSectPtr->additional_descriptors, (*tvctPtr)->additional_descriptor_length); } } int j; for ( j=0; jnum_channels_in_section; j++) { memcpy(&((*tvctPtr)->channel[numChannels]), &(tvctSectPtr->channel[j]), sizeof(tvctChannel_t)); /* allocate space for descriptors and copy (if any) */ if (tvctSectPtr->channel[j].descriptor_length > 0) { (*tvctPtr)->channel[numChannels].descriptors = (DS_U8 *)memChainAlloc(memId,tvctSectPtr->channel[j].descriptor_length*sizeof(DS_U8)); if ((*tvctPtr)->channel[numChannels].descriptors == 0) { DHL_PSI_FreeMpegSection(tvctSectPtr); err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } memcpy((*tvctPtr)->channel[numChannels].descriptors,tvctSectPtr->channel[j].descriptors, (*tvctPtr)->channel[numChannels].descriptor_length); } numChannels++; } DHL_PSI_FreeMpegSection(tvctSectPtr); } /* parsing complete */ *(((memId_t *)(*tvctPtr))-1) = memId; memId = 0; /* so memChain not deleted */ ParseExit: if (memId) { /* delete the tvct memory */ memChainDestroy(memId); } return (err); } /*============================================================================== ParseCaptionServiceDescriptor *p: Pointer to the un-parsed descriptor. *descripPtr Pointer to parsed descriptor passed here. Parses the descriptor and passes the result back via the descripPtr variable. ==============================================================================*/ int DHL_PSI_ParseCaptionServiceDescriptor (DS_U8* p, captionServiceDescriptorPtr_t *descripPtr) { memId_t memId; if (memChainCreate(&memId)) return DHL_FAIL_OUT_OF_RESOURCE; /* create the memChain */ /* create the descriptor memory */ *descripPtr = (captionServiceDescriptorPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(captionServiceDescriptor_t)+sizeof(memId_t))) + 1); if (*descripPtr == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } /* parse the descriptor */ int count_i = (*descripPtr)->number_of_services = p[2] & 0x1F; if (0) DST_Printf("count_i = %d\n", count_i); (*descripPtr)->service = (captionServicePtr_t)memChainAlloc(memId,count_i*sizeof(captionService_t)); if ((*descripPtr)->service == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } int nPos = 3; int i; for ( i=0; iservice[i].language[0] = p[nPos++]; (*descripPtr)->service[i].language[1] = p[nPos++]; (*descripPtr)->service[i].language[2] = p[nPos++]; (*descripPtr)->service[i].language[3] = 0; (*descripPtr)->service[i].cc_type = (cc_type_k)((p[nPos] >> 7) & 0x01); if ((*descripPtr)->service[i].cc_type == cct_line21) { (*descripPtr)->service[i].cc_id.line21_field = (line21_field_k)(p[nPos] &0x01); } else { (*descripPtr)->service[i].cc_id.caption_service_number = (p[nPos] &0x3F); } nPos++; (*descripPtr)->service[i].easy_reader = (p[nPos] >> 7) & 0x01; (*descripPtr)->service[i].wide_aspect_ratio = (p[nPos] >> 6) & 0x01; (*descripPtr)->service[i].korean_code = (p[nPos] >> 5) & 0x01; nPos += 2; } /* parsing complete */ *(((memId_t *)(*descripPtr))-1) = memId; memId = 0; /* so memChain not deleted */ //ParseDescriptorExit: memChainDestroy(memId); /* delete the descriptor memory */ return 0; } /*============================================================================== void DHL_PSI_FreeMpegDescriptor (void *descriptorPtr) descriptorPtr Pointer to a parsed descriptor. Frees the memory associated with a parsed descriptor. ==============================================================================*/ void DHL_PSI_FreeMpegDescriptor (void *descriptorPtr) { if(descriptorPtr ) memChainDestroy(*(((memId_t *)descriptorPtr)-1)); } /*============================================================================== ParseAc3AudioStreamDescriptor *p: Pointer to the un-parsed descriptor. *descripPtr Pointer to parsed descriptor passed here. Parses the descriptor and passes the result back via the descripPtr variable. ==============================================================================*/ int DHL_PSI_ParseAc3AudioStreamDescriptor (DS_U8* p, ac3AudioStreamDescriptorPtr_t *descripPtr) { /* create the memChain */ memId_t memId; if (memChainCreate(&memId)) return DHL_FAIL_OUT_OF_RESOURCE; /* create the descriptor memory */ *descripPtr = (ac3AudioStreamDescriptorPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(ac3AudioStreamDescriptor_t)+sizeof(memId_t))) + 1); if (*descripPtr == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } /* parse the descriptor */ DS_U8 length = p[1]; (*descripPtr)->sample_rate_code = (sample_rate_code_k)((p[2] >> 5) & 0x07); (*descripPtr)->bsid = (p[2] & 0x1F); (*descripPtr)->bit_rate_code = (bit_rate_code_k) ((p[3] >> 2) & 0x3F); (*descripPtr)->surround_mode = (surround_mode_k)(p[3] & 0x03); (*descripPtr)->bsmod = (bit_stream_mode_k)((p[4] >> 5) & 0x07); (*descripPtr)->num_channels = (num_channels_k)((p[4] >> 1) & 0x0F); (*descripPtr)->full_svc = (p[4] & 0x01); int nPos = 5; if (length > 3) { (*descripPtr)->additional_elements1 = true; (*descripPtr)->langcod = (language_code_k)p[nPos++]; /* compute length of lang2 field */ DS_U8 lang2_len = (*descripPtr)->num_channels == nc_acmod_1_1 ? 1 : 0; if (length > 4 && lang2_len) { (*descripPtr)->langcod2 = (language_code_k)p[nPos++]; } if (length > 4+lang2_len) { (*descripPtr)->additional_elements2 = true; if ((*descripPtr)->bsmod < 2) { (*descripPtr)->bsmod_ext.mainid = (p[nPos++] >> 5) & 0x07; } else { (*descripPtr)->bsmod_ext.asvcflags = (p[nPos++] >> 5); } if (length > 5+lang2_len) { DS_U16 count_i = (*descripPtr)->textlen = (p[nPos] >> 1) & 0x7F; (*descripPtr)->text_code = (text_code_k)(p[nPos++] & 0x01); (*descripPtr)->text = 0; if (count_i > 0) { (*descripPtr)->text = (DS_U8 *)memChainAlloc(memId,count_i*sizeof(DS_U8)); if ((*descripPtr)->text == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } int i; for ( i=0; itext[i] = p[nPos++]; } } (*descripPtr)->langflag = 0; (*descripPtr)->langflag_2 = 0; (*descripPtr)->language[0] = 0; (*descripPtr)->language[1] = 0; (*descripPtr)->language[2] = 0; (*descripPtr)->language[3] = 0; (*descripPtr)->language2[0] = 0; (*descripPtr)->language2[1] = 0; (*descripPtr)->language2[2] = 0; (*descripPtr)->language2[3] = 0; if (length > 5+lang2_len+1+count_i) { /* see if we have 0, 1, or 2 ISO 639 language fields */ (*descripPtr)->langflag = (p[nPos] >> 7) & 0x01; (*descripPtr)->langflag_2 =(p[nPos] >> 6) & 0x01; nPos++; int lang639_len = 6 + lang2_len + 1 + count_i; if (((*descripPtr)->langflag) && (length >= lang639_len + 3)) { lang639_len += 3; /* so lang2 is independent! */ (*descripPtr)->language[0] =p[nPos++]; (*descripPtr)->language[1] =p[nPos++]; (*descripPtr)->language[2] =p[nPos++]; (*descripPtr)->language[3] = 0; } if (((*descripPtr)->langflag_2) && (length >= lang639_len + 3)) { (*descripPtr)->language2[0] = p[nPos++]; (*descripPtr)->language2[1] = p[nPos++]; (*descripPtr)->language2[2] = p[nPos++]; (*descripPtr)->language2[3] = 0; } } } } } /* Ignore remaining 'additional_info' bytes */ /* parsing complete */ *(((memId_t *)(*descripPtr))-1) = memId; memId = 0; /* so memChain not deleted */ // ParseDescriptorExit: // if (bits) { // /* delete the bitBuffer */ // bitBufferDestroy(bits); // } if (memId) { /* delete the descriptor memory */ memChainDestroy(memId); } return 0; } /*============================================================================== DHL_RESULT DHL_PSI_ParseMGTSection (DS_U8 *section, mgtSectionPtr_t *mgtSectionPtr) *section: Pointer to the first byte of the section. *mgtSectionPtr: Return pointer to a parsed MGT section. Parses an MGT section and returns the decoded section via the provided handle. ==============================================================================*/ int DHL_PSI_ParseMGTSection (DS_U8 *section, mgtSectionPtr_t *mgtSectionPtr) { if (get_section_syntax_indicator(section) == 0) { if (0) DST_Printf("MGT: section_syntax_indicator not set\n"); } if (get_private_indicator(section) == 0) { if (0) DST_Printf("MGT: private_indicator not set\n"); } int section_length = get_section_length(section); if (section_length > 4093) { if (0) DST_Printf("MGT: section_length=%d\n",section_length); return DHL_FAIL_INVALID_PARAM; } /* create the memChain */ memId_t memId; if (memChainCreate(&memId)) { return DHL_FAIL_OUT_OF_RESOURCE; } /* allocate memory for mgtSection */ mgtSectionPtr_t mgtSectPtr = (mgtSectionPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(mgtSection_t)+sizeof(memId_t))) + 1); if (mgtSectPtr == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } DS_U8 *p = section; /* parse section */ DS_U16 table_id_extension = p[3]*256+p[4];//(p[nPos++]*256) + p[nPos++]; if (table_id_extension != 0x0000) { /*if (0) DST_Printf("MGT: table_id_extension != 0x0000");*/ } if (0) DST_Printf("table_id_extension=%d\n",table_id_extension); mgtSectPtr->version_number = (p[5] >> 1) & 0x1F; int current_next_indicator = p[5]&0x01; if (0) DST_Printf("mgtSectPtr->version_number=%d\n",mgtSectPtr->version_number); if (0) DST_Printf("current_next_indicator=%d\n",current_next_indicator); if (current_next_indicator != 1) { if (0) DST_Printf("MGT: current_next_indicator != 1\n"); } int section_number = p[6]; if (0) DST_Printf("section_number=%d\n",section_number); if (section_number != 0x00) { if (0) DST_Printf("MGT: section_number != 0x00\n"); } int last_section_number = p[7]; if (0) DST_Printf("last_section_number=%d\n",last_section_number); if (last_section_number != 0x00) { if (0) DST_Printf("MGT: last_section_number != 0x00\n"); } int protocol_version = p[8]; if (0) DST_Printf("protocol_version=%d\n",protocol_version); if (protocol_version > 0x00/* PSIP_PROTOCOL_VERSION*/) { memChainDestroy(memId); return DHL_FAIL_INVALID_VERSION; } int count_i = mgtSectPtr->tables_defined = p[9]*256 + p[10]; mgtSectPtr->table = (mgtTablePtr_t)memChainAlloc(memId,count_i*sizeof(mgtTable_t)); if (mgtSectPtr->table == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } int nPos = 11; int i; for ( i=0; itable[i].table_type = (table_type_k)(p[nPos]*256 + p[nPos+1]); nPos += 2; mgtSectPtr->table[i].table_type_PID = (p[nPos]&0x1F)*256 + p[nPos+1]; nPos += 2; mgtSectPtr->table[i].table_type_version_number = p[nPos++]&0x1F; mgtSectPtr->table[i].number_bytes = p[nPos] * 0x1000000 + p[nPos+1] * 0x10000 + p[nPos+2] * 0x100 + p[nPos+3]; nPos += 4; int count_j = mgtSectPtr->table[i].descriptor_length= (p[nPos]&0x0F)*256 + p[nPos+1]; nPos += 2; mgtSectPtr->table[i].descriptors = (DS_U8 *)memChainAlloc(memId,count_j); if (mgtSectPtr->table[i].descriptors == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } int j; for ( j=0; jtable[i].descriptors[j] = p[nPos++]; } } count_i = mgtSectPtr->descriptor_length = (p[nPos]&0x0F)*256 + p[nPos+1]; nPos += 2; mgtSectPtr->descriptors = (DS_U8 *)memChainAlloc(memId,count_i); if (mgtSectPtr->descriptors == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } for ( i=0; idescriptors[i] = p[nPos++]; } mgtSectPtr->CRC32 = p[nPos] * 0x1000000 + p[nPos+1] * 0x10000 + p[nPos+2] * 0x100 + p[nPos+3]; nPos += 4; /* parsing complete */ *(((memId_t *)mgtSectPtr)-1) = memId; memId = 0; /* so memChain not deleted */ //ParseExit: memChainDestroy(memId); *mgtSectionPtr = mgtSectPtr; return 0; } #if EPG_SUPPORT /*============================================================================== DHL_RESULT DHL_PSI_ParseEIT (DS_U8 **sectionArr, eitPtr_t *eitPtr) **sectionArr: Array of pointers to all EIT sections. *eitPtr: Returned pointer to the parsed EIT. Parses an EIT and returns the parsed table via the return pointer. ==============================================================================*/ int DHL_PSI_ParseEIT (DS_U8 **sectionArr, eitPtr_t *eitPtr) { // DS_U8 numSections; // DS_U16 numEvents; // DS_U16 section_length; // DS_U8 protocol_version; // DS_U16 i,j,k; // DS_U16 count_j, count_k; // memChainSetup_t memSetup = {MEM_LIMIT,0,0}; // memId_t memId = 0; // bitBufferPtr_t bits = 0; // DHL_RESULT err; if (sectionArr == 0 || (eitPtr == 0)) { return (DHL_FAIL_NULL_POINTER); } if (sectionArr[0] == 0) { return (DHL_FAIL_NULL_POINTER); } int numSections = get_last_section_number(sectionArr[0]) + 1; /* now verify all other sections are present */ int i; for ( i=1; inumEvents = numEvents; /* allocate space in eit for events */ (*eitPtr)->event = (eitEventPtr_t)memChainAlloc(memId,numEvents*sizeof(eitEvent_t)); if ((*eitPtr)->event == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } /* Parse each section and copy channels */ numEvents = 0; for ( i=0; isource_id = p[0] * 256 + p[1]; //bitBufferSkipBits(bits,2); /* reserved */ (*eitPtr)->version_number = (p[2] >> 1) & 0x1F; //bitBufferSkipBits(bits,1); /* current_next_indicator */ //bitBufferSkipBits(bits,8); /* section_number */ //bitBufferSkipBits(bits,8); /* last_section_number */ int protocol_version = p[5]; if (protocol_version > 0/*PSIP_PROTOCOL_VERSION*/) { memChainDestroy(memId); return DHL_FAIL_INVALID_VERSION; } int count_j = p[6];//bitBufferGetBits(bits,8); int nPos = 7; int j; for ( j=0; jevent[numEvents].event_id = (p[nPos]&0x3F)*0x100 + p[nPos+1]; //bitBufferGetBits(bits,14); nPos += 2; (*eitPtr)->event[numEvents].start_time = p[nPos] * 0x1000000 + p[nPos+1] * 0x10000 + p[nPos+2] * 0x100 + p[nPos+3];//bitBufferGetBits(bits,32); nPos += 4; //bitBufferSkipBits(bits,2); /* reserved */ (*eitPtr)->event[numEvents].ETM_location = (ETM_location_k)((p[nPos] >> 4) & 0x03); //(ETM_location_k)bitBufferGetBits(bits,2); (*eitPtr)->event[numEvents].length_in_seconds = (p[nPos]&0x0F) * 0x10000 + p[nPos+1] * 0x100 + p[nPos+2];//bitBufferGetBits(bits,20); nPos += 3; int count_k = (*eitPtr)->event[numEvents].title_length = p[nPos]; //bitBufferGetBits(bits,8); nPos += 1; (*eitPtr)->event[numEvents].title = (DS_U8 *)memChainAlloc(memId, count_k); //checkMemoryError((*eitPtr)->event[numEvents].title); if ((*eitPtr)->event[numEvents].title == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } int k; for ( k=0; kevent[numEvents].title[k] = p[nPos++]; } //bitBufferSkipBits(bits,4); /* reserved */ count_k = (*eitPtr)->event[numEvents].descriptor_length= (p[nPos]&0x0F) * 0x100 + p[nPos+1] ;//bitBufferGetBits(bits,12); nPos += 2; (*eitPtr)->event[numEvents].descriptors = (DS_U8 *)memChainAlloc(memId,count_k); if ((*eitPtr)->event[numEvents].descriptors == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } // int k; for ( k=0; kevent[numEvents].descriptors[k]= p[nPos++]; } numEvents++; } // bitBufferDestroy(bits); // bits = 0; } /* parsing complete */ *(((memId_t *)(*eitPtr))-1) = memId; memId = 0; /* so memChain not deleted */ //ParseExit: // if (bits) { // bitBufferDestroy(bits); // } if (memId) { /* delete the cvct memory */ memChainDestroy(memId); } return 0; } #endif #if EPG_SUPPORT /*============================================================================== DHL_RESULT DHL_PSI_ParseETTSection (DS_U8 *section, ettSectionPtr_t *ettSectionPtr) *section: Pointer to the first byte of the section. *ettSectionPtr: Return pointer to a parsed ETT section. Parses an ETT section and returns the decoded section via the provided handle. ==============================================================================*/ int DHL_PSI_ParseETTSection (DS_U8 *section, ettSectionPtr_t *ettSectionPtr) { if (get_section_syntax_indicator(section) == 0) { if (0) DST_Printf("ETT: section_syntax_indicator not set\n"); } if (get_private_indicator(section) == 0) { if (0) DST_Printf("ETT: private_indicator not set\n"); } int section_length = get_section_length(section); if (section_length > 4093) { if (0) DST_Printf("ETT: section_length=%d\n",section_length); return DHL_FAIL_INVALID_PARAM; } /* create the memChain */ memId_t memId = 0; if (memChainCreate(&memId)) { return DHL_FAIL_OUT_OF_RESOURCE; } /* allocate memory for ettSection */ ettSectionPtr_t ettSectPtr = (ettSectionPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(ettSection_t)+sizeof(memId_t))) + 1); //checkMemoryError(ettSectPtr); if (ettSectPtr == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } /* parse section */ DS_U8 *p = §ion[3]; int table_id_extension = p[0] * 0x100 + p[1]; if (table_id_extension != 0x0000) { /*if (0) DST_Printf("ETT: table_id_extension != 0x0000\n");*/ } ettSectPtr->version_number = (p[2]>>1)&0x1F; int current_next_indicator = p[2] & 0x01; if (current_next_indicator != 1) { if (0) DST_Printf("ETT: current_next_indicator != 1\n"); } int section_number = p[3]; //if (0) DST_Printf("section_number=%d\n",section_number); if (section_number != 0x00) { if (0) DST_Printf("ETT: section_number != 0x00\n"); } int last_section_number = p[4]; //if (0) DST_Printf("last_section_number=%d\n",last_section_number); if (last_section_number != 0x00) { if (0) DST_Printf("ETT: last_section_number != 0x00\n"); } int protocol_version = p[5]; //if (0) DST_Printf("protocol_version=%d\n",protocol_version); //T(); if (protocol_version > 0/*PSIP_PROTOCOL_VERSION*/) { memChainDestroy(memId); return DHL_FAIL_INVALID_VERSION; } ettSectPtr->ETM_id = p[6]*0x1000000 + p[7]*0x10000 + p[8]*0x100 + p[9]; //if (0) DST_Printf("ettSectPtr->ETM_id=%d\n",ettSectPtr->ETM_id); int count_i = ettSectPtr->extended_text_message_length = section_length - 14; ettSectPtr->extended_text_message = (DS_U8 *)memChainAlloc(memId, count_i); if (ettSectPtr->extended_text_message == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } int i; for ( i=0; iextended_text_message[i] = p[10+i]; } /* parsing complete */ *(((memId_t *)ettSectPtr)-1) = memId; memId = 0; /* so memChain not deleted */ if (memId) { /* delete the cvctSection memory */ memChainDestroy(memId); } *ettSectionPtr = ettSectPtr; return 0; } #endif #if CVCT_SUPPORT /*============================================================================== DHL_RESULT DHL_PSI_ParseCVCTSection (DS_U8 *section, cvctSectionPtr_t *cvctSectionPtr) *section: Pointer to the first byte of the section. *cvctSectionPtr: Return pointer to a parsed CVCT section. Parses an CVCT section and returns the decoded section via the provided handle. ==============================================================================*/ static int DHL_PSI_ParseCVCTSection (DS_U8 *section, cvctSectionPtr_t *cvctSectionPtr) { // cvctSectionPtr_t cvctSectPtr = 0; // memChainSetup_t memSetup = {MEM_LIMIT,0,0}; // DS_U16 section_length; // DS_U8 protocol_version; // // bitBufferPtr_t bits = 0; // DS_S32 count_i,count_j; // DS_S32 i,j; // DHL_RESULT err = DHL_OK; if (get_section_syntax_indicator(section) == 0) { if (0) DST_Printf("CVCT: section_syntax_indicator not set\n"); } if (get_private_indicator(section) == 0) { if (0) DST_Printf("CVCT: private_indicator not set\n"); } DS_U16 section_length = get_section_length(section); if (section_length > 1021) { if (0) DST_Printf("CVCT: section_length=%d\n",section_length); return DHL_FAIL_INVALID_PARAM; } memId_t memId = 0; if (memChainCreate(&memId)) /* create the memChain */ { return DHL_FAIL_OUT_OF_RESOURCE; } /* allocate memory for cvctSection */ cvctSectionPtr_t cvctSectPtr = (cvctSectionPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(cvctSection_t)+sizeof(memId_t))) + 1); if (cvctSectPtr == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } DS_U8 *p = section + 3; /* parse section */ cvctSectPtr->transport_stream_id = p[0] * 0x100 + p[1]; //bitBufferSkipBits(bits,2); /* reserved */ cvctSectPtr->version_number = (p[2] >> 1) & 0x1F; cvctSectPtr->current_next_indicator = p[2] & 0x01; cvctSectPtr->section_number = p[3]; cvctSectPtr->last_section_number = p[4]; DS_U8 protocol_version = p[5]; if (protocol_version > 0 /*PSIP_PROTOCOL_VERSION*/) { memChainDestroy(memId); return DHL_FAIL_INVALID_VERSION; } int count_i = cvctSectPtr->num_channels_in_section = p[6]; cvctSectPtr->channel = (cvctChannelPtr_t)memChainAlloc(memId,count_i*sizeof(cvctChannel_t)); if (cvctSectPtr->channel == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } p += 7; int nPos = 0; int i; for ( i=0; ichannel[i].short_name[j] = p[nPos] * 0x100 + p[nPos+1]; nPos+=2; } //bitBufferSkipBits(bits,4); /* reserved */ cvctSectPtr->channel[i].major_channel_number = ((p[nPos] >> 4) & 0x0F) * 0x40 + ((p[nPos+1] >> 2) & 0x3F); #ifdef ENABLE_SYNTAX_CHECKING if (cvctSectPtr->channel[i].major_channel_number < CABL_MAJOR_CHAN_MIN || cvctSectPtr->channel[i].major_channel_number > CABL_MAJOR_CHAN_MAX) { if (0) DST_Printf("CVCT: major_channel_number=%d\n",cvctSectPtr->channel[i].major_channel_number); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } #endif /* ENABLE_SYNTAX_CHECKING */ cvctSectPtr->channel[i].minor_channel_number = (p[nPos+1] & 0x03) * 0x100 + p[nPos+2]; #ifdef ENABLE_SYNTAX_CHECKING if (cvctSectPtr->channel[i].minor_channel_number > CABL_MINOR_CHAN_MAX) { if (0) DST_Printf("CVCT: minor_channel_number=%d\n",cvctSectPtr->channel[i].minor_channel_number); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } #endif /* ENABLE_SYNTAX_CHECKING */ nPos+=3; cvctSectPtr->channel[i].modulation_mode = (modulation_mode_k)p[nPos++]; cvctSectPtr->channel[i].carrier_frequency = p[nPos] * 0x1000000 + p[nPos+1] * 0x10000 + p[nPos+2] * 0x100 + p[nPos+3]; nPos+=4; cvctSectPtr->channel[i].channel_TSID = p[nPos] * 0x100 + p[nPos+1]; nPos+=2; cvctSectPtr->channel[i].program_number = p[nPos] * 0x100 + p[nPos+1]; nPos+=2; cvctSectPtr->channel[i].ETM_location = (ETM_location_k)((p[nPos] >> 6) & 0x03); cvctSectPtr->channel[i].access_controlled = ((p[nPos] >> 5) & 0x01); cvctSectPtr->channel[i].hidden = ((p[nPos] >> 4) & 0x01); cvctSectPtr->channel[i].path_select = (path_select_k) ((p[nPos] >> 3) & 0x01); cvctSectPtr->channel[i].out_of_band = ((p[nPos] >> 2) & 0x01); cvctSectPtr->channel[i].show_guide = ((p[nPos] >> 1) & 0x01); //bitBufferSkipBits(bits,3); /* reserved */ nPos++; cvctSectPtr->channel[i].service_type = (service_type_k)(p[nPos++] & 0x3F); cvctSectPtr->channel[i].source_id = p[nPos] * 0x100 + p[nPos+1]; nPos+=2; //bitBufferSkipBits(bits,6); /* reserved */ int count_j = cvctSectPtr->channel[i].descriptor_length = (p[nPos]&0x03) * 0x100 + p[nPos+1]; nPos+=2; cvctSectPtr->channel[i].descriptors = (DS_U8 *)memChainAlloc(memId,count_j); if (cvctSectPtr->channel[i].descriptors == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } // int j; for ( j=0; jchannel[i].descriptors[j] = p[nPos++]; } } //bitBufferSkipBits(bits,6); /* reserved */ cvctSectPtr->additional_descriptors = (DS_U8 *)memChainAlloc(memId,count_i); if (cvctSectPtr->additional_descriptors == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } for ( i=0; iadditional_descriptors[i] = p[nPos++]; } /* parsing complete */ *(((memId_t *)cvctSectPtr)-1) = memId; memId = 0; /* so memChain not deleted */ //ParseExit: if (memId) { /* delete the cvctSection memory */ memChainDestroy(memId); } *cvctSectionPtr = cvctSectPtr; return 0; } #endif #if CVCT_SUPPORT /*============================================================================== DHL_RESULT DHL_PSI_ParseCVCT (DS_U8 **sectionArr, cvctPtr_t *cvctPtr) **sectionArr: Array of pointers to all CVCT sections. *cvctPtr: Returned pointer to the parsed CVCT. Parses an CVCT and returns the parsed table via the return pointer. ==============================================================================*/ int DHL_PSI_ParseCVCT (DS_U8 **sectionArr, cvctPtr_t *cvctPtr) { // DS_U8 numSections; // DS_U16 numChannels; // // DS_U16 i,j; // memChainSetup_t memSetup = {MEM_LIMIT_BIG,0,0}; // memId_t memId = 0; // DHL_RESULT err; if (sectionArr == 0 || (cvctPtr == 0)) { return (DHL_FAIL_NULL_POINTER); } if (sectionArr[0] == 0) { return (DHL_FAIL_NULL_POINTER); } DS_U8 numSections = get_last_section_number(sectionArr[0]) + 1; /* now verify all other sections are present */ int i; for ( i=1; inumChannels = numChannels; /* allocate space in cvct for channels */ (*cvctPtr)->channel = (cvctChannelPtr_t)memChainAlloc(memId,numChannels*sizeof(cvctChannel_t)); if ((*cvctPtr)->channel == 0) { memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } /* Parse each section and copy channels */ numChannels = 0; for ( i=0; itransport_stream_id = cvctSectPtr->transport_stream_id; (*cvctPtr)->version_number = cvctSectPtr->version_number; /* allocate space for descriptors and copy (if any) */ if (cvctSectPtr->additional_descriptor_length > 0) { (*cvctPtr)->additional_descriptors = (DS_U8 *)memChainAlloc(memId,cvctSectPtr->additional_descriptor_length*sizeof(DS_U8)); if ((*cvctPtr)->additional_descriptors == 0) { DHL_PSI_FreeMpegSection(cvctSectPtr); memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } memcpy((*cvctPtr)->additional_descriptors,cvctSectPtr->additional_descriptors, (*cvctPtr)->additional_descriptor_length); } } int j; for ( j=0; jnum_channels_in_section; j++) { memcpy(&((*cvctPtr)->channel[numChannels]), &(cvctSectPtr->channel[j]), sizeof(cvctChannel_t)); /* allocate space for descriptors and copy (if any) */ if (cvctSectPtr->channel[j].descriptor_length > 0) { (*cvctPtr)->channel[numChannels].descriptors = (DS_U8 *)memChainAlloc(memId,cvctSectPtr->channel[j].descriptor_length*sizeof(DS_U8)); if ((*cvctPtr)->channel[numChannels].descriptors == 0) { DHL_PSI_FreeMpegSection(cvctSectPtr); memChainDestroy(memId); return DHL_FAIL_OUT_OF_RESOURCE; } /*memcpy((*cvctPtr)->channel[numChannels].descriptors,cvctSectPtr->channel[j].descriptors, (*cvctPtr)->channel[j].descriptor_length);*/ /*cafrii 030910, bugfix*/ memcpy((*cvctPtr)->channel[numChannels].descriptors,cvctSectPtr->channel[j].descriptors, (*cvctPtr)->channel[numChannels].descriptor_length); } numChannels++; } DHL_PSI_FreeMpegSection(cvctSectPtr); } /* parsing complete */ *(((memId_t *)(*cvctPtr))-1) = memId; memId = 0; /* so memChain not deleted */ //ParseExit: if (memId) { /* delete the cvct memory */ memChainDestroy(memId); } return 0; } #endif