GF_Err gf_sm_load_init_isom(GF_SceneLoader *load) { u32 i; GF_BIFSConfig *bc; GF_ESD *esd; GF_Err e; char *scene_msg = "MPEG-4 BIFS Scene Parsing"; if (!load->isom) return GF_BAD_PARAM; /*load IOD*/ load->ctx->root_od = (GF_ObjectDescriptor *) gf_isom_get_root_od(load->isom); if (!load->ctx->root_od) { e = gf_isom_last_error(load->isom); if (e) return e; } else if ((load->ctx->root_od->tag != GF_ODF_OD_TAG) && (load->ctx->root_od->tag != GF_ODF_IOD_TAG)) { gf_odf_desc_del((GF_Descriptor *) load->ctx->root_od); load->ctx->root_od = NULL; } esd = NULL; /*get root scene stream*/ for (i=0; i<gf_isom_get_track_count(load->isom); i++) { u32 type = gf_isom_get_media_type(load->isom, i+1); if (type != GF_ISOM_MEDIA_SCENE) continue; if (! gf_isom_is_track_in_root_od(load->isom, i+1) ) continue; esd = gf_isom_get_esd(load->isom, i+1, 1); if (esd && esd->URLString) { gf_odf_desc_del((GF_Descriptor *)esd); esd = NULL; continue; } /*make sure we load the root BIFS stream first*/ if (esd && esd->dependsOnESID && (esd->dependsOnESID!=esd->ESID) ) { u32 track = gf_isom_get_track_by_id(load->isom, esd->dependsOnESID); if (gf_isom_get_media_type(load->isom, track) != GF_ISOM_MEDIA_OD) { gf_odf_desc_del((GF_Descriptor *)esd); esd = NULL; continue; } } if (esd->decoderConfig->objectTypeIndication==0x09) scene_msg = "MPEG-4 LASeR Scene Parsing"; break; } if (!esd) return GF_OK; e = GF_OK; GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("%s\n", scene_msg)); /*BIFS: update size & pixel metrics info*/ if (esd->decoderConfig->objectTypeIndication<=2) { bc = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication); if (!bc->elementaryMasks && bc->pixelWidth && bc->pixelHeight) { load->ctx->scene_width = bc->pixelWidth; load->ctx->scene_height = bc->pixelHeight; load->ctx->is_pixel_metrics = bc->pixelMetrics; } gf_odf_desc_del((GF_Descriptor *) bc); /*note we don't load the first BIFS AU to avoid storing the BIFS decoder, needed to properly handle quantization*/ } /*LASeR*/ else if (esd->decoderConfig->objectTypeIndication==0x09) { load->ctx->is_pixel_metrics = 1; } gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; load->process = gf_sm_load_run_isom; load->done = gf_sm_load_done_isom; load->suspend = gf_sm_isom_suspend; return GF_OK; }
static GF_Err gf_sm_setup_bifsenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF_ESD *esd) { char *data; u32 data_len; u32 nbb; Bool encode_names, delete_bcfg; GF_BIFSConfig *bcfg; if (!esd->decoderConfig || (esd->decoderConfig->streamType != GF_STREAM_SCENE)) return GF_BAD_PARAM; if (!seng->bifsenc) seng->bifsenc = gf_bifs_encoder_new(seng->ctx->scene_graph); delete_bcfg = 0; /*inputctx is not properly setup, do it*/ if (!esd->decoderConfig->decoderSpecificInfo) { bcfg = (GF_BIFSConfig*)gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); bcfg->pixelMetrics = seng->ctx->is_pixel_metrics; bcfg->pixelWidth = seng->ctx->scene_width; bcfg->pixelHeight = seng->ctx->scene_height; delete_bcfg = 1; } /*regular case*/ else if (esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_BIFS_CFG_TAG) { bcfg = (GF_BIFSConfig *)esd->decoderConfig->decoderSpecificInfo; } /*happens when loading from MP4 in which case BIFSc is not decoded*/ else { bcfg = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication); delete_bcfg = 1; } /*NO CHANGE TO BIFSC otherwise the generated update will not match the input context The only case we modify the bifs config is when XXXBits is not specified*/ nbb = gf_get_bit_size(seng->ctx->max_node_id); if (!bcfg->nodeIDbits) bcfg->nodeIDbits = nbb; else if (bcfg->nodeIDbits<nbb) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.NodeIDBits too small (%d bits vs %d nodes)\n", bcfg->nodeIDbits, seng->ctx->max_node_id)); } nbb = gf_get_bit_size(seng->ctx->max_route_id); if (!bcfg->routeIDbits) bcfg->routeIDbits = nbb; else if (bcfg->routeIDbits<nbb) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.RouteIDBits too small (%d bits vs %d routes)\n", bcfg->routeIDbits, seng->ctx->max_route_id)); } nbb = gf_get_bit_size(seng->ctx->max_proto_id); if (!bcfg->protoIDbits) bcfg->protoIDbits=nbb; else if (bcfg->protoIDbits<nbb) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.ProtoIDBits too small (%d bits vs %d protos)\n", bcfg->protoIDbits, seng->ctx->max_proto_id)); } /*this is the real pb, not stored in cfg or file level, set at EACH replaceScene*/ encode_names = 0; /* The BIFS Config that is passed here should be the BIFSConfig from the IOD */ gf_bifs_encoder_new_stream(seng->bifsenc, esd->ESID, bcfg, encode_names, 0); if (delete_bcfg) gf_odf_desc_del((GF_Descriptor *)bcfg); gf_bifs_encoder_get_config(seng->bifsenc, esd->ESID, &data, &data_len); if (esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); esd->decoderConfig->decoderSpecificInfo->data = data; esd->decoderConfig->decoderSpecificInfo->dataLength = data_len; sc->dec_cfg = gf_malloc(sizeof(char)*data_len); memcpy(sc->dec_cfg, data, data_len); sc->dec_cfg_len = data_len; esd->decoderConfig->objectTypeIndication = gf_bifs_encoder_get_version(seng->bifsenc, esd->ESID); return GF_OK; }
static GF_Err gf_sm_live_setup(GF_BifsEngine *codec) { GF_Err e; char *data; u32 data_len; GF_InitialObjectDescriptor *iod; u32 i, j, count, nbb; GF_ESD *esd; Bool is_in_iod, delete_desc, encode_names, delete_bcfg; GF_BIFSConfig *bcfg; e = GF_OK; iod = (GF_InitialObjectDescriptor *) codec->ctx->root_od; /*if no iod check we only have one bifs*/ if (!iod) { count = 0; i=0; while ((codec->sc = (GF_StreamContext*)gf_list_enum(codec->ctx->streams, &i))) { if (codec->sc->streamType == GF_STREAM_OD) count++; codec->sc = NULL; } if (!iod && count>1) return GF_NOT_SUPPORTED; } codec->sc = NULL; count = gf_list_count(codec->ctx->streams); i=0; while ((codec->sc = (GF_StreamContext*)gf_list_enum(codec->ctx->streams, &i))) { if (codec->sc->streamType == GF_STREAM_SCENE) break; } if (!codec->sc) return GF_NOT_SUPPORTED; if (!codec->sc->ESID) codec->sc->ESID = 1; codec->bifsenc = gf_bifs_encoder_new(codec->ctx->scene_graph); delete_desc = 0; esd = NULL; is_in_iod = 1; if (iod) { is_in_iod = 0; j=0; while ((esd = (GF_ESD*)gf_list_enum(iod->ESDescriptors, &j))) { if (esd->decoderConfig && esd->decoderConfig->streamType == GF_STREAM_SCENE) { if (!codec->sc->ESID) codec->sc->ESID = esd->ESID; if (codec->sc->ESID == esd->ESID) { is_in_iod = 1; break; } } /*special BIFS direct import from NHNT*/ else if (gf_list_count(iod->ESDescriptors)==1) { codec->sc->ESID = esd->ESID; is_in_iod = 1; break; } esd = NULL; } } if (!esd) { delete_desc = 1; esd = gf_odf_desc_esd_new(2); gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); esd->decoderConfig->decoderSpecificInfo = NULL; esd->ESID = codec->sc->ESID; esd->decoderConfig->streamType = GF_STREAM_SCENE; } delete_bcfg = 0; /*should NOT happen (means inputctx is not properly setup)*/ if (!esd->decoderConfig->decoderSpecificInfo) { bcfg = (GF_BIFSConfig*)gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); bcfg->pixelMetrics = codec->ctx->is_pixel_metrics; bcfg->pixelWidth = codec->ctx->scene_width; bcfg->pixelHeight = codec->ctx->scene_height; delete_bcfg = 1; } /*regular retrieve from ctx*/ else if (esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_BIFS_CFG_TAG) { bcfg = (GF_BIFSConfig *)esd->decoderConfig->decoderSpecificInfo; } /*should not happen either (unless loading from MP4 in which case BIFSc is not decoded)*/ else { bcfg = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication); delete_bcfg = 1; } /*NO CHANGE TO BIFSC otherwise the generated update will not match the input context, UNLESS NO NbBits were specified*/ nbb = gf_get_bit_size(codec->ctx->max_node_id); if (!bcfg->nodeIDbits) bcfg->nodeIDbits = nbb; else if (bcfg->nodeIDbits<nbb) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.NodeIDBits too small (%d bits vs %d nodes)\n", bcfg->nodeIDbits, codec->ctx->max_node_id)); } nbb = gf_get_bit_size(codec->ctx->max_route_id); if (!bcfg->routeIDbits) bcfg->routeIDbits = nbb; else if (bcfg->routeIDbits<nbb) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.RouteIDBits too small (%d bits vs %d routes)\n", bcfg->routeIDbits, codec->ctx->max_route_id)); } nbb = gf_get_bit_size(codec->ctx->max_proto_id); if (!bcfg->protoIDbits) bcfg->protoIDbits=nbb; else if (bcfg->protoIDbits<nbb) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.ProtoIDBits too small (%d bits vs %d protos)\n", bcfg->protoIDbits, codec->ctx->max_proto_id)); } /*this is the real pb, not stored in cfg or file level, set at EACH replaceScene*/ encode_names = 0; /* The BIFS Config that is passed here should be the BIFSConfig from the IOD */ gf_bifs_encoder_new_stream(codec->bifsenc, codec->sc->ESID, bcfg, encode_names, 0); if (delete_bcfg) gf_odf_desc_del((GF_Descriptor *)bcfg); if (!esd->slConfig) esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); if (codec->sc->timeScale) esd->slConfig->timestampResolution = codec->sc->timeScale; if (!esd->slConfig->timestampResolution) esd->slConfig->timestampResolution = 1000; esd->ESID = codec->sc->ESID; gf_bifs_encoder_get_config(codec->bifsenc, codec->sc->ESID, &data, &data_len); if (esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); esd->decoderConfig->decoderSpecificInfo->data = data; esd->decoderConfig->decoderSpecificInfo->dataLength = data_len; codec->stream_ts_res = esd->slConfig->timestampResolution; memcpy(codec->encoded_bifs_config, data, data_len); codec->encoded_bifs_config_size = data_len; esd->decoderConfig->objectTypeIndication = gf_bifs_encoder_get_version(codec->bifsenc, codec->sc->ESID); return e; }