static GF_Err IS_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd) { GF_BitStream *bs; u32 len, size, i; char devName[255]; u16 termSeq[20]; ISPriv *is = (ISPriv *)plug->privateStack; if (esd->decoderConfig->upstream) return GF_NOT_SUPPORTED; if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->dataLength) return GF_NON_COMPLIANT_BITSTREAM; /*no more than one UI stream per object*/ if (is->ES_ID) return GF_NOT_SUPPORTED; is->ES_ID = esd->ESID; /*parse config*/ bs = gf_bs_new(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ); len = gf_bs_read_int(bs, 8); for (i=0; i<len; i++) { devName[i] = gf_bs_read_int(bs, 8); } devName[i] = 0; is->type = gf_crc_32(devName, len); size = len + 1; if (!stricmp(devName, "KeySensor")) { is->type = IS_KeySensor; add_field(is, GF_SG_VRML_SFINT32, "keyPressed"); add_field(is, GF_SG_VRML_SFINT32, "keyReleased"); add_field(is, GF_SG_VRML_SFINT32, "actionKeyPressed"); add_field(is, GF_SG_VRML_SFINT32, "actionKeyReleased"); add_field(is, GF_SG_VRML_SFBOOL, "shiftKeyPressed"); add_field(is, GF_SG_VRML_SFBOOL, "controlKeyPressed"); add_field(is, GF_SG_VRML_SFBOOL, "altKeyPressed"); } else if (!stricmp(devName, "StringSensor")) { is->type = IS_StringSensor; add_field(is, GF_SG_VRML_SFSTRING, "enteredText"); add_field(is, GF_SG_VRML_SFSTRING, "finalText"); is->termChar = '\r'; is->delChar = '\b'; /*get escape chars if any specified*/ if (size<esd->decoderConfig->decoderSpecificInfo->dataLength) { const char *src = esd->decoderConfig->decoderSpecificInfo->data + size; gf_utf8_mbstowcs(termSeq, esd->decoderConfig->decoderSpecificInfo->dataLength - size, &src); is->termChar = termSeq[0]; is->delChar = termSeq[1]; } } else if (!stricmp(devName, "Mouse")) { is->type = IS_Mouse; add_field(is, GF_SG_VRML_SFVEC2F, "position"); add_field(is, GF_SG_VRML_SFBOOL, "leftButtonDown"); add_field(is, GF_SG_VRML_SFBOOL, "middleButtonDown"); add_field(is, GF_SG_VRML_SFBOOL, "rightButtonDown"); add_field(is, GF_SG_VRML_SFFLOAT, "wheel"); } else { GF_InputSensorDevice *ifce; /*not found, check all modules*/ u32 plugCount = gf_modules_get_count(is->scene->root_od->term->user->modules); for (i = 0; i < plugCount ; i++) { ifce = (GF_InputSensorDevice *) gf_modules_load_interface(is->scene->root_od->term->user->modules, i, GF_INPUT_DEVICE_INTERFACE); if (!ifce) continue; ifce->input_decoder = plug; if (ifce->RegisterDevice && ifce->RegisterDevice(ifce, devName, bs, isdev_add_field) ) { is->io_dev = ifce; break; } gf_modules_close_interface((GF_BaseInterface *) ifce); } if (!is->io_dev) return GF_NOT_SUPPORTED; is->io_dev->DispatchFrame = isdev_dispatch_frame; plug->module_name = is->io_dev->module_name; plug->author_name = is->io_dev->author_name; } gf_bs_del(bs); return GF_OK; }
/** * A function which takes FFmpeg H265 extradata (SPS/PPS) and bring them ready to be pushed to the MP4 muxer. * @param extradata * @param extradata_size * @param dstcfg * @returns GF_OK is the extradata was parsed and is valid, other values otherwise. */ static GF_Err hevc_import_ffextradata(const u8 *extradata, const u64 extradata_size, GF_HEVCConfig *dst_cfg) { #ifdef GPAC_DISABLE_AV_PARSERS return GF_OK; #else HEVCState hevc; GF_HEVCParamArray *vpss = NULL, *spss = NULL, *ppss = NULL; GF_BitStream *bs; char *buffer = NULL; u32 buffer_size = 0; if (!extradata || (extradata_size < sizeof(u32))) return GF_BAD_PARAM; bs = gf_bs_new(extradata, extradata_size, GF_BITSTREAM_READ); if (!bs) return GF_BAD_PARAM; memset(&hevc, 0, sizeof(HEVCState)); hevc.sps_active_idx = -1; while (gf_bs_available(bs)) { s32 idx; GF_AVCConfigSlot *slc; u8 nal_unit_type, temporal_id, layer_id; u64 nal_start; u32 nal_size; if (gf_bs_read_u32(bs) != 0x00000001) { gf_bs_del(bs); return GF_BAD_PARAM; } nal_start = gf_bs_get_position(bs); nal_size = gf_media_nalu_next_start_code_bs(bs); if (nal_start + nal_size > extradata_size) { gf_bs_del(bs); return GF_BAD_PARAM; } if (nal_size > buffer_size) { buffer = (char*)gf_realloc(buffer, nal_size); buffer_size = nal_size; } gf_bs_read_data(bs, buffer, nal_size); gf_bs_seek(bs, nal_start); gf_media_hevc_parse_nalu(bs, &hevc, &nal_unit_type, &temporal_id, &layer_id); if (layer_id) { gf_bs_del(bs); gf_free(buffer); return GF_BAD_PARAM; } switch (nal_unit_type) { case GF_HEVC_NALU_VID_PARAM: idx = gf_media_hevc_read_vps(buffer, nal_size , &hevc); if (idx < 0) { gf_bs_del(bs); gf_free(buffer); return GF_BAD_PARAM; } assert(hevc.vps[idx].state == 1); //we don't expect multiple VPS if (hevc.vps[idx].state == 1) { hevc.vps[idx].state = 2; hevc.vps[idx].crc = gf_crc_32(buffer, nal_size); dst_cfg->avgFrameRate = hevc.vps[idx].rates[0].avg_pic_rate; dst_cfg->constantFrameRate = hevc.vps[idx].rates[0].constand_pic_rate_idc; dst_cfg->numTemporalLayers = hevc.vps[idx].max_sub_layers; dst_cfg->temporalIdNested = hevc.vps[idx].temporal_id_nesting; if (!vpss) { GF_SAFEALLOC(vpss, GF_HEVCParamArray); vpss->nalus = gf_list_new(); gf_list_add(dst_cfg->param_array, vpss); vpss->array_completeness = 1; vpss->type = GF_HEVC_NALU_VID_PARAM; } slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); slc->size = nal_size; slc->id = idx; slc->data = (char*)gf_malloc(sizeof(char)*slc->size); memcpy(slc->data, buffer, sizeof(char)*slc->size); gf_list_add(vpss->nalus, slc); } break; case GF_HEVC_NALU_SEQ_PARAM: idx = gf_media_hevc_read_sps(buffer, nal_size, &hevc); if (idx < 0) { gf_bs_del(bs); gf_free(buffer); return GF_BAD_PARAM; } assert(!(hevc.sps[idx].state & AVC_SPS_DECLARED)); //we don't expect multiple SPS if ((hevc.sps[idx].state & AVC_SPS_PARSED) && !(hevc.sps[idx].state & AVC_SPS_DECLARED)) { hevc.sps[idx].state |= AVC_SPS_DECLARED; hevc.sps[idx].crc = gf_crc_32(buffer, nal_size); } dst_cfg->configurationVersion = 1; dst_cfg->profile_space = hevc.sps[idx].ptl.profile_space; dst_cfg->tier_flag = hevc.sps[idx].ptl.tier_flag; dst_cfg->profile_idc = hevc.sps[idx].ptl.profile_idc; dst_cfg->general_profile_compatibility_flags = hevc.sps[idx].ptl.profile_compatibility_flag; dst_cfg->progressive_source_flag = hevc.sps[idx].ptl.general_progressive_source_flag; dst_cfg->interlaced_source_flag = hevc.sps[idx].ptl.general_interlaced_source_flag; dst_cfg->non_packed_constraint_flag = hevc.sps[idx].ptl.general_non_packed_constraint_flag; dst_cfg->frame_only_constraint_flag = hevc.sps[idx].ptl.general_frame_only_constraint_flag; dst_cfg->constraint_indicator_flags = hevc.sps[idx].ptl.general_reserved_44bits; dst_cfg->level_idc = hevc.sps[idx].ptl.level_idc; dst_cfg->chromaFormat = hevc.sps[idx].chroma_format_idc; dst_cfg->luma_bit_depth = hevc.sps[idx].bit_depth_luma; dst_cfg->chroma_bit_depth = hevc.sps[idx].bit_depth_chroma; if (!spss) { GF_SAFEALLOC(spss, GF_HEVCParamArray); spss->nalus = gf_list_new(); gf_list_add(dst_cfg->param_array, spss); spss->array_completeness = 1; spss->type = GF_HEVC_NALU_SEQ_PARAM; } slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); slc->size = nal_size; slc->id = idx; slc->data = (char*)gf_malloc(sizeof(char)*slc->size); memcpy(slc->data, buffer, sizeof(char)*slc->size); gf_list_add(spss->nalus, slc); break; case GF_HEVC_NALU_PIC_PARAM: idx = gf_media_hevc_read_pps(buffer, nal_size, &hevc); if (idx < 0) { gf_bs_del(bs); gf_free(buffer); return GF_BAD_PARAM; } assert(hevc.pps[idx].state == 1); //we don't expect multiple PPS if (hevc.pps[idx].state == 1) { hevc.pps[idx].state = 2; hevc.pps[idx].crc = gf_crc_32(buffer, nal_size); if (!ppss) { GF_SAFEALLOC(ppss, GF_HEVCParamArray); ppss->nalus = gf_list_new(); gf_list_add(dst_cfg->param_array, ppss); ppss->array_completeness = 1; ppss->type = GF_HEVC_NALU_PIC_PARAM; } slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); slc->size = nal_size; slc->id = idx; slc->data = (char*)gf_malloc(sizeof(char)*slc->size); memcpy(slc->data, buffer, sizeof(char)*slc->size); gf_list_add(ppss->nalus, slc); } break; default: break; } if (gf_bs_seek(bs, nal_start+nal_size)) { assert(nal_start+nal_size <= gf_bs_get_size(bs)); break; } } gf_bs_del(bs); gf_free(buffer); return GF_OK; #endif }