GF_Err gf_bifs_flush_command_list(GF_BifsDecoder *codec) { GF_BitStream *bs; GF_Err e; CommandBufferItem *cbi; u32 NbPass = gf_list_count(codec->command_buffers); GF_List *nextPass = gf_list_new(); while (NbPass) { while (gf_list_count(codec->command_buffers)) { cbi = (CommandBufferItem *)gf_list_get(codec->command_buffers, 0); gf_list_rem(codec->command_buffers, 0); codec->current_graph = gf_node_get_graph(cbi->node); e = GF_OK; if (cbi->cb->bufferSize) { bs = gf_bs_new((char*)cbi->cb->buffer, cbi->cb->bufferSize, GF_BITSTREAM_READ); gf_bs_set_eos_callback(bs, BM_EndOfStream, codec); e = BM_ParseCommand(codec, bs, cbi->cb->commandList); gf_bs_del(bs); } if (!e) { gf_free(cbi); continue; } /*this may be an error or a dependency pb - reset coimmand list and move to next pass*/ while (gf_list_count(cbi->cb->commandList)) { u32 i; GF_CommandField *cf; GF_Command *com = (GF_Command *)gf_list_get(cbi->cb->commandList, 0); gf_list_rem(cbi->cb->commandList, 0); cf = (GF_CommandField *) gf_list_get(com->command_fields, 0); if (cf && cf->fieldType==GF_SG_VRML_SFCOMMANDBUFFER) { for (i=0; i<gf_list_count(codec->command_buffers); i++) { CommandBufferItem *cbi2 = (CommandBufferItem *)gf_list_get(codec->command_buffers, i); if (cbi2->cb == cf->field_ptr) { gf_free(cbi2); gf_list_rem(codec->command_buffers, i); i--; } } } gf_sg_command_del(com); } gf_list_add(nextPass, cbi); } if (!gf_list_count(nextPass)) break; /*prepare next pass*/ while (gf_list_count(nextPass)) { cbi = (CommandBufferItem *)gf_list_get(nextPass, 0); gf_list_rem(nextPass, 0); gf_list_add(codec->command_buffers, cbi); } NbPass --; if (NbPass > gf_list_count(codec->command_buffers)) NbPass = gf_list_count(codec->command_buffers); codec->LastError = GF_OK; } gf_list_del(nextPass); return GF_OK; }
void gf_sg_sfcommand_del(SFCommandBuffer cb) { u32 i; for (i=gf_list_count(cb.commandList); i>0; i--) { GF_Command *com = (GF_Command *)gf_list_get(cb.commandList, i-1); gf_sg_command_del(com); } gf_list_del(cb.commandList); if (cb.buffer) gf_free(cb.buffer); }
static GF_Err BM_ParseMultipleIndexedReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 ID, ind, field_ind, NumBits, lenpos, lennum, count; GF_Node *node; GF_Err e; GF_Command *com; GF_CommandField *inf; GF_FieldInfo field; ID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, ID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, NumBits); e = gf_bifs_get_field_index(node, ind, GF_SG_FIELD_CODING_IN, &field_ind); if (e) return e; e = gf_node_get_field(node, field_ind, &field); if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; lenpos = gf_bs_read_int(bs, 5); lennum = gf_bs_read_int(bs, 5); count = gf_bs_read_int(bs, lennum); com = gf_sg_command_new(codec->current_graph, GF_SG_MULTIPLE_INDEXED_REPLACE); BM_SetCommandNode(com, node); field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType); while (count) { inf = gf_sg_command_field_new(com); inf->pos = gf_bs_read_int(bs, lenpos); inf->fieldIndex = field.fieldIndex; inf->fieldType = field.fieldType; if (field.fieldType==GF_SG_VRML_SFNODE) { inf->new_node = gf_bifs_dec_node(codec, bs, field.NDTtype); if (codec->LastError) goto err; inf->field_ptr = &inf->new_node; gf_node_register(inf->new_node, NULL); } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); e = gf_bifs_dec_sf_field(codec, bs, node, &field, 1); if (e) goto err; } count--; } err: if (e) gf_sg_command_del(com); else gf_list_add(com_list, com); return e; }
GF_EXPORT GF_Err gf_sm_make_random_access(GF_SceneManager *ctx) { GF_Err e; u32 i, j, stream_count, au_count, com_count; GF_AUContext *au; GF_Command *com; e = GF_OK; stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); /*FIXME - do this as well for ODs*/ if (sc->streamType == GF_STREAM_SCENE) { /*apply all commands - this will also apply the SceneReplace*/ j=0; while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { e = gf_sg_command_apply_list(ctx->scene_graph, au->commands, 0); if (e) return e; } /* Delete all the commands in the stream */ while ( (au_count = gf_list_count(sc->AUs)) ) { au = (GF_AUContext *)gf_list_get(sc->AUs, au_count-1); gf_list_rem(sc->AUs, au_count-1); while ( (com_count = gf_list_count(au->commands)) ) { com = (GF_Command*)gf_list_get(au->commands, com_count - 1); gf_list_rem(au->commands, com_count - 1); gf_sg_command_del(com); } gf_list_del(au->commands); free(au); } /*and recreate scene replace*/ au = gf_sm_stream_au_new(sc, 0, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_SCENE_REPLACE); com->node = ctx->scene_graph->RootNode; ctx->scene_graph->RootNode = NULL; gf_list_del(com->new_proto_list); com->new_proto_list = ctx->scene_graph->protos; ctx->scene_graph->protos = NULL; /*FIXME - check routes & protos*/ gf_list_add(au->commands, com); } } return e; }
static void gf_sm_au_del(GF_StreamContext *sc, GF_AUContext *au) { while (gf_list_count(au->commands)) { void *comptr = gf_list_last(au->commands); gf_list_rem_last(au->commands); switch (sc->streamType) { case GF_STREAM_OD: gf_odf_com_del((GF_ODCom**) & comptr); break; case GF_STREAM_SCENE: gf_sg_command_del((GF_Command *)comptr); break; } } gf_list_del(au->commands); gf_free(au); }
static GF_Err BM_ParseExtendedUpdates(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 type = gf_bs_read_int(bs, 8); GF_Err e; switch (type) { case 0: { GF_Command *com = gf_sg_command_new(codec->current_graph, GF_SG_PROTO_INSERT); e = gf_bifs_dec_proto_list(codec, bs, com->new_proto_list); if (e) gf_sg_command_del(com); else gf_list_add(com_list, com); } return e; case 1: return BM_ParseProtoDelete(codec, bs, com_list); case 2: { GF_Command *com = gf_sg_command_new(codec->current_graph, GF_SG_PROTO_DELETE_ALL); return gf_list_add(com_list, com); } case 3: return BM_ParseMultipleIndexedReplace(codec, bs, com_list); case 4: return BM_ParseMultipleReplace(codec, bs, com_list); case 5: return BM_ParseGlobalQuantizer(codec, bs, com_list); case 6: { GF_Command *com; u32 ID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); GF_Node *n = gf_sg_find_node(codec->current_graph, ID); if (!n) return GF_OK; com = gf_sg_command_new(codec->current_graph, GF_SG_NODE_DELETE_EX); BM_SetCommandNode(com, n); gf_list_add(com_list, com); } return GF_OK; case 7: return BM_XReplace(codec, bs, com_list); default: return GF_BIFS_UNKNOWN_VERSION; } }
static void seng_exec_conditional(M_Conditional *c, GF_SceneGraph *scene) { GF_List *clist = c->buffer.commandList; c->buffer.commandList = NULL; gf_sg_command_apply_list(gf_node_get_graph((GF_Node*)c), clist, 0.0); if (c->buffer.commandList != NULL) { while (gf_list_count(clist)) { GF_Command *sub_com = (GF_Command *)gf_list_get(clist, 0); gf_sg_command_del(sub_com); gf_list_rem(clist, 0); } gf_list_del(clist); } else { c->buffer.commandList = clist; } }
GF_EXPORT GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID) { GF_Err e; u32 i, stream_count; #ifndef GPAC_DISABLE_VRML u32 j; GF_AUContext *au; GF_Command *com; #endif e = GF_OK; #if DEBUG_RAP com_count = 0; stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); if (sc->streamType == GF_STREAM_SCENE) { au_count = gf_list_count(sc->AUs); for (j=0; j<au_count; j++) { au = (GF_AUContext *)gf_list_get(sc->AUs, j); com_count += gf_list_count(au->commands); } } } GF_LOG(GF_LOG_INFO, GF_LOG_SCENE, ("[SceneManager] Making RAP with %d commands\n", com_count)); #endif stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_AUContext *carousel_au; GF_List *carousel_commands; GF_StreamContext *aggregate_on_stream; GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); if (ESID && (sc->ESID!=ESID)) continue; /*locate the AU in which our commands will be aggregated*/ carousel_au = NULL; carousel_commands = NULL; aggregate_on_stream = sc->aggregate_on_esid ? gf_sm_get_stream(ctx, sc->aggregate_on_esid) : NULL; if (aggregate_on_stream==sc) { carousel_commands = gf_list_new(); } else if (aggregate_on_stream) { if (!gf_list_count(aggregate_on_stream->AUs)) { carousel_au = gf_sm_stream_au_new(aggregate_on_stream, 0, 0, 1); } else { /* assert we already performed aggregation */ assert(gf_list_count(aggregate_on_stream->AUs)==1); carousel_au = gf_list_get(aggregate_on_stream->AUs, 0); } carousel_commands = carousel_au->commands; } /*TODO - do this as well for ODs*/ #ifndef GPAC_DISABLE_VRML if (sc->streamType == GF_STREAM_SCENE) { Bool has_modif = 0; /*we check for each stream if it is a base stream (SceneReplace ...) - several streams may carry RAPs if inline nodes are used*/ Bool base_stream_found = 0; /*in DIMS we use an empty initial AU with no commands to signal the RAP*/ if (sc->objectType == GPAC_OTI_SCENE_DIMS) base_stream_found = 1; /*apply all commands - this will also apply the SceneReplace*/ while (gf_list_count(sc->AUs)) { u32 count; au = (GF_AUContext *) gf_list_get(sc->AUs, 0); gf_list_rem(sc->AUs, 0); /*AU not aggregated*/ if (au->flags & GF_SM_AU_NOT_AGGREGATED) { gf_sm_au_del(sc, au); continue; } count = gf_list_count(au->commands); for (j=0; j<count; j++) { u32 store=0; com = gf_list_get(au->commands, j); if (!base_stream_found) { switch (com->tag) { case GF_SG_SCENE_REPLACE: case GF_SG_LSR_NEW_SCENE: case GF_SG_LSR_REFRESH_SCENE: base_stream_found = 1; break; } } /*aggregate the command*/ /*if stream doesn't carry a carousel or carries the base carousel (scene replace), always apply the command*/ if (base_stream_found || !sc->aggregate_on_esid) { store = 0; } /*otherwise, check wether the command should be kept in this stream as is, or can be aggregated on this stream*/ else { switch (com->tag) { /*the following commands do not impact a sub-tree (eg do not deal with nodes), we cannot aggregate them... */ case GF_SG_ROUTE_REPLACE: case GF_SG_ROUTE_DELETE: case GF_SG_ROUTE_INSERT: case GF_SG_PROTO_INSERT: case GF_SG_PROTO_DELETE: case GF_SG_PROTO_DELETE_ALL: case GF_SG_GLOBAL_QUANTIZER: case GF_SG_LSR_RESTORE: case GF_SG_LSR_SAVE: case GF_SG_LSR_SEND_EVENT: case GF_SG_LSR_CLEAN: /*todo check in which category to put these commands*/ // case GF_SG_LSR_ACTIVATE: // case GF_SG_LSR_DEACTIVATE: store = 1; break; /*other commands: !!! we need to know if the target node of the command has been inserted in this stream !!! This is a tedious task, for now we will consider the following cases: - locate a similar command in the stored list: remove the similar one and aggregate on stream - by default all AUs are stored if the stream is in aggregate mode - we should fix that by checking insertion points: if a command apllies on a node that has been inserted in this stream, we can aggregate, otherwise store */ default: /*check if we can directly store the command*/ assert(carousel_commands); store = store_or_aggregate(sc, com, carousel_commands, &has_modif); break; } } switch (store) { /*command has been merged with a previous command in carousel and needs to be destroyed*/ case 2: gf_list_rem(au->commands, j); j--; count--; gf_sg_command_del((GF_Command *)com); break; /*command shall be moved to carousel without being applied*/ case 1: gf_list_insert(carousel_commands, com, 0); gf_list_rem(au->commands, j); j--; count--; break; /*command can be applied*/ default: e = gf_sg_command_apply(ctx->scene_graph, com, 0); break; } } gf_sm_au_del(sc, au); } /*and recreate scene replace*/ if (base_stream_found) { au = gf_sm_stream_au_new(sc, 0, 0, 1); switch (sc->objectType) { case GPAC_OTI_SCENE_BIFS: case GPAC_OTI_SCENE_BIFS_V2: com = gf_sg_command_new(ctx->scene_graph, GF_SG_SCENE_REPLACE); break; case GPAC_OTI_SCENE_LASER: com = gf_sg_command_new(ctx->scene_graph, GF_SG_LSR_NEW_SCENE); break; case GPAC_OTI_SCENE_DIMS: /* We do not create a new command, empty AU is enough in DIMS*/ default: com = NULL; break; } if (com) { com->node = ctx->scene_graph->RootNode; ctx->scene_graph->RootNode = NULL; gf_list_del(com->new_proto_list); com->new_proto_list = ctx->scene_graph->protos; ctx->scene_graph->protos = NULL; /*indicate the command is the aggregated scene graph, so that PROTOs and ROUTEs are taken from the scenegraph when encoding*/ com->aggregated = 1; gf_list_add(au->commands, com); } } /*update carousel flags of the AU*/ else if (carousel_commands) { /*if current stream caries its own carousel*/ if (!carousel_au) { carousel_au = gf_sm_stream_au_new(sc, 0, 0, 1); gf_list_del(carousel_au->commands); carousel_au->commands = carousel_commands; } carousel_au->flags |= GF_SM_AU_RAP | GF_SM_AU_CAROUSEL; if (has_modif) carousel_au->flags |= GF_SM_AU_MODIFIED; } } #endif } return e; }
static u32 store_or_aggregate(GF_StreamContext *sc, GF_Command *com, GF_List *commands, Bool *has_modif) { #ifndef GPAC_DISABLE_VRML u32 i, count, j, nb_fields; GF_CommandField *field, *check_field; /*if our command deals with a node inserted in the commands list, apply command list*/ if (node_in_commands_subtree(com->node, commands)) return 0; /*otherwise, check if we can substitute a previous command with this one*/ count = gf_list_count(commands); for (i=0; i<count; i++) { GF_Command *check = gf_list_get(commands, i); if (sc->streamType == GF_STREAM_SCENE) { Bool check_index=0; Bool original_is_index = 0; Bool apply; switch (com->tag) { case GF_SG_INDEXED_REPLACE: check_index=1; case GF_SG_MULTIPLE_INDEXED_REPLACE: case GF_SG_FIELD_REPLACE: case GF_SG_MULTIPLE_REPLACE: if (check->node != com->node) break; /*we may aggregate an indexed insertion and a replace one*/ if (check_index) { if (check->tag == GF_SG_INDEXED_REPLACE) {} else if (check->tag == GF_SG_INDEXED_INSERT) { original_is_index = 1; } else { break; } } else { if (check->tag != com->tag) break; } nb_fields = gf_list_count(com->command_fields); if (gf_list_count(check->command_fields) != nb_fields) break; apply=1; for (j=0; j<nb_fields; j++) { field = gf_list_get(com->command_fields, j); check_field = gf_list_get(check->command_fields, j); if ((field->pos != check_field->pos) || (field->fieldIndex != check_field->fieldIndex)) { apply=0; break; } } /*same target node+fields, destroy first command and store new one*/ if (apply) { /*if indexed, change command tag*/ if (original_is_index) com->tag = GF_SG_INDEXED_INSERT; gf_sg_command_del((GF_Command *)check); gf_list_rem(commands, i); if (has_modif) *has_modif = 1; return 1; } break; case GF_SG_NODE_REPLACE: if (check->tag != GF_SG_NODE_REPLACE) { break; } /*TODO - THIS IS NOT SUPPORTED IN GPAC SINCE WE NEVER ALLOW FOR DUPLICATE NODE IDs IN THE SCENE !!!*/ if (gf_node_get_id(check->node) != gf_node_get_id(com->node) ) { break; } /*same node ID, destroy first command and store new one*/ gf_sg_command_del((GF_Command *)check); gf_list_rem(commands, i); if (has_modif) *has_modif = 1; return 1; case GF_SG_INDEXED_DELETE: /*look for an indexed insert before the indexed delete with same target pos and node. If found, discard both commands!*/ if (check->tag != GF_SG_INDEXED_INSERT) break; if (com->node != check->node) break; field = gf_list_get(com->command_fields, 0); check_field = gf_list_get(check->command_fields, 0); if (!field || !check_field) break; if (field->pos != check_field->pos) break; if (field->fieldIndex != check_field->fieldIndex) break; gf_sg_command_del((GF_Command *)check); gf_list_rem(commands, i); if (has_modif) *has_modif = 1; return 2; default: GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[Scene Manager] Stream Aggregation not implemented for command - aggregating on main scene\n")); break; } } } /*the command modifies another stream than associated current carousel stream, we have to store it.*/ if (has_modif) *has_modif=1; #endif return 1; }
GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com) { GF_Err e; GF_Node *new_node; u32 size, length, w, h, i; char *buffer; //blindly call unquantize. return is OK, error or GF_EOS if (codec->ActiveQP && node) { e = gf_bifs_dec_unquant_field(codec, bs, node, field); if (e != GF_EOS) return e; } //not quantized, use normal scheme switch (field->fieldType) { case GF_SG_VRML_SFBOOL: * ((SFBool *) field->far_ptr) = (SFBool) gf_bs_read_int(bs, 1); break; case GF_SG_VRML_SFCOLOR: ((SFColor *)field->far_ptr)->red = BD_ReadSFFloat(codec, bs);; ((SFColor *)field->far_ptr)->green = BD_ReadSFFloat(codec, bs); ((SFColor *)field->far_ptr)->blue = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFFLOAT: *((SFFloat *)field->far_ptr) = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFINT32: *((SFInt32 *)field->far_ptr) = (s32) gf_bs_read_int(bs, 32); break; case GF_SG_VRML_SFTIME: *((SFTime *)field->far_ptr) = gf_bs_read_double(bs); if (node) BD_CheckSFTimeOffset(codec, node, field); break; case GF_SG_VRML_SFVEC2F: ((SFVec2f *)field->far_ptr)->x = BD_ReadSFFloat(codec, bs); ((SFVec2f *)field->far_ptr)->y = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFVEC3F: ((SFVec3f *)field->far_ptr)->x = BD_ReadSFFloat(codec, bs); ((SFVec3f *)field->far_ptr)->y = BD_ReadSFFloat(codec, bs); ((SFVec3f *)field->far_ptr)->z = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFROTATION: ((SFRotation *)field->far_ptr)->x = BD_ReadSFFloat(codec, bs); ((SFRotation *)field->far_ptr)->y = BD_ReadSFFloat(codec, bs); ((SFRotation *)field->far_ptr)->z = BD_ReadSFFloat(codec, bs); ((SFRotation *)field->far_ptr)->q = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFSTRING: size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; if (node && (node->sgprivate->tag==TAG_MPEG4_CacheTexture) && (field->fieldIndex<=2)) { M_CacheTexture *ct = (M_CacheTexture *) node; ct->data_len = length; if (ct->data) gf_free(ct->data); ct->data = gf_malloc(sizeof(char)*length); gf_bs_read_data(bs, (char*)ct->data, length); } else if (node && (node->sgprivate->tag==TAG_MPEG4_BitWrapper) ) { M_BitWrapper *bw = (M_BitWrapper*) node; if (bw->buffer.buffer) gf_free(bw->buffer.buffer); bw->buffer_len = length; bw->buffer.buffer = gf_malloc(sizeof(char)*length); gf_bs_read_data(bs, (char*)bw->buffer.buffer, length); } else { if ( ((SFString *)field->far_ptr)->buffer ) gf_free( ((SFString *)field->far_ptr)->buffer); ((SFString *)field->far_ptr)->buffer = (char *)gf_malloc(sizeof(char)*(length+1)); memset(((SFString *)field->far_ptr)->buffer , 0, length+1); for (i=0; i<length; i++) { ((SFString *)field->far_ptr)->buffer[i] = gf_bs_read_int(bs, 8); } } break; case GF_SG_VRML_SFURL: { SFURL *url = (SFURL *) field->far_ptr; size = gf_bs_read_int(bs, 1); if (size) { if (url->url) gf_free(url->url ); url->url = NULL; length = gf_bs_read_int(bs, 10); url->OD_ID = length; } else { if ( url->OD_ID ) url->OD_ID = (u32) -1; size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; buffer = NULL; if (length) { buffer = (char *)gf_malloc(sizeof(char)*(length+1)); memset(buffer, 0, length+1); for (i=0; i<length; i++) buffer[i] = gf_bs_read_int(bs, 8); } if (url->url) gf_free( url->url); /*if URL is empty set it to NULL*/ if (buffer && strlen(buffer)) { url->url = buffer; } else { gf_free(buffer); url->url = NULL; } } } break; case GF_SG_VRML_SFIMAGE: if (((SFImage *)field->far_ptr)->pixels) gf_free(((SFImage *)field->far_ptr)->pixels); w = gf_bs_read_int(bs, 12); h = gf_bs_read_int(bs, 12); length = gf_bs_read_int(bs, 2); if (length > 3) length = 3; length += 1; size = w * h * length; if (gf_bs_available(bs) < size) return GF_NON_COMPLIANT_BITSTREAM; ((SFImage *)field->far_ptr)->width = w; ((SFImage *)field->far_ptr)->height = h; ((SFImage *)field->far_ptr)->numComponents = length; ((SFImage *)field->far_ptr)->pixels = (unsigned char *)gf_malloc(sizeof(char)*size); //WARNING: Buffers are NOT ALIGNED IN THE BITSTREAM for (i=0; i<size; i++) { ((SFImage *)field->far_ptr)->pixels[i] = gf_bs_read_int(bs, 8); } break; case GF_SG_VRML_SFCOMMANDBUFFER: { SFCommandBuffer *sfcb = (SFCommandBuffer *)field->far_ptr; if (sfcb->buffer) { gf_free(sfcb->buffer); sfcb->buffer = NULL; } while (gf_list_count(sfcb->commandList)) { GF_Command *com = (GF_Command*)gf_list_get(sfcb->commandList, 0); gf_list_rem(sfcb->commandList, 0); gf_sg_command_del(com); } size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; sfcb->bufferSize = length; if (length) { sfcb->buffer = (unsigned char *)gf_malloc(sizeof(char)*(length)); //WARNING Buffers are NOT ALIGNED IN THE BITSTREAM for (i=0; i<length; i++) { sfcb->buffer[i] = gf_bs_read_int(bs, 8); } } //notify the node - this is needed in case an enhencement layer replaces the buffer, in which case //the # ID Bits may change SFCommandBufferChanged(codec, node); /* 1 - memory mode, register command buffer for later parsing 2 - InputSensor only works on decompressed commands */ if (codec->dec_memory_mode || (node->sgprivate->tag==TAG_MPEG4_InputSensor)) { CommandBufferItem *cbi = (CommandBufferItem *)gf_malloc(sizeof(CommandBufferItem)); cbi->node = node; cbi->cb = sfcb; gf_list_add(codec->command_buffers, cbi); } } break; case GF_SG_VRML_SFNODE: //for nodes the field ptr is a ptr to the field, which is a node ptr ;) new_node = gf_bifs_dec_node(codec, bs, field->NDTtype); if (new_node) { e = gf_node_register(new_node, is_mem_com ? NULL : node); if (e) return e; } //it may happen that new_node is NULL (this is valid for a proto declaration) *((GF_Node **) field->far_ptr) = new_node; break; case GF_SG_VRML_SFSCRIPT: #ifdef GPAC_HAS_SPIDERMONKEY codec->LastError = SFScript_Parse(codec, (SFScript*)field->far_ptr, bs, node); #else return GF_NOT_SUPPORTED; #endif break; case GF_SG_VRML_SFATTRREF: { SFAttrRef *ar = (SFAttrRef *)field->far_ptr; u32 nodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); ar->node = gf_sg_find_node(codec->current_graph, nodeID); if (!ar->node) { } else { u32 nbBitsDEF = gf_get_bit_size(gf_node_get_num_fields_in_mode(ar->node, GF_SG_FIELD_CODING_DEF) - 1); u32 field_ref = gf_bs_read_int(bs, nbBitsDEF); codec->LastError = gf_bifs_get_field_index(ar->node, field_ref, GF_SG_FIELD_CODING_DEF, &ar->fieldIndex); } } break; default: return GF_NON_COMPLIANT_BITSTREAM; } return codec->LastError; }
static GF_Err BM_ParseMultipleReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 i, numFields, index, flag, nbBits, field_ref, fieldind; GF_Err e; GF_FieldInfo field; u32 NodeID; GF_Node *node; GF_Command *com; GF_CommandField *inf; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, NodeID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; e = GF_OK; com = gf_sg_command_new(codec->current_graph, GF_SG_MULTIPLE_REPLACE); BM_SetCommandNode(com, node); flag = gf_bs_read_int(bs, 1); if (flag) { numFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_DEF); for (i=0; i<numFields; i++) { flag = gf_bs_read_int(bs, 1); if (!flag) continue; gf_bifs_get_field_index(node, i, GF_SG_FIELD_CODING_DEF, &index); e = gf_node_get_field(node, index, &field); if (e) goto exit; inf = gf_sg_command_field_new(com); inf->fieldType = field.fieldType; inf->fieldIndex = field.fieldIndex; if (inf->fieldType==GF_SG_VRML_SFNODE) { field.far_ptr = inf->field_ptr = &inf->new_node; } else if (inf->fieldType==GF_SG_VRML_MFNODE) { field.far_ptr = inf->field_ptr = &inf->node_list; } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); } e = gf_bifs_dec_field(codec, bs, node, &field, 1); if (e) goto exit; } } else { flag = gf_bs_read_int(bs, 1); nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_DEF)-1); while (!flag && (codec->LastError>=0)) { field_ref = gf_bs_read_int(bs, nbBits); e = gf_bifs_get_field_index(node, field_ref, GF_SG_FIELD_CODING_DEF, &fieldind); if (e) goto exit; e = gf_node_get_field(node, fieldind, &field); if (e) goto exit; inf = gf_sg_command_field_new(com); inf->fieldType = field.fieldType; inf->fieldIndex = field.fieldIndex; if (inf->fieldType==GF_SG_VRML_SFNODE) { field.far_ptr = inf->field_ptr = &inf->new_node; } else if (inf->fieldType==GF_SG_VRML_MFNODE) { field.far_ptr = inf->field_ptr = &inf->node_list; } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); } e = gf_bifs_dec_field(codec, bs, node, &field, 1); if (e) goto exit; flag = gf_bs_read_int(bs, 1); } } exit: if (e) gf_sg_command_del(com); else gf_list_add(com_list, com); return e; }
static GF_Err CTXLoad_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 stream_time, u32 mmlevel) { GF_Err e = GF_OK; u32 i, j, k, nb_updates, last_rap=0; GF_AUContext *au; Bool can_delete_com; GF_StreamContext *sc; CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack; /*something failed*/ if (priv->load_flags==3) return GF_EOS; /*this signals main scene deconnection, destroy the context if needed*/ assert(ES_ID); if (!priv->ctx) { e = CTXLoad_Setup((GF_BaseDecoder *)plug); if (e) return e; } if (stream_time==(u32)-1) { /*seek on root stream: destroy the context manager and reload it. We cannot seek on the main stream because commands may have changed node attributes/children and we d'ont track the initial value*/ if (priv->load_flags && (priv->base_stream_id == ES_ID)) { if (priv->src) gf_fclose(priv->src); priv->src = NULL; gf_sm_load_done(&priv->load); priv->file_pos = 0; /*queue scene for detach*/ gf_term_lock_media_queue(priv->scene->root_od->term, GF_TRUE); priv->scene->root_od->action_type = GF_ODM_ACTION_SCENE_RECONNECT; gf_list_add(priv->scene->root_od->term->media_queue, priv->scene->root_od); gf_term_lock_media_queue(priv->scene->root_od->term, GF_FALSE); return CTXLoad_Setup((GF_BaseDecoder *)plug); } i=0; while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) { /*not our stream*/ if (!sc->in_root_od && (sc->ESID != ES_ID)) continue; /*not the base stream*/ if (sc->in_root_od && (priv->base_stream_id != ES_ID)) continue; /*handle SWF media extraction*/ if ((sc->streamType == GF_STREAM_OD) && (priv->load_flags==1)) continue; sc->last_au_time = 0; } return GF_OK; } if (priv->load_flags != 2) { if (priv->progressive_support) { u32 entry_time; char file_buf[4096+1]; if (!priv->src) { priv->src = gf_fopen(priv->file_name, "rb"); if (!priv->src) return GF_URL_ERROR; priv->file_pos = 0; } priv->load.type = GF_SM_LOAD_XMTA; e = GF_OK; entry_time = gf_sys_clock(); gf_fseek(priv->src, priv->file_pos, SEEK_SET); while (1) { u32 diff; s32 nb_read = (s32) fread(file_buf, 1, 4096, priv->src); if (nb_read<0) { return GF_IO_ERR; } file_buf[nb_read] = 0; if (!nb_read) { if (priv->file_pos==priv->file_size) { gf_fclose(priv->src); priv->src = NULL; priv->load_flags = 2; gf_sm_load_done(&priv->load); break; } break; } e = gf_sm_load_string(&priv->load, file_buf, GF_FALSE); priv->file_pos += nb_read; if (e) break; diff = gf_sys_clock() - entry_time; if (diff > priv->sax_max_duration) break; } if (!priv->scene->graph_attached) { gf_sg_set_scene_size_info(priv->scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics); gf_scene_attach_to_compositor(priv->scene); CTXLoad_CheckStreams(priv); } } /*load first frame only*/ else if (!priv->load_flags) { /*we need the whole file*/ if (!CTXLoad_CheckDownload(priv)) return GF_OK; priv->load_flags = 1; e = gf_sm_load_init(&priv->load); if (!e) { CTXLoad_CheckStreams(priv); gf_sg_set_scene_size_info(priv->scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics); /*VRML, override base clock*/ if ((priv->load.type==GF_SM_LOAD_VRML) || (priv->load.type==GF_SM_LOAD_X3DV) || (priv->load.type==GF_SM_LOAD_X3D)) { /*override clock callback*/ gf_sg_set_scene_time_callback(priv->scene->graph, CTXLoad_GetVRMLTime); } } } /*load the rest*/ else { priv->load_flags = 2; e = gf_sm_load_run(&priv->load); gf_sm_load_done(&priv->load); /*in case this was not set in the first pass (XMT)*/ gf_sg_set_scene_size_info(priv->scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics); } if (e<0) { gf_sm_load_done(&priv->load); gf_sm_del(priv->ctx); priv->ctx = NULL; priv->load_flags = 3; return e; } /*and figure out duration of root scene, and take care of XMT timing*/ if (priv->load_flags==2) { CTXLoad_CheckStreams(priv); if (!gf_list_count(priv->ctx->streams)) { gf_scene_attach_to_compositor(priv->scene); } } } nb_updates = 0; i=0; while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) { /*not our stream*/ if (!sc->in_root_od && (sc->ESID != ES_ID)) continue; /*not the base stream*/ if (sc->in_root_od && (priv->base_stream_id != ES_ID)) continue; /*handle SWF media extraction*/ if ((sc->streamType == GF_STREAM_OD) && (priv->load_flags==1)) continue; /*check for seek*/ if (sc->last_au_time > 1 + stream_time) { sc->last_au_time = 0; } can_delete_com = GF_FALSE; if (sc->in_root_od && (priv->load_flags==2)) can_delete_com = GF_TRUE; /*we're in the right stream, apply update*/ j=0; /*seek*/ if (!sc->last_au_time) { while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { u32 au_time = (u32) (au->timing*1000/sc->timeScale); if (au_time > stream_time) break; if (au->flags & GF_SM_AU_RAP) last_rap = j-1; } j = last_rap; } while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { u32 au_time = (u32) (au->timing*1000/sc->timeScale); if (au_time + 1 <= sc->last_au_time) { /*remove first replace command*/ if (can_delete_com && (sc->streamType==GF_STREAM_SCENE)) { while (gf_list_count(au->commands)) { GF_Command *com = (GF_Command *)gf_list_get(au->commands, 0); gf_list_rem(au->commands, 0); gf_sg_command_del(com); } j--; gf_list_rem(sc->AUs, j); gf_list_del(au->commands); gf_free(au); } continue; } if (au_time > stream_time) { nb_updates++; break; } if (sc->streamType == GF_STREAM_SCENE) { GF_Command *com; /*apply the commands*/ k=0; while ((com = (GF_Command *)gf_list_enum(au->commands, &k))) { e = gf_sg_command_apply(priv->scene->graph, com, 0); if (e) break; /*remove commands on base layer*/ if (can_delete_com) { k--; gf_list_rem(au->commands, k); gf_sg_command_del(com); } } } else if (sc->streamType == GF_STREAM_OD) { /*apply the commands*/ while (gf_list_count(au->commands)) { Bool keep_com = GF_FALSE; GF_ODCom *com = (GF_ODCom *)gf_list_get(au->commands, 0); gf_list_rem(au->commands, 0); switch (com->tag) { case GF_ODF_OD_UPDATE_TAG: { GF_ODUpdate *odU = (GF_ODUpdate *)com; while (gf_list_count(odU->objectDescriptors)) { GF_ESD *esd; char *remote; GF_MuxInfo *mux = NULL; GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, 0); gf_list_rem(odU->objectDescriptors, 0); /*we can only work with single-stream ods*/ esd = (GF_ESD*)gf_list_get(od->ESDescriptors, 0); if (!esd) { if (od->URLString) { ODS_SetupOD(priv->scene, od); } else { gf_odf_desc_del((GF_Descriptor *) od); } continue; } /*fix OCR dependencies*/ if (CTXLoad_StreamInRootOD(priv->ctx->root_od, esd->OCRESID)) esd->OCRESID = priv->base_stream_id; /*forbidden if ESD*/ if (od->URLString) { gf_odf_desc_del((GF_Descriptor *) od); continue; } /*look for MUX info*/ k=0; while ((mux = (GF_MuxInfo*)gf_list_enum(esd->extensionDescriptors, &k))) { if (mux->tag == GF_ODF_MUXINFO_TAG) break; mux = NULL; } /*we need a mux if not animation stream*/ if (!mux || !mux->file_name) { /*only animation streams are handled*/ if (!esd->decoderConfig) { gf_odf_desc_del((GF_Descriptor *) od); } else if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { /*set ST to private scene to get sure the stream will be redirected to us*/ esd->decoderConfig->streamType = GF_STREAM_PRIVATE_SCENE; esd->dependsOnESID = priv->base_stream_id; ODS_SetupOD(priv->scene, od); } else if (esd->decoderConfig->streamType==GF_STREAM_INTERACT) { GF_UIConfig *cfg = (GF_UIConfig *) esd->decoderConfig->decoderSpecificInfo; gf_odf_encode_ui_config(cfg, &esd->decoderConfig->decoderSpecificInfo); gf_odf_desc_del((GF_Descriptor *) cfg); ODS_SetupOD(priv->scene, od); } else { gf_odf_desc_del((GF_Descriptor *) od); } continue; } //solve url before import if (mux->src_url) { char *res_url = gf_url_concatenate(mux->src_url, mux->file_name); if (res_url) { gf_free(mux->file_name); mux->file_name = res_url; } gf_free(mux->src_url); mux->src_url = NULL; } /*text import*/ if (mux->textNode) { #ifdef GPAC_DISABLE_MEDIA_IMPORT gf_odf_desc_del((GF_Descriptor *) od); continue; #else e = gf_sm_import_bifs_subtitle(priv->ctx, esd, mux); if (e) { e = GF_OK; gf_odf_desc_del((GF_Descriptor *) od); continue; } /*set ST to private scene and dependency to base to get sure the stream will be redirected to us*/ esd->decoderConfig->streamType = GF_STREAM_PRIVATE_SCENE; esd->dependsOnESID = priv->base_stream_id; ODS_SetupOD(priv->scene, od); continue; #endif } /*soundstreams are a bit of a pain, they may be declared before any data gets written*/ if (mux->delete_file) { FILE *t = gf_fopen(mux->file_name, "rb"); if (!t) { keep_com = GF_TRUE; gf_list_insert(odU->objectDescriptors, od, 0); break; } gf_fclose(t); } /*remap to remote URL - warning, the URL has already been resolved according to the parent path*/ remote = (char*)gf_malloc(sizeof(char) * (strlen("gpac://")+strlen(mux->file_name)+1) ); strcpy(remote, "gpac://"); strcat(remote, mux->file_name); k = od->objectDescriptorID; /*if files were created we'll have to clean up (swf import)*/ if (mux->delete_file) gf_list_add(priv->files_to_delete, gf_strdup(remote)); gf_odf_desc_del((GF_Descriptor *) od); od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->URLString = remote; od->objectDescriptorID = k; ODS_SetupOD(priv->scene, od); } if (keep_com) break; } break; case GF_ODF_OD_REMOVE_TAG: { GF_ODRemove *odR = (GF_ODRemove*)com; for (k=0; k<odR->NbODs; k++) { GF_ObjectManager *odm = gf_scene_find_odm(priv->scene, odR->OD_ID[k]); if (odm) gf_odm_disconnect(odm, 1); } } break; default: break; } if (keep_com) { gf_list_insert(au->commands, com, 0); break; } else { gf_odf_com_del(&com); } if (e) break; } } sc->last_au_time = au_time + 1; /*attach graph to renderer*/ if (!priv->scene->graph_attached) gf_scene_attach_to_compositor(priv->scene); if (e) return e; /*for root streams remove completed AUs (no longer needed)*/ if (sc->in_root_od && !gf_list_count(au->commands) ) { j--; gf_list_rem(sc->AUs, j); gf_list_del(au->commands); gf_free(au); } } } if (e) return e; if ((priv->load_flags==2) && !nb_updates) return GF_EOS; return GF_OK; }
GF_EXPORT GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset) { GF_Err e; GF_CommandField *inf; #ifndef GPAC_DISABLE_VRML GF_FieldInfo field; void *slot_ptr; GF_Node *def; #endif GF_Node *node; if (!com || !graph) return GF_BAD_PARAM; if (com->never_apply) return GF_OK; e = GF_OK; switch (com->tag) { #ifndef GPAC_DISABLE_VRML case GF_SG_SCENE_REPLACE: /*unregister root*/ gf_node_unregister(graph->RootNode, NULL); /*remove all protos and routes*/ while (gf_list_count(graph->routes_to_activate)) gf_list_rem(graph->routes_to_activate, 0); if (!com->aggregated) { /*destroy all routes*/ while (gf_list_count(graph->Routes)) { GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0); /*this will unregister the route from the graph, so don't delete the chain entry*/ gf_sg_route_del(r); } /*destroy all proto*/ while (gf_list_count(graph->protos)) { GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0); /*this will unregister the proto from the graph, so don't delete the chain entry*/ gf_sg_proto_del(p); } } /*DO NOT TOUCH node registry*/ /*DO NOT TOUCH UNREGISTERED PROTOS*/ /*if no protos (previously aggregated command) create proto list*/ if (!graph->protos) graph->protos = gf_list_new(); /*move all protos in graph*/ while (gf_list_count(com->new_proto_list)) { GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0); gf_list_rem(com->new_proto_list, 0); gf_list_del_item(graph->unregistered_protos, p); gf_list_add(graph->protos, p); } /*assign new root (no need to register/unregister)*/ graph->RootNode = com->node; com->node = NULL; break; case GF_SG_NODE_REPLACE: if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_replace(com->node, inf->new_node, 0); if (inf->new_node) gf_node_register(inf->new_node, NULL); break; case GF_SG_MULTIPLE_REPLACE: case GF_SG_FIELD_REPLACE: { u32 j; GF_ChildNodeItem *list, *cur, *prev; j=0; while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &j))) { e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; switch (field.fieldType) { case GF_SG_VRML_SFNODE: { node = *((GF_Node **) field.far_ptr); e = gf_node_unregister(node, com->node); *((GF_Node **) field.far_ptr) = inf->new_node; if (!e) gf_node_register(inf->new_node, com->node); break; } case GF_SG_VRML_MFNODE: gf_node_unregister_children(com->node, * ((GF_ChildNodeItem **) field.far_ptr)); * ((GF_ChildNodeItem **) field.far_ptr) = NULL; list = * ((GF_ChildNodeItem **) inf->field_ptr); prev=NULL; while (list) { cur = gf_malloc(sizeof(GF_ChildNodeItem)); cur->next = NULL; cur->node = list->node; if (prev) { prev->next = cur; } else { * ((GF_ChildNodeItem **) field.far_ptr) = cur; } gf_node_register(list->node, com->node); prev = cur; list = list->next; } break; case GF_SG_VRML_SFCOMMANDBUFFER: { u32 i, count; GF_SceneGraph *sg; SFCommandBuffer *cb_dst = (SFCommandBuffer *)field.far_ptr; SFCommandBuffer *cb_src = (SFCommandBuffer *)inf->field_ptr; /*reset dest*/ if (!cb_dst->commandList) cb_dst->commandList = gf_list_new(); while (gf_list_count(cb_dst->commandList)) { GF_Command *sub_com = (GF_Command *)gf_list_get(cb_dst->commandList, 0); gf_sg_command_del(sub_com); gf_list_rem(cb_dst->commandList, 0); } if (cb_dst->buffer) { gf_free(cb_dst->buffer); cb_dst->buffer = NULL; } /*clone command list*/ sg = gf_node_get_graph(com->node); count = gf_list_count(cb_src->commandList); for (i=0; i<count;i++) { GF_Command *sub_com = (GF_Command *)gf_list_get(cb_src->commandList, i); GF_Command *new_com = gf_sg_vrml_command_clone(sub_com, sg, 0); gf_list_add(cb_dst->commandList, new_com); } } break; default: /*this is a regular field, reset it and clone - we cannot switch pointers since the original fields are NOT pointers*/ if (!gf_sg_vrml_is_sf_field(field.fieldType)) { e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType); } if (e) return e; gf_sg_vrml_field_copy(field.far_ptr, inf->field_ptr, field.fieldType); if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media")) *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset; break; } SG_CheckFieldChange(com->node, &field); } break; } case GF_SG_MULTIPLE_INDEXED_REPLACE: case GF_SG_INDEXED_REPLACE: { u32 sftype, i=0; while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &i))) { e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; /*if MFNode remove the child and set new node*/ if (field.fieldType == GF_SG_VRML_MFNODE) { /*we must remove the node before in case the new node uses the same ID (not forbidden) and this command removes the last instance of the node with the same ID*/ gf_node_replace_child(com->node, (GF_ChildNodeItem**) field.far_ptr, inf->pos, inf->new_node); if (inf->new_node) gf_node_register(inf->new_node, NULL); } /*erase the field item*/ else { if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) { inf->pos = ((GenMFField *)field.far_ptr)->count - 1; /*may happen with text and default value*/ if (inf->pos < 0) { inf->pos = 0; gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1); } } e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, inf->pos); if (e) return e; sftype = gf_sg_vrml_get_sf_type(field.fieldType); gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype); /*note we don't add time offset, since there's no MFTime*/ } SG_CheckFieldChange(com->node, &field); } break; } case GF_SG_ROUTE_REPLACE: { GF_Route *r; char *name; r = gf_sg_route_find(graph, com->RouteID); def = gf_sg_find_node(graph, com->fromNodeID); node = gf_sg_find_node(graph, com->toNodeID); if (!node || !def) return GF_SG_UNKNOWN_NODE; name = NULL; if (r) { name = r->name; r->name = NULL; gf_sg_route_del(r); } r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex); gf_sg_route_set_id(r, com->RouteID); if (name) { gf_sg_route_set_name(r, name); gf_free(name); } break; } case GF_SG_NODE_DELETE_EX: case GF_SG_NODE_DELETE: { if (com->node) gf_node_replace(com->node, NULL, (com->tag==GF_SG_NODE_DELETE_EX) ? 1 : 0); break; } case GF_SG_ROUTE_DELETE: { return gf_sg_route_del_by_id(graph, com->RouteID); } case GF_SG_INDEXED_DELETE: { if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; /*then we need special handling in case of a node*/ if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) { e = gf_node_replace_child(com->node, (GF_ChildNodeItem **) field.far_ptr, inf->pos, NULL); } else { if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) { inf->pos = ((GenMFField *)field.far_ptr)->count - 1; } /*this is a regular MFField, just remove the item (gf_realloc)*/ e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos); } /*deletion -> node has changed*/ if (!e) SG_CheckFieldChange(com->node, &field); break; } case GF_SG_NODE_INSERT: { if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_insert_child(com->node, inf->new_node, inf->pos); if (!e) gf_node_register(inf->new_node, com->node); if (!e) gf_node_event_out(com->node, inf->fieldIndex); if (!e) gf_node_changed(com->node, NULL); break; } case GF_SG_ROUTE_INSERT: { GF_Route *r; def = gf_sg_find_node(graph, com->fromNodeID); node = gf_sg_find_node(graph, com->toNodeID); if (!node || !def) return GF_SG_UNKNOWN_NODE; r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex); if (com->RouteID) gf_sg_route_set_id(r, com->RouteID); if (com->def_name) { gf_sg_route_set_name(r, com->def_name); gf_free(com->def_name); com->def_name = NULL; } break; } case GF_SG_INDEXED_INSERT: { u32 sftype; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; /*rescale the MFField and parse the SFField*/ if (field.fieldType != GF_SG_VRML_MFNODE) { if (inf->pos == -1) { e = gf_sg_vrml_mf_append(field.far_ptr, field.fieldType, & slot_ptr); } else { e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & slot_ptr, inf->pos); } if (e) return e; sftype = gf_sg_vrml_get_sf_type(field.fieldType); gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype); } else { if (inf->new_node) { if (inf->pos == -1) { gf_node_list_add_child( (GF_ChildNodeItem **) field.far_ptr, inf->new_node); } else { gf_node_list_insert_child((GF_ChildNodeItem **) field.far_ptr, inf->new_node, inf->pos); } gf_node_register(inf->new_node, com->node); } } if (!e) SG_CheckFieldChange(com->node, &field); break; } case GF_SG_PROTO_INSERT: /*destroy all proto*/ while (gf_list_count(com->new_proto_list)) { GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0); gf_list_rem(com->new_proto_list, 0); gf_list_del_item(graph->unregistered_protos, p); gf_list_add(graph->protos, p); } return GF_OK; case GF_SG_PROTO_DELETE: { u32 i; for (i=0; i<com->del_proto_list_size; i++) { /*note this will check for unregistered protos, but since IDs are unique we are sure we will not destroy an unregistered one*/ GF_Proto *proto = gf_sg_find_proto(graph, com->del_proto_list[i], NULL); if (proto) gf_sg_proto_del(proto); } } return GF_OK; case GF_SG_PROTO_DELETE_ALL: /*destroy all proto*/ while (gf_list_count(graph->protos)) { GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0); gf_list_rem(graph->protos, 0); /*this will unregister the proto from the graph, so don't delete the chain entry*/ gf_sg_proto_del(p); } /*DO NOT TOUCH UNREGISTERED PROTOS*/ return GF_OK; case GF_SG_XREPLACE: { s32 pos = -2; GF_Node *target = NULL; GF_ChildNodeItem *list, *cur, *prev; GF_FieldInfo value; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); if (!inf) return GF_SG_UNKNOWN_NODE; e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; target = com->node; if (!gf_sg_vrml_is_sf_field(field.fieldType)) { GF_FieldInfo idxField; if ((inf->pos != -2) || com->toNodeID) { if (com->toNodeID) { GF_Node *idxNode = gf_sg_find_node(graph, com->toNodeID); if (!idxNode) return GF_SG_UNKNOWN_NODE; if (gf_node_get_field(idxNode, com->toFieldIndex, &idxField) != GF_OK) return GF_OK; pos = 0; switch (idxField.fieldType) { case GF_SG_VRML_SFBOOL: if (*(SFBool*)idxField.far_ptr) pos = 1; break; case GF_SG_VRML_SFINT32: if (*(SFInt32*)idxField.far_ptr >=0) pos = *(SFInt32*)idxField.far_ptr; break; case GF_SG_VRML_SFFLOAT: if ( (*(SFFloat *)idxField.far_ptr) >=0) pos = (s32) floor( FIX2FLT(*(SFFloat*)idxField.far_ptr) ); break; case GF_SG_VRML_SFTIME: if ( (*(SFTime *)idxField.far_ptr) >=0) pos = (s32) floor( (*(SFTime *)idxField.far_ptr) ); break; } } else { pos = inf->pos; } } } /*override target node*/ if ((field.fieldType==GF_SG_VRML_MFNODE) && (pos>=-1) && com->ChildNodeTag) { target = gf_node_list_get_child(*(GF_ChildNodeItem **)field.far_ptr, pos); if (!target) return GF_SG_UNKNOWN_NODE; if (gf_node_get_field(target, com->child_field, &field) != GF_OK) return GF_SG_UNKNOWN_NODE; pos=-2; } if (com->fromNodeID) { GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID); if (!fromNode) return GF_SG_UNKNOWN_NODE; e = gf_node_get_field(fromNode, com->fromFieldIndex, &value); if (e) return e; } else { value.far_ptr = inf->field_ptr; value.fieldType = inf->fieldType; } /*indexed replacement*/ if (pos>=-1) { /*if MFNode remove the child and set new node*/ if (field.fieldType == GF_SG_VRML_MFNODE) { GF_Node *nn = *(GF_Node**)value.far_ptr; gf_node_replace_child(target, (GF_ChildNodeItem**) field.far_ptr, pos, nn); if (nn) gf_node_register(nn, NULL); } /*erase the field item*/ else { u32 sftype; if ((pos < 0) || ((u32) pos >= ((GenMFField *) field.far_ptr)->count) ) { pos = ((GenMFField *)field.far_ptr)->count - 1; /*may happen with text and default value*/ if (pos < 0) { pos = 0; gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1); } } e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, pos); if (e) return e; sftype = gf_sg_vrml_get_sf_type(field.fieldType); gf_sg_vrml_field_copy(slot_ptr, value.far_ptr, sftype); /*note we don't add time offset, since there's no MFTime*/ } } else { switch (field.fieldType) { case GF_SG_VRML_SFNODE: { node = *((GF_Node **) field.far_ptr); e = gf_node_unregister(node, target); *((GF_Node **) field.far_ptr) = *((GF_Node **) value.far_ptr) ; if (!e) gf_node_register(*(GF_Node **) value.far_ptr, target); break; } case GF_SG_VRML_MFNODE: gf_node_unregister_children(target, * ((GF_ChildNodeItem **) field.far_ptr)); * ((GF_ChildNodeItem **) field.far_ptr) = NULL; list = * ((GF_ChildNodeItem **) value.far_ptr); prev=NULL; while (list) { cur = gf_malloc(sizeof(GF_ChildNodeItem)); cur->next = NULL; cur->node = list->node; if (prev) { prev->next = cur; } else { * ((GF_ChildNodeItem **) field.far_ptr) = cur; } gf_node_register(list->node, target); prev = cur; list = list->next; } break; default: if (!gf_sg_vrml_is_sf_field(field.fieldType)) { e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType); } if (e) return e; gf_sg_vrml_field_clone(field.far_ptr, value.far_ptr, field.fieldType, graph); if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media")) *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset; break; } } SG_CheckFieldChange(target, &field); } return GF_OK; /*only used by BIFS*/ case GF_SG_GLOBAL_QUANTIZER: return GF_OK; #endif /*GPAC_DISABLE_VRML*/ #ifndef GPAC_DISABLE_SVG /*laser commands*/ case GF_SG_LSR_NEW_SCENE: /*DO NOT TOUCH node registry*/ /*assign new root (no need to register/unregister)*/ graph->RootNode = com->node; com->node = NULL; break; case GF_SG_LSR_DELETE: if (!com->node) return GF_NON_COMPLIANT_BITSTREAM; if (!gf_list_count(com->command_fields)) { gf_node_replace(com->node, NULL, 0); gf_node_deactivate(com->node); return GF_OK; } inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); node = gf_node_list_get_child(((SVG_Element *)com->node)->children, inf->pos); if (node) { e = gf_node_replace_child(com->node, &((SVG_Element *)com->node)->children, inf->pos, NULL); gf_node_deactivate(node); } break; case GF_SG_LSR_INSERT: inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM; if (inf->new_node) { if (inf->pos<0) gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node); else gf_node_list_insert_child(& ((SVG_Element *)com->node)->children, inf->new_node, inf->pos); gf_node_register(inf->new_node, com->node); gf_node_activate(inf->new_node); gf_node_changed(com->node, NULL); } else { /*NOT SUPPORTED*/ GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[LASeR] VALUE INSERTION NOT SUPPORTED\n")); } break; case GF_SG_LSR_ADD: case GF_SG_LSR_REPLACE: inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM; if (inf->new_node) { if (inf->pos<0) { /*if fieldIndex (eg attributeName) is set, this is children replacement*/ if (inf->fieldIndex>0) { gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children); ((SVG_Element *)com->node)->children = NULL; gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node); gf_node_register(inf->new_node, com->node); gf_node_activate(inf->new_node); } else { e = gf_node_replace(com->node, inf->new_node, 0); gf_node_activate(inf->new_node); } } else { node = gf_node_list_get_child( ((SVG_Element *)com->node)->children, inf->pos); gf_node_replace_child(com->node, & ((SVG_Element *)com->node)->children, inf->pos, inf->new_node); gf_node_register(inf->new_node, com->node); if (node) gf_node_deactivate(node); gf_node_activate(inf->new_node); } /*signal node modif*/ gf_node_changed(com->node, NULL); return e; } else if (inf->node_list) { GF_ChildNodeItem *child, *cur, *prev; gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children); ((SVG_Element *)com->node)->children = NULL; prev = NULL; child = inf->node_list; while (child) { cur = (GF_ChildNodeItem*)gf_malloc(sizeof(GF_ChildNodeItem)); cur->next = NULL; cur->node = child->node; gf_node_register(child->node, com->node); gf_node_activate(child->node); if (prev) prev->next = cur; else ((SVG_Element *)com->node)->children = cur; prev = cur; child = child->next; } /*signal node modif*/ gf_node_changed(com->node, NULL); return GF_OK; } /*attribute modif*/ else if (inf->field_ptr) { GF_FieldInfo a, b; if (inf->fieldIndex==(u32) -2) { GF_Point2D scale, translate; Fixed rotate; GF_Matrix2D *dest; gf_node_get_field_by_name(com->node, "transform", &a); dest = (GF_Matrix2D*)a.far_ptr; if (com->tag==GF_SG_LSR_REPLACE) { if (gf_mx2d_decompose(dest, &scale, &rotate, &translate)) { gf_mx2d_init(*dest); if (inf->fieldType==SVG_TRANSFORM_SCALE) scale = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) translate = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldType==SVG_TRANSFORM_ROTATE) rotate = ((SVG_Point_Angle*)inf->field_ptr)->angle; gf_mx2d_add_scale(dest, scale.x, scale.y); gf_mx2d_add_rotation(dest, 0, 0, rotate); gf_mx2d_add_translation(dest, translate.x, translate.y); } } else { GF_Point2D *pt = (GF_Point2D *)inf->field_ptr; if (inf->fieldType==SVG_TRANSFORM_SCALE) gf_mx2d_add_scale(dest, pt->x, pt->y); else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) gf_mx2d_add_translation(dest, pt->x, pt->y); else if (inf->fieldType == SVG_TRANSFORM_ROTATE) gf_mx2d_add_rotation(dest, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle); } /*signal node modif*/ gf_node_changed(com->node, &a); } else { if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) { char *str = *(SVG_String*)inf->field_ptr; if (com->tag == GF_SG_LSR_REPLACE) { GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL; if (t && (t->sgprivate->tag==TAG_DOMText)) { if (t->textContent) gf_free(t->textContent); t->textContent = NULL; if (str) t->textContent = gf_strdup(str); } } else { if (str) gf_dom_add_text_node(com->node, gf_strdup(str)); } /*signal node modif*/ gf_node_changed(com->node, NULL); } else if ((inf->fieldIndex==TAG_LSR_ATT_scale) || (inf->fieldIndex==TAG_LSR_ATT_translation) || (inf->fieldIndex==TAG_LSR_ATT_rotation) ) { SVG_Transform *mx; gf_node_get_attribute_by_tag(com->node, TAG_SVG_ATT_transform, 1, 0, &a); mx = a.far_ptr; if (com->tag == GF_SG_LSR_REPLACE) { GF_Point2D scale, translate; SVG_Point_Angle rotate; if (gf_mx2d_decompose(&mx->mat, &scale, &rotate.angle, &translate)) { gf_mx2d_init(mx->mat); if (inf->fieldIndex==TAG_LSR_ATT_scale) scale = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldIndex==TAG_LSR_ATT_translation) translate = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldIndex==TAG_LSR_ATT_rotation) rotate = *(SVG_Point_Angle*)inf->field_ptr; gf_mx2d_add_scale(&mx->mat, scale.x, scale.y); gf_mx2d_add_rotation(&mx->mat, 0, 0, rotate.angle); gf_mx2d_add_translation(&mx->mat, translate.x, translate.y); } } else { if (inf->fieldIndex==TAG_LSR_ATT_scale) gf_mx2d_add_scale(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y); if (inf->fieldIndex==TAG_LSR_ATT_translation) gf_mx2d_add_translation(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y); if (inf->fieldIndex==TAG_LSR_ATT_rotation) gf_mx2d_add_rotation(&mx->mat, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle); } /*signal node modif*/ gf_node_changed(com->node, &a); } else if (gf_node_get_attribute_by_tag(com->node, inf->fieldIndex, 1, 0, &a) == GF_OK) { b = a; b.far_ptr = inf->field_ptr; if (com->tag == GF_SG_LSR_REPLACE) { gf_svg_attributes_copy(&a, &b, 0); } else { gf_svg_attributes_add(&a, &b, &a, 0); } if (a.fieldType==XMLRI_datatype) { gf_node_dirty_set(com->node, GF_SG_SVG_XLINK_HREF_DIRTY, 0); } /*signal node modif*/ gf_node_changed(com->node, &a); } } } else if (com->fromNodeID) { GF_FieldInfo a, b; GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID); if (!fromNode) return GF_NON_COMPLIANT_BITSTREAM; if (gf_node_get_field(fromNode, com->fromFieldIndex, &b) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM; if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) { char *str = *(SVG_String*)inf->field_ptr; if (com->tag == GF_SG_LSR_REPLACE) { GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL; if (t && (t->sgprivate->tag==TAG_DOMText)) { if (t->textContent) gf_free(t->textContent); t->textContent = NULL; if (str) t->textContent = gf_strdup(str); } } else { if (str) gf_dom_add_text_node(com->node, gf_strdup(str)); } } else { gf_node_get_field(com->node, inf->fieldIndex, &a); if (com->tag == GF_SG_LSR_REPLACE) { e = gf_svg_attributes_copy(&a, &b, 0); } else { e = gf_svg_attributes_add(&a, &b, &a, 0); } } gf_node_changed(com->node, &a); return e; } else { return GF_NON_COMPLIANT_BITSTREAM; } break; case GF_SG_LSR_ACTIVATE: gf_node_activate(com->node); break; case GF_SG_LSR_DEACTIVATE: gf_node_deactivate(com->node); gf_node_changed(com->node, NULL); break; case GF_SG_LSR_SEND_EVENT: { GF_DOM_Event evt; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.type = com->send_event_name; evt.detail = com->send_event_integer; evt.clientX = com->send_event_x; evt.clientY = com->send_event_y; gf_dom_event_fire(com->node, &evt); } break; #endif default: return GF_NOT_SUPPORTED; } if (e) return e; #ifndef GPAC_DISABLE_VRML if (com->scripts_to_load) { while (gf_list_count(com->scripts_to_load)) { GF_Node *script = (GF_Node *)gf_list_get(com->scripts_to_load, 0); gf_list_rem(com->scripts_to_load, 0); gf_sg_script_load(script); } gf_list_del(com->scripts_to_load); com->scripts_to_load = NULL; } #endif return GF_OK; }
GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) { GF_Err e; GF_Node *new_node; u32 size, length, w, h, i; char *buffer; //blindly call unquantize. return is OK, error or GF_EOS if (codec->ActiveQP && node) { e = gf_bifs_dec_unquant_field(codec, bs, node, field); if (e != GF_EOS) return e; } //not quantized, use normal scheme switch (field->fieldType) { case GF_SG_VRML_SFBOOL: * ((SFBool *) field->far_ptr) = (SFBool) gf_bs_read_int(bs, 1); break; case GF_SG_VRML_SFCOLOR: ((SFColor *)field->far_ptr)->red = BD_ReadSFFloat(codec, bs);; ((SFColor *)field->far_ptr)->green = BD_ReadSFFloat(codec, bs); ((SFColor *)field->far_ptr)->blue = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFFLOAT: *((SFFloat *)field->far_ptr) = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFINT32: *((SFInt32 *)field->far_ptr) = (s32) gf_bs_read_int(bs, 32); break; case GF_SG_VRML_SFTIME: *((SFTime *)field->far_ptr) = gf_bs_read_double(bs); if (node) BD_CheckSFTimeOffset(codec, node, field); break; case GF_SG_VRML_SFVEC2F: ((SFVec2f *)field->far_ptr)->x = BD_ReadSFFloat(codec, bs); ((SFVec2f *)field->far_ptr)->y = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFVEC3F: ((SFVec3f *)field->far_ptr)->x = BD_ReadSFFloat(codec, bs); ((SFVec3f *)field->far_ptr)->y = BD_ReadSFFloat(codec, bs); ((SFVec3f *)field->far_ptr)->z = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFROTATION: ((SFRotation *)field->far_ptr)->x = BD_ReadSFFloat(codec, bs); ((SFRotation *)field->far_ptr)->y = BD_ReadSFFloat(codec, bs); ((SFRotation *)field->far_ptr)->z = BD_ReadSFFloat(codec, bs); ((SFRotation *)field->far_ptr)->q = BD_ReadSFFloat(codec, bs); break; case GF_SG_VRML_SFSTRING: size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; if (node && (node->sgprivate->tag==TAG_MPEG4_CacheTexture) && (field->fieldIndex<=2)) { Bool skip_file_url_proto=0; char *name; FILE *f; M_CacheTexture *ct = (M_CacheTexture *) node; char *buf = gf_malloc(sizeof(char)*length); gf_bs_read_data(bs, buf, length); if (ct->cacheURL.buffer) { name = gf_strdup(ct->cacheURL.buffer); } else { char szImg[100], *ext; switch (ct->objectTypeIndication) { case GPAC_OTI_IMAGE_JPEG: ext = "jpg"; break; case GPAC_OTI_IMAGE_PNG: ext = "png"; break; case GPAC_OTI_IMAGE_JPEG_2000: ext = "jp2"; break; default: ext = "img"; } sprintf(szImg, "%p%p.%s", codec, ct, ext); name = gf_strdup(szImg); } if (codec->extraction_path) { char *path; u32 len = strlen(name)+strlen(codec->extraction_path)+2; if (strnicmp(codec->extraction_path, "file://", 7)) len+=7; /*SHA1 of service in hexa*/ if (codec->service_url) len += 41; path = gf_malloc(sizeof(char)*len); path[0] = 0; /*force using file:// URL prototype to avoid confusion with resources adressed from the root of the source server*/ if (strnicmp(codec->extraction_path, "file://", 7)) strcpy(path, "file://"); strcat(path, codec->extraction_path); strcat(path, "/"); if (codec->service_url) { u8 hash[20]; u32 i; gf_sha1_csum(codec->service_url, strlen(codec->service_url), hash); for (i=0; i<20; i++) { char t[3]; t[2] = 0; sprintf(t, "%02X", hash[i]); strcat(path, t); } strcat(path, "_"); } strcat(path, name); gf_free(name); name = path; skip_file_url_proto = 1; } ((SFString *)field->far_ptr)->buffer = name; /*skip the initial file://*/ f = gf_f64_open(name + (skip_file_url_proto ? 7 : 0), "wb"); fwrite(buf, 1, length, f); fclose(f); gf_free(buf); } else { if ( ((SFString *)field->far_ptr)->buffer ) gf_free( ((SFString *)field->far_ptr)->buffer); ((SFString *)field->far_ptr)->buffer = (char *)gf_malloc(sizeof(char)*(length+1)); memset(((SFString *)field->far_ptr)->buffer , 0, length+1); for (i=0; i<length; i++) { ((SFString *)field->far_ptr)->buffer[i] = gf_bs_read_int(bs, 8); } } break; case GF_SG_VRML_SFURL: { SFURL *url = (SFURL *) field->far_ptr; size = gf_bs_read_int(bs, 1); if (size) { if (url->url) gf_free(url->url ); url->url = NULL; length = gf_bs_read_int(bs, 10); url->OD_ID = length; } else { if ( url->OD_ID ) url->OD_ID = (u32) -1; size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; buffer = NULL; if (length) { buffer = (char *)gf_malloc(sizeof(char)*(length+1)); memset(buffer, 0, length+1); for (i=0; i<length; i++) buffer[i] = gf_bs_read_int(bs, 8); } if (url->url) gf_free( url->url); /*if URL is empty set it to NULL*/ if (buffer && strlen(buffer)) { url->url = buffer; } else { gf_free(buffer); url->url = NULL; } } } break; case GF_SG_VRML_SFIMAGE: if (((SFImage *)field->far_ptr)->pixels) gf_free(((SFImage *)field->far_ptr)->pixels); w = gf_bs_read_int(bs, 12); h = gf_bs_read_int(bs, 12); length = gf_bs_read_int(bs, 2); if (length > 3) length = 3; length += 1; size = w * h * length; if (gf_bs_available(bs) < size) return GF_NON_COMPLIANT_BITSTREAM; ((SFImage *)field->far_ptr)->width = w; ((SFImage *)field->far_ptr)->height = h; ((SFImage *)field->far_ptr)->numComponents = length; ((SFImage *)field->far_ptr)->pixels = (unsigned char *)gf_malloc(sizeof(char)*size); //WARNING: Buffers are NOT ALIGNED IN THE BITSTREAM for (i=0; i<size; i++) { ((SFImage *)field->far_ptr)->pixels[i] = gf_bs_read_int(bs, 8); } break; case GF_SG_VRML_SFCOMMANDBUFFER: { SFCommandBuffer *sfcb = (SFCommandBuffer *)field->far_ptr; if (sfcb->buffer) { gf_free(sfcb->buffer); sfcb->buffer = NULL; } while (gf_list_count(sfcb->commandList)) { GF_Command *com = (GF_Command*)gf_list_get(sfcb->commandList, 0); gf_list_rem(sfcb->commandList, 0); gf_sg_command_del(com); } size = gf_bs_read_int(bs, 5); length = gf_bs_read_int(bs, size); if (gf_bs_available(bs) < length) return GF_NON_COMPLIANT_BITSTREAM; sfcb->bufferSize = length; if (length) { sfcb->buffer = (unsigned char *)gf_malloc(sizeof(char)*(length)); //WARNING Buffers are NOT ALIGNED IN THE BITSTREAM for (i=0; i<length; i++) { sfcb->buffer[i] = gf_bs_read_int(bs, 8); } } //notify the node - this is needed in case an enhencement layer replaces the buffer, in which case //the # ID Bits may change SFCommandBufferChanged(codec, node); /* 1 - memory mode, register command buffer for later parsing 2 - InputSensor only works on decompressed commands */ if (codec->dec_memory_mode || (node->sgprivate->tag==TAG_MPEG4_InputSensor)) { CommandBufferItem *cbi = (CommandBufferItem *)gf_malloc(sizeof(CommandBufferItem)); cbi->node = node; cbi->cb = sfcb; gf_list_add(codec->command_buffers, cbi); } } break; case GF_SG_VRML_SFNODE: //for nodes the field ptr is a ptr to the field, which is a node ptr ;) new_node = gf_bifs_dec_node(codec, bs, field->NDTtype); if (new_node) { e = gf_node_register(new_node, node); if (e) return e; } //it may happen that new_node is NULL (this is valid for a proto declaration) *((GF_Node **) field->far_ptr) = new_node; break; case GF_SG_VRML_SFSCRIPT: #ifdef GPAC_HAS_SPIDERMONKEY codec->LastError = SFScript_Parse(codec, (SFScript*)field->far_ptr, bs, node); #else return GF_NOT_SUPPORTED; #endif break; case GF_SG_VRML_SFATTRREF: { SFAttrRef *ar = (SFAttrRef *)field->far_ptr; u32 nodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); ar->node = gf_sg_find_node(codec->current_graph, nodeID); if (!ar->node) { } else { u32 nbBitsDEF = gf_get_bit_size(gf_node_get_num_fields_in_mode(ar->node, GF_SG_FIELD_CODING_DEF) - 1); u32 field_ref = gf_bs_read_int(bs, nbBitsDEF); codec->LastError = gf_bifs_get_field_index(ar->node, field_ref, GF_SG_FIELD_CODING_DEF, &ar->fieldIndex); } } break; default: return GF_NON_COMPLIANT_BITSTREAM; } return codec->LastError; }