This source file includes following definitions.
- SFCommandBufferChanged
- BD_OffsetSFTime
- BD_CheckSFTimeOffset
- BD_ReadSFFloat
- gf_bifs_dec_sf_field
- BD_DecMFFieldList
- BD_DecMFFieldVec
- gf_bifs_check_field_change
- gf_bifs_dec_field
- BD_SetProtoISed
- gf_bifs_dec_node_list
- gf_bifs_dec_node_mask
- UpdateTimeNode
- gf_bifs_dec_node
#include <gpac/internal/bifs_dev.h>
#include "quant.h"
#include "script.h"
#ifndef GPAC_DISABLE_BIFS
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;
}
}
void 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, Bool is_mem_com)
{
GF_Err e;
GF_Node *new_node;
u32 size, length, w, h, i;
char *buffer;
if (codec->ActiveQP && node) {
e = gf_bifs_dec_unquant_field(codec, bs, node, field);
if (e != GF_EOS) return e;
}
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 = (u8*)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 = (char*)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 (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);
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 (!node) return GF_BAD_PARAM;
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));
for (i=0; i<length; i++) {
sfcb->buffer[i] = gf_bs_read_int(bs, 8);
}
}
SFCommandBufferChanged(codec, node);
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:
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;
}
*((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;
}
GF_Err BD_DecMFFieldList(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com)
{
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 && (codec->LastError>=0)) {
if (field->fieldType != GF_SG_VRML_MFNODE) {
e = gf_sg_vrml_mf_append(field->far_ptr, field->fieldType, & sffield.far_ptr);
if (e) return e;
e = gf_bifs_dec_sf_field(codec, bs, node, &sffield, GF_FALSE);
if (e) return e;
} else {
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;
if (node) {
if (gf_node_get_tag(new_node) == TAG_MPEG4_QuantizationParameter) {
qp_local = ((M_QuantizationParameter *)new_node)->isLocal;
if (qp_on) gf_bifs_dec_qp_remove(codec, GF_FALSE);
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);
}
else if (codec->pCurrentProto) {
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);
if (qp_on && qp_local) {
if (qp_local == 2) {
qp_local = 1;
} else {
gf_bifs_dec_qp_remove(codec, initial_qp);
qp_local = 0;
qp_on = 0;
}
}
nbF += 1;
}
if (qp_on) gf_bifs_dec_qp_remove(codec, initial_qp);
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, Bool is_mem_com)
{
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;
NbBits = gf_bs_read_int(bs, 5);
nbFields = gf_bs_read_int(bs, NbBits);
if (codec->ActiveQP) {
initial_qp = 1;
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, GF_FALSE);
if (e) return e;
}
} 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, is_mem_com ? NULL : node);
if (e) return e;
if (node) {
if (gf_node_get_tag(new_node) == TAG_MPEG4_QuantizationParameter) {
qp_local = ((M_QuantizationParameter *)new_node)->isLocal;
if (qp_on) gf_bifs_dec_qp_remove(codec, GF_FALSE);
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);
if (e) return e;
} 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);
if (e) return e;
}
}
else if (codec->pCurrentProto) {
e = gf_node_list_add_child_last( (GF_ChildNodeItem **)field->far_ptr, new_node, &last);
if (e) return e;
}
} else {
return codec->LastError ? codec->LastError : GF_NON_COMPLIANT_BITSTREAM;
}
}
if (qp_on && qp_local) {
if (qp_local == 2) {
} else {
gf_bifs_dec_qp_remove(codec, initial_qp);
}
}
}
if (qp_on) gf_bifs_dec_qp_remove(codec, GF_TRUE);
return GF_OK;
}
void gf_bifs_check_field_change(GF_Node *node, GF_FieldInfo *field)
{
if (field->fieldType==GF_SG_VRML_MFNODE) node->sgprivate->flags |= GF_SG_CHILD_DIRTY;
gf_node_changed(node, field);
gf_node_event_out(node, field->fieldIndex);
if (field->on_event_in) {
field->on_event_in(node, NULL);
} 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, Bool is_mem_com)
{
GF_Err e;
u8 flag;
assert(node);
if (gf_sg_vrml_is_sf_field(field->fieldType)) {
e = gf_bifs_dec_sf_field(codec, bs, node, field, is_mem_com);
if (e) return e;
} else {
if (field->eventType == GF_SG_EVENT_IN) {
if (field->fieldType == GF_SG_VRML_MFNODE) {
gf_node_unregister_children(node, * (GF_ChildNodeItem **)field->far_ptr);
* (GF_ChildNodeItem **)field->far_ptr = NULL;
} else {
gf_sg_vrml_mf_reset(field->far_ptr, field->fieldType);
}
}
if (codec->info->config.UsePredictiveMFField) {
flag = gf_bs_read_int(bs, 1);
if (flag) {
GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] Stream uses Predictive Field Coding!\n"));
#ifdef GPAC_ENABLE_BIFS_PMF
return gf_bifs_dec_pred_mf_field(codec, bs, node, field);
#else
return GF_NOT_SUPPORTED;
#endif
}
}
flag = gf_bs_read_int(bs, 1);
if (!flag) {
if (field->fieldType != GF_SG_VRML_MFNODE) {
e = gf_sg_vrml_mf_reset(field->far_ptr, field->fieldType);
if (e) return e;
}
flag = gf_bs_read_int(bs, 1);
if (flag) {
e = BD_DecMFFieldList(codec, bs, node, field, is_mem_com);
} else {
e = BD_DecMFFieldVec(codec, bs, node, field, is_mem_com);
}
if (e) return e;
}
}
return GF_OK;
}
GF_Err BD_SetProtoISed(GF_BifsDecoder * codec, u32 protofield, GF_Node *n, u32 nodefield)
{
if (codec->current_graph->pOwningProto) {
return gf_sg_proto_instance_set_ised((GF_Node *) codec->current_graph->pOwningProto, protofield, n, nodefield);
}
else {
return gf_sg_proto_field_set_ised(codec->pCurrentProto, protofield, n, nodefield);
}
}
GF_Err gf_bifs_dec_node_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, Bool is_proto)
{
u8 flag;
GF_Err e;
u32 numBitsALL, numBitsDEF, field_all, field_ref, numProtoBits;
GF_FieldInfo field;
numProtoBits = numBitsALL = 0;
if (codec->pCurrentProto) {
numProtoBits = gf_get_bit_size(gf_sg_proto_get_field_count(codec->pCurrentProto) - 1);
numBitsALL = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL)-1);
}
numBitsDEF = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_DEF)-1);
flag = gf_bs_read_int(bs, 1);
while (!flag && (codec->LastError>=0)) {
if (codec->pCurrentProto) {
flag = gf_bs_read_int(bs, 1);
if (flag) {
field_ref = gf_bs_read_int(bs, numBitsALL);
field_all = gf_bs_read_int(bs, numProtoBits);
e = gf_node_get_field(node, field_ref, &field);
if (e) return e;
e = BD_SetProtoISed(codec, field_all, node, field_ref);
if (e) return e;
flag = gf_bs_read_int(bs, 1);
continue;
}
}
field_ref = gf_bs_read_int(bs, numBitsDEF);
e = gf_bifs_get_field_index(node, field_ref, GF_SG_FIELD_CODING_DEF, &field_all);
if (e) return e;
e = gf_node_get_field(node, field_all, &field);
if (e) return e;
e = gf_bifs_dec_field(codec, bs, node, &field, GF_FALSE);
if (e) return e;
flag = gf_bs_read_int(bs, 1);
if (is_proto) gf_sg_proto_mark_field_loaded(node, &field);
}
return codec->LastError;
}
GF_Err gf_bifs_dec_node_mask(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, Bool is_proto)
{
u32 i, numFields, numProtoFields, index, flag, nbBits;
GF_Err e;
GF_FieldInfo field;
if (codec->pCurrentProto) {
numFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL);
numProtoFields = gf_sg_proto_get_field_count(codec->pCurrentProto);
nbBits = gf_get_bit_size(numProtoFields-1);
for (i=0; i<numFields; i++) {
flag = gf_bs_read_int(bs, 1);
if (!flag) continue;
flag = gf_bs_read_int(bs, 1);
if (flag) {
flag = gf_bs_read_int(bs, nbBits);
e = gf_node_get_field(node, i, &field);
if (e) return e;
e = BD_SetProtoISed(codec, flag, node, i);
}
else {
e = gf_node_get_field(node, i, &field);
if (e) return e;
e = gf_bifs_dec_field(codec, bs, node, &field, GF_FALSE);
}
if (e) return e;
}
}
else {
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) return e;
e = gf_bifs_dec_field(codec, bs, node, &field, GF_FALSE);
if (e) return e;
if (is_proto) gf_sg_proto_mark_field_loaded(node, &field);
}
}
return GF_OK;
}
static void UpdateTimeNode(GF_BifsDecoder * codec, GF_Node *node)
{
switch (gf_node_get_tag(node)) {
case TAG_MPEG4_AnimationStream:
BD_OffsetSFTime(codec, & ((M_AnimationStream*)node)->startTime);
BD_OffsetSFTime(codec, & ((M_AnimationStream*)node)->stopTime);
break;
case TAG_MPEG4_AudioBuffer:
BD_OffsetSFTime(codec, & ((M_AudioBuffer*)node)->startTime);
BD_OffsetSFTime(codec, & ((M_AudioBuffer*)node)->stopTime);
break;
case TAG_MPEG4_AudioClip:
BD_OffsetSFTime(codec, & ((M_AudioClip*)node)->startTime);
BD_OffsetSFTime(codec, & ((M_AudioClip*)node)->stopTime);
break;
case TAG_MPEG4_AudioSource:
BD_OffsetSFTime(codec, & ((M_AudioSource*)node)->startTime);
BD_OffsetSFTime(codec, & ((M_AudioSource*)node)->stopTime);
break;
case TAG_MPEG4_MovieTexture:
BD_OffsetSFTime(codec, & ((M_MovieTexture*)node)->startTime);
BD_OffsetSFTime(codec, & ((M_MovieTexture*)node)->stopTime);
break;
case TAG_MPEG4_TimeSensor:
BD_OffsetSFTime(codec, & ((M_TimeSensor*)node)->startTime);
BD_OffsetSFTime(codec, & ((M_TimeSensor*)node)->stopTime);
break;
case TAG_ProtoNode:
{
u32 i, nbFields;
GF_FieldInfo inf;
nbFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL);
for (i=0; i<nbFields; i++) {
gf_node_get_field(node, i, &inf);
if (inf.fieldType != GF_SG_VRML_SFTIME) continue;
BD_CheckSFTimeOffset(codec, node, &inf);
}
}
break;
}
}
GF_Node *gf_bifs_dec_node(GF_BifsDecoder * codec, GF_BitStream *bs, u32 NDT_Tag)
{
u32 nodeID, NDTBits, node_type, node_tag, ProtoID, BVersion;
Bool skip_init, reset_qp14;
GF_Node *new_node;
GF_Err e;
GF_Proto *proto;
void SetupConditional(GF_BifsDecoder *codec, GF_Node *node);
char name[1000];
#if 0
if (!codec->info) {
codec->LastError = GF_BAD_PARAM;
return NULL;
}
#endif
BVersion = GF_BIFS_V1;
if (gf_bs_read_int(bs, 1)) {
nodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits);
if (nodeID == (u32) (1<<codec->info->config.NodeIDBits))
return NULL;
new_node = gf_sg_find_node(codec->current_graph, nodeID);
if (!new_node) {
codec->LastError = GF_SG_UNKNOWN_NODE;
} else {
switch (gf_node_get_tag(new_node)) {
case TAG_MPEG4_Coordinate:
{
u32 nbCoord = ((M_Coordinate *)new_node)->point.count;
gf_bifs_dec_qp14_enter(codec, GF_TRUE);
gf_bifs_dec_qp14_set_length(codec, nbCoord);
gf_bifs_dec_qp14_enter(codec, GF_FALSE);
}
break;
case TAG_MPEG4_Coordinate2D:
{
u32 nbCoord = ((M_Coordinate2D *)new_node)->point.count;
gf_bifs_dec_qp14_enter(codec, GF_TRUE);
gf_bifs_dec_qp14_set_length(codec, nbCoord);
gf_bifs_dec_qp14_enter(codec, GF_FALSE);
}
break;
}
}
return new_node;
}
nodeID = 0;
name[0] = 0;
node_tag = 0;
proto = NULL;
while (1) {
NDTBits = gf_bifs_get_ndt_bits(NDT_Tag, BVersion);
if ((BVersion==1) && (NDTBits > 8 * gf_bs_available(bs)) ) {
codec->LastError = GF_OK;
return NULL;
}
node_type = gf_bs_read_int(bs, NDTBits);
if (node_type) break;
BVersion += 1;
if (BVersion > GF_BIFS_NUM_VERSION) {
codec->LastError = GF_BIFS_UNKNOWN_VERSION;
return NULL;
}
}
if (BVersion==2 && node_type==1) {
ProtoID = gf_bs_read_int(bs, codec->info->config.ProtoIDBits);
proto = gf_sg_find_proto(codec->current_graph, ProtoID, NULL);
if (!proto && codec->current_graph != codec->scenegraph)
proto = gf_sg_find_proto(codec->scenegraph, ProtoID, NULL);
if (!proto) {
codec->LastError = GF_SG_UNKNOWN_NODE;
return NULL;
}
} else {
node_tag = gf_bifs_ndt_get_node_type(NDT_Tag, node_type, BVersion);
}
if ((node_tag == TAG_MPEG4_IndexedFaceSet) && codec->info->config.Use3DMeshCoding) {
if (gf_bs_read_int(bs, 1)) {
gf_bs_read_int(bs, codec->info->config.NodeIDBits);
if (codec->UseName) gf_bifs_dec_name(bs, name);
}
return NULL;
}
if (!node_tag && !proto) {
codec->LastError = GF_SG_UNKNOWN_NODE;
return NULL;
}
if (gf_bs_read_int(bs, 1)) {
if (!codec->info->config.NodeIDBits) {
codec->LastError = GF_NON_COMPLIANT_BITSTREAM;
return NULL;
}
nodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits);
if (codec->UseName) gf_bifs_dec_name(bs, name);
}
new_node = NULL;
skip_init = GF_FALSE;
#if 0
if (nodeID && !codec->dec_memory_mode) {
new_node = gf_sg_find_node(codec->current_graph, nodeID);
if (new_node) {
if (proto) {
if ((gf_node_get_tag(new_node) != TAG_ProtoNode) || (gf_node_get_proto(new_node) != proto)) {
codec->LastError = GF_NON_COMPLIANT_BITSTREAM;
return NULL;
}
skip_init = 1;
} else {
if (gf_node_get_tag(new_node) != node_tag) {
codec->LastError = GF_NON_COMPLIANT_BITSTREAM;
return NULL;
}
skip_init = 1;
}
}
}
#endif
if (!new_node) {
if (proto) {
new_node = gf_sg_proto_create_instance(codec->current_graph, proto);
if (! proto->ExternProto.count) skip_init = GF_TRUE;
} else {
new_node = gf_node_new(codec->current_graph, node_tag);
}
}
if (!new_node) {
codec->LastError = GF_NOT_SUPPORTED;
return NULL;
}
if (nodeID) {
if (strlen(name)) {
gf_node_set_id(new_node, nodeID, name);
} else {
gf_node_set_id(new_node, nodeID, NULL);
}
}
if (!codec->pCurrentProto) UpdateTimeNode(codec, new_node);
else skip_init = GF_TRUE;
reset_qp14 = !codec->coord_stored;
switch (node_tag) {
case TAG_MPEG4_Coordinate:
case TAG_MPEG4_Coordinate2D:
gf_bifs_dec_qp14_enter(codec, GF_TRUE);
}
if (gf_bs_read_int(bs, 1)) {
e = gf_bifs_dec_node_mask(codec, bs, new_node, proto ? GF_TRUE : GF_FALSE);
} else {
e = gf_bifs_dec_node_list(codec, bs, new_node, proto ? GF_TRUE : GF_FALSE);
}
if (codec->coord_stored && reset_qp14)
gf_bifs_dec_qp14_reset(codec);
if (e) {
codec->LastError = e;
gf_node_register(new_node, NULL);
gf_node_unregister(new_node, NULL);
return NULL;
}
if (!skip_init)
gf_node_init(new_node);
switch (node_tag) {
case TAG_MPEG4_Coordinate:
case TAG_MPEG4_Coordinate2D:
gf_bifs_dec_qp14_enter(codec, GF_FALSE);
break;
case TAG_MPEG4_Script:
if (codec->scenegraph == codec->current_graph) {
gf_sg_script_load(new_node);
}
break;
case TAG_MPEG4_Conditional:
SetupConditional(codec, new_node);
break;
}
#if 0
if (proto && (codec->scenegraph == codec->current_graph)) {
codec->LastError = gf_sg_proto_load_code(new_node);
}
#endif
return new_node;
}
#endif