📄 field_decode.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / BIFS codec 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/internal/bifs_dev.h>#include <gpac/internal/scenegraph_dev.h>#include "quant.h" #include "script.h" void SFCommandBufferChanged(GF_BifsDecoder * codec, GF_Node *node){ void Conditional_BufferReplaced(GF_BifsDecoder * codec, GF_Node *node); switch (gf_node_get_tag(node)) { case TAG_MPEG4_Conditional: Conditional_BufferReplaced(codec, node); break; }}//startTimes, stopTimes and co are coded as relative to their AU timestamp when received//on the wire. If from scripts or within proto the offset doesn't applyvoid BD_OffsetSFTime(GF_BifsDecoder * codec, Double *time){ if ((!codec->is_com_dec && codec->pCurrentProto) || codec->dec_memory_mode) return; *time += codec->cts_offset;}void BD_CheckSFTimeOffset(GF_BifsDecoder *codec, GF_Node *node, GF_FieldInfo *inf){ if (gf_node_get_tag(node) != TAG_ProtoNode) { if (!stricmp(inf->name, "startTime") || !stricmp(inf->name, "stopTime")) BD_OffsetSFTime(codec, (Double *)inf->far_ptr); } else if (gf_sg_proto_field_is_sftime_offset(node, inf)) { BD_OffsetSFTime(codec, (Double *)inf->far_ptr); }}Fixed BD_ReadSFFloat(GF_BifsDecoder * codec, GF_BitStream *bs){ if (codec->ActiveQP && codec->ActiveQP->useEfficientCoding) return gf_bifs_dec_mantissa_float(codec, bs); return FLT2FIX(gf_bs_read_float(bs));}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 ( ((SFString *)field->far_ptr)->buffer ) free( ((SFString *)field->far_ptr)->buffer); ((SFString *)field->far_ptr)->buffer = (char *)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) 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 *)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) free( url->url); /*if URL is empty set it to NULL*/ if (buffer && strlen(buffer)) { url->url = buffer; } else { free(buffer); url->url = NULL; } } } break; case GF_SG_VRML_SFIMAGE: if (((SFImage *)field->far_ptr)->pixels) 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 *)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) { 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 *)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); /*memory mode, register command buffer for later parsing*/ if (codec->dec_memory_mode) { CommandBufferItem *cbi = (CommandBufferItem *)malloc(sizeof(CommandBufferItem)); cbi->node = node; cbi->cb = sfcb; gf_list_add(codec->command_buffers, cbi); } /*InputSensor only work on decompressed commands*/ else if (node->sgprivate->tag==TAG_MPEG4_InputSensor) { GF_Err BM_ParseCommand(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list); GF_BitStream *is_bs; is_bs = gf_bs_new((char*)sfcb->buffer, sfcb->bufferSize, GF_BITSTREAM_READ); e = BM_ParseCommand(codec, is_bs, sfcb->commandList); gf_bs_del(is_bs); } } 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: codec->LastError = SFScript_Parse(codec, (SFScript*)field->far_ptr, bs, node); break; default: return GF_NON_COMPLIANT_BITSTREAM; } return codec->LastError;}GF_Err BD_DecMFFieldList(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field){ GF_Node *new_node; GF_Err e; u8 endFlag, qp_local, qp_on, initial_qp; GF_ChildNodeItem *last = NULL; u32 nbF; GF_FieldInfo sffield; memset(&sffield, 0, sizeof(GF_FieldInfo)); sffield.fieldIndex = field->fieldIndex; sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType); sffield.NDTtype = field->NDTtype; nbF = 0; qp_on = qp_local = 0; initial_qp = codec->ActiveQP ? 1 : 0; endFlag = gf_bs_read_int(bs, 1); while (!endFlag) { e = GF_OK;; if (field->fieldType != GF_SG_VRML_MFNODE) { e = gf_sg_vrml_mf_append(field->far_ptr, field->fieldType, & sffield.far_ptr); e = gf_bifs_dec_sf_field(codec, bs, node, &sffield); } else { new_node = gf_bifs_dec_node(codec, bs, field->NDTtype); //append if (new_node) { e = gf_node_register(new_node, node); if (e) return e; //regular coding if (node) { //special case for QP, register as the current QP if (gf_node_get_tag(new_node) == TAG_MPEG4_QuantizationParameter) { qp_local = ((M_QuantizationParameter *)new_node)->isLocal; //we have a QP in the same scope, remove previous if (qp_on) gf_bifs_dec_qp_remove(codec, 0); e = gf_bifs_dec_qp_set(codec, new_node); if (e) return e; qp_on = 1; if (qp_local) qp_local = 2; if (codec->force_keep_qp) { e = gf_node_list_add_child_last( field->far_ptr, new_node, &last); } else { gf_node_register(new_node, NULL); gf_node_unregister(new_node, node); } } else //this is generic MFNode container e = gf_node_list_add_child_last(field->far_ptr, new_node, &last); } //proto coding: directly add the child else if (codec->pCurrentProto) { //TO DO: what happens if this is a QP node on the interface ? e = gf_node_list_add_child_last( (GF_ChildNodeItem **)field->far_ptr, new_node, &last); } } else { return codec->LastError; } } if (e) return e; endFlag = gf_bs_read_int(bs, 1); //according to the spec, the QP applies to the current node itself, //not just children. If IsLocal is TRUE remove the node if (qp_on && qp_local) { if (qp_local == 2) { qp_local = 1; } else { //ask to get rid of QP and reactivate if we had a QP when entering gf_bifs_dec_qp_remove(codec, initial_qp); qp_local = 0; qp_on = 0; } } nbF += 1; } /*finally delete the QP if any (local or not) as we get out of this node and reactivate previous one*/ if (qp_on) gf_bifs_dec_qp_remove(codec, initial_qp); /*this is for QP 14*/ gf_bifs_dec_qp14_set_length(codec, nbF); return GF_OK;}GF_Err BD_DecMFFieldVec(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field){ GF_Err e; u32 NbBits, nbFields; u32 i; GF_ChildNodeItem *last; u8 qp_local, qp_on, initial_qp; GF_Node *new_node; GF_FieldInfo sffield; memset(&sffield, 0, sizeof(GF_FieldInfo)); sffield.fieldIndex = field->fieldIndex; sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType); sffield.NDTtype = field->NDTtype; initial_qp = qp_local = qp_on = 0; //vector description - alloc the MF size before NbBits = gf_bs_read_int(bs, 5); nbFields = gf_bs_read_int(bs, NbBits); if (codec->ActiveQP) { initial_qp = 1; /*this is for QP 14*/ gf_bifs_dec_qp14_set_length(codec, nbFields); } if (field->fieldType != GF_SG_VRML_MFNODE) { e = gf_sg_vrml_mf_alloc(field->far_ptr, field->fieldType, nbFields); if (e) return e; for (i=0;i<nbFields; i++) { e = gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, & sffield.far_ptr, i); if (e) return e; e = gf_bifs_dec_sf_field(codec, bs, node, &sffield); } } else { last = NULL; for (i=0;i<nbFields; i++) { new_node = gf_bifs_dec_node(codec, bs, field->NDTtype); if (new_node) { e = gf_node_register(new_node, node); if (e) return e; if (node) { /*special case for QP, register as the current QP*/ if (gf_node_get_tag(new_node) == TAG_MPEG4_QuantizationParameter) { qp_local = ((M_QuantizationParameter *)new_node)->isLocal; /*we have a QP in the same scope, remove previous NB: we assume this is the right behaviour, the spec doesn't say whether QP is cumulative or not*/ if (qp_on) gf_bifs_dec_qp_remove(codec, 0); e = gf_bifs_dec_qp_set(codec, new_node); if (e) return e; qp_on = 1; if (qp_local) qp_local = 2; if (codec->force_keep_qp) { e = gf_node_list_add_child_last(field->far_ptr, new_node, &last); } else { gf_node_register(new_node, NULL); gf_node_unregister(new_node, node); } } else { e = gf_node_list_add_child_last(field->far_ptr, new_node, &last); } } /*proto coding*/ else if (codec->pCurrentProto) { /*TO DO: what happens if this is a QP node on the interface ?*/ e = gf_node_list_add_child_last( (GF_ChildNodeItem **)field->far_ptr, new_node, &last); } } else { return codec->LastError ? codec->LastError : GF_NON_COMPLIANT_BITSTREAM; } } /*according to the spec, the QP applies to the current node itself, not just children. If IsLocal is TRUE remove the node*/ if (qp_on && qp_local) { if (qp_local == 2) { qp_local = 1; } else { //ask to get rid of QP and reactivate if we had a QP when entering the node gf_bifs_dec_qp_remove(codec, initial_qp); qp_local = 0; } } } /*finally delete the QP if any (local or not) as we get out of this node*/ if (qp_on) gf_bifs_dec_qp_remove(codec, 1); return GF_OK;}void gf_bifs_check_field_change(GF_Node *node, GF_FieldInfo *field){ if ((field->fieldType==GF_SG_VRML_MFNODE) || (field->fieldType==GF_SG_VRML_MFNODE)) node->sgprivate->flags |= GF_SG_CHILD_DIRTY; /*signal node modif*/ gf_node_changed(node, field); /*Notify eventOut in all cases to handle protos*/ gf_node_event_out(node, field->fieldIndex); /*and propagate eventIn if any*/ if (field->on_event_in) { field->on_event_in(node); } else if ((gf_node_get_tag(node) == TAG_MPEG4_Script) && (field->eventType==GF_SG_EVENT_IN)) { gf_sg_script_event_in(node, field); }}GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field){ GF_Err e;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -