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; }
static GF_Err CTXLoad_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd) { const char *ext; GF_BitStream *bs; u32 size; CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack; if (esd->decoderConfig->upstream) return GF_NOT_SUPPORTED; /*animation stream like*/ if (priv->ctx) { GF_StreamContext *sc; u32 i = 0; while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) { if (esd->ESID == sc->ESID) { priv->nb_streams++; return GF_OK; } } return GF_NON_COMPLIANT_BITSTREAM; } /*main dummy stream we need a dsi*/ if (!esd->decoderConfig->decoderSpecificInfo) return GF_NON_COMPLIANT_BITSTREAM; bs = gf_bs_new(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ); priv->file_size = gf_bs_read_u32(bs); gf_bs_del(bs); size = esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32); priv->file_name = (char *) gf_malloc(sizeof(char)*(1 + size) ); memcpy(priv->file_name, esd->decoderConfig->decoderSpecificInfo->data + sizeof(u32), sizeof(char)*(esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32)) ); priv->file_name[size] = 0; priv->nb_streams = 1; priv->load_flags = 0; priv->base_stream_id = esd->ESID; priv->service_url = esd->service_url; CTXLoad_Setup(plug); priv->progressive_support = GF_FALSE; priv->sax_max_duration = 0; ext = strrchr(priv->file_name, '.'); if (!ext) return GF_OK; ext++; if (!stricmp(ext, "xmt") || !stricmp(ext, "xmtz") || !stricmp(ext, "xmta") || !stricmp(ext, "x3d") || !stricmp(ext, "x3dz") ) { ext = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "Progressive"); priv->progressive_support = (ext && !stricmp(ext, "yes")) ? GF_TRUE : GF_FALSE; } if (priv->progressive_support) { ext = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "MaxDuration"); if (ext) priv->sax_max_duration = atoi(ext); } return GF_OK; }
/*special authoring functions*/ GF_EXPORT GF_BIFSConfig *gf_odf_get_bifs_config(GF_DefaultDescriptor *dsi, u8 oti) { Bool hasSize, cmd_stream; GF_BitStream *bs; GF_BIFSConfig *cfg; if (oti>=GPAC_OTI_SCENE_BIFS_EXTENDED) return NULL; if (!dsi || !dsi->data || !dsi->dataLength ) { /* Hack for T-DMB non compliant streams (OnTimeTek ?) */ cfg = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); cfg->pixelMetrics = 1; cfg->version = 1; return cfg; } bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ); cfg = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); if (oti==2) { /*3D Mesh Coding*/ gf_bs_read_int(bs, 1); /*PMF*/ gf_bs_read_int(bs, 1); } cfg->nodeIDbits = gf_bs_read_int(bs, 5); cfg->routeIDbits = gf_bs_read_int(bs, 5); if (oti==2) cfg->protoIDbits = gf_bs_read_int(bs, 5); cmd_stream = gf_bs_read_int(bs, 1); if (!cmd_stream) { cfg->elementaryMasks = gf_list_new(); while (1) { GF_ElementaryMask* em = (GF_ElementaryMask* ) gf_odf_New_ElemMask(); em->node_id = gf_bs_read_int(bs, cfg->nodeIDbits); gf_list_add(cfg->elementaryMasks, em); /*this assumes only FDP, BDP and IFS2D (no elem mask)*/ if (gf_bs_read_int(bs, 1) == 0) break; } gf_bs_align(bs); if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODF] Reading bifs config: shift in sizes (not supported)\n")); } } else { cfg->pixelMetrics = gf_bs_read_int(bs, 1); hasSize = gf_bs_read_int(bs, 1); if (hasSize) { cfg->pixelWidth = gf_bs_read_int(bs, 16); cfg->pixelHeight = gf_bs_read_int(bs, 16); } gf_bs_align(bs); if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODF] Reading bifs config: shift in sizes (invalid descriptor)\n")); } gf_bs_del(bs); return cfg; }
GF_EXPORT GF_Err gf_bifs_decoder_configure_stream(GF_BifsDecoder * codec, u16 ESID, char *DecoderSpecificInfo, u32 DecoderSpecificInfoLength, u32 objectTypeIndication) { GF_BitStream *bs; BIFSStreamInfo *pInfo; GF_Err e; if (!DecoderSpecificInfo) { /* Hack for T-DMB non compliant streams */ GF_SAFEALLOC(pInfo, BIFSStreamInfo); pInfo->ESID = ESID; pInfo->config.PixelMetrics = 1; pInfo->config.version = (objectTypeIndication==2) ? 1 : 2; assert( codec ); assert( codec->streamInfo ); return gf_list_add(codec->streamInfo, pInfo); } // gf_mx_p(codec->mx); assert( codec ); if (gf_bifs_dec_get_stream(codec, ESID) != NULL) { // gf_mx_v(codec->mx); return GF_BAD_PARAM; } bs = gf_bs_new(DecoderSpecificInfo, DecoderSpecificInfoLength, GF_BITSTREAM_READ); GF_SAFEALLOC(pInfo, BIFSStreamInfo); pInfo->ESID = ESID; pInfo->config.version = objectTypeIndication; /*parse config with indicated oti*/ e = ParseConfig(bs, pInfo, (u32) objectTypeIndication); if (e) { pInfo->ESID = ESID; /*some content indicates a wrong OTI, so try to parse with v1 or v2*/ gf_bs_seek(bs, 0); /*try with reverse config*/ e = ParseConfig(bs, pInfo, (objectTypeIndication==2) ? 1 : 2); pInfo->config.version = (objectTypeIndication==2) ? 1 : 2; } if (e && (e != GF_ODF_INVALID_DESCRIPTOR)) { gf_free(pInfo); gf_bs_del(bs); return GF_BIFS_UNKNOWN_VERSION; } gf_bs_del(bs); assert( codec->streamInfo ); //first stream, configure size if (!codec->ignore_size && !gf_list_count(codec->streamInfo)) { gf_sg_set_scene_size_info(codec->scenegraph, pInfo->config.Width, pInfo->config.Height, pInfo->config.PixelMetrics); } gf_list_add(codec->streamInfo, pInfo); // gf_mx_v(codec->mx); return GF_OK; }
static GF_Err gf_isom_cenc_get_sai_by_saiz_saio(GF_MediaBox *mdia, u32 sampleNumber, u8 IV_size, GF_CENCSampleAuxInfo **sai) { GF_BitStream *bs; u32 prev_sai_size, size, i, j, nb_saio; u64 cur_position, offset; GF_Err e = GF_OK; char *buffer; nb_saio = size = prev_sai_size = 0; offset = 0; for (i = 0; i < gf_list_count(mdia->information->sampleTable->sai_offsets); i++) { GF_SampleAuxiliaryInfoOffsetBox *saio = (GF_SampleAuxiliaryInfoOffsetBox *)gf_list_get(mdia->information->sampleTable->sai_offsets, i); if (saio->aux_info_type == GF_4CC('c', 'e', 'n', 'c')) { if (saio->entry_count == 1) offset = saio->version ? saio->offsets_large[0] : saio->offsets[0]; else offset = saio->version ? saio->offsets_large[sampleNumber-1]: saio->offsets[sampleNumber-1]; nb_saio = saio->entry_count; break; } } for (i = 0; i < gf_list_count(mdia->information->sampleTable->sai_sizes); i++) { GF_SampleAuxiliaryInfoSizeBox *saiz = (GF_SampleAuxiliaryInfoSizeBox *)gf_list_get(mdia->information->sampleTable->sai_sizes, i); if (saiz->aux_info_type == GF_4CC('c', 'e', 'n', 'c')) { for (j = 0; j < sampleNumber-1; j++) prev_sai_size += saiz->default_sample_info_size ? saiz->default_sample_info_size : saiz->sample_info_size[j]; size = saiz->default_sample_info_size ? saiz->default_sample_info_size : saiz->sample_info_size[sampleNumber-1]; break; } } offset += (nb_saio == 1) ? prev_sai_size : 0; cur_position = gf_bs_get_position(mdia->information->dataHandler->bs); gf_bs_seek(mdia->information->dataHandler->bs, offset); buffer = (char *)gf_malloc(size); gf_bs_read_data(mdia->information->dataHandler->bs, buffer, size); gf_bs_seek(mdia->information->dataHandler->bs, cur_position); *sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); memset(*sai, 0, sizeof(GF_CENCSampleAuxInfo)); bs = gf_bs_new(buffer, size, GF_BITSTREAM_READ); gf_bs_read_data(bs, (char *)(*sai)->IV, IV_size); if (size > IV_size) { (*sai)->subsample_count = gf_bs_read_u16(bs); (*sai)->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sizeof(GF_CENCSubSampleEntry)*(*sai)->subsample_count); for (i = 0; i < (*sai)->subsample_count; i++) { (*sai)->subsamples[i].bytes_clear_data = gf_bs_read_u16(bs); (*sai)->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(bs); } } gf_bs_del(bs); return e; }
GF_Err gp_rtp_builder_do_h263(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize) { GF_BitStream *bs; char hdr[2]; Bool Pbit; u32 offset, size, max_size; builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp; /*the H263 hinter doesn't perform inter-sample concatenation*/ if (!data) return GF_OK; Pbit = 1; /*skip 16 0'ed bits of start code*/ offset = 2; data_size -= 2; max_size = builder->Path_MTU - 2; while(data_size > 0) { if(data_size > max_size){ size = max_size; builder->rtp_header.Marker = 0; }else{ size = data_size; builder->rtp_header.Marker = 1; } data_size -= size; /*create new RTP Packet */ builder->rtp_header.SequenceNumber += 1; builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header); bs = gf_bs_new(hdr, 2, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, 0, 5); gf_bs_write_int(bs, Pbit, 1); gf_bs_write_int(bs, 0, 10); gf_bs_del(bs); /*add header*/ builder->OnData(builder->cbk_obj, (char*) hdr, 2, 1); /*add payload*/ if (builder->OnDataReference) builder->OnDataReference(builder->cbk_obj, size, offset); else builder->OnData(builder->cbk_obj, data + offset, size, 0); builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); offset += size; Pbit = 0; } return GF_OK; }
GF_HEVCConfig *HEVC_DuplicateConfig(GF_HEVCConfig *cfg) { char *data; u32 data_size; GF_HEVCConfig *new_cfg; GF_BitStream *bs; if (!cfg) return NULL; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_odf_hevc_cfg_write_bs(cfg, bs); gf_bs_get_content(bs, &data, &data_size); gf_bs_del(bs); bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ); new_cfg = gf_odf_hevc_cfg_read_bs(bs); gf_bs_del(bs); gf_free(data); return new_cfg; }
static void VTT_ReadFileNameFromDSI(VTTDec *vttdec, GF_DefaultDescriptor *dsi) { GF_BitStream *bs; bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ); vttdec->file_size = gf_bs_read_u32(bs); vttdec->file_pos = 0; gf_bs_del(bs); vttdec->file_name = (char *) gf_malloc(sizeof(char)*(1 + dsi->dataLength - sizeof(u32)) ); memcpy(vttdec->file_name, dsi->data + sizeof(u32), dsi->dataLength - sizeof(u32) ); vttdec->file_name[dsi->dataLength - sizeof(u32) ] = 0; }
GF_EXPORT GF_Err gf_bifs_encoder_get_config(GF_BifsEncoder *codec, u16 ESID, char **out_data, u32 *out_data_length) { GF_BitStream *bs; if (!codec || !out_data || !out_data_length) return GF_BAD_PARAM; // gf_mx_p(codec->mx); codec->info = BE_GetStream(codec, ESID); if (!codec->info) { // gf_mx_v(codec->mx); return GF_BAD_PARAM; } bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); if (codec->info->config.version==2) { gf_bs_write_int(bs, codec->info->config.Use3DMeshCoding ? 1 : 0, 1); gf_bs_write_int(bs, codec->info->config.UsePredictiveMFField ? 1 : 0, 1); } gf_bs_write_int(bs, codec->info->config.NodeIDBits, 5); gf_bs_write_int(bs, codec->info->config.RouteIDBits, 5); if (codec->info->config.version==2) { gf_bs_write_int(bs, codec->info->config.ProtoIDBits, 5); } if (codec->info->config.elementaryMasks) { u32 i, count; gf_bs_write_int(bs, 0, 1); gf_bs_write_int(bs, codec->info->config.BAnimRAP, 1); count = gf_list_count(codec->info->config.elementaryMasks); for (i=0; i<count; i++) { BIFSElementaryMask *em = (BIFSElementaryMask *)gf_list_get(codec->info->config.elementaryMasks, i); if (em->node) gf_bs_write_int(bs, gf_node_get_id((GF_Node*)em->node), codec->info->config.NodeIDBits); else gf_bs_write_int(bs, em->node_id, codec->info->config.NodeIDBits); gf_bs_write_int(bs, (i+1==count) ? 0 : 1, 1); } } else { gf_bs_write_int(bs, 1, 1); gf_bs_write_int(bs, codec->info->config.PixelMetrics ? 1 : 0, 1); if (codec->info->config.Width || codec->info->config.Height) { gf_bs_write_int(bs, 1, 1); gf_bs_write_int(bs, codec->info->config.Width, 16); gf_bs_write_int(bs, codec->info->config.Height, 16); } else { gf_bs_write_int(bs, 0, 1); } } gf_bs_align(bs); gf_bs_get_content(bs, out_data, out_data_length); gf_bs_del(bs); // gf_mx_v(codec->mx); return GF_OK; }
GF_EXPORT GF_Err gf_odf_avc_cfg_write(GF_AVCConfig *cfg, char **outData, u32 *outSize) { u32 i, count; GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, cfg->configurationVersion, 8); gf_bs_write_int(bs, cfg->AVCProfileIndication , 8); gf_bs_write_int(bs, cfg->profile_compatibility, 8); gf_bs_write_int(bs, cfg->AVCLevelIndication, 8); gf_bs_write_int(bs, 0x3F, 6); gf_bs_write_int(bs, cfg->nal_unit_size - 1, 2); gf_bs_write_int(bs, 0x7, 3); count = gf_list_count(cfg->sequenceParameterSets); gf_bs_write_int(bs, count, 5); for (i=0; i<count; i++) { GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->sequenceParameterSets, i); gf_bs_write_int(bs, sl->size, 16); gf_bs_write_data(bs, sl->data, sl->size); } count = gf_list_count(cfg->pictureParameterSets); gf_bs_write_int(bs, count, 8); for (i=0; i<count; i++) { GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->pictureParameterSets, i); gf_bs_write_int(bs, sl->size, 16); gf_bs_write_data(bs, sl->data, sl->size); } switch (cfg->AVCProfileIndication) { case 100: case 110: case 122: case 144: gf_bs_write_int(bs, 0xFF, 6); gf_bs_write_int(bs, cfg->chroma_format, 2); gf_bs_write_int(bs, 0xFF, 5); gf_bs_write_int(bs, cfg->luma_bit_depth - 8, 3); gf_bs_write_int(bs, 0xFF, 5); gf_bs_write_int(bs, cfg->chroma_bit_depth - 8, 3); count = cfg->sequenceParameterSetExtensions ? gf_list_count(cfg->sequenceParameterSetExtensions) : 0; gf_bs_write_u8(bs, count); for (i=0; i<count; i++) { GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *) gf_list_get(cfg->sequenceParameterSetExtensions, i); gf_bs_write_u16(bs, sl->size); gf_bs_write_data(bs, sl->data, sl->size); } break; } *outSize = 0; *outData = NULL; gf_bs_get_content(bs, outData, outSize); gf_bs_del(bs); return GF_OK; }
GF_Err gf_isom_rewrite_text_sample(GF_ISOSample *samp, u32 sampleDescriptionIndex, u32 sample_dur) { GF_BitStream *bs; u32 pay_start, txt_size; Bool is_utf_16 = 0; if (!samp || !samp->data || !samp->dataLength) return GF_OK; bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ); txt_size = gf_bs_read_u16(bs); gf_bs_del(bs); /*remove BOM*/ pay_start = 2; if (txt_size>2) { /*seems 3GP only accepts BE UTF-16 (no LE, no UTF32)*/ if (((u8) samp->data[2]==(u8) 0xFE) && ((u8)samp->data[3]==(u8) 0xFF)) { is_utf_16 = 1; pay_start = 4; txt_size -= 2; } } /*rewrite as TTU(1)*/ bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, is_utf_16, 1); gf_bs_write_int(bs, 0, 4); gf_bs_write_int(bs, 1, 3); gf_bs_write_u16(bs, 8 + samp->dataLength - pay_start); gf_bs_write_u8(bs, sampleDescriptionIndex + SAMPLE_INDEX_OFFSET); gf_bs_write_u24(bs, sample_dur); /*write text size*/ gf_bs_write_u16(bs, txt_size); if (txt_size) gf_bs_write_data(bs, samp->data + pay_start, samp->dataLength - pay_start); gf_free(samp->data); samp->data = NULL; gf_bs_get_content(bs, &samp->data, &samp->dataLength); gf_bs_del(bs); return GF_OK; }
static GF_Err SVG_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd) { const char *sOpt; GF_BitStream *bs; SVGIn *svgin = (SVGIn *)plug->privateStack; if (esd->decoderConfig->upstream) return GF_NOT_SUPPORTED; svgin->loader.type = GF_SM_LOAD_SVG; /* decSpecInfo is not null only when reading from an SVG file (local or distant, cached or not) */ switch (esd->decoderConfig->objectTypeIndication) { case GPAC_OTI_SCENE_SVG: case GPAC_OTI_SCENE_SVG_GZ: svgin->loader.flags |= GF_SM_LOAD_CONTEXT_STREAMING; /*no decSpecInfo defined for streaming svg yet*/ break; case GPAC_OTI_SCENE_DIMS: svgin->loader.type = GF_SM_LOAD_DIMS; svgin->loader.flags |= GF_SM_LOAD_CONTEXT_STREAMING; /*decSpecInfo not yet supported for DIMS svg - we need properties at the scene level to store the various indications*/ break; case GPAC_OTI_PRIVATE_SCENE_SVG: default: if (!esd->decoderConfig->decoderSpecificInfo) return GF_NON_COMPLIANT_BITSTREAM; bs = gf_bs_new(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ); svgin->file_size = gf_bs_read_u32(bs); svgin->file_pos = 0; gf_bs_del(bs); svgin->file_name = (char *) gf_malloc(sizeof(char)*(1 + esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32)) ); memcpy(svgin->file_name, esd->decoderConfig->decoderSpecificInfo->data + sizeof(u32), esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32) ); svgin->file_name[esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32) ] = 0; break; } svgin->oti = esd->decoderConfig->objectTypeIndication; if (!esd->dependsOnESID) svgin->base_es_id = esd->ESID; sOpt = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "Progressive"); if (sOpt && !strcmp(sOpt, "yes")) { svgin->sax_max_duration = 30; sOpt = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "MaxDuration"); if (sOpt) { svgin->sax_max_duration = atoi(sOpt); } else { svgin->sax_max_duration = 30; gf_modules_set_option((GF_BaseInterface *)plug, "SAXLoader", "MaxDuration", "30"); } } else { svgin->sax_max_duration = (u32) -1; } return GF_OK; }
GF_ISMASample *gf_isom_ismacryp_sample_from_data(char *data, u32 dataLength, Bool use_selective_encryption, u8 KI_length, u8 IV_length) { GF_ISMASample *s; GF_BitStream *bs; /*empty text sample*/ if (!data || !dataLength) { return gf_isom_ismacryp_new_sample(); } s = gf_isom_ismacryp_new_sample(); /*empty sample*/ if (!data || !dataLength) return s; bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); s->dataLength = dataLength; s->IV_length = IV_length; s->KI_length = KI_length; if (use_selective_encryption) { s->flags = GF_ISOM_ISMA_USE_SEL_ENC; if (s->dataLength < 1) goto exit; if (gf_bs_read_int(bs, 1)) s->flags |= GF_ISOM_ISMA_IS_ENCRYPTED; gf_bs_read_int(bs, 7); s->dataLength -= 1; } else { s->flags = GF_ISOM_ISMA_IS_ENCRYPTED; } if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) { if (IV_length != 0) { if (s->dataLength < IV_length) goto exit; s->IV = gf_bs_read_long_int(bs, 8*IV_length); s->dataLength -= IV_length; } if (KI_length) { if (s->dataLength < KI_length) goto exit; s->key_indicator = (u8 *)malloc(KI_length); gf_bs_read_data(bs, (char*)s->key_indicator, KI_length); s->dataLength -= KI_length; } } s->data = (char*)malloc(sizeof(char)*s->dataLength); gf_bs_read_data(bs, s->data, s->dataLength); gf_bs_del(bs); return s; exit: gf_isom_ismacryp_delete_sample(s); return NULL; }
GF_EXPORT void gf_sl_depacketize (GF_SLConfig *slConfig, GF_SLHeader *Header, char *PDU, u32 PDULength, u32 *HeaderLen) { GF_BitStream *bs; *HeaderLen = 0; if (!Header) return; //reset the input header memset(Header, 0, sizeof(GF_SLHeader)); bs = gf_bs_new(PDU, PDULength, GF_BITSTREAM_READ); if (!bs) return; if (slConfig->useAccessUnitStartFlag) Header->accessUnitStartFlag = gf_bs_read_int(bs, 1); if (slConfig->useAccessUnitEndFlag) Header->accessUnitEndFlag = gf_bs_read_int(bs, 1); if ( !slConfig->useAccessUnitStartFlag && !slConfig->useAccessUnitEndFlag) { Header->accessUnitStartFlag = 1; Header->accessUnitEndFlag = 1; } if (slConfig->OCRLength > 0) Header->OCRflag = gf_bs_read_int(bs, 1); if (slConfig->useIdleFlag) Header->idleFlag = gf_bs_read_int(bs, 1); if (slConfig->usePaddingFlag) { Header->paddingFlag = gf_bs_read_int(bs, 1); if (Header->paddingFlag) Header->paddingBits = gf_bs_read_int(bs, 3); } if (!Header->idleFlag && (!Header->paddingFlag || Header->paddingBits != 0)) { if (slConfig->packetSeqNumLength > 0) Header->packetSequenceNumber = gf_bs_read_int(bs, slConfig->packetSeqNumLength); if (slConfig->degradationPriorityLength > 0) { Header->degradationPriorityFlag = gf_bs_read_int(bs, 1); if (Header->degradationPriorityFlag) Header->degradationPriority = gf_bs_read_int(bs, slConfig->degradationPriorityLength); } if (Header->OCRflag) Header->objectClockReference = gf_bs_read_int(bs, slConfig->OCRLength); if (Header->accessUnitStartFlag) { if (slConfig->useRandomAccessPointFlag) Header->randomAccessPointFlag = gf_bs_read_int(bs, 1); if (slConfig->AUSeqNumLength > 0) Header->AU_sequenceNumber = gf_bs_read_int(bs, slConfig->AUSeqNumLength); if (slConfig->useTimestampsFlag) { Header->decodingTimeStampFlag = gf_bs_read_int(bs, 1); Header->compositionTimeStampFlag = gf_bs_read_int(bs, 1); } if (slConfig->instantBitrateLength > 0) Header->instantBitrateFlag = gf_bs_read_int(bs, 1); if (Header->decodingTimeStampFlag) Header->decodingTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength); if (Header->compositionTimeStampFlag) Header->compositionTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength); if (slConfig->AULength > 0) Header->accessUnitLength = gf_bs_read_int(bs, slConfig->AULength); if (Header->instantBitrateFlag) Header->instantBitrate = gf_bs_read_int(bs, slConfig->instantBitrateLength); } } gf_bs_align(bs); *HeaderLen = (u32) gf_bs_get_position(bs); gf_bs_del(bs); }
/*allocates and writes the SL-PDU (Header + PDU) given the SLConfig and the GF_SLHeader for this PDU. AUs must be split in PDUs by another process if needed (packetizer).*/ GF_EXPORT void gf_sl_packetize(GF_SLConfig* slConfig, GF_SLHeader *Header, char *PDU, u32 size, char **outPacket, u32 *OutSize) { GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); *OutSize = 0; if (!bs) return; if (slConfig->useAccessUnitStartFlag) gf_bs_write_int(bs, Header->accessUnitStartFlag, 1); if (slConfig->useAccessUnitEndFlag) gf_bs_write_int(bs, Header->accessUnitEndFlag, 1); if (slConfig->OCRLength > 0) gf_bs_write_int(bs, Header->OCRflag, 1); if (slConfig->useIdleFlag) gf_bs_write_int(bs, Header->idleFlag, 1); if (slConfig->usePaddingFlag) { gf_bs_write_int(bs, Header->paddingFlag, 1); if (Header->paddingFlag) gf_bs_write_int(bs, Header->paddingBits, 3); } if (! Header->idleFlag && (! Header->paddingFlag || Header->paddingBits != 0)) { if (slConfig->packetSeqNumLength > 0) gf_bs_write_int(bs, Header->packetSequenceNumber, slConfig->packetSeqNumLength); if (slConfig->degradationPriorityLength > 0) { gf_bs_write_int(bs, Header->degradationPriorityFlag, 1); if (Header->degradationPriorityFlag) gf_bs_write_int(bs, Header->degradationPriority, slConfig->degradationPriorityLength); } if (Header->OCRflag) gf_bs_write_long_int(bs, Header->objectClockReference, slConfig->OCRLength); if (Header->accessUnitStartFlag) { if (slConfig->useRandomAccessPointFlag) gf_bs_write_int(bs, Header->randomAccessPointFlag, 1); if (slConfig->AUSeqNumLength > 0) gf_bs_write_int(bs, Header->AU_sequenceNumber, slConfig->AUSeqNumLength); if (slConfig->useTimestampsFlag) { gf_bs_write_int(bs, Header->decodingTimeStampFlag, 1); gf_bs_write_int(bs, Header->compositionTimeStampFlag, 1); } if (slConfig->instantBitrateLength > 0) gf_bs_write_int(bs, Header->instantBitrateFlag, 1); if (Header->decodingTimeStampFlag) gf_bs_write_long_int(bs, Header->decodingTimeStamp, slConfig->timestampLength); if (Header->compositionTimeStampFlag) gf_bs_write_long_int(bs, Header->compositionTimeStamp, slConfig->timestampLength); if (slConfig->AULength > 0) gf_bs_write_int(bs, Header->accessUnitLength, slConfig->AULength); if (Header->instantBitrateFlag) gf_bs_write_int(bs, Header->instantBitrate, slConfig->instantBitrateLength); } } //done with the Header, Alin gf_bs_align(bs); //write the PDU - already byte aligned with stuffing (paddingBits in SL Header) gf_bs_write_data(bs, PDU, size); gf_bs_align(bs); gf_bs_get_content(bs, outPacket, OutSize); gf_bs_del(bs); }
GF_EXPORT GF_Err gf_odf_hevc_cfg_write(GF_HEVCConfig *cfg, char **outData, u32 *outSize) { GF_Err e; GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); *outSize = 0; *outData = NULL; e = gf_odf_hevc_cfg_write_bs(cfg, bs); if (e==GF_OK) gf_bs_get_content(bs, outData, outSize); gf_bs_del(bs); return e; }
GF_EXPORT GF_List *gf_webvtt_parse_cues_from_data(const char *data, u32 dataLength, u64 start) { GF_List *cues; GF_WebVTTCue *cue; GF_VTTCueBox *cuebox; GF_BitStream *bs; char *pre_text; cue = NULL; pre_text = NULL; cues = gf_list_new(); bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); while(gf_bs_available(bs)) { GF_Err e; GF_Box *box; e = gf_isom_parse_box(&box, bs); if (e) return NULL; if (box->type == GF_ISOM_BOX_TYPE_VTCU) { cuebox = (GF_VTTCueBox *)box; cue = gf_webvtt_cue_new(); if (pre_text) { gf_webvtt_cue_add_property(cue, WEBVTT_PRECUE_TEXT, pre_text, (u32) strlen(pre_text)); gf_free(pre_text); pre_text = NULL; } gf_list_add(cues, cue); gf_webvtt_timestamp_set(&cue->start, start); if (cuebox->id) { gf_webvtt_cue_add_property(cue, WEBVTT_ID, cuebox->id->string, (u32) strlen(cuebox->id->string)); } if (cuebox->settings) { gf_webvtt_cue_add_property(cue, WEBVTT_SETTINGS, cuebox->settings->string, (u32) strlen(cuebox->settings->string)); } if (cuebox->payload) { gf_webvtt_cue_add_property(cue, WEBVTT_PAYLOAD, cuebox->payload->string, (u32) strlen(cuebox->payload->string)); } } else if (box->type == GF_ISOM_BOX_TYPE_VTTA) { GF_StringBox *sbox = (GF_StringBox *)box; if (cue) { gf_webvtt_cue_add_property(cue, WEBVTT_POSTCUE_TEXT, sbox->string, (u32) strlen(sbox->string)); } else { pre_text = gf_strdup(sbox->string); } } gf_isom_box_del(box); } gf_bs_del(bs); return cues; }
GF_TextSample *gf_isom_parse_texte_sample_from_data(char *data, u32 dataLength) { GF_TextSample *s; GF_BitStream *bs; /*empty text sample*/ if (!data || !dataLength) { return gf_isom_new_text_sample(); } bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); s = gf_isom_parse_texte_sample(bs); gf_bs_del(bs); return s; }
/*special function for authoring - convert DSI to LASERConfig*/ GF_EXPORT GF_Err gf_odf_get_laser_config(GF_DefaultDescriptor *dsi, GF_LASERConfig *cfg) { u32 to_skip; GF_BitStream *bs; if (!cfg) return GF_BAD_PARAM; memset(cfg, 0, sizeof(GF_LASERConfig)); if (!dsi || !dsi->data || !dsi->dataLength || !cfg) return GF_BAD_PARAM; bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ); memset(cfg, 0, sizeof(GF_LASERConfig)); cfg->tag = GF_ODF_LASER_CFG_TAG; cfg->profile = gf_bs_read_int(bs, 8); cfg->level = gf_bs_read_int(bs, 8); /*cfg->reserved = */gf_bs_read_int(bs, 3); cfg->pointsCodec = gf_bs_read_int(bs, 2); cfg->pathComponents = gf_bs_read_int(bs, 4); cfg->fullRequestHost = gf_bs_read_int(bs, 1); if (gf_bs_read_int(bs, 1)) cfg->time_resolution = gf_bs_read_int(bs, 16); else cfg->time_resolution = 1000; cfg->colorComponentBits = 1 + gf_bs_read_int(bs, 4); cfg->resolution = gf_bs_read_int(bs, 4); if (cfg->resolution>7) cfg->resolution -= 16; cfg->coord_bits = gf_bs_read_int(bs, 5); cfg->scale_bits_minus_coord_bits = gf_bs_read_int(bs, 4); cfg->newSceneIndicator = gf_bs_read_int(bs, 1); /*reserved2*/ gf_bs_read_int(bs, 3); cfg->extensionIDBits = gf_bs_read_int(bs, 4); /*hasExtConfig - we just ignore it*/ if (gf_bs_read_int(bs, 1)) { to_skip = gf_bs_read_vluimsbf5(bs); while (to_skip) { gf_bs_read_int(bs, 8); to_skip--; } } /*hasExtension - we just ignore it*/ if (gf_bs_read_int(bs, 1)) { to_skip = gf_bs_read_vluimsbf5(bs); while (to_skip) { gf_bs_read_int(bs, 8); to_skip--; } } gf_bs_del(bs); return GF_OK; }
static void VTT_ReadConfigFromDSI(VTTDec *vttdec, GF_DefaultDescriptor *dsi) { GF_BitStream *bs; u32 entry_type; bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ); entry_type = gf_bs_read_u32(bs); if (entry_type == GF_ISOM_BOX_TYPE_WVTT) { GF_Box *b; gf_isom_parse_box(&b, bs); vttdec->config = ((GF_StringBox *)b)->string; ((GF_StringBox *)b)->string = NULL; gf_isom_box_del(b); } gf_bs_del(bs); }
GF_EXPORT GF_Err gf_odf_codec_set_au(GF_ODCodec *codec, const char *au, u32 au_length) { if (!codec) return GF_BAD_PARAM; if (!au || !au_length) return GF_OK; //if the command list is not empty, this is an error if (gf_list_count(codec->CommandList)) return GF_BAD_PARAM; //the bitStream should not be here if (codec->bs) return GF_BAD_PARAM; codec->bs = gf_bs_new(au, (u64)au_length, (unsigned char)GF_BITSTREAM_READ); if (!codec->bs) return GF_OUT_OF_MEM; return GF_OK; }
GF_Err gf_isom_track_cenc_add_sample_info(GF_ISOFile *the_file, u32 trackNumber, u32 container_type, u8 IV_size, char *buf, u32 len) { u32 i; GF_SampleEncryptionBox *senc; GF_CENCSampleAuxInfo *sai; GF_SampleTableBox *stbl; GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; stbl = trak->Media->information->sampleTable; if (!stbl) return GF_BAD_PARAM; switch (container_type) { case GF_ISOM_BOX_UUID_PSEC: senc = (GF_SampleEncryptionBox *) stbl->piff_psec; break; case GF_ISOM_BOX_TYPE_SENC: senc = (GF_SampleEncryptionBox *)stbl->senc; break; default: return GF_NOT_SUPPORTED; } sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); if (!sai) return GF_OUT_OF_MEM; memset(sai, 0, sizeof(GF_CENCSampleAuxInfo)); if (len) { GF_BitStream *bs = gf_bs_new(buf, len, GF_BITSTREAM_READ); sai->IV_size = IV_size; gf_bs_read_data(bs, (char *)sai->IV, IV_size); sai->subsample_count = gf_bs_read_u16(bs); if (sai->subsample_count) senc->flags = 0x00000002; sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry)); for (i = 0; i < sai->subsample_count; i++) { sai->subsamples[i].bytes_clear_data = gf_bs_read_u16(bs); sai->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(bs); } gf_bs_del(bs); } gf_list_add(senc->samp_aux_info, sai); #ifndef GPAC_DISABLE_ISOM_FRAGMENTS gf_isom_cenc_set_saiz_saio(senc, stbl, NULL, len); #endif return GF_OK; }
/*Dummy input just send a file name, no multitrack to handle so we don't need to check sub_url nor expected type*/ static GF_Descriptor *DC_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url) { u32 size = 0; char *uri; GF_ESD *esd; GF_BitStream *bs; DCReader *read = (DCReader *) plug->priv; GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG); iod->scene_profileAndLevel = 1; iod->graphics_profileAndLevel = 1; iod->OD_profileAndLevel = 1; iod->audio_profileAndLevel = 0xFE; iod->visual_profileAndLevel = 0xFE; iod->objectDescriptorID = 1; if (read->is_views_url) { iod->URLString = gf_strdup(read->url); return (GF_Descriptor *)iod; } esd = gf_odf_desc_esd_new(0); esd->slConfig->timestampResolution = 1000; esd->slConfig->useTimestampsFlag = 1; esd->ESID = 0xFFFE; esd->decoderConfig->streamType = GF_STREAM_PRIVATE_SCENE; esd->decoderConfig->objectTypeIndication = read->oti; if (read->dnload) { uri = (char *) gf_dm_sess_get_cache_name(read->dnload); gf_dm_sess_get_stats(read->dnload, NULL, NULL, &size, NULL, NULL, NULL); } else { FILE *f = gf_fopen(read->url, "rt"); gf_fseek(f, 0, SEEK_END); size = (u32) gf_ftell(f); gf_fclose(f); uri = read->url; } bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_u32(bs, size); gf_bs_write_data(bs, uri, (u32) strlen(uri)); gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength); gf_bs_del(bs); gf_list_add(iod->ESDescriptors, esd); return (GF_Descriptor *)iod; }
//stores the hint sample in the file //set IsRandomAccessPoint if you want to indicate that this is a random access point //in the stream GF_Err gf_isom_end_hint_sample(GF_ISOFile *the_file, u32 trackNumber, u8 IsRandomAccessPoint) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; u32 dataRefIndex; GF_Err e; GF_BitStream *bs; GF_ISOSample *samp; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &dataRefIndex); if (e) return e; if (!entry->hint_sample) return GF_BAD_PARAM; //first of all, we need to adjust the offset for data referenced IN THIS hint sample //and get some PckSize e = AdjustHintInfo(entry, trak->Media->information->sampleTable->SampleSize->sampleCount + 1); if (e) return e; //ok, let's write the sample bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); e = gf_isom_hint_sample_write(entry->hint_sample, bs); if (e) { gf_bs_del(bs); return e; } samp = gf_isom_sample_new(); samp->CTS_Offset = 0; samp->IsRAP = IsRandomAccessPoint; samp->DTS = entry->hint_sample->TransmissionTime; //get the sample gf_bs_get_content(bs, &samp->data, &samp->dataLength); gf_bs_del(bs); //finally add the sample e = gf_isom_add_sample(the_file, trackNumber, trak->Media->information->sampleTable->currentEntryIndex, samp); gf_isom_sample_del(&samp); //and delete the sample in our entry ... gf_isom_hint_sample_del(entry->hint_sample); entry->hint_sample = NULL; return e; }
GF_EXPORT GF_Err gf_bifs_decode_command_list(GF_BifsDecoder *codec, u16 ESID, char *data, u32 data_length, GF_List *com_list) { GF_BitStream *bs; GF_Err e; if (!codec || !data || !codec->dec_memory_mode || !com_list) return GF_BAD_PARAM; codec->info = gf_bifs_dec_get_stream(codec, ESID); if (!codec->info) return GF_BAD_PARAM; if (codec->info->config.elementaryMasks ) return GF_NOT_SUPPORTED; /*root parse (not conditionals)*/ assert(codec->scenegraph); /*setup current scene graph*/ codec->current_graph = codec->scenegraph; codec->ActiveQP = (M_QuantizationParameter*) codec->scenegraph->global_qp; bs = gf_bs_new(data, data_length, GF_BITSTREAM_READ); gf_bs_set_eos_callback(bs, BM_EndOfStream, codec); e = BM_ParseCommand(codec, bs, com_list); gf_bs_del(bs); /*decode conditionals / input sensors*/ if (!e) { gf_bifs_flush_command_list(codec); } /*if err or not reset conditionals*/ while (gf_list_count(codec->command_buffers)) { CommandBufferItem *cbi = (CommandBufferItem *)gf_list_get(codec->command_buffers, 0); gf_free(cbi); gf_list_rem(codec->command_buffers, 0); } /*reset current config*/ codec->info = NULL; codec->current_graph = NULL; // gf_mx_v(codec->mx); return e; }
GF_Err MCDec_InitMpeg4Decoder(MCDec *ctx) { char *dsi_data = NULL; u32 dsi_data_size = 0; if (!ctx->esd->decoderConfig->decoderSpecificInfo) { ctx->esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); } if (ctx->esd->decoderConfig->decoderSpecificInfo->data) { GF_M4VDecSpecInfo vcfg; GF_BitStream *bs; gf_m4v_get_config(ctx->esd->decoderConfig->decoderSpecificInfo->data, ctx->esd->decoderConfig->decoderSpecificInfo->dataLength, &vcfg); ctx->width = vcfg.width; ctx->height = vcfg.height; if (ctx->esd->slConfig) { ctx->esd->slConfig->predefined = 2; } bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_u32(bs, 0); gf_odf_desc_write_bs((GF_Descriptor *) ctx->esd, bs); gf_bs_get_content(bs, &dsi_data, &dsi_data_size); gf_bs_del(bs); ctx->mime = "video/mp4v-es"; char *esds = (char *)malloc(dsi_data_size); memcpy(esds, dsi_data, dsi_data_size); esds[0] = 0x00; esds[1] = 0x00; esds[2] = 0x00; esds[3] = 0x01; AMediaFormat_setBuffer(ctx->format, "csd-0", esds, dsi_data_size); gf_free(dsi_data); return GF_OK; } return GF_NOT_SUPPORTED; }
GF_EXPORT GF_Err gf_odf_desc_write(GF_Descriptor *desc, char **outEncDesc, u32 *outSize) { GF_Err e; GF_BitStream *bs; if (!desc || !outEncDesc || !outSize) return GF_BAD_PARAM; *outEncDesc = NULL; *outSize = 0; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); if (!bs) return GF_OUT_OF_MEM; e = gf_odf_desc_write_bs(desc, bs); //then get the content from our bitstream gf_bs_get_content(bs, outEncDesc, outSize); gf_bs_del(bs); return e; }
GF_Err gf_webvtt_dump_header_boxed(FILE *dump, const char *data, u32 dataLength, u32 *dumpedLength) { GF_Err e; GF_Box *box; GF_StringBox *config; GF_BitStream *bs; *dumpedLength = 0; bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); e = gf_isom_parse_box(&box, bs); if (!box || (box->type != GF_ISOM_BOX_TYPE_VTTC)) return GF_BAD_PARAM; config = (GF_StringBox *)box; if (config->string) { fprintf(dump, "%s", config->string); *dumpedLength = (u32)strlen(config->string)+1; } gf_bs_del(bs); gf_isom_box_del(box); return e; }
GF_Err gf_webvtt_dump_iso_sample(FILE *dump, u32 timescale, GF_ISOSample *iso_sample, Bool box_mode) { GF_Err e; GF_BitStream *bs; if (box_mode) { fprintf(dump, "<WebVTTSample decodingTimeStamp=\""LLU"\" compositionTimeStamp=\""LLD"\" RAP=\"%d\" dataLength=\"%d\" >\n", iso_sample->DTS, (s64)iso_sample->DTS + iso_sample->CTS_Offset, iso_sample->IsRAP, iso_sample->dataLength); } bs = gf_bs_new(iso_sample->data, iso_sample->dataLength, GF_BITSTREAM_READ); while(gf_bs_available(bs)) { GF_Box *box; GF_WebVTTTimestamp ts; e = gf_isom_box_parse(&box, bs); if (e) return e; if (box_mode) { gf_isom_box_dump(box, dump); } else if (box->type == GF_ISOM_BOX_TYPE_VTCC_CUE) { GF_VTTCueBox *cuebox = (GF_VTTCueBox *)box; if (cuebox->id) fprintf(dump, "%s", cuebox->id->string); gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale); gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE); fprintf(dump, " --> NEXT"); if (cuebox->settings) fprintf(dump, " %s", cuebox->settings->string); fprintf(dump, "\n"); if (cuebox->payload) fprintf(dump, "%s", cuebox->payload->string); fprintf(dump, "\n"); } else if (box->type == GF_ISOM_BOX_TYPE_VTTE) { gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale); gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE); fprintf(dump, " --> NEXT\n\n"); } else if (box->type == GF_ISOM_BOX_TYPE_VTTA) { fprintf(dump, "%s\n\n", ((GF_StringBox *)box)->string); } gf_isom_box_del(box); } gf_bs_del(bs); if (box_mode) { fprintf(dump, "</WebVTTSample>\n"); } return GF_OK; }
GF_EXPORT GF_Err gf_odf_codec_encode(GF_ODCodec *codec, u32 cleanup_type) { GF_ODCom *com; GF_Err e = GF_OK; u32 i; if (!codec) return GF_BAD_PARAM; //check our bitstream: if existing, this means the previous encoded AU was not retrieved //we DON'T allow that if (codec->bs) return GF_BAD_PARAM; codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); if (!codec->bs) return GF_OUT_OF_MEM; /*encode each command*/ i = 0; while ((com = (GF_ODCom *)gf_list_enum(codec->CommandList, &i))) { e = gf_odf_write_command(codec->bs, com); if (e) goto err_exit; //don't forget OD Commands are aligned... gf_bs_align(codec->bs); } //if an error occurs, delete the GF_BitStream and empty the codec err_exit: if (e) { gf_bs_del(codec->bs); codec->bs = NULL; } if (cleanup_type == 1) { while (gf_list_count(codec->CommandList)) { com = (GF_ODCom *)gf_list_get(codec->CommandList, 0); gf_odf_delete_command(com); gf_list_rem(codec->CommandList, 0); } } if (cleanup_type == 0) { gf_list_reset(codec->CommandList); } return e; }