| /* | |
| * GPAC - Multimedia Framework C SDK | |
| * | |
| * Authors: Jonathan Sillan, Jean Le Feuvre | |
| * Copyright (c) Telecom ParisTech 2011-2023 | |
| * All rights reserved | |
| * | |
| * This file is part of GPAC / media tools sub-project | |
| * | |
| * GPAC is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation; either version 2, or (at your option) | |
| * any later version. | |
| * | |
| * GPAC is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; see the file COPYING. If not, write to | |
| * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| */ | |
| #include <gpac/dsmcc.h> | |
| #ifdef GPAC_ENABLE_DSMCC | |
| /* DSMCC */ | |
| /* static functions */ | |
| static GF_Err dsmcc_download_data_validation(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 downloadId); | |
| static GF_Err gf_m2ts_dsmcc_process_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc, char* data,GF_BitStream *bs,u32* data_shift); | |
| static GF_Err gf_m2ts_dsmcc_process_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader, char* data,GF_BitStream *bs,u32* data_shift,u32 mode); | |
| static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char *data, GF_BitStream *bs,u32* data_shift); | |
| static GF_Err gf_m2ts_dsmcc_section_delete(GF_M2TS_DSMCC_SECTION *dsmcc); | |
| static GF_Err gf_m2ts_dsmcc_delete_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader); | |
| static GF_Err gf_m2ts_dsmcc_delete_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc); | |
| static GF_Err dsmcc_module_delete(GF_M2TS_DSMCC_MODULE* dsmcc_module); | |
| //static GF_Err dsmcc_module_state(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 moduleId,u32 moduleVersion); | |
| static GF_Err dsmcc_create_module_validation(GF_M2TS_DSMCC_INFO_MODULES* InfoModules, u32 downloadId, GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 nb_module); | |
| static GF_Err dsmcc_module_complete(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 moduleIndex); | |
| static GF_Err dsmcc_get_biop_module_info(GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u8 data_size); | |
| static GF_M2TS_DSMCC_MODULE* dsmcc_create_module(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord, GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication); | |
| /* BIOP */ | |
| static GF_Err dsmcc_process_biop_data(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u32 data_size); | |
| static GF_M2TS_DSMCC_BIOP_HEADER* dsmcc_process_biop_header(GF_BitStream* bs); | |
| static GF_Err dsmcc_process_biop_file(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,u16 moduleId,u32 downloadId); | |
| static GF_Err dsmcc_process_biop_directory(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,Bool IsServiceGateway); | |
| static GF_Err dsmcc_process_biop_stream_event(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway); | |
| static GF_Err dsmcc_process_biop_stream_message(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway); | |
| /* Tools */ | |
| static void dsmcc_biop_get_context(GF_BitStream* bs,GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count); | |
| static void dsmcc_biop_descriptor(GF_BitStream* bs,GF_List* list,u32 size); | |
| static GF_Err dsmcc_biop_get_ior(GF_BitStream* bs,GF_M2TS_DSMCC_IOR* IOR); | |
| static GF_M2TS_DSMCC_DIR* dsmcc_get_directory(GF_List* List, u32 objectKey_data); | |
| static GF_M2TS_DSMCC_FILE* dsmcc_get_file(GF_List* ServiceGatewayList,u16 moduleId,u32 downloadId,u32 objectKey_data); | |
| static GF_Err dsmcc_check_element_validation(GF_List* List,char* Parent_name,GF_M2TS_DSMCC_BIOP_NAME Name); | |
| static char* dsmcc_get_file_namepath(GF_M2TS_DSMCC_DIR* Dir,char* name); | |
| /* Free */ | |
| static void dsmcc_free_biop_context(GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count); | |
| static void dsmcc_free_biop_name(GF_M2TS_DSMCC_BIOP_NAME* Name, u32 nb_name); | |
| static void dsmcc_free_biop_descriptor(GF_List* list); | |
| static void dsmcc_free_biop_ior(GF_M2TS_DSMCC_IOR* IOR); | |
| static void dsmcc_free_biop_header(GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header); | |
| static void dsmcc_free_biop_directory(GF_M2TS_DSMCC_BIOP_DIRECTORY* BIOP_Directory); | |
| static void dsmcc_free_biop_file(GF_M2TS_DSMCC_BIOP_FILE* BIOP_File); | |
| static void dsmcc_free_biop_stream_event(GF_M2TS_DSMCC_BIOP_STREAM_EVENT* BIOP_StreamEvent); | |
| static void dsmcc_free_biop_stream_message(GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE* BIOP_StreamMessage); | |
| GF_EXPORT | |
| GF_M2TS_DSMCC_OVERLORD* gf_m2ts_init_dsmcc_overlord(u32 service_id) { | |
| GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord; | |
| GF_SAFEALLOC(dsmcc_overlord,GF_M2TS_DSMCC_OVERLORD); | |
| dsmcc_overlord->dsmcc_modules = gf_list_new(); | |
| dsmcc_overlord->service_id = service_id; | |
| return dsmcc_overlord; | |
| } | |
| GF_EXPORT | |
| GF_M2TS_DSMCC_OVERLORD* gf_m2ts_get_dmscc_overlord(GF_List* Dsmcc_controller,u32 service_id) | |
| { | |
| u16 nb_dsmcc,i; | |
| nb_dsmcc = gf_list_count(Dsmcc_controller); | |
| if(!nb_dsmcc) { | |
| return NULL; | |
| } else { | |
| for(i =0; i<nb_dsmcc; i++) { | |
| GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord = (GF_M2TS_DSMCC_OVERLORD*)gf_list_get(Dsmcc_controller,i); | |
| if(dsmcc_overlord->service_id == service_id) { | |
| return dsmcc_overlord; | |
| } | |
| } | |
| } | |
| return NULL; | |
| } | |
| void on_dsmcc_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) | |
| { | |
| GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)par; | |
| char *data; | |
| u32 u32_data_size; | |
| u32 u32_table_id; | |
| GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord; | |
| dsmcc_overlord = gf_m2ts_get_dmscc_overlord(ts->dsmcc_controler,pck->stream->service_id); | |
| if (dsmcc_overlord && evt_type == GF_M2TS_EVT_DSMCC_FOUND) { | |
| GF_Err e; | |
| GF_M2TS_DSMCC_SECTION* dsmcc; | |
| data = pck->data; | |
| u32_data_size = pck->data_len; | |
| u32_table_id = data[0]; | |
| GF_SAFEALLOC(dsmcc,GF_M2TS_DSMCC_SECTION); | |
| e = gf_m2ts_process_dsmcc(dsmcc_overlord,dsmcc,data,u32_data_size,u32_table_id); | |
| if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_DSMCC_FOUND, pck); | |
| gf_assert(e == GF_OK); | |
| } | |
| } | |
| GF_EXPORT | |
| GF_Err gf_m2ts_process_dsmcc(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char *data, u32 data_size, u32 table_id) | |
| { | |
| GF_BitStream *bs; | |
| u32 data_shift,reserved_test; | |
| data_shift = 0; | |
| //first_section = *first_section_received; | |
| bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ); | |
| dsmcc->table_id = gf_bs_read_int(bs,8); | |
| dsmcc->section_syntax_indicator = gf_bs_read_int(bs,1); | |
| dsmcc->private_indicator = gf_bs_read_int(bs,1); | |
| reserved_test = gf_bs_read_int(bs,2); | |
| if (reserved_test != 3) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] test reserved flag is not at 3. Corrupted section, abording processing\n")); | |
| gf_bs_del(bs); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| dsmcc->dsmcc_section_length = gf_bs_read_int(bs,12); | |
| if (dsmcc->dsmcc_section_length > DSMCC_SECTION_LENGTH_MAX) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] section length should not exceed 4096. Wrong section, abording processing \n")); | |
| gf_bs_del(bs); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| dsmcc->table_id_extension = gf_bs_read_int(bs,16); | |
| /*bit shifting */ | |
| gf_bs_read_int(bs,2); | |
| dsmcc->version_number = gf_bs_read_int(bs,5); | |
| if(dsmcc->version_number != 0 &&(dsmcc->table_id == GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA || dsmcc->table_id == GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE)) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Version number should be 0 for Encapsulated Data or UN Message, abording processing \n")); | |
| gf_bs_del(bs); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| dsmcc->current_next_indicator = gf_bs_read_int(bs,1); | |
| if (!dsmcc->current_next_indicator) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] current next indicator should be at 1 \n")); | |
| gf_bs_del(bs); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| dsmcc->section_number = gf_bs_read_int(bs,8); | |
| /*if(dsmcc->section_number >0 && ((*first_section_received) == 0)){ | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Wainting for the first section \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| *first_section_received = 1;*/ | |
| dsmcc->last_section_number = gf_bs_read_int(bs,8); | |
| switch (dsmcc->table_id) { | |
| case GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA: | |
| { | |
| data_shift = (u32)(gf_bs_get_position(bs)); | |
| break; | |
| } | |
| case GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE: | |
| case GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE: | |
| { | |
| data_shift = (u32)(gf_bs_get_position(bs)); | |
| gf_m2ts_dsmcc_download_data(dsmcc_overlord,dsmcc,data,bs,&data_shift); | |
| break; | |
| } | |
| case GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION: | |
| { | |
| data_shift = (u32)(gf_bs_get_position(bs)); | |
| break; | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unknown DSMCC Section Type \n")); | |
| break; | |
| } | |
| } | |
| if (dsmcc->section_syntax_indicator == 0) { | |
| dsmcc->checksum = gf_bs_read_int(bs,32); | |
| } else { | |
| dsmcc->CRC_32= gf_bs_read_int(bs,32); | |
| } | |
| data_shift = (u32)(gf_bs_get_position(bs)); | |
| /*if(data_shift != dsmcc->dsmcc_section_length){. | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] AIT processed length error. Difference between byte shifting %d and data size %d \n",data_shift,data_size)); | |
| return GF_CORRUPTED_DATA; | |
| }*/ | |
| //gf_m2ts_dsmcc_extract_info(ts,dsmcc); | |
| gf_m2ts_dsmcc_section_delete(dsmcc); | |
| gf_bs_del(bs); | |
| return GF_OK; | |
| } | |
| static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char *data, GF_BitStream *bs,u32* data_shift) | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE* DataMessage; | |
| GF_SAFEALLOC(DataMessage,GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE); | |
| /* Header */ | |
| gf_m2ts_dsmcc_process_message_header(&DataMessage->DownloadDataHeader,data,bs,data_shift,1); | |
| dsmcc->DSMCC_Extension = DataMessage; | |
| switch (DataMessage->DownloadDataHeader.messageId) | |
| { | |
| case DOWNLOAD_INFO_REQUEST: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST* DownloadInfoRequest; | |
| GF_SAFEALLOC(DownloadInfoRequest,GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST); | |
| DataMessage->dataMessagePayload = DownloadInfoRequest; | |
| /* Payload */ | |
| DownloadInfoRequest->bufferSize = gf_bs_read_int(bs,32); | |
| DownloadInfoRequest->maximumBlockSize = gf_bs_read_int(bs,16); | |
| gf_m2ts_dsmcc_process_compatibility_descriptor(&DownloadInfoRequest->CompatibilityDescr,data,bs,data_shift); | |
| DownloadInfoRequest->privateDataLength = gf_bs_read_int(bs,16); | |
| DownloadInfoRequest->privateDataByte = (char*)gf_calloc(DownloadInfoRequest->privateDataLength,sizeof(char)); | |
| gf_bs_read_data(bs,DownloadInfoRequest->privateDataByte,(u32)(DownloadInfoRequest->privateDataLength)); | |
| break; | |
| } | |
| case DOWNLOAD_INFO_REPONSE_INDICATION: | |
| { | |
| u32 i,nb_modules; | |
| GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication; | |
| GF_SAFEALLOC(DownloadInfoIndication,GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC); | |
| DataMessage->dataMessagePayload = DownloadInfoIndication; | |
| /* Payload */ | |
| DownloadInfoIndication->downloadId = gf_bs_read_int(bs,32); | |
| DownloadInfoIndication->blockSize = gf_bs_read_int(bs,16); | |
| DownloadInfoIndication->windowSize = gf_bs_read_int(bs,8); | |
| DownloadInfoIndication->ackPeriod = gf_bs_read_int(bs,8); | |
| DownloadInfoIndication->tCDownloadWindow = gf_bs_read_int(bs,32); | |
| DownloadInfoIndication->tCDownloadScenario = gf_bs_read_int(bs,32); | |
| /* Compatibility Descr */ | |
| gf_m2ts_dsmcc_process_compatibility_descriptor(&DownloadInfoIndication->CompatibilityDescr,data,bs,data_shift); | |
| DownloadInfoIndication->numberOfModules = gf_bs_read_int(bs,16); | |
| /* Versioning of the DownloadInfoIndication is made by the field transactionId (here known as downloadId) */ | |
| if(DataMessage->DownloadDataHeader.downloadId > dsmcc_overlord->transactionId) { | |
| dsmcc_overlord->transactionId = DataMessage->DownloadDataHeader.downloadId; | |
| nb_modules = gf_list_count(dsmcc_overlord->dsmcc_modules); | |
| for(i = 0; i<DownloadInfoIndication->numberOfModules; i++) { | |
| DownloadInfoIndication->Modules.moduleId = gf_bs_read_int(bs,16); | |
| DownloadInfoIndication->Modules.moduleSize = gf_bs_read_int(bs,32); | |
| DownloadInfoIndication->Modules.moduleVersion = gf_bs_read_int(bs,8); | |
| DownloadInfoIndication->Modules.moduleInfoLength = gf_bs_read_int(bs,8); | |
| DownloadInfoIndication->Modules.moduleInfoByte = (char*)gf_calloc(DownloadInfoIndication->Modules.moduleInfoLength,sizeof(char)); | |
| gf_bs_read_data(bs,DownloadInfoIndication->Modules.moduleInfoByte,(u32)(DownloadInfoIndication->Modules.moduleInfoLength)); | |
| if(!dsmcc_create_module_validation(&DownloadInfoIndication->Modules,DownloadInfoIndication->downloadId,dsmcc_overlord,nb_modules)) { | |
| /* Creation of the module */ | |
| GF_M2TS_DSMCC_MODULE*dsmcc_module = dsmcc_create_module(dsmcc_overlord,DownloadInfoIndication); | |
| if(DownloadInfoIndication->Modules.moduleInfoLength) { | |
| GF_Err e; | |
| e = dsmcc_get_biop_module_info(dsmcc_module,DownloadInfoIndication->Modules.moduleInfoByte,DownloadInfoIndication->Modules.moduleInfoLength); | |
| if(e) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in BIOP Module Info for module %d, abording the processing \n",dsmcc_module->moduleId)); | |
| gf_free(DownloadInfoIndication->Modules.moduleInfoByte); | |
| DownloadInfoIndication->Modules.moduleInfoByte = NULL; | |
| return GF_CORRUPTED_DATA; | |
| } | |
| } | |
| } | |
| gf_free(DownloadInfoIndication->Modules.moduleInfoByte); | |
| DownloadInfoIndication->Modules.moduleInfoByte = NULL; | |
| } | |
| DownloadInfoIndication->privateDataLength = gf_bs_read_int(bs,16); | |
| DownloadInfoIndication->privateDataByte = (char*)gf_calloc(DownloadInfoIndication->privateDataLength,sizeof(char)); | |
| gf_bs_read_data(bs,DownloadInfoIndication->privateDataByte,(u32)(DownloadInfoIndication->privateDataLength)); | |
| } | |
| break; | |
| } | |
| case DOWNLOAD_DATA_BLOCK: | |
| { | |
| u32 modules_count, i; | |
| GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock; | |
| GF_SAFEALLOC(DownloadDataBlock,GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK); | |
| DataMessage->dataMessagePayload = DownloadDataBlock; | |
| modules_count = gf_list_count(dsmcc_overlord->dsmcc_modules); | |
| if(!modules_count) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Download Information Indicator has not been received yet, waiting before processing data block \n")); | |
| break; | |
| } | |
| DownloadDataBlock->moduleId = gf_bs_read_int(bs,16); | |
| DownloadDataBlock->moduleVersion = gf_bs_read_int(bs,8); | |
| DownloadDataBlock->reserved = gf_bs_read_int(bs,8); | |
| if(DownloadDataBlock->reserved != 0xFF) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader reserved slot does not have the correct value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| DownloadDataBlock->blockNumber = gf_bs_read_int(bs,16); | |
| for(i=0; i<modules_count; i++) { | |
| GF_M2TS_DSMCC_MODULE* dsmcc_module = gf_list_get(dsmcc_overlord->dsmcc_modules,i); | |
| /* Test if the data are compatible with the module configuration */ | |
| if(!dsmcc_download_data_validation(dsmcc_overlord,DownloadDataBlock,dsmcc_module,DataMessage->DownloadDataHeader.downloadId)) { | |
| DownloadDataBlock->dataBlocksize = (DataMessage->DownloadDataHeader.messageLength - 6); | |
| if(dsmcc_module->block_size < DownloadDataBlock->dataBlocksize) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error block_size should be >= to DownloadDataBlock->dataBlocksize , abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| DownloadDataBlock->blockDataByte = (char*)gf_calloc(DownloadDataBlock->dataBlocksize,sizeof(char)); | |
| *data_shift = (u32)(gf_bs_get_position(bs)); | |
| gf_bs_read_data(bs,DownloadDataBlock->blockDataByte,DownloadDataBlock->dataBlocksize); | |
| memcpy(dsmcc_module->buffer+dsmcc_module->byte_sift,DownloadDataBlock->blockDataByte,DownloadDataBlock->dataBlocksize*sizeof(char)); | |
| dsmcc_module->byte_sift += DownloadDataBlock->dataBlocksize; | |
| dsmcc_module->last_section_number = dsmcc->last_section_number; | |
| dsmcc_module->section_number++; | |
| if(dsmcc_module->section_number == (dsmcc_module->last_section_number+1)) { | |
| dsmcc_module_complete(dsmcc_overlord,dsmcc_module,i); | |
| } | |
| break; | |
| } | |
| } | |
| break; | |
| } | |
| case DOWNLOAD_DATA_REQUEST: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE* DownloadDataRequest; | |
| GF_SAFEALLOC(DownloadDataRequest,GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE); | |
| DataMessage->dataMessagePayload = DownloadDataRequest; | |
| DownloadDataRequest->moduleId = gf_bs_read_int(bs,16); | |
| DownloadDataRequest->blockNumber = gf_bs_read_int(bs,16); | |
| DownloadDataRequest->downloadReason = gf_bs_read_int(bs,8); | |
| break; | |
| } | |
| case DOWNLOAD_DATA_CANCEL: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_CANCEL* DownloadCancel; | |
| GF_SAFEALLOC(DownloadCancel,GF_M2TS_DSMCC_DOWNLOAD_CANCEL); | |
| DataMessage->dataMessagePayload = DownloadCancel; | |
| DownloadCancel->downloadId = gf_bs_read_int(bs,32); | |
| DownloadCancel->moduleId = gf_bs_read_int(bs,16); | |
| DownloadCancel->blockNumber = gf_bs_read_int(bs,16); | |
| DownloadCancel->downloadCancelReason = gf_bs_read_int(bs,8); | |
| DownloadCancel->reserved = gf_bs_read_int(bs,8); | |
| DownloadCancel->privateDataLength = gf_bs_read_int(bs,16); | |
| if(DownloadCancel->privateDataLength) { | |
| DownloadCancel->privateDataByte = (char*)gf_calloc(DownloadCancel->privateDataLength,sizeof(char)); | |
| gf_bs_read_data(bs,DownloadCancel->privateDataByte,(u32)(DownloadCancel->privateDataLength)); | |
| } | |
| break; | |
| } | |
| case DOWNLOAD_SERVER_INITIATE: | |
| { | |
| GF_Err e; | |
| GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT* DownloadServerInit; | |
| GF_SAFEALLOC(DownloadServerInit,GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT); | |
| DataMessage->dataMessagePayload = DownloadServerInit; | |
| gf_bs_read_data(bs,DownloadServerInit->serverId,20); | |
| gf_m2ts_dsmcc_process_compatibility_descriptor(&DownloadServerInit->CompatibilityDescr,data,bs,data_shift); | |
| DownloadServerInit->privateDataLength = gf_bs_read_int(bs,16); | |
| if(DownloadServerInit->privateDataLength) { | |
| u32 i; | |
| GF_M2TS_DSMCC_SERVICE_GATEWAY_INFO* ServiceGateWayInfo; | |
| GF_SAFEALLOC(ServiceGateWayInfo,GF_M2TS_DSMCC_SERVICE_GATEWAY_INFO); | |
| /* IOR */ | |
| e = dsmcc_biop_get_ior(bs,&ServiceGateWayInfo->IOR); | |
| if(e) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Corrupted IOR, abording the processing \n")); | |
| gf_free(ServiceGateWayInfo); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| ServiceGateWayInfo->downloadTaps_count = gf_bs_read_int(bs,8); | |
| ServiceGateWayInfo->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(ServiceGateWayInfo->downloadTaps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS)); | |
| for(i=0; i<ServiceGateWayInfo->downloadTaps_count; i++) { | |
| ServiceGateWayInfo->Taps[i].id = gf_bs_read_int(bs,16); | |
| ServiceGateWayInfo->Taps[i].use = gf_bs_read_int(bs,16); | |
| ServiceGateWayInfo->Taps[i].assocTag = gf_bs_read_int(bs,16); | |
| ServiceGateWayInfo->Taps[i].selector_length = gf_bs_read_int(bs,8); | |
| ServiceGateWayInfo->Taps[i].selector_type = gf_bs_read_int(bs,16); | |
| ServiceGateWayInfo->Taps[i].transactionId = gf_bs_read_int(bs,32); | |
| ServiceGateWayInfo->Taps[i].timeout = gf_bs_read_int(bs,32); | |
| } | |
| ServiceGateWayInfo->serviceContextList_count = gf_bs_read_int(bs,8); | |
| ServiceGateWayInfo->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(ServiceGateWayInfo->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT)); | |
| dsmcc_biop_get_context(bs,ServiceGateWayInfo->ServiceContext,ServiceGateWayInfo->serviceContextList_count); | |
| ServiceGateWayInfo->userInfoLength = gf_bs_read_int(bs,16); | |
| if(ServiceGateWayInfo->userInfoLength != 0) { | |
| ServiceGateWayInfo->userInfo_data = (char*)gf_calloc(ServiceGateWayInfo->userInfoLength,sizeof(char)); | |
| gf_bs_read_data(bs,ServiceGateWayInfo->userInfo_data,(u32)(ServiceGateWayInfo->userInfoLength)); | |
| } | |
| if(!dsmcc_overlord->ServiceGateway && gf_list_count(ServiceGateWayInfo->IOR.taggedProfile)) { | |
| GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(ServiceGateWayInfo->IOR.taggedProfile,0); | |
| dsmcc_overlord->ServiceGateway = (GF_M2TS_DSMCC_SERVICE_GATEWAY*)gf_calloc(1,sizeof(GF_M2TS_DSMCC_SERVICE_GATEWAY)); | |
| dsmcc_overlord->ServiceGateway->downloadId = taggedProfile->BIOPProfileBody->ObjectLocation.carouselId; | |
| dsmcc_overlord->ServiceGateway->moduleId = taggedProfile->BIOPProfileBody->ObjectLocation.moduleId; | |
| dsmcc_overlord->ServiceGateway->service_id = dsmcc_overlord->service_id; | |
| dsmcc_overlord->ServiceGateway->File = gf_list_new(); | |
| dsmcc_overlord->ServiceGateway->Dir = gf_list_new(); | |
| } | |
| } | |
| break; | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unknown dataMessagePayload Type \n")); | |
| break; | |
| } | |
| } | |
| //dsmcc->DSMCC_Extension = DataMessage; | |
| return GF_OK; | |
| } | |
| static GF_Err gf_m2ts_dsmcc_process_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader, char* data,GF_BitStream *bs,u32* data_shift,u32 mode) | |
| { | |
| u32 byte_shift; | |
| byte_shift = *data_shift; | |
| MessageHeader->protocolDiscriminator = gf_bs_read_int(bs,8); | |
| if (MessageHeader->protocolDiscriminator != 0x11) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader Protocol Discriminator slot does not have the correct value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| MessageHeader->dsmccType = gf_bs_read_int(bs,8); | |
| MessageHeader->messageId = gf_bs_read_int(bs,16); | |
| /* mode 0 for Message Header - 1 for Download Data header */ | |
| if (mode == 0) { | |
| MessageHeader->transactionId = gf_bs_read_int(bs,32); | |
| } else if (mode == 1) { | |
| MessageHeader->downloadId = gf_bs_read_int(bs,32); | |
| } | |
| MessageHeader->reserved = gf_bs_read_int(bs,8); | |
| if (MessageHeader->reserved != 0xFF) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader reserved slot does not have the correct value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| MessageHeader->adaptationLength = gf_bs_read_int(bs,8); | |
| MessageHeader->header_length = ((u32)(gf_bs_get_position(bs)) - byte_shift); | |
| MessageHeader->messageLength = gf_bs_read_int(bs,16); | |
| if (MessageHeader->adaptationLength > 0) { | |
| MessageHeader->DsmccAdaptationHeader = (GF_M2TS_DSMCC_ADAPTATION_HEADER*)gf_calloc(1, sizeof(GF_M2TS_DSMCC_ADAPTATION_HEADER)); | |
| MessageHeader->DsmccAdaptationHeader->adaptationType = gf_bs_read_int(bs,8); | |
| MessageHeader->DsmccAdaptationHeader->adaptationDataByte = (char*)gf_calloc(MessageHeader->adaptationLength,sizeof(char)); | |
| gf_bs_read_data(bs,MessageHeader->DsmccAdaptationHeader->adaptationDataByte,(u32)(MessageHeader->adaptationLength)); | |
| } | |
| *data_shift = (u32)(gf_bs_get_position(bs)); | |
| return GF_OK; | |
| } | |
| static GF_Err gf_m2ts_dsmcc_process_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc, char* data,GF_BitStream *bs,u32* data_shift) | |
| { | |
| u32 i,j,byte_shift; | |
| byte_shift = (u32)(gf_bs_get_position(bs)); | |
| CompatibilityDesc->compatibilityDescriptorLength = gf_bs_read_int(bs,16); | |
| if(CompatibilityDesc->compatibilityDescriptorLength) { | |
| CompatibilityDesc->descriptorCount = gf_bs_read_int(bs,16); | |
| if(CompatibilityDesc->descriptorCount) { | |
| CompatibilityDesc->Descriptor = (GF_M2TS_DSMCC_DESCRIPTOR*)gf_calloc(CompatibilityDesc->descriptorCount,sizeof(GF_M2TS_DSMCC_DESCRIPTOR)); | |
| for(i=0; i<CompatibilityDesc->descriptorCount; i++) { | |
| CompatibilityDesc->Descriptor[i].descriptorType = gf_bs_read_int(bs,8); | |
| CompatibilityDesc->Descriptor[i].descriptorLength = gf_bs_read_int(bs,8); | |
| CompatibilityDesc->Descriptor[i].specifierType = gf_bs_read_int(bs,8); | |
| CompatibilityDesc->Descriptor[i].specifierData = gf_bs_read_int(bs,21); | |
| CompatibilityDesc->Descriptor[i].model = gf_bs_read_int(bs,16); | |
| CompatibilityDesc->Descriptor[i].version = gf_bs_read_int(bs,16); | |
| CompatibilityDesc->Descriptor[i].subDescriptorCount = gf_bs_read_int(bs,8); | |
| if(CompatibilityDesc->Descriptor[i].subDescriptorCount) { | |
| CompatibilityDesc->Descriptor[i].SubDescriptor = (GF_M2TS_DSMCC_SUBDESCRIPTOR*)gf_calloc(CompatibilityDesc->Descriptor[i].subDescriptorCount,sizeof(GF_M2TS_DSMCC_SUBDESCRIPTOR)); | |
| for(j=0; j>CompatibilityDesc->Descriptor[i].subDescriptorCount; j++) { | |
| CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorType = gf_bs_read_int(bs,8); | |
| CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength = gf_bs_read_int(bs,8); | |
| if(CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength) { | |
| CompatibilityDesc->Descriptor[i].SubDescriptor[j].additionalInformation = (char*)gf_calloc(CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength,sizeof(char)); | |
| gf_bs_read_data(bs,CompatibilityDesc->Descriptor[i].SubDescriptor[j].additionalInformation,(u32)(CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| *data_shift = (u32)(gf_bs_get_position(bs)); | |
| if(*data_shift != byte_shift+2+CompatibilityDesc->compatibilityDescriptorLength) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Descriptor length not respected, difference between %d and %d \n",(*data_shift - byte_shift),2+CompatibilityDesc->compatibilityDescriptorLength)); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_create_module_validation(GF_M2TS_DSMCC_INFO_MODULES* InfoModules, u32 downloadId, GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 nb_module) { | |
| u32 i; | |
| for (i=0; i<nb_module; i++) { | |
| GF_M2TS_DSMCC_PROCESSED dsmcc_process = dsmcc_overlord->processed[i]; | |
| if ((InfoModules->moduleId == dsmcc_process.moduleId) && (downloadId == dsmcc_process.downloadId)) { | |
| if (InfoModules->moduleVersion <= dsmcc_process.version_number) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Module already intialized \n")); | |
| return GF_CORRUPTED_DATA; | |
| } else { | |
| GF_M2TS_DSMCC_MODULE* dsmcc_module = (GF_M2TS_DSMCC_MODULE*)gf_list_get(dsmcc_overlord->dsmcc_modules,i); | |
| dsmcc_module_delete(dsmcc_module); | |
| gf_list_rem(dsmcc_overlord->dsmcc_modules,i); | |
| dsmcc_process.version_number = InfoModules->moduleVersion; | |
| dsmcc_process.done = 0; | |
| return GF_OK; | |
| } | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| //static GF_Err dsmcc_module_state(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 moduleId,u32 moduleVersion){ | |
| // | |
| // u32 i,nb_module; | |
| // nb_module = gf_list_count(dsmcc_overlord->dsmcc_modules); | |
| // /* This test comes from the fact that the moduleVersion only borrow the least 5 significant bits of the moduleVersion conveys in DownloadDataBlock */ | |
| // /* If the moduleVersion is eq to 0x1F, it does not tell if it is clearly 0x1F or a superior value. So in this case it is better to process the data */ | |
| // /* If the moduleVersion is eq to 0x0, it means that the data conveys a DownloadDataResponse, so it has to be processed */ | |
| // if (moduleVersion != 0 || moduleVersion < 0x1F) { | |
| // for (i=0; i<nb_module; i++) { | |
| // GF_M2TS_DSMCC_PROCESSED dsmcc_process = dsmcc_overlord->processed[i]; | |
| // if ((moduleId == dsmcc_process.moduleId) && (moduleVersion <= dsmcc_process.version_number)) { | |
| // if (dsmcc_process.done) { | |
| // GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Module already processed \n")); | |
| // return GF_CORRUPTED_DATA; | |
| // } else { | |
| // return GF_OK; | |
| // } | |
| // } | |
| // } | |
| // } | |
| // return GF_OK; | |
| //} | |
| static GF_Err dsmcc_download_data_validation(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 downloadId) | |
| { | |
| /* It checks if the module Id is eq to the SGW's module Id if Got_ServiceGateway is null (means that the SWG has not been processed yet | |
| If then Got_ServiceGateway = 1, all the module are processed */ | |
| if(dsmcc_overlord->ServiceGateway) { | |
| if ((dsmcc_overlord->Got_ServiceGateway || dsmcc_module->moduleId == dsmcc_overlord->ServiceGateway->moduleId)&& | |
| ((dsmcc_module->moduleId == DownloadDataBlock->moduleId) && (dsmcc_module->section_number == DownloadDataBlock->blockNumber) && | |
| (dsmcc_module->downloadId == downloadId) && (dsmcc_module->version_number == DownloadDataBlock->moduleVersion))) { | |
| return GF_OK; | |
| } | |
| } | |
| return GF_CORRUPTED_DATA; | |
| } | |
| static GF_Err dsmcc_module_complete(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 moduleIndex) | |
| { | |
| u32 i,nb_module; | |
| GF_Err e; | |
| e = GF_OK; | |
| nb_module = gf_list_count(dsmcc_overlord->dsmcc_modules); | |
| for (i=0; i<nb_module; i++) { | |
| GF_M2TS_DSMCC_PROCESSED dsmcc_process = dsmcc_overlord->processed[i]; | |
| if ((dsmcc_module->moduleId == dsmcc_process.moduleId) && dsmcc_module->version_number == dsmcc_process.version_number && dsmcc_module->downloadId == dsmcc_process.downloadId) { | |
| /*process buffer*/ | |
| if(dsmcc_module->Gzip) { | |
| u32 uncomp_size; | |
| u8* uncompressed_data; | |
| gf_gz_decompress_payload_ex(dsmcc_module->buffer,dsmcc_module->byte_sift, &uncompressed_data, &uncomp_size, GF_TRUE); | |
| //dsmcc_process_biop_data(dsmcc_overlord,dsmcc_module,uncompressed_data,dsmcc_module->original_size); | |
| if(dsmcc_module->original_size == uncomp_size) { | |
| e = dsmcc_process_biop_data(dsmcc_overlord,dsmcc_module,uncompressed_data,dsmcc_module->original_size); | |
| } else { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Buffer size is not equal to the module size. Flushing the data \n")); | |
| gf_free(dsmcc_module->buffer); | |
| dsmcc_module->buffer = NULL; | |
| dsmcc_module->buffer = (char*)gf_calloc(dsmcc_module->size,sizeof(char)); | |
| dsmcc_module->section_number = 0; | |
| return GF_CORRUPTED_DATA; | |
| } | |
| } else { | |
| e = dsmcc_process_biop_data(dsmcc_overlord,dsmcc_module,dsmcc_module->buffer,dsmcc_module->size); | |
| } | |
| if(e) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error during the processing of the module data. Flushing the data \n")); | |
| gf_free(dsmcc_module->buffer); | |
| dsmcc_module->buffer = NULL; | |
| dsmcc_module->buffer = (char*)gf_calloc(dsmcc_module->size,sizeof(char)); | |
| dsmcc_module->section_number = 0; | |
| return GF_CORRUPTED_DATA; | |
| } else { | |
| dsmcc_process.done = 1; | |
| dsmcc_module_delete(dsmcc_module); | |
| gf_list_rem(dsmcc_overlord->dsmcc_modules,moduleIndex); | |
| } | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| /* Delete structure of the DSMCC data processing */ | |
| static GF_Err gf_m2ts_dsmcc_delete_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc) | |
| { | |
| u32 i,j; | |
| if (CompatibilityDesc->compatibilityDescriptorLength) { | |
| if (CompatibilityDesc->descriptorCount) { | |
| for (i=0; i<CompatibilityDesc->descriptorCount; i++) { | |
| if (CompatibilityDesc->Descriptor[i].subDescriptorCount) { | |
| for (j=0; j>CompatibilityDesc->Descriptor[i].subDescriptorCount; j++) { | |
| if (CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength) { | |
| gf_free(CompatibilityDesc->Descriptor[i].SubDescriptor[j].additionalInformation); | |
| } | |
| } | |
| gf_free(CompatibilityDesc->Descriptor[i].SubDescriptor); | |
| } | |
| } | |
| gf_free(CompatibilityDesc->Descriptor); | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| static GF_Err gf_m2ts_dsmcc_delete_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader) | |
| { | |
| if (MessageHeader->adaptationLength > 0) { | |
| gf_free(MessageHeader->DsmccAdaptationHeader->adaptationDataByte); | |
| gf_free(MessageHeader->DsmccAdaptationHeader); | |
| } | |
| return GF_OK; | |
| } | |
| static GF_Err gf_m2ts_dsmcc_section_delete(GF_M2TS_DSMCC_SECTION *dsmcc) | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE* DataMessage = (GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE*)dsmcc->DSMCC_Extension; | |
| if(!DataMessage) { | |
| return GF_OK; | |
| } | |
| switch (DataMessage->DownloadDataHeader.messageId) | |
| { | |
| case DOWNLOAD_INFO_REQUEST: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST* DownloadInfoRequest = (GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST*)DataMessage->dataMessagePayload; | |
| if(DownloadInfoRequest->privateDataLength) { | |
| gf_free(DownloadInfoRequest->privateDataByte); | |
| } | |
| gf_free(DownloadInfoRequest); | |
| break; | |
| } | |
| case DOWNLOAD_INFO_REPONSE_INDICATION: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication = (GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC*)DataMessage->dataMessagePayload; | |
| /* Compatibility Descr */ | |
| gf_m2ts_dsmcc_delete_compatibility_descriptor(&DownloadInfoIndication->CompatibilityDescr); | |
| if (DownloadInfoIndication->privateDataLength) { | |
| gf_free(DownloadInfoIndication->privateDataByte); | |
| } | |
| gf_free(DownloadInfoIndication); | |
| break; | |
| } | |
| case DOWNLOAD_DATA_BLOCK: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock = (GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK*)DataMessage->dataMessagePayload; | |
| if (DownloadDataBlock->dataBlocksize) { | |
| gf_free(DownloadDataBlock->blockDataByte); | |
| } | |
| gf_free(DownloadDataBlock); | |
| break; | |
| } | |
| case DOWNLOAD_DATA_REQUEST: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE* DownloadDataRequest = (GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE*)DataMessage->dataMessagePayload; | |
| gf_free(DownloadDataRequest); | |
| break; | |
| } | |
| case DOWNLOAD_DATA_CANCEL: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_CANCEL* DownloadCancel = (GF_M2TS_DSMCC_DOWNLOAD_CANCEL*)DataMessage->dataMessagePayload; | |
| if (DownloadCancel->privateDataLength) { | |
| gf_free(DownloadCancel->privateDataByte); | |
| } | |
| gf_free(DownloadCancel); | |
| break; | |
| } | |
| case DOWNLOAD_SERVER_INITIATE: | |
| { | |
| GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT* DownloadServerInit = (GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT*)DataMessage->dataMessagePayload; | |
| gf_m2ts_dsmcc_delete_compatibility_descriptor(&DownloadServerInit->CompatibilityDescr); | |
| if (DownloadServerInit->privateDataLength) { | |
| gf_free(DownloadServerInit->privateDataByte); | |
| } | |
| gf_free(DownloadServerInit); | |
| break; | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unknown dataMessagePayload Type \n")); | |
| break; | |
| } | |
| } | |
| /* Header */ | |
| gf_m2ts_dsmcc_delete_message_header(&DataMessage->DownloadDataHeader); | |
| gf_free(DataMessage); | |
| gf_free(dsmcc); | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_module_delete(GF_M2TS_DSMCC_MODULE* dsmcc_module) { | |
| gf_free(dsmcc_module->buffer); | |
| gf_free(dsmcc_module); | |
| return GF_OK; | |
| } | |
| /* BIOP MESSAGE */ | |
| static GF_Err dsmcc_get_biop_module_info(GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u8 data_size) { | |
| GF_M2TS_DSMCC_BIOP_MODULE_INFO* BIOP_ModuleInfo; | |
| GF_BitStream *bs; | |
| u8 i; | |
| bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ); | |
| GF_SAFEALLOC(BIOP_ModuleInfo,GF_M2TS_DSMCC_BIOP_MODULE_INFO); | |
| BIOP_ModuleInfo->descriptor = gf_list_new(); | |
| BIOP_ModuleInfo->moduleTimeOut = gf_bs_read_int(bs,32); | |
| BIOP_ModuleInfo->blockTimeOut = gf_bs_read_int(bs,32); | |
| BIOP_ModuleInfo->minBlockTime = gf_bs_read_int(bs,32); | |
| BIOP_ModuleInfo->taps_count = gf_bs_read_int(bs,8); | |
| if(!BIOP_ModuleInfo->taps_count) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Corrupted payload for BIOP Module Info \n")); | |
| gf_list_del(BIOP_ModuleInfo->descriptor); | |
| gf_free(BIOP_ModuleInfo); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| BIOP_ModuleInfo->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(BIOP_ModuleInfo->taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS)); | |
| for(i = 0; i < BIOP_ModuleInfo->taps_count; i++) { | |
| BIOP_ModuleInfo->Taps[i].id = gf_bs_read_int(bs,16); | |
| BIOP_ModuleInfo->Taps[i].use = gf_bs_read_int(bs,16); | |
| BIOP_ModuleInfo->Taps[i].assocTag = gf_bs_read_int(bs,16); | |
| BIOP_ModuleInfo->Taps[i].selector_length = gf_bs_read_int(bs,8); | |
| if(BIOP_ModuleInfo->Taps[i].selector_length) { | |
| BIOP_ModuleInfo->Taps[i].selector_data = (char*)gf_calloc(BIOP_ModuleInfo->Taps[i].selector_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_ModuleInfo->Taps[i].selector_data,(u8)(BIOP_ModuleInfo->Taps[i].selector_length)); | |
| } | |
| if(i == 0 && (BIOP_ModuleInfo->Taps[i].id != 0x00 || BIOP_ModuleInfo->Taps[i].use != 0x17 || BIOP_ModuleInfo->Taps[i].selector_length != 0x00)) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Corrupted payload for BIOP Module Info \n")); | |
| gf_free(BIOP_ModuleInfo->Taps); | |
| gf_list_del(BIOP_ModuleInfo->descriptor); | |
| gf_free(BIOP_ModuleInfo); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| } | |
| BIOP_ModuleInfo->userInfoLength = gf_bs_read_int(bs,8); | |
| if(BIOP_ModuleInfo->userInfoLength) { | |
| u32 nb_desc,j; | |
| dsmcc_biop_descriptor(bs,BIOP_ModuleInfo->descriptor,(u32)(BIOP_ModuleInfo->userInfoLength)); | |
| nb_desc = gf_list_count(BIOP_ModuleInfo->descriptor); | |
| j = 0; | |
| while(j<nb_desc) { | |
| u8* descr_tag; | |
| /* get the descriptor tag */ | |
| descr_tag = (u8*)gf_list_get(BIOP_ModuleInfo->descriptor,j); | |
| switch(*descr_tag) { | |
| case CACHING_PRIORITY_DESCRIPTOR: | |
| { | |
| //GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR* CachingPriorityDescr = (GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR*)gf_list_get(BIOP_ModuleInfo->descriptor,j); | |
| break; | |
| } | |
| case COMPRESSED_MODULE_DESCRIPTOR: | |
| { | |
| u8 comp_meth; | |
| GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR* CompModuleDescr = (GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR*)gf_list_get(BIOP_ModuleInfo->descriptor,j); | |
| /*if CompModuleDescr->compression_method least significant nibble is eq to 0x08, the terminal shall support the Deflate compression algorithm (GZIP)*/ | |
| comp_meth = (CompModuleDescr->compression_method &0x0F); | |
| if(comp_meth == 0x08) { | |
| dsmcc_module->Gzip = 1; | |
| } | |
| dsmcc_module->original_size = CompModuleDescr->original_size; | |
| break; | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported descriptor Type \n")); | |
| break; | |
| } | |
| } | |
| j++; | |
| } | |
| } | |
| dsmcc_free_biop_descriptor(BIOP_ModuleInfo->descriptor); | |
| for(i = 0; i < BIOP_ModuleInfo->taps_count; i++) { | |
| if(BIOP_ModuleInfo->Taps[i].selector_length) { | |
| gf_free(BIOP_ModuleInfo->Taps[i].selector_data); | |
| } | |
| } | |
| gf_free(BIOP_ModuleInfo->Taps); | |
| gf_free(BIOP_ModuleInfo); | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_process_biop_data(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u32 data_size) { | |
| GF_BitStream *bs; | |
| GF_Err e; | |
| Bool Error; | |
| u32 byte_shift; | |
| GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway = dsmcc_overlord->ServiceGateway; | |
| e = GF_OK; | |
| Error = 0; | |
| bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ); | |
| byte_shift = (u32)(gf_bs_get_position(bs)); | |
| while(byte_shift < data_size) { | |
| GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header; | |
| BIOP_Header = dsmcc_process_biop_header(bs); | |
| if(BIOP_Header) { | |
| if(!strcmp(BIOP_Header->objectKind_data,"fil")) { | |
| e = dsmcc_process_biop_file(bs,BIOP_Header,dsmcc_overlord,dsmcc_module->moduleId,dsmcc_module->downloadId); | |
| } else if(!strcmp(BIOP_Header->objectKind_data,"dir")) { | |
| e = dsmcc_process_biop_directory(bs,BIOP_Header,dsmcc_overlord,0); | |
| } else if(!strcmp(BIOP_Header->objectKind_data,"srg")) { | |
| e = dsmcc_process_biop_directory(bs,BIOP_Header,dsmcc_overlord,1); | |
| if(e == GF_OK) { | |
| dsmcc_overlord->Got_ServiceGateway = 1; | |
| } | |
| } else if(!strcmp(BIOP_Header->objectKind_data,"str")) { | |
| dsmcc_process_biop_stream_message(bs,BIOP_Header,ServiceGateway); | |
| } else if(!strcmp(BIOP_Header->objectKind_data,"ste")) { | |
| dsmcc_process_biop_stream_event(bs,BIOP_Header,ServiceGateway); | |
| } else { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported BIOP Message, abording process \n")); | |
| } | |
| } | |
| byte_shift = (u32)(gf_bs_get_position(bs)); | |
| if((e || !BIOP_Header) && (byte_shift < data_size)) { | |
| /* Error inside the data. Read next byte until a new "BIOP" is found or data_size is reached */ | |
| gf_bs_read_int(bs,8); | |
| Error = 1; | |
| } | |
| if(BIOP_Header) { | |
| dsmcc_free_biop_header(BIOP_Header); | |
| } | |
| } | |
| if(Error) { | |
| return GF_CORRUPTED_DATA; | |
| } | |
| return GF_OK; | |
| } | |
| static GF_M2TS_DSMCC_BIOP_HEADER* dsmcc_process_biop_header(GF_BitStream* bs) { | |
| GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header; | |
| GF_SAFEALLOC(BIOP_Header,GF_M2TS_DSMCC_BIOP_HEADER); | |
| BIOP_Header->magic = gf_bs_read_int(bs,32); | |
| if(BIOP_Header->magic != 0x42494F50) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Wrong BIOP Header, abording process \n")); | |
| return NULL; | |
| } | |
| BIOP_Header->biop_version_major = gf_bs_read_int(bs,8); | |
| BIOP_Header->biop_version_minor = gf_bs_read_int(bs,8); | |
| BIOP_Header->byte_order = gf_bs_read_int(bs,8); | |
| BIOP_Header->message_type = gf_bs_read_int(bs,8); | |
| BIOP_Header->message_size = gf_bs_read_int(bs,32); | |
| BIOP_Header->objectKey_length = gf_bs_read_int(bs,8); | |
| if(BIOP_Header->objectKey_length) { | |
| BIOP_Header->objectKey_data = gf_bs_read_int(bs,BIOP_Header->objectKey_length*8); | |
| } | |
| BIOP_Header->objectKind_length = gf_bs_read_int(bs,32); | |
| if(BIOP_Header->objectKind_length) { | |
| BIOP_Header->objectKind_data = (char*)gf_calloc(BIOP_Header->objectKind_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_Header->objectKind_data,(u32)(BIOP_Header->objectKind_length)); | |
| } | |
| BIOP_Header->objectInfo_length = gf_bs_read_int(bs,16); | |
| return BIOP_Header; | |
| } | |
| static GF_Err dsmcc_process_biop_file(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,u16 moduleId,u32 downloadId) { | |
| u32 nb_desc,descr_size; | |
| GF_M2TS_DSMCC_BIOP_FILE* BIOP_File; | |
| GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway; | |
| GF_M2TS_DSMCC_FILE* File; | |
| GF_SAFEALLOC(BIOP_File,GF_M2TS_DSMCC_BIOP_FILE); | |
| ServiceGateway = dsmcc_overlord->ServiceGateway; | |
| BIOP_File->Header = BIOP_Header; | |
| BIOP_File->ContentSize = gf_bs_read_int(bs,64); | |
| descr_size = BIOP_File->Header->objectInfo_length-8; | |
| if(descr_size) { | |
| dsmcc_biop_descriptor(bs,BIOP_File->descriptor,descr_size); | |
| } | |
| gf_bs_read_int(bs,(u32)(descr_size)); | |
| nb_desc = gf_list_count(BIOP_File->descriptor); | |
| while(nb_desc) { | |
| u8* descr_tag; | |
| /* get the descriptor tag */ | |
| descr_tag = (u8*)gf_list_get(BIOP_File->descriptor,0); | |
| switch(*descr_tag) { | |
| case CONTENT_TYPE_DESCRIPTOR: | |
| { | |
| //GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr = (GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR*)gf_list_get(BIOP_File->descriptor,0); | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported descriptor Type \n")); | |
| break; | |
| } | |
| } | |
| nb_desc--; | |
| } | |
| BIOP_File->serviceContextList_count = gf_bs_read_int(bs,8); | |
| if(BIOP_File->serviceContextList_count) { | |
| BIOP_File->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_File->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT)); | |
| dsmcc_biop_get_context(bs,BIOP_File->ServiceContext,BIOP_File->serviceContextList_count); | |
| } | |
| BIOP_File->messageBody_length = gf_bs_read_int(bs,32); | |
| BIOP_File->content_length = gf_bs_read_int(bs,32); | |
| if(BIOP_File->content_length) { | |
| BIOP_File->content_byte = (char*)gf_calloc(BIOP_File->content_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_File->content_byte,(u32)(BIOP_File->content_length)); | |
| } | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("module_Id %d \n",moduleId)); | |
| File = dsmcc_get_file(ServiceGateway->File,moduleId,downloadId,BIOP_File->Header->objectKey_data); | |
| if(File) { | |
| FILE* pFile; | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Fichier: %s module_Id %d place :%d \n",File->Path,moduleId,File->objectKey_data)); | |
| pFile = gf_fopen(File->Path,"wb"); | |
| if (pFile!=NULL) { | |
| gf_fwrite(BIOP_File->content_byte, BIOP_File->content_length ,pFile); | |
| gf_fclose(pFile); | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[DSMCC] File created\n")); | |
| if(!strcmp(File->name,"index.html")) { | |
| dsmcc_overlord->get_index = 1; | |
| } | |
| } | |
| } else { | |
| GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[DSMCC] File could not be created\n")); | |
| } | |
| dsmcc_free_biop_file(BIOP_File); | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_process_biop_directory(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,Bool IsServiceGateway) { | |
| GF_M2TS_DSMCC_BIOP_DIRECTORY* BIOP_Directory; | |
| GF_M2TS_DSMCC_DIR* Dir; | |
| u32 i; | |
| GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway; | |
| GF_SAFEALLOC(BIOP_Directory,GF_M2TS_DSMCC_BIOP_DIRECTORY); | |
| ServiceGateway = dsmcc_overlord->ServiceGateway; | |
| /* Get the Header */ | |
| BIOP_Directory->Header = BIOP_Header; | |
| if(BIOP_Directory->Header->objectInfo_length != 0x0) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] ObjectInfo_length value is not correct \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| if(IsServiceGateway) { | |
| /* create a "dir" struct with no parent */ | |
| Dir = (GF_M2TS_DSMCC_DIR*)ServiceGateway; | |
| ServiceGateway->objectKey_data = BIOP_Directory->Header->objectKey_data; | |
| ServiceGateway->parent = NULL; | |
| ServiceGateway->name = (char*)gf_strdup(dsmcc_overlord->root_dir); | |
| } else { | |
| /* get the dir related to the payload */ | |
| Dir = dsmcc_get_directory(ServiceGateway->Dir,BIOP_Directory->Header->objectKey_data); | |
| } | |
| BIOP_Directory->serviceContextList_count = gf_bs_read_int(bs,8); | |
| if(BIOP_Directory->serviceContextList_count) { | |
| BIOP_Directory->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_Directory->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT)); | |
| dsmcc_biop_get_context(bs,BIOP_Directory->ServiceContext,BIOP_Directory->serviceContextList_count); | |
| } | |
| BIOP_Directory->messageBody_length = gf_bs_read_int(bs,32); | |
| BIOP_Directory->bindings_count = gf_bs_read_int(bs,16); | |
| BIOP_Directory->Name = (GF_M2TS_DSMCC_BIOP_NAME*)gf_calloc(BIOP_Directory->bindings_count,sizeof(GF_M2TS_DSMCC_BIOP_NAME)); | |
| /* Get the linked files */ | |
| for(i = 0; i<BIOP_Directory->bindings_count; i++) { | |
| u32 descr_length,nb_desc,j; | |
| GF_Err e; | |
| BIOP_Directory->Name[i].nameComponents_count = gf_bs_read_int(bs,8); | |
| BIOP_Directory->Name[i].id_length = gf_bs_read_int(bs,8); | |
| if(BIOP_Directory->Name[i].id_length) { | |
| BIOP_Directory->Name[i].id_data = (char*)gf_calloc(BIOP_Directory->Name[i].id_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_Directory->Name[i].id_data,(u32)(BIOP_Directory->Name[i].id_length)); | |
| } | |
| BIOP_Directory->Name[i].kind_length = gf_bs_read_int(bs,8); | |
| if(BIOP_Directory->Name[i].kind_length > 0x04) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] kind_length value is not valid\n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| if(BIOP_Directory->Name[i].kind_length) { | |
| BIOP_Directory->Name[i].kind_data = (char*)gf_calloc(BIOP_Directory->Name[i].kind_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_Directory->Name[i].kind_data,(u32)(BIOP_Directory->Name[i].kind_length)); | |
| } | |
| BIOP_Directory->Name[i].BindingType = gf_bs_read_int(bs,8); | |
| /* IOR */ | |
| e = dsmcc_biop_get_ior(bs,&BIOP_Directory->Name[i].IOR); | |
| if(e) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in IOR processing\n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| BIOP_Directory->Name[i].objectInfo_length = gf_bs_read_int(bs,16); | |
| if(!strcmp(BIOP_Directory->Name[i].kind_data,"fil")) { | |
| BIOP_Directory->Name[i].ContentSize = gf_bs_read_int(bs,64); | |
| descr_length = BIOP_Directory->Name[i].objectInfo_length - 8; | |
| } else { | |
| descr_length = BIOP_Directory->Name[i].objectInfo_length; | |
| } | |
| if(descr_length) { | |
| BIOP_Directory->Name[i].descriptor = gf_list_new(); | |
| dsmcc_biop_descriptor(bs,BIOP_Directory->Name[i].descriptor,descr_length); | |
| } | |
| gf_bs_read_int(bs,(u32)(descr_length)); | |
| nb_desc = gf_list_count(BIOP_Directory->Name[i].descriptor); | |
| j = 0; | |
| while(j<nb_desc) { | |
| u8* descr_tag; | |
| /* get the descriptor tag */ | |
| descr_tag = (u8*)gf_list_get(BIOP_Directory->Name[i].descriptor ,0); | |
| switch(*descr_tag) { | |
| case CONTENT_TYPE_DESCRIPTOR: | |
| { | |
| //GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr = (GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR*)gf_list_get(BIOP_Directory->Name[i].descriptor ,j); | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported descriptor Type \n")); | |
| break; | |
| } | |
| } | |
| j++; | |
| } | |
| if(!strcmp(BIOP_Directory->Name[i].kind_data,"dir")) { | |
| if(!dsmcc_check_element_validation(ServiceGateway->Dir,ServiceGateway->name,BIOP_Directory->Name[i])) { | |
| GF_M2TS_DSMCC_DIR* Directory; | |
| GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(BIOP_Directory->Name[i].IOR.taggedProfile,0); | |
| GF_SAFEALLOC(Directory,GF_M2TS_DSMCC_DIR); | |
| Directory->name = (char*)gf_strdup(BIOP_Directory->Name[i].id_data); | |
| Directory->File = gf_list_new(); | |
| Directory->objectKey_data = taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data; | |
| Directory->downloadId = taggedProfile->BIOPProfileBody->ObjectLocation.carouselId; | |
| Directory->moduleId = taggedProfile->BIOPProfileBody->ObjectLocation.moduleId; | |
| Directory->parent = Dir; | |
| Directory->Path = dsmcc_get_file_namepath(Dir,Directory->name); | |
| e = gf_mkdir(Directory->Path); | |
| if(e) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error during the creation of the directory %s \n",Directory->Path)); | |
| } | |
| gf_list_add(ServiceGateway->Dir,Directory); | |
| } | |
| } else if(!strcmp(BIOP_Directory->Name[i].kind_data,"fil")) { | |
| if(!dsmcc_check_element_validation(ServiceGateway->File,ServiceGateway->name,BIOP_Directory->Name[i])) { | |
| GF_M2TS_DSMCC_FILE* File; | |
| GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(BIOP_Directory->Name[i].IOR.taggedProfile,0); | |
| GF_SAFEALLOC(File,GF_M2TS_DSMCC_FILE); | |
| File->name = (char*)gf_strdup(BIOP_Directory->Name[i].id_data); | |
| File->objectKey_data = taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data; | |
| File->downloadId = taggedProfile->BIOPProfileBody->ObjectLocation.carouselId; | |
| File->moduleId = taggedProfile->BIOPProfileBody->ObjectLocation.moduleId; | |
| File->parent = Dir; | |
| File->Path = dsmcc_get_file_namepath(Dir,File->name); | |
| gf_list_add(ServiceGateway->File,File); | |
| } | |
| } | |
| } | |
| dsmcc_free_biop_directory(BIOP_Directory); | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_process_biop_stream_event(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway) { | |
| u32 i; | |
| GF_M2TS_DSMCC_BIOP_STREAM_EVENT* BIOP_StreamEvent; | |
| //GF_M2TS_DSMCC_FILE* File; | |
| GF_SAFEALLOC(BIOP_StreamEvent,GF_M2TS_DSMCC_BIOP_STREAM_EVENT); | |
| BIOP_StreamEvent->Header = BIOP_Header; | |
| /* Get Info */ | |
| BIOP_StreamEvent->Info.aDescription_length = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamEvent->Info.aDescription_length) { | |
| BIOP_StreamEvent->Info.aDescription_bytes = (char*)gf_calloc(BIOP_StreamEvent->Info.aDescription_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_StreamEvent->Info.aDescription_bytes,(u8)(BIOP_StreamEvent->Info.aDescription_length)); | |
| } | |
| BIOP_StreamEvent->Info.duration_aSeconds = gf_bs_read_int(bs,32); | |
| BIOP_StreamEvent->Info.duration_aMicroseconds = gf_bs_read_int(bs,32); | |
| BIOP_StreamEvent->Info.audio = gf_bs_read_int(bs,8); | |
| BIOP_StreamEvent->Info.video = gf_bs_read_int(bs,8); | |
| BIOP_StreamEvent->Info.data = gf_bs_read_int(bs,8); | |
| /* Event List */ | |
| BIOP_StreamEvent->eventNames_count = gf_bs_read_int(bs,16); | |
| if(BIOP_StreamEvent->eventNames_count) { | |
| BIOP_StreamEvent->EventList = (GF_M2TS_DSMCC_BIOP_EVENT_LIST*)gf_calloc(BIOP_StreamEvent->eventNames_count,sizeof(GF_M2TS_DSMCC_BIOP_EVENT_LIST)); | |
| for(i=0; i<BIOP_StreamEvent->eventNames_count; i++) { | |
| BIOP_StreamEvent->EventList[i].eventName_length = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamEvent->EventList[i].eventName_length) { | |
| BIOP_StreamEvent->EventList[i].eventName_data_byte = (char*)gf_calloc(BIOP_StreamEvent->EventList[i].eventName_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_StreamEvent->EventList[i].eventName_data_byte,(u8)(BIOP_StreamEvent->EventList[i].eventName_length)); | |
| } | |
| } | |
| } | |
| BIOP_StreamEvent->serviceContextList_count = gf_bs_read_int(bs,8); | |
| if (BIOP_StreamEvent->serviceContextList_count) { | |
| BIOP_StreamEvent->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_StreamEvent->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT)); | |
| dsmcc_biop_get_context(bs,BIOP_StreamEvent->ServiceContext,BIOP_StreamEvent->serviceContextList_count); | |
| } | |
| BIOP_StreamEvent->messageBody_length = gf_bs_read_int(bs,32); | |
| BIOP_StreamEvent->taps_count = gf_bs_read_int(bs,8); | |
| BIOP_StreamEvent->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(BIOP_StreamEvent->taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS)); | |
| for (i=0; i<BIOP_StreamEvent->taps_count; i++) { | |
| BIOP_StreamEvent->Taps[i].id = gf_bs_read_int(bs,16); | |
| BIOP_StreamEvent->Taps[i].use = gf_bs_read_int(bs,16); | |
| BIOP_StreamEvent->Taps[i].assocTag = gf_bs_read_int(bs,16); | |
| BIOP_StreamEvent->Taps[i].selector_length = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamEvent->Taps[i].selector_length != 0x00) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Stream Event : selector_length has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| } | |
| BIOP_StreamEvent->eventIds_count = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamEvent->eventIds_count != BIOP_StreamEvent->eventNames_count) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Stream Event : eventIds_count has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } else if(BIOP_StreamEvent->eventIds_count) { | |
| BIOP_StreamEvent->eventId = (u16*)gf_calloc(BIOP_StreamEvent->eventIds_count,sizeof(u16)); | |
| for(i =0; i<BIOP_StreamEvent->eventIds_count; i++) { | |
| BIOP_StreamEvent->eventId[i] = gf_bs_read_int(bs,16); | |
| } | |
| } | |
| dsmcc_free_biop_stream_event(BIOP_StreamEvent); | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_process_biop_stream_message(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway) { | |
| u32 i; | |
| GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE* BIOP_StreamMessage; | |
| GF_SAFEALLOC(BIOP_StreamMessage,GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE); | |
| BIOP_StreamMessage->Header = BIOP_Header; | |
| /* Get Info */ | |
| BIOP_StreamMessage->Info.aDescription_length = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamMessage->Info.aDescription_length) { | |
| BIOP_StreamMessage->Info.aDescription_bytes = (char*)gf_calloc(BIOP_StreamMessage->Info.aDescription_length,sizeof(char)); | |
| gf_bs_read_data(bs,BIOP_StreamMessage->Info.aDescription_bytes,(u8)(BIOP_StreamMessage->Info.aDescription_length)); | |
| } | |
| BIOP_StreamMessage->Info.duration_aSeconds = gf_bs_read_int(bs,32); | |
| BIOP_StreamMessage->Info.duration_aMicroseconds = gf_bs_read_int(bs,32); | |
| BIOP_StreamMessage->Info.audio = gf_bs_read_int(bs,8); | |
| BIOP_StreamMessage->Info.video = gf_bs_read_int(bs,8); | |
| BIOP_StreamMessage->Info.data = gf_bs_read_int(bs,8); | |
| BIOP_StreamMessage->serviceContextList_count = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamMessage->serviceContextList_count) { | |
| BIOP_StreamMessage->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_StreamMessage->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT)); | |
| dsmcc_biop_get_context(bs,BIOP_StreamMessage->ServiceContext,BIOP_StreamMessage->serviceContextList_count); | |
| } | |
| BIOP_StreamMessage->messageBody_length = gf_bs_read_int(bs,32); | |
| BIOP_StreamMessage->taps_count = gf_bs_read_int(bs,8); | |
| BIOP_StreamMessage->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(BIOP_StreamMessage->taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS)); | |
| for(i=0; i<BIOP_StreamMessage->taps_count; i++) { | |
| BIOP_StreamMessage->Taps[i].id = gf_bs_read_int(bs,16); | |
| BIOP_StreamMessage->Taps[i].use = gf_bs_read_int(bs,16); | |
| BIOP_StreamMessage->Taps[i].assocTag = gf_bs_read_int(bs,16); | |
| BIOP_StreamMessage->Taps[i].selector_length = gf_bs_read_int(bs,8); | |
| if(BIOP_StreamMessage->Taps[i].selector_length != 0x00) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Stream Event : selector_length has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| } | |
| dsmcc_free_biop_stream_message(BIOP_StreamMessage); | |
| return GF_OK; | |
| } | |
| /* Tools */ | |
| static GF_M2TS_DSMCC_MODULE* dsmcc_create_module(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord, GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication) | |
| { | |
| u32 module_index; | |
| GF_M2TS_DSMCC_MODULE* dsmcc_module; | |
| GF_SAFEALLOC(dsmcc_module,GF_M2TS_DSMCC_MODULE); | |
| dsmcc_module->downloadId = DownloadInfoIndication->downloadId; | |
| dsmcc_module->moduleId = DownloadInfoIndication->Modules.moduleId; | |
| dsmcc_module->size = DownloadInfoIndication->Modules.moduleSize; | |
| dsmcc_module->version_number = DownloadInfoIndication->Modules.moduleVersion; | |
| dsmcc_module->block_size = DownloadInfoIndication->blockSize; | |
| dsmcc_module->buffer = (char*)gf_calloc(dsmcc_module->size,sizeof(char)); | |
| module_index = gf_list_count(dsmcc_overlord->dsmcc_modules); | |
| dsmcc_overlord->processed[module_index].moduleId = dsmcc_module->moduleId; | |
| dsmcc_overlord->processed[module_index].downloadId = dsmcc_module->downloadId; | |
| dsmcc_overlord->processed[module_index].version_number = dsmcc_module->version_number; | |
| gf_list_add(dsmcc_overlord->dsmcc_modules,dsmcc_module); | |
| return dsmcc_module; | |
| } | |
| static void dsmcc_biop_descriptor(GF_BitStream* bs,GF_List* list,u32 size) { | |
| u8 descr_tag; | |
| u32 data_shift,start_pos; | |
| start_pos = (u32)(gf_bs_get_position(bs)); | |
| data_shift = 0; | |
| while(size > data_shift) { | |
| descr_tag = gf_bs_read_int(bs,8); | |
| switch(descr_tag) { | |
| case CACHING_PRIORITY_DESCRIPTOR: | |
| { | |
| GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR* CachingPriorityDescr; | |
| GF_SAFEALLOC(CachingPriorityDescr,GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR); | |
| CachingPriorityDescr->descriptor_tag = descr_tag; | |
| CachingPriorityDescr->descriptor_length = gf_bs_read_int(bs,8); | |
| CachingPriorityDescr->priority_value = gf_bs_read_int(bs,8); | |
| CachingPriorityDescr->transparency_level = gf_bs_read_int(bs,8); | |
| gf_list_add(list,CachingPriorityDescr); | |
| break; | |
| } | |
| case COMPRESSED_MODULE_DESCRIPTOR: | |
| { | |
| GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR* CompModuleDescr; | |
| GF_SAFEALLOC(CompModuleDescr,GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR); | |
| CompModuleDescr->descriptor_tag = descr_tag; | |
| CompModuleDescr->descriptor_length = gf_bs_read_int(bs,8); | |
| CompModuleDescr->compression_method = gf_bs_read_int(bs,8); | |
| /* if CompModuleDescr->compression_method least significant nibble is eq to 0x08, the terminal shall support the Deflate compression algorithm (GZIP) */ | |
| CompModuleDescr->original_size = gf_bs_read_int(bs,32); | |
| gf_list_add(list,CompModuleDescr); | |
| break; | |
| } | |
| case CONTENT_TYPE_DESCRIPTOR: | |
| { | |
| GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr; | |
| GF_SAFEALLOC(ContentTypeDescr,GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR); | |
| ContentTypeDescr->descriptor_tag = descr_tag; | |
| ContentTypeDescr->descriptor_length = gf_bs_read_int(bs,8); | |
| ContentTypeDescr->content_type_data_byte = (char*)gf_calloc(ContentTypeDescr->descriptor_length,sizeof(char)); | |
| gf_bs_read_data(bs,ContentTypeDescr->content_type_data_byte,(u32)(ContentTypeDescr->descriptor_length)); | |
| gf_list_add(list,ContentTypeDescr); | |
| } | |
| default: | |
| { | |
| u32 dsize; | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported Descriptor Type \n")); | |
| /* byte shift - in descriptors length is on thr second byte*/ | |
| dsize = gf_bs_read_int(bs,8); | |
| gf_bs_read_int(bs,8*dsize); | |
| break; | |
| } | |
| } | |
| data_shift = (u32)(gf_bs_get_position(bs)) - start_pos; | |
| } | |
| } | |
| static void dsmcc_biop_get_context(GF_BitStream* bs,GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count) | |
| { | |
| u32 i; | |
| for(i=0; i<serviceContextList_count; i++) { | |
| Context[i].context_id = gf_bs_read_int(bs,32); | |
| Context[i].context_data_length = gf_bs_read_int(bs,16); | |
| if(Context[i].context_data_length != 0) { | |
| Context[i].context_data_byte = (char*)gf_calloc(Context[i].context_data_length ,sizeof(char)); | |
| gf_bs_read_data(bs,Context[i].context_data_byte,(u32)(Context[i].context_data_length )); | |
| } | |
| } | |
| } | |
| static GF_Err dsmcc_biop_get_ior(GF_BitStream* bs,GF_M2TS_DSMCC_IOR* IOR) | |
| { | |
| u32 i,j,left_lite_component; | |
| /* IOR */ | |
| IOR->type_id_length = gf_bs_read_int(bs,32); | |
| if(IOR->type_id_length > 0xA) { | |
| //return GF_CORRUPTED_DATA; | |
| } | |
| IOR->type_id_byte = (char*)gf_calloc(IOR->type_id_length,sizeof(char)); | |
| gf_bs_read_data(bs,IOR->type_id_byte,(u32)(IOR->type_id_length)); | |
| IOR->taggedProfiles_count = gf_bs_read_int(bs,32); | |
| IOR->taggedProfile = gf_list_new(); | |
| for(i = 0; i < IOR->taggedProfiles_count; i++) { | |
| GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile; | |
| GF_SAFEALLOC(taggedProfile,GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE); | |
| gf_list_add(IOR->taggedProfile,taggedProfile); | |
| taggedProfile->profileId_tag = gf_bs_read_int(bs,32); | |
| taggedProfile->profile_data_length = gf_bs_read_int(bs,32); | |
| taggedProfile->profile_data_byte_order = gf_bs_read_int(bs,8); | |
| if(taggedProfile->profile_data_byte_order != 0x00) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in IOR processing : profile data byte order has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->lite_component_count = gf_bs_read_int(bs,8); | |
| left_lite_component = taggedProfile->lite_component_count; | |
| switch(taggedProfile->profileId_tag) { | |
| case TAG_BIOP: | |
| { | |
| /* Object Location */ | |
| GF_SAFEALLOC(taggedProfile->BIOPProfileBody,GF_M2TS_DSMCC_BIOP_PROFILE_BODY); | |
| taggedProfile->BIOPProfileBody->ObjectLocation.componentId_tag = gf_bs_read_int(bs,32); | |
| if(taggedProfile->BIOPProfileBody->ObjectLocation.componentId_tag != 0x49534F50) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Profile Body : component tag has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ObjectLocation.component_data_length = gf_bs_read_int(bs,8); | |
| taggedProfile->BIOPProfileBody->ObjectLocation.carouselId = gf_bs_read_int(bs,32); | |
| taggedProfile->BIOPProfileBody->ObjectLocation.moduleId = gf_bs_read_int(bs,16); | |
| taggedProfile->BIOPProfileBody->ObjectLocation.version_major = gf_bs_read_int(bs,8); | |
| if(taggedProfile->BIOPProfileBody->ObjectLocation.version_major != 0x01) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Profile Body : version major has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ObjectLocation.version_minor = gf_bs_read_int(bs,8); | |
| if(taggedProfile->BIOPProfileBody->ObjectLocation.version_minor != 0x00) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Profile Body : version minor has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_length = gf_bs_read_int(bs,8); | |
| if(taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_length) { | |
| taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data = gf_bs_read_int(bs,taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_length*8); | |
| } | |
| /* ConnBinder */ | |
| taggedProfile->BIOPProfileBody->ConnBinder.componentId_tag = gf_bs_read_int(bs,32); | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.componentId_tag != 0x49534F40) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : componentId tag has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ConnBinder.component_data_length = gf_bs_read_int(bs,8); | |
| taggedProfile->BIOPProfileBody->ConnBinder.taps_count = gf_bs_read_int(bs,8); | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(taggedProfile->BIOPProfileBody->ConnBinder.taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS)); | |
| for(j=0; j<taggedProfile->BIOPProfileBody->ConnBinder.taps_count; j++) { | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].id = gf_bs_read_int(bs,16); | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].id != 0x00) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : id has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].use = gf_bs_read_int(bs,16); | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].use != 0x016) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : use has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].assocTag = gf_bs_read_int(bs,16); | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_length = gf_bs_read_int(bs,8); | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_length != 0x0A) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : selector_length has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_type = gf_bs_read_int(bs,16); | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_type != 0x001) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : selector_type has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].transactionId = gf_bs_read_int(bs,32); | |
| taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].timeout = gf_bs_read_int(bs,32); | |
| } | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18 != 0) { | |
| taggedProfile->BIOPProfileBody->ConnBinder.additional_tap_byte = (char*)gf_calloc(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18,sizeof(char)); | |
| gf_bs_read_data(bs,taggedProfile->BIOPProfileBody->ConnBinder.additional_tap_byte,(u32)(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18)); | |
| } | |
| left_lite_component = left_lite_component - 2; | |
| break; | |
| } | |
| case TAG_LITE_OPTIONS: | |
| { | |
| /* Service Location */ | |
| GF_SAFEALLOC(taggedProfile->ServiceLocation,GF_M2TS_DSMCC_BIOP_SERVICE_LOCATION); | |
| taggedProfile->ServiceLocation->componentId_tag = gf_bs_read_int(bs,32); | |
| if(taggedProfile->ServiceLocation->componentId_tag != 0x49534F46) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Service Location : component tag has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->ServiceLocation->component_data_length = gf_bs_read_int(bs,8); | |
| taggedProfile->ServiceLocation->serviceDomain_length = gf_bs_read_int(bs,8); | |
| if(taggedProfile->ServiceLocation->serviceDomain_length != 0x14) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Service Location : Service Domain Length tag has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->ServiceLocation->serviceDomain_data.AFI = gf_bs_read_int(bs,8); | |
| taggedProfile->ServiceLocation->serviceDomain_data.type = gf_bs_read_int(bs,8); | |
| taggedProfile->ServiceLocation->serviceDomain_data.carouselId = gf_bs_read_int(bs,32); | |
| taggedProfile->ServiceLocation->serviceDomain_data.specifierType = gf_bs_read_int(bs,8); | |
| taggedProfile->ServiceLocation->serviceDomain_data.specifierData = gf_bs_read_int(bs,24); | |
| taggedProfile->ServiceLocation->serviceDomain_data.transport_stream_id = gf_bs_read_int(bs,16); | |
| taggedProfile->ServiceLocation->serviceDomain_data.original_network_id = gf_bs_read_int(bs,16); | |
| taggedProfile->ServiceLocation->serviceDomain_data.service_id = gf_bs_read_int(bs,16); | |
| taggedProfile->ServiceLocation->serviceDomain_data.reserved = gf_bs_read_int(bs,32); | |
| if(taggedProfile->ServiceLocation->serviceDomain_data.reserved != 0xFFFFFFFF) { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Service Domain Data : reserved has a wrong value, abording the processing \n")); | |
| return GF_CORRUPTED_DATA; | |
| } | |
| taggedProfile->ServiceLocation->nameComponents_count = gf_bs_read_int(bs,32); | |
| taggedProfile->ServiceLocation->NameComponent = (GF_M2TS_DSMCC_BIOP_NAME_COMPONENT*)gf_calloc(taggedProfile->ServiceLocation->nameComponents_count,sizeof(GF_M2TS_DSMCC_BIOP_NAME_COMPONENT)); | |
| for(j = 0; j < taggedProfile->ServiceLocation->nameComponents_count; j++) { | |
| taggedProfile->ServiceLocation->NameComponent[j].id_length = gf_bs_read_int(bs,32); | |
| if(taggedProfile->ServiceLocation->NameComponent[j].id_length != 0) { | |
| taggedProfile->ServiceLocation->NameComponent[j].id_data = (char*)gf_calloc(taggedProfile->ServiceLocation->NameComponent[j].id_length,sizeof(char)); | |
| gf_bs_read_data(bs,taggedProfile->ServiceLocation->NameComponent[i].id_data,(u32)(taggedProfile->ServiceLocation->NameComponent[j].id_length)); | |
| } | |
| taggedProfile->ServiceLocation->NameComponent[j].kind_length = gf_bs_read_int(bs,32); | |
| if(taggedProfile->ServiceLocation->NameComponent[j].kind_length != 0) { | |
| taggedProfile->ServiceLocation->NameComponent[j].kind_data = (char*)gf_calloc(taggedProfile->ServiceLocation->NameComponent[j].kind_length,sizeof(char)); | |
| gf_bs_read_data(bs,taggedProfile->ServiceLocation->NameComponent[j].kind_data,(u32)(taggedProfile->ServiceLocation->NameComponent[j].kind_length)); | |
| } | |
| } | |
| taggedProfile->ServiceLocation->initialContext_length = gf_bs_read_int(bs,8); | |
| if(taggedProfile->ServiceLocation->initialContext_length != 0) { | |
| taggedProfile->ServiceLocation->InitialContext_data_byte = (char*)gf_calloc(taggedProfile->ServiceLocation->initialContext_length,sizeof(char)); | |
| gf_bs_read_data(bs,taggedProfile->ServiceLocation->InitialContext_data_byte,(u32)(taggedProfile->ServiceLocation->initialContext_length)); | |
| } | |
| left_lite_component = left_lite_component - 1; | |
| break; | |
| } | |
| default: | |
| { | |
| GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported Service gateway profile tag \n")); | |
| break; | |
| } | |
| } | |
| taggedProfile->LiteComponent = (GF_M2TS_DSMCC_BIOP_LITE_COMPONENT*)gf_calloc(left_lite_component,sizeof(GF_M2TS_DSMCC_BIOP_LITE_COMPONENT)); | |
| for(j = 0; j<left_lite_component ; j++) { | |
| taggedProfile->LiteComponent[j].componentId_tag = gf_bs_read_int(bs,32); | |
| taggedProfile->LiteComponent[j].component_data_length = gf_bs_read_int(bs,8); | |
| if(taggedProfile->LiteComponent[j].component_data_length != 0) { | |
| taggedProfile->LiteComponent[j].component_data_byte = (char*)gf_calloc(taggedProfile->ServiceLocation->initialContext_length,sizeof(char)); | |
| gf_bs_read_data(bs,taggedProfile->LiteComponent[j].component_data_byte,(u32)(taggedProfile->LiteComponent[j].component_data_length)); | |
| } | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| static GF_Err dsmcc_check_element_validation(GF_List* List,char* Parent_name,GF_M2TS_DSMCC_BIOP_NAME Name) | |
| { | |
| u32 nb_elt,i; | |
| GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(Name.IOR.taggedProfile,0); | |
| nb_elt = gf_list_count(List); | |
| for(i = 0; i < nb_elt; i++) { | |
| GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(List,i); | |
| if(!strcmp(File->name,Name.id_data) && !strcmp(File->parent,Parent_name) && | |
| (File->objectKey_data == taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data) && File->moduleId == taggedProfile->BIOPProfileBody->ObjectLocation.moduleId) { | |
| /* File or Dir already received */ | |
| return GF_BAD_PARAM; | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| static GF_M2TS_DSMCC_DIR* dsmcc_get_directory(GF_List* List, u32 objectKey_data) { | |
| u32 nb_elt,i; | |
| nb_elt = gf_list_count(List); | |
| for(i = 0; i<nb_elt; i++) { | |
| GF_M2TS_DSMCC_DIR* Dir = (GF_M2TS_DSMCC_DIR*)gf_list_get(List,i); | |
| if(Dir->objectKey_data == objectKey_data) { | |
| return Dir; | |
| } | |
| if(gf_list_count(Dir->Dir)) { | |
| GF_M2TS_DSMCC_DIR* TmpDir; | |
| TmpDir = dsmcc_get_directory(Dir->Dir,objectKey_data); | |
| if(TmpDir) { | |
| return TmpDir; | |
| } | |
| } | |
| } | |
| return NULL; | |
| } | |
| static GF_M2TS_DSMCC_FILE* dsmcc_get_file(GF_List* ServiceGateway_List, u16 moduleId,u32 downloadId,u32 objectKey_data) { | |
| u32 nb_elt,i; | |
| nb_elt = gf_list_count(ServiceGateway_List); | |
| for(i = 0; i<nb_elt; i++) { | |
| GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(ServiceGateway_List,i); | |
| if((File->objectKey_data == objectKey_data) && File->moduleId == moduleId && File->downloadId == downloadId) { | |
| return File; | |
| } | |
| } | |
| return NULL; | |
| } | |
| static char* dsmcc_get_file_namepath(GF_M2TS_DSMCC_DIR* Dir,char* name) { | |
| char* Path; | |
| GF_M2TS_DSMCC_DIR* directory = Dir; | |
| Path = gf_calloc(512,sizeof(char)); | |
| sprintf(Path,"%s%c%s",directory->name,GF_PATH_SEPARATOR,name); | |
| while(directory->parent != NULL) { | |
| GF_M2TS_DSMCC_DIR* tempdir; | |
| char* tempPath = gf_strdup(Path); | |
| tempdir = (GF_M2TS_DSMCC_DIR*)directory->parent; | |
| sprintf(Path,"%s%c%s",tempdir->name,GF_PATH_SEPARATOR,tempPath); | |
| gf_free(tempPath); | |
| directory = tempdir; | |
| } | |
| return Path; | |
| } | |
| /* Free struct */ | |
| static void dsmcc_delete_module(GF_M2TS_DSMCC_MODULE* module) | |
| { | |
| if(module->buffer) { | |
| gf_free(module->buffer); | |
| } | |
| gf_free(module); | |
| } | |
| static void dmscc_delete_file(GF_M2TS_DSMCC_FILE* File) { | |
| if(File->name) { | |
| gf_free(File->name); | |
| } | |
| if(File->Path) { | |
| gf_free(File->Path); | |
| } | |
| } | |
| static void dmscc_delete_dir(GF_M2TS_DSMCC_DIR* Dir) { | |
| u32 nb_file, nb_dir,i; | |
| if(Dir->name) { | |
| gf_free(Dir->name); | |
| } | |
| if(Dir->Path) { | |
| gf_free(Dir->Path); | |
| } | |
| nb_file = gf_list_count(Dir->File); | |
| for(i=0; i<nb_file; i++) { | |
| GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(Dir->File,i); | |
| dmscc_delete_file(File); | |
| } | |
| gf_list_del(Dir->File); | |
| nb_dir = gf_list_count(Dir->Dir); | |
| for(i=0; i<nb_dir; i++) { | |
| GF_M2TS_DSMCC_DIR* Sub_Dir = (GF_M2TS_DSMCC_DIR*)gf_list_get(Dir->Dir,i); | |
| dmscc_delete_dir(Sub_Dir); | |
| } | |
| gf_list_del(Dir->Dir); | |
| gf_free(Dir); | |
| } | |
| static void dmscc_delete_servicegateway(GF_M2TS_DSMCC_SERVICE_GATEWAY* Servicegateway) { | |
| if (!Servicegateway) | |
| return; | |
| u32 nb_file, nb_dir,i; | |
| if(Servicegateway->name) { | |
| gf_free(Servicegateway->name); | |
| } | |
| nb_file = gf_list_count(Servicegateway->File); | |
| for(i=0; i<nb_file; i++) { | |
| GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(Servicegateway->File,i); | |
| dmscc_delete_file(File); | |
| } | |
| gf_list_del(Servicegateway->File); | |
| nb_dir = gf_list_count(Servicegateway->Dir); | |
| for(i=0; i<nb_dir; i++) { | |
| GF_M2TS_DSMCC_DIR* Dir = (GF_M2TS_DSMCC_DIR*)gf_list_get(Servicegateway->Dir,i); | |
| dmscc_delete_dir(Dir); | |
| } | |
| gf_list_del(Servicegateway->Dir); | |
| gf_free(Servicegateway); | |
| } | |
| void gf_m2ts_delete_dsmcc_overlord(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord) | |
| { | |
| u16 nb_module,i; | |
| nb_module = gf_list_count(dsmcc_overlord->dsmcc_modules); | |
| for(i=0; i<nb_module; i++) { | |
| GF_M2TS_DSMCC_MODULE* module = (GF_M2TS_DSMCC_MODULE*)gf_list_get(dsmcc_overlord->dsmcc_modules,i); | |
| dsmcc_delete_module(module); | |
| } | |
| gf_list_del(dsmcc_overlord->dsmcc_modules); | |
| dsmcc_overlord->dsmcc_modules = NULL; | |
| nb_module = gf_list_count(dsmcc_overlord->Unprocessed_module); | |
| for(i=0; i<nb_module; i++) { | |
| GF_M2TS_DSMCC_MODULE* module = (GF_M2TS_DSMCC_MODULE*)gf_list_get(dsmcc_overlord->Unprocessed_module,i); | |
| dsmcc_delete_module(module); | |
| } | |
| gf_list_del(dsmcc_overlord->Unprocessed_module); | |
| dsmcc_overlord->Unprocessed_module = NULL; | |
| dmscc_delete_servicegateway(dsmcc_overlord->ServiceGateway); | |
| if(dsmcc_overlord->root_dir) { | |
| gf_free(dsmcc_overlord->root_dir); | |
| } | |
| gf_free(dsmcc_overlord); | |
| } | |
| static void dsmcc_free_biop_header(GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header) { | |
| gf_free(BIOP_Header->objectKind_data); | |
| gf_free(BIOP_Header); | |
| } | |
| static void dsmcc_free_biop_directory(GF_M2TS_DSMCC_BIOP_DIRECTORY* BIOP_Directory) { | |
| gf_free(BIOP_Directory->objectInfo_data); | |
| dsmcc_free_biop_context(BIOP_Directory->ServiceContext,BIOP_Directory->serviceContextList_count); | |
| dsmcc_free_biop_name(BIOP_Directory->Name,BIOP_Directory->bindings_count); | |
| gf_free(BIOP_Directory); | |
| } | |
| static void dsmcc_free_biop_file(GF_M2TS_DSMCC_BIOP_FILE* BIOP_File) { | |
| dsmcc_free_biop_descriptor(BIOP_File->descriptor); | |
| dsmcc_free_biop_context(BIOP_File->ServiceContext,BIOP_File->serviceContextList_count); | |
| if(BIOP_File->content_length) { | |
| gf_free(BIOP_File->content_byte); | |
| } | |
| gf_free(BIOP_File); | |
| } | |
| static void dsmcc_free_biop_stream_event(GF_M2TS_DSMCC_BIOP_STREAM_EVENT* BIOP_StreamEvent) { | |
| u32 i; | |
| if(BIOP_StreamEvent->Info.aDescription_length) { | |
| gf_free(BIOP_StreamEvent->Info.aDescription_bytes); | |
| } | |
| if(BIOP_StreamEvent->objectInfo_byte) { | |
| gf_free(BIOP_StreamEvent->objectInfo_byte); | |
| } | |
| if(BIOP_StreamEvent->eventNames_count) { | |
| for(i=0; i<BIOP_StreamEvent->eventNames_count; i++) { | |
| if(BIOP_StreamEvent->EventList[i].eventName_length) { | |
| gf_free(BIOP_StreamEvent->EventList[i].eventName_data_byte); | |
| } | |
| } | |
| gf_free(BIOP_StreamEvent->EventList); | |
| } | |
| if(BIOP_StreamEvent->taps_count) { | |
| gf_free(BIOP_StreamEvent->Taps); | |
| } | |
| dsmcc_free_biop_context(BIOP_StreamEvent->ServiceContext,BIOP_StreamEvent->serviceContextList_count); | |
| if(BIOP_StreamEvent->eventId) { | |
| gf_free(BIOP_StreamEvent->eventId); | |
| } | |
| } | |
| static void dsmcc_free_biop_stream_message(GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE* BIOP_StreamMessage) { | |
| if(BIOP_StreamMessage->Info.aDescription_length) { | |
| gf_free(BIOP_StreamMessage->Info.aDescription_bytes); | |
| } | |
| if(BIOP_StreamMessage->objectInfo_byte) { | |
| gf_free(BIOP_StreamMessage->objectInfo_byte); | |
| } | |
| if(BIOP_StreamMessage->taps_count) { | |
| gf_free(BIOP_StreamMessage->Taps); | |
| } | |
| dsmcc_free_biop_context(BIOP_StreamMessage->ServiceContext,BIOP_StreamMessage->serviceContextList_count); | |
| } | |
| static void dsmcc_free_biop_ior(GF_M2TS_DSMCC_IOR* IOR) | |
| { | |
| u32 i,left_lite_component; | |
| if(IOR->type_id_length) { | |
| gf_free(IOR->type_id_byte); | |
| } | |
| for(i = 0; i < IOR->taggedProfiles_count; i++) { | |
| GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = gf_list_get(IOR->taggedProfile,0); | |
| left_lite_component = taggedProfile->lite_component_count; | |
| switch(taggedProfile->profileId_tag) { | |
| case TAG_BIOP: | |
| { | |
| /* Object Location */ | |
| GF_SAFEALLOC(taggedProfile->BIOPProfileBody,GF_M2TS_DSMCC_BIOP_PROFILE_BODY); | |
| gf_free(taggedProfile->BIOPProfileBody->ConnBinder.Taps); | |
| if(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18 != 0) { | |
| gf_free(taggedProfile->BIOPProfileBody->ConnBinder.additional_tap_byte); | |
| } | |
| gf_free(taggedProfile->BIOPProfileBody); | |
| left_lite_component = left_lite_component - 2; | |
| break; | |
| } | |
| case TAG_LITE_OPTIONS: | |
| { | |
| /* Service Location */ | |
| u32 j; | |
| for(j = 0; j < taggedProfile->ServiceLocation->nameComponents_count; j++) { | |
| if(taggedProfile->ServiceLocation->NameComponent[j].id_length != 0) { | |
| gf_free(taggedProfile->ServiceLocation->NameComponent[j].id_data); | |
| } | |
| if(taggedProfile->ServiceLocation->NameComponent[j].kind_length != 0) { | |
| gf_free(taggedProfile->ServiceLocation->NameComponent[j].kind_data); | |
| } | |
| } | |
| gf_free(taggedProfile->ServiceLocation->NameComponent); | |
| if(taggedProfile->ServiceLocation->initialContext_length != 0) { | |
| gf_free(taggedProfile->ServiceLocation->InitialContext_data_byte); | |
| } | |
| left_lite_component = left_lite_component - 1; | |
| break; | |
| } | |
| } | |
| for(i = 0; i<left_lite_component ; i++) { | |
| if(taggedProfile->LiteComponent[i].component_data_length != 0) { | |
| gf_free(taggedProfile->LiteComponent[i].component_data_byte); | |
| } | |
| } | |
| gf_free(taggedProfile->LiteComponent); | |
| gf_list_rem(IOR->taggedProfile,0); | |
| gf_free(taggedProfile); | |
| } | |
| gf_list_del(IOR->taggedProfile); | |
| } | |
| static void dsmcc_free_biop_descriptor(GF_List* list) | |
| { | |
| while(gf_list_count(list)) { | |
| u8* descr_tag; | |
| descr_tag = (u8*)gf_list_get(list,0); | |
| switch(*descr_tag) { | |
| case CACHING_PRIORITY_DESCRIPTOR: | |
| { | |
| GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR* CachingPriorityDescr = (GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR*)gf_list_get(list,0); | |
| gf_list_rem(list,0); | |
| gf_free(CachingPriorityDescr); | |
| break; | |
| } | |
| case COMPRESSED_MODULE_DESCRIPTOR: | |
| { | |
| GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR* CompModuleDescr = (GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR*)gf_list_get(list,0); | |
| gf_list_rem(list,0); | |
| gf_free(CompModuleDescr); | |
| break; | |
| } | |
| case CONTENT_TYPE_DESCRIPTOR: | |
| { | |
| GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr = (GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR*)gf_list_get(list,0); | |
| gf_list_rem(list,0); | |
| if(ContentTypeDescr->descriptor_length) { | |
| gf_free(ContentTypeDescr->content_type_data_byte); | |
| } | |
| gf_free(ContentTypeDescr); | |
| break; | |
| } | |
| default: | |
| { | |
| break; | |
| } | |
| } | |
| } | |
| gf_list_del(list); | |
| } | |
| static void dsmcc_free_biop_name(GF_M2TS_DSMCC_BIOP_NAME* Name, u32 nb_name) { | |
| u32 i; | |
| for(i =0; i<nb_name; i++) { | |
| if(Name[i].id_length) { | |
| gf_free(Name[i].id_data); | |
| } | |
| if(Name[i].kind_length) { | |
| gf_free(Name[i].kind_data); | |
| } | |
| /* IOR */ | |
| dsmcc_free_biop_ior(&Name[i].IOR); | |
| dsmcc_free_biop_descriptor(Name[i].descriptor); | |
| } | |
| } | |
| static void dsmcc_free_biop_context(GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count) { | |
| u32 i; | |
| for(i=0; i<serviceContextList_count; i++) { | |
| if(Context[i].context_data_length != 0) { | |
| gf_free(Context[i].context_data_byte); | |
| } | |
| } | |
| gf_free(Context); | |
| } | |
| #endif //GPAC_ENABLE_DSMCC |