void dc_cmd_data_destroy(CmdData *cmd_data) { while (gf_list_count(cmd_data->audio_lst)) { AudioDataConf *audio_data_conf = gf_list_last(cmd_data->audio_lst); gf_free(audio_data_conf->custom); gf_list_rem_last(cmd_data->audio_lst); gf_free(audio_data_conf); } gf_list_del(cmd_data->audio_lst); while (gf_list_count(cmd_data->video_lst)) { VideoDataConf *video_data_conf = gf_list_last(cmd_data->video_lst); gf_free(video_data_conf->custom); gf_list_rem_last(cmd_data->video_lst); gf_free(video_data_conf); } gf_list_del(cmd_data->video_lst); gf_list_del(cmd_data->asrc); gf_list_del(cmd_data->vsrc); gf_cfg_del(cmd_data->conf); gf_cfg_del(cmd_data->switch_conf); if (cmd_data->logfile) fclose(cmd_data->logfile); dc_task_destroy(&cmd_data->task_list); gf_sys_close(); }
GF_EXPORT void gf_xml_dom_node_del(GF_XMLNode *node) { if (node->attributes) { while (gf_list_count(node->attributes)) { GF_XMLAttribute *att = (GF_XMLAttribute *)gf_list_last(node->attributes); gf_list_rem_last(node->attributes); if (att->name) gf_free(att->name); if (att->value) gf_free(att->value); gf_free(att); } gf_list_del(node->attributes); } if (node->content) { while (gf_list_count(node->content)) { GF_XMLNode *child = (GF_XMLNode *)gf_list_last(node->content); gf_list_rem_last(node->content); gf_xml_dom_node_del(child); } gf_list_del(node->content); } if (node->ns) gf_free(node->ns); if (node->name) gf_free(node->name); gf_free(node); }
void dc_audio_decoder_close(AudioInputFile *audio_input_file) { /* * Close the audio format context */ avformat_close_input(&audio_input_file->av_fmt_ctx); if (audio_input_file->av_pkt_list_mutex) { gf_mx_p(audio_input_file->av_pkt_list_mutex); while (gf_list_count(audio_input_file->av_pkt_list)) { AVPacket *pkt = gf_list_last(audio_input_file->av_pkt_list); av_free_packet(pkt); gf_list_rem_last(audio_input_file->av_pkt_list); } gf_list_del(audio_input_file->av_pkt_list); gf_mx_v(audio_input_file->av_pkt_list_mutex); gf_mx_del(audio_input_file->av_pkt_list_mutex); } av_fifo_free(audio_input_file->fifo); #ifdef DC_AUDIO_RESAMPLER avresample_free(&audio_input_file->aresampler); #endif }
static void gf_sm_reset_stream(GF_StreamContext *sc) { while (gf_list_count(sc->AUs)) { GF_AUContext *au = (GF_AUContext *)gf_list_last(sc->AUs); gf_list_rem_last(sc->AUs); gf_sm_au_del(sc, au); } }
static void bifs_info_del(BIFSStreamInfo *info) { while (1) { BIFSElementaryMask *em = (BIFSElementaryMask *)gf_list_last(info->config.elementaryMasks); if (!em) break; gf_list_rem_last(info->config.elementaryMasks); gf_free(em); } gf_free(info); }
void gf_saf_mux_del(GF_SAFMuxer *mux) { while (gf_list_count(mux->streams)) { GF_SAFStream *str = (GF_SAFStream *)gf_list_last(mux->streams); gf_list_rem_last(mux->streams); saf_stream_del(str); } gf_list_del(mux->streams); gf_mx_del(mux->mx); gf_free(mux); }
static void xml_sax_parse_entity(GF_SAXParser *parser) { char szName[1024]; u32 i = 0; XML_Entity *ent = (XML_Entity *)gf_list_last(parser->entities); char *skip_chars = " \t\n\r"; i=0; if (ent && ent->value) ent = NULL; if (ent) skip_chars = NULL; while (parser->current_pos+i < parser->line_size) { u8 c = parser->buffer[parser->current_pos+i]; if (skip_chars && strchr(skip_chars, c)) { if (c=='\n') parser->line++; parser->current_pos++; continue; } if (!ent && (c=='%')) { parser->current_pos+=i+1; parser->sax_state = SAX_STATE_SKIP_DOCTYPE; return; } else if (!ent && ((c=='\"') || (c=='\'')) ) { szName[i] = 0; GF_SAFEALLOC(ent, XML_Entity); ent->name = gf_strdup(szName); ent->namelen = strlen(ent->name); ent->sep = c; parser->current_pos += 1+i; assert(parser->current_pos < parser->line_size); xml_sax_swap(parser); i=0; gf_list_add(parser->entities, ent); skip_chars = NULL; } else if (ent && c==ent->sep) { xml_sax_store_text(parser, i); ent->value = xml_get_current_text(parser); if (!ent->value) ent->value = gf_strdup(""); parser->current_pos += 1; assert(parser->current_pos < parser->line_size); xml_sax_swap(parser); parser->sax_state = SAX_STATE_SKIP_DOCTYPE; return; } else if (!ent) { szName[i] = c; i++; } else { i++; } } xml_sax_store_text(parser, i); }
static GF_AUContext *gf_seng_create_new_au(GF_StreamContext *sc, u32 time) { GF_AUContext *new_au, *last_au; last_au = gf_list_last(sc->AUs); if (last_au && last_au->timing == time) { GF_LOG(GF_LOG_DEBUG, GF_LOG_SCENE, ("[SceneEngine] Forcing new AU\n")); time++; } new_au = gf_sm_stream_au_new(sc, time, 0, 0); return new_au; }
GF_Err gf_isom_add_subsample_info(GF_SubSampleInformationBox *sub_samples, u32 sampleNumber, u32 subSampleSize, u8 priority, u32 reserved, Bool discardable) { u32 i, count, last_sample; GF_SubSampleInfoEntry *pSamp; GF_SubSampleEntry *pSubSamp; pSamp = NULL; last_sample = 0; count = gf_list_count(sub_samples->Samples); for (i=0; i<count; i++) { pSamp = (GF_SubSampleInfoEntry*) gf_list_get(sub_samples->Samples, i); /*TODO - do we need to support insertion of subsample info ?*/ if (last_sample + pSamp->sample_delta > sampleNumber) return GF_NOT_SUPPORTED; if (last_sample + pSamp->sample_delta == sampleNumber) break; last_sample += pSamp->sample_delta; pSamp = NULL; } if (!pSamp) { GF_SAFEALLOC(pSamp, GF_SubSampleInfoEntry); if (!pSamp) return GF_OUT_OF_MEM; pSamp->SubSamples = gf_list_new(); if (!pSamp->SubSamples ) { gf_free(pSamp); return GF_OUT_OF_MEM; } pSamp->sample_delta = sampleNumber - last_sample; gf_list_add(sub_samples->Samples, pSamp); } if ((subSampleSize>0xFFFF) && !sub_samples->version) { sub_samples->version = 1; } /*remove last subsample info*/ if (!subSampleSize) { pSubSamp = gf_list_last(pSamp->SubSamples); gf_list_rem_last(pSamp->SubSamples); gf_free(pSubSamp); if (!gf_list_count(pSamp->SubSamples)) { gf_list_del_item(sub_samples->Samples, pSamp); gf_list_del(pSamp->SubSamples); gf_free(pSamp); } return GF_OK; } /*add subsample*/ GF_SAFEALLOC(pSubSamp, GF_SubSampleEntry); if (!pSubSamp) return GF_OUT_OF_MEM; pSubSamp->subsample_size = subSampleSize; pSubSamp->subsample_priority = priority; pSubSamp->reserved = reserved; pSubSamp->discardable = discardable; return gf_list_add(pSamp->SubSamples, pSubSamp); }
static void on_dom_node_end(void *cbk, const char *name, const char *ns) { GF_DOMParser *par = (GF_DOMParser *)cbk; GF_XMLNode *last = (GF_XMLNode *)gf_list_last(par->stack); gf_list_rem_last(par->stack); if (!last || strcmp(last->name, name) || (!ns && last->ns) || (ns && !last->ns) || (ns && strcmp(last->ns, ns) ) ) { par->parser->suspended = 1; gf_xml_dom_node_del(last); if (last==par->root) par->root=NULL; return; } if (last != par->root) { GF_XMLNode *node = (GF_XMLNode *)gf_list_last(par->stack); assert(node->content); assert(gf_list_find(node->content, last) == -1); gf_list_add(node->content, last); } }
GPAC_MediaRenderer::~GPAC_MediaRenderer() { if (m_mediaHistoryList) { /* empty mediaHistoryList */ while (gf_list_count(m_mediaHistoryList) > 0) { char * last = (char*)gf_list_last(m_mediaHistoryList); gf_list_rem_last(m_mediaHistoryList); gf_free(last); } gf_list_del(m_mediaHistoryList); } }
static void on_dom_node_end(void *cbk, const char *name, const char *ns) { GF_DOMParser *par = (GF_DOMParser *)cbk; GF_XMLNode *last = (GF_XMLNode *)gf_list_last(par->stack); gf_list_rem_last(par->stack); if (!last || strcmp(last->name, name) || (!ns && last->ns) || (ns && !last->ns) || (ns && strcmp(last->ns, ns) ) ) { format_sax_error(par->parser, 0, "Invalid node stack: closing node is %s but %s was expected", name, last->name); par->parser->suspended = 1; gf_xml_dom_node_del(last); if (last==par->root) par->root=NULL; return; } if (last != par->root) { GF_XMLNode *node = (GF_XMLNode *)gf_list_last(par->stack); assert(node->content); assert(gf_list_find(node->content, last) == -1); gf_list_add(node->content, last); } }
static void on_dom_text_content(void *cbk, const char *content, Bool is_cdata) { GF_DOMParser *par = (GF_DOMParser *)cbk; GF_XMLNode *node; GF_XMLNode *last = (GF_XMLNode *)gf_list_last(par->stack); if (!last) return; assert(last->content); GF_SAFEALLOC(node, GF_XMLNode); node->type = is_cdata ? GF_XML_CDATA_TYPE : GF_XML_TEXT_TYPE; node->name = gf_strdup(content); gf_list_add(last->content, node); }
static void gf_sm_delete_stream(GF_StreamContext *sc) { while (gf_list_count(sc->AUs)) { GF_AUContext *au = (GF_AUContext *)gf_list_last(sc->AUs); gf_list_rem_last(sc->AUs); 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); free(au); } gf_list_del(sc->AUs); free(sc); }
static void saf_stream_del(GF_SAFStream *str) { if (str->mime_type) gf_free(str->mime_type); if (str->remote_url) gf_free(str->remote_url); if (str->dsi) gf_free(str->dsi); while (gf_list_count(str->aus)) { GF_SAFSample *au = (GF_SAFSample *)gf_list_last(str->aus); gf_list_rem_last(str->aus); if (au->data) gf_free(au->data); gf_free(au); } gf_list_del(str->aus); gf_free(str); }
static void xml_sax_reset(GF_SAXParser *parser) { while (1) { XML_Entity *ent = (XML_Entity *)gf_list_last(parser->entities); if (!ent) break; gf_list_rem_last(parser->entities); if (ent->name) gf_free(ent->name); if (ent->value) gf_free(ent->value); gf_free(ent); } if (parser->buffer) gf_free(parser->buffer); parser->buffer = NULL; parser->current_pos = 0; gf_free(parser->attrs); parser->attrs = NULL; gf_free(parser->sax_attrs); parser->sax_attrs = NULL; parser->nb_alloc_attrs = parser->nb_attrs = 0; }
void DeleteSAFReader(void *ifce) { GF_InputService *plug = (GF_InputService *) ifce; SAFIn *read = (SAFIn *)plug->priv; if (!ifce) return; while (gf_list_count(read->channels)) { SAFChannel *ch = (SAFChannel *)gf_list_last(read->channels); gf_list_rem_last(read->channels); if (ch->esd) gf_odf_desc_del((GF_Descriptor *) ch->esd); gf_free(ch); } gf_list_del(read->channels); if (read->saf_data) gf_free(read->saf_data); read->saf_data = NULL; gf_free(read); plug->priv = NULL; gf_free(plug); }
static void gf_xml_dom_reset(GF_DOMParser *dom, Bool full_reset) { if (full_reset && dom->parser) { gf_xml_sax_del(dom->parser); dom->parser = NULL; } if (dom->stack) { while (gf_list_count(dom->stack)) { GF_XMLNode *n = (GF_XMLNode *)gf_list_last(dom->stack); gf_list_rem_last(dom->stack); if (dom->root==n) dom->root = NULL; gf_xml_dom_node_del(n); } gf_list_del(dom->stack); dom->stack = NULL; } if (full_reset && dom->root) { gf_xml_dom_node_del(dom->root); dom->root = NULL; } }
GF_Err SetTrackDuration(GF_TrackBox *trak) { u64 trackDuration; u32 i; GF_EdtsEntry *ent; GF_EditListBox *elst; GF_Err e; //the total duration is the media duration: adjust it in case... e = Media_SetDuration(trak); if (e) return e; //assert the timeScales are non-NULL if (!trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale) return GF_ISOM_INVALID_FILE; trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale; //if we have an edit list, the duration is the sum of all the editList //entries' duration (always expressed in MovieTimeScale) if (trak->editBox && !trak->editBox->last_is_empty && trak->editBox->editList) { trackDuration = 0; elst = trak->editBox->editList; i=0; while ((ent = (GF_EdtsEntry*)gf_list_enum(elst->entryList, &i))) { trackDuration += ent->segmentDuration; if (ent->mediaRate && !ent->segmentDuration) { trak->editBox->last_is_empty = 1; } } if (trak->editBox->last_is_empty) { ent = (GF_EdtsEntry*) gf_list_last(elst->entryList); ent->segmentDuration = trackDuration; } } trak->Header->duration = trackDuration; trak->Header->modificationTime = gf_isom_get_mp4time(); return GF_OK; }
static void RP_cleanup(RTPClient *rtp) { RTSPSession *sess; while (gf_list_count(rtp->channels)) { RTPStream *ch = (RTPStream *)gf_list_get(rtp->channels, 0); gf_list_rem(rtp->channels, 0); RP_DeleteStream(ch); } while ( (sess = (RTSPSession *)gf_list_last(rtp->sessions)) ) { gf_list_rem_last(rtp->sessions); RP_DelSession(sess); } if (rtp->session_desc) gf_odf_desc_del(rtp->session_desc); rtp->session_desc = NULL; if (rtp->sdp_temp) { gf_free(rtp->sdp_temp->remote_url); gf_free(rtp->sdp_temp); } rtp->sdp_temp = NULL; }
static Bool validator_xvs_open(GF_Validator *validator) { GF_Err e; GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Validator] Opening Validation Script: %s\n", validator->xvs_filename)); validator->snapshot_number = 0; validator->xvs_parser = gf_xml_dom_new(); e = gf_xml_dom_parse(validator->xvs_parser, validator->xvs_filename, NULL, NULL); if (e != GF_OK) { if (validator->is_recording) { GF_SAFEALLOC(validator->xvs_node, GF_XMLNode); validator->xvs_node->name = gf_strdup("TestValidationScript"); validator->xvs_node->attributes = gf_list_new(); validator->xvs_node->content = gf_list_new(); } else { gf_xml_dom_del(validator->xvs_parser); validator->xvs_parser = NULL; return 0; } } else { validator->xvs_node = gf_xml_dom_get_root(validator->xvs_parser); } /* Get the file name from the XVS if not found in the XVL */ if (!validator->test_filename) { GF_XMLAttribute *att; GF_XMLAttribute *att_file; u32 att_index = 0; att_file = NULL; while (1) { att = gf_list_get(validator->xvs_node->attributes, att_index); if (!att) { break; } else if (!strcmp(att->name, "file")) { att_file = att; } att_index++; } if (!att_file) { gf_xml_dom_del(validator->xvs_parser); validator->xvs_parser = NULL; validator->xvs_node = NULL; return 0; } else { char *sep; sep = strrchr(att_file->value, GF_PATH_SEPARATOR); if (!sep) { validator->test_filename = att_file->value; } else { sep[0] = 0; validator->test_base = gf_strdup(att_file->value); sep[0] = GF_PATH_SEPARATOR; validator->test_filename = sep+1; } } } if (validator->is_recording) { GF_XMLNode *node; /* Removing prerecorded interactions */ while (gf_list_count(validator->xvs_node->content)) { GF_XMLNode *child = (GF_XMLNode *)gf_list_last(validator->xvs_node->content); gf_list_rem_last(validator->xvs_node->content); gf_xml_dom_node_del(child); } /* adding an extra text node for line break in serialization */ GF_SAFEALLOC(node, GF_XMLNode); node->type = GF_XML_TEXT_TYPE; node->name = gf_strdup("\n"); gf_list_add(validator->xvs_node->content, node); } else { validator->xvs_result = 1; } return 1; }
GF_Err gf_webvtt_merge_cues(GF_WebVTTParser *parser, u64 start, GF_List *cues) { GF_WebVTTSample *wsample; GF_WebVTTSample *prev_wsample; Bool has_continuation_cue = GF_FALSE; assert(gf_list_count(parser->samples) <= 1); wsample = gf_webvtt_sample_new(); wsample->start = start; prev_wsample = (GF_WebVTTSample *)gf_list_last(parser->samples); while (gf_list_count(cues)) { GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(cues, 0); gf_list_rem(cues, 0); /* add the cue to the current sample */ gf_list_add(wsample->cues, cue); /* update with the previous sample */ if (prev_wsample) { Bool found = GF_FALSE; while (!found && gf_list_count(prev_wsample->cues)) { GF_WebVTTCue *old_cue = (GF_WebVTTCue *)gf_list_get(prev_wsample->cues, 0); gf_list_rem(prev_wsample->cues, 0); if ( ((!cue->id && !old_cue->id) || (old_cue->id && cue->id && !strcmp(old_cue->id, cue->id))) && ((!cue->settings && !old_cue->settings) || (old_cue->settings && cue->settings && !strcmp(old_cue->settings, cue->settings))) && ((!cue->text && !old_cue->text) || (old_cue->text && cue->text && !strcmp(old_cue->text, cue->text))) ) { /* if it is the same cue, update its start with the initial start */ cue->start = old_cue->start; has_continuation_cue = GF_TRUE; found = GF_TRUE; if (old_cue->pre_text) { cue->pre_text = old_cue->pre_text; old_cue->pre_text = NULL; } if (old_cue->post_text) { cue->post_text = old_cue->post_text; old_cue->post_text = NULL; } /* delete the old cue */ gf_webvtt_cue_del(old_cue); } else { /* finalize the end cue time */ if (gf_webvtt_timestamp_is_zero(&old_cue->end)) { gf_webvtt_timestamp_set(&old_cue->end, wsample->start); } /* transfer the cue */ if (!has_continuation_cue) { /* the cue can be safely serialized while keeping the order */ parser->on_cue_read(parser->user, old_cue); } else { /* keep the cue in the current sample to respect cue start ordering */ gf_list_add(wsample->cues, old_cue); } } } } } /* No cue in the current sample */ if (prev_wsample) { while (gf_list_count(prev_wsample->cues)) { GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(prev_wsample->cues, 0); gf_list_rem(prev_wsample->cues, 0); /* finalize the end cue time */ if (gf_webvtt_timestamp_is_zero(&cue->end)) { gf_webvtt_timestamp_set(&cue->end, wsample->start); } /* transfer the cue */ if (!has_continuation_cue) { /* the cue can be safely serialized while keeping the order */ parser->on_cue_read(parser->user, cue); } else { /* keep the cue in the current sample to respect cue start ordering */ gf_list_add(wsample->cues, cue); } } gf_webvtt_sample_del(prev_wsample); gf_list_rem_last(parser->samples); prev_wsample = NULL; } else { /* nothing to do */ } if (gf_list_count(wsample->cues)) { gf_list_add(parser->samples, wsample); } else { gf_webvtt_sample_del(wsample); } return GF_OK; }
//WARNING: MOVIETIME IS EXPRESSED IN MEDIA TS GF_Err GetMediaTime(GF_TrackBox *trak, Bool force_non_empty, u64 movieTime, u64 *MediaTime, s64 *SegmentStartTime, s64 *MediaOffset, u8 *useEdit, u64 *next_edit_start_plus_one) { #if 0 GF_Err e; u32 sampleNumber, prevSampleNumber; u64 firstDTS; #endif u32 i, count; Bool last_is_empty = 0; u64 time, lastSampleTime; s64 mtime; GF_EdtsEntry *ent; Double scale_ts; GF_SampleTableBox *stbl = trak->Media->information->sampleTable; if (next_edit_start_plus_one) *next_edit_start_plus_one = 0; *useEdit = 1; *MediaTime = 0; //no segment yet... *SegmentStartTime = -1; *MediaOffset = -1; if (!trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale || !stbl->SampleSize) { return GF_ISOM_INVALID_FILE; } //no samples... if (!stbl->SampleSize->sampleCount) { lastSampleTime = 0; } else { lastSampleTime = trak->Media->mediaHeader->duration; } //No edits, 1 to 1 mapping if (! trak->editBox || !trak->editBox->editList) { *MediaTime = movieTime; //check this is in our media time line if ((*MediaTime > lastSampleTime) #ifndef GPAC_DISABLE_ISOM_FRAGMENTS && !trak->moov->mov->moof #endif ) { *MediaTime = lastSampleTime; } *useEdit = 0; return GF_OK; } //browse the edit list and get the time scale_ts = trak->Media->mediaHeader->timeScale; scale_ts /= trak->moov->mvhd->timeScale; time = 0; ent = NULL; count=gf_list_count(trak->editBox->editList->entryList); for (i=0; i<count; i++) { ent = (GF_EdtsEntry *)gf_list_get(trak->editBox->editList->entryList, i); if ( (time + ent->segmentDuration) * scale_ts > movieTime) { if (!force_non_empty || (ent->mediaTime >= 0)) { if (next_edit_start_plus_one) *next_edit_start_plus_one = 1 + (u64) ((time + ent->segmentDuration) * scale_ts); goto ent_found; } } time += ent->segmentDuration; last_is_empty = ent->segmentDuration ? 0 : 1; } if (last_is_empty) { ent = (GF_EdtsEntry *)gf_list_last(trak->editBox->editList->entryList); if (ent->mediaRate==1) { *MediaTime = movieTime + ent->mediaTime; } else { ent = (GF_EdtsEntry *)gf_list_get(trak->editBox->editList->entryList, 0); if (ent->mediaRate==-1) { u64 dur = (u64) (ent->segmentDuration * scale_ts); *MediaTime = (movieTime > dur) ? (movieTime-dur) : 0; } } *useEdit = 0; return GF_OK; } //we had nothing in the list (strange file but compliant...) //return the 1 to 1 mapped vale of the last media sample if (!ent) { *MediaTime = movieTime; //check this is in our media time line if (*MediaTime > lastSampleTime) *MediaTime = lastSampleTime; *useEdit = 0; return GF_OK; } //request for a bigger time that what we can give: return the last sample (undefined behavior...) *MediaTime = lastSampleTime; return GF_OK; ent_found: //OK, we found our entry, set the SegmentTime *SegmentStartTime = time; //we request an empty list, there's no media here... if (ent->mediaTime < 0) { *MediaTime = 0; return GF_OK; } //we request a dwell edit if (! ent->mediaRate) { *MediaTime = ent->mediaTime; //no media offset *MediaOffset = 0; *useEdit = 2; return GF_OK; } /*WARNING: this can be "-1" when doing searchForward mode (to prevent jumping to next entry)*/ mtime = ent->mediaTime + movieTime - (time * trak->Media->mediaHeader->timeScale / trak->moov->mvhd->timeScale); if (mtime<0) mtime = 0; *MediaTime = (u64) mtime; *MediaOffset = ent->mediaTime; #if 0 // //Sanity check: is the requested time valid ? This is to cope with wrong EditLists //we have the translated time, but we need to make sure we have a sample at this time ... //we have to find a COMPOSITION time e = findEntryForTime(stbl, (u32) *MediaTime, 1, &sampleNumber, &prevSampleNumber); if (e) return e; //first case: our time is after the last sample DTS (it's a broken editList somehow) //set the media time to the last sample if (!sampleNumber && !prevSampleNumber) { *MediaTime = lastSampleTime; return GF_OK; } //get the appropriated sample if (!sampleNumber) sampleNumber = prevSampleNumber; stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &DTS); CTS = 0; if (stbl->CompositionOffset) stbl_GetSampleCTS(stbl->CompositionOffset, sampleNumber, &CTS); //now get the entry sample (the entry time gives the CTS, and we need the DTS e = findEntryForTime(stbl, (u32) ent->mediaTime, 0, &sampleNumber, &prevSampleNumber); if (e) return e; //oops, the mediaTime indicates a sample that is not in our media ! if (!sampleNumber && !prevSampleNumber) { *MediaTime = lastSampleTime; return GF_ISOM_INVALID_FILE; } if (!sampleNumber) sampleNumber = prevSampleNumber; stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &firstDTS); //and store the "time offset" of the desired sample in this segment //this is weird, used to rebuild the timeStamp when reading from the track, not the //media ... *MediaOffset = firstDTS; #endif return GF_OK; }
static void get_domtext_width(GF_Node *node, SVGAllAttributes *atts, GF_TraverseState *tr_state) { u32 i; GF_Font *font; Fixed block_width, *entry; GF_FontManager *fm; GF_TextSpan *span; GF_DOMText *dom_text = (GF_DOMText *)node; if (!dom_text->textContent) return; fm = tr_state->visual->compositor->font_manager; if (!fm) return; font = svg_set_font(tr_state, fm); if (!font) return; span = svg_get_text_span(fm, font, tr_state->svg_props->font_size->value, (tr_state->count_x>1), (tr_state->count_y>1), GF_FALSE, atts, dom_text->textContent, atts->xml_lang ? *atts->xml_lang : NULL, tr_state); if (!span) return; i=0; //count_x, _y: number of x- (y-) position of characters to come in the text flow while ( (i<span->nb_glyphs) && ( (tr_state->count_x>1) || (tr_state->count_y>1) ) ) { block_width = (span->glyphs[i] ? span->glyphs[i]->horiz_advance : font->max_advance_h) * span->font_scale; //store width in tr_state->x_anchors entry = (Fixed*)gf_malloc(sizeof(Fixed)); if (span->flags & GF_TEXT_SPAN_RIGHT_TO_LEFT) *entry = -block_width; else *entry = block_width; gf_list_add(tr_state->x_anchors, entry); if (tr_state->count_x>0) tr_state->count_x--; if (tr_state->count_y>0) tr_state->count_y--; i++; } //chars are taken one by one while there are indicated positions, then remaining chars are treated as a block if (i<span->nb_glyphs) { block_width = 0; while (i<span->nb_glyphs) { block_width += (span->glyphs[i] ? span->glyphs[i]->horiz_advance : font->max_advance_h) * span->font_scale; i++; } //if last indicated position, create a new item if ((tr_state->count_x==1)||(tr_state->count_y==1) || !gf_list_count(tr_state->x_anchors) ) { entry = (Fixed*)gf_malloc(sizeof(Fixed)); *entry = block_width; if (span->flags & GF_TEXT_SPAN_RIGHT_TO_LEFT) *entry = -block_width; else *entry = block_width; gf_list_add(tr_state->x_anchors, entry); } else { // (count_x == 0 && count_y == 0) otherwise increment last one Fixed *prec_lw = gf_list_last(tr_state->x_anchors); (*prec_lw) += block_width; } //force counters to 0 for next spans/DOM texts if (tr_state->count_x==1) tr_state->count_x = 0; if (tr_state->count_y==1) tr_state->count_y = 0; } gf_font_manager_delete_span(fm, span); }
void gf_svg_delete_attribute_value(u32 type, void *value, GF_SceneGraph *sg) { GF_List *l; switch (type) { case SVG_Paint_datatype: gf_svg_delete_paint(sg, (SVG_Paint *)value); break; case XMLRI_datatype: case XML_IDREF_datatype: gf_svg_reset_iri(sg, (XMLRI *)value); gf_free(value); break; case SVG_Focus_datatype: gf_svg_reset_iri(sg, & ((SVG_Focus*)value)->target); gf_free(value); break; case SVG_PathData_datatype: #if USE_GF_PATH gf_path_del((GF_Path *)value); #else gf_free(value); #endif break; case SVG_ID_datatype: case DOM_String_datatype: case SVG_ContentType_datatype: case SVG_LanguageID_datatype: if (*(SVG_String *)value) gf_free(*(SVG_String *)value); gf_free(value); break; case SVG_StrokeDashArray_datatype: if (((SVG_StrokeDashArray*)value)->array.vals) gf_free(((SVG_StrokeDashArray*)value)->array.vals); gf_free(value); break; case SVG_Numbers_datatype: case SVG_Coordinates_datatype: case SVG_Points_datatype: l = *(GF_List**)value; while (gf_list_count(l)) { void *n = gf_list_last(l); gf_list_rem_last(l); gf_free(n); } gf_list_del(l); gf_free(value); break; case SVG_FontFamily_datatype: { SVG_FontFamily *ff = (SVG_FontFamily *)value; if (ff->value) gf_free(ff->value); gf_free(value); } break; case SMIL_AttributeName_datatype: { SMIL_AttributeName *an = (SMIL_AttributeName *)value; if (an->name) gf_free(an->name); gf_free(value); } break; case SMIL_Times_datatype: gf_smil_delete_times(*(SMIL_Times *)value); gf_free(value); break; case SMIL_AnimateValue_datatype: svg_delete_one_anim_value(((SMIL_AnimateValue *)value)->type, ((SMIL_AnimateValue *)value)->value, sg); gf_free(value); break; case SMIL_AnimateValues_datatype: gf_svg_reset_animate_values(*((SMIL_AnimateValues *)value), sg); gf_free(value); break; case DOM_StringList_datatype: l = *(GF_List**)value; while (gf_list_count(l)) { char *n = gf_list_last(l); gf_list_rem_last(l); gf_free(n); } gf_list_del(l); gf_free(value); break; case XMLRI_List_datatype: l = *(GF_List**)value; while (gf_list_count(l)) { XMLRI *r = gf_list_last(l); gf_list_rem_last(l); if (r->string) gf_free(r->string); gf_free(r); } gf_list_del(l); gf_free(value); break; case SMIL_KeyTimes_datatype: case SMIL_KeySplines_datatype: l = *(GF_List**)value; while (gf_list_count(l)) { Fixed *f = gf_list_last(l); gf_list_rem_last(l); gf_free(f); } gf_list_del(l); gf_free(value); break; case SMIL_RepeatCount_datatype: case SMIL_Duration_datatype: case SVG_Length_datatype: case SVG_Coordinate_datatype: case SVG_Visibility_datatype: case SVG_Display_datatype: default: gf_free(value); } }
static void svg_traverse_text(GF_Node *node, void *rs, Bool is_destroy) { SVGPropertiesPointers backup_props; u32 backup_flags; GF_Matrix2D backup_matrix; GF_Matrix mx3d; GF_ChildNodeItem *child; DrawableContext *ctx; SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; SVG_Element *text = (SVG_Element *)node; SVGAllAttributes atts; u32 i,imax; Fixed * lw; if (is_destroy) { drawable_del(st->drawable); svg_reset_text_stack(st); gf_list_del(st->spans); gf_free(st); return; } if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) { svg_text_draw_2d(st, tr_state); return; } else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) { tr_state->text_parent = node; gf_font_spans_get_selection(node, st->spans, tr_state); /*and browse children*/ child = ((GF_ParentNode *) text)->children; while (child) { switch (gf_node_get_tag(child->node)) { case TAG_SVG_tspan: gf_node_traverse(child->node, tr_state); break; } child = child->next; } tr_state->text_parent = NULL; return; } gf_svg_flatten_attributes(text, &atts); if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags)) return; tr_state->in_svg_text++; tr_state->text_parent = node; if (tr_state->traversing_mode==TRAVERSE_PICK) { compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d); if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE) gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, 1, st->drawable); /*and browse children*/ child = ((GF_ParentNode *) text)->children; while (child) { switch (gf_node_get_tag(child->node)) { case TAG_SVG_tspan: gf_node_traverse(child->node, tr_state); break; } child = child->next; } memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d); tr_state->svg_flags = backup_flags; tr_state->text_parent = NULL; tr_state->in_svg_text--; return; } else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) { gf_font_spans_get_selection(node, st->spans, tr_state); memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; tr_state->text_parent = NULL; tr_state->in_svg_text--; return; } compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d); if ( (st->prev_size != tr_state->svg_props->font_size->value) || (st->prev_flags != *tr_state->svg_props->font_style) || (st->prev_anchor != *tr_state->svg_props->text_anchor) || (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) ) || tr_state->visual->compositor->reset_fonts ) { u32 mode; child = ((GF_ParentNode *) text)->children; svg_reset_text_stack(st); tr_state->text_end_x = 0; tr_state->text_end_y = 0; /*init the xml:space algo*/ tr_state->last_char_type = 0; /*initialize x and y counters - stored at the traverse level for handling tspan & co*/ if (atts.text_x) tr_state->count_x = gf_list_count(*atts.text_x); else tr_state->count_x=0; if (atts.text_y) tr_state->count_y = gf_list_count(*atts.text_y); else tr_state->count_y=0; if (atts.text_rotate) tr_state->count_rotate = gf_list_count(*atts.text_rotate); else tr_state->count_rotate=0; /*horizontal justifiers container*/ tr_state->x_anchors = gf_list_new(); /*compute length of all text blocks*/ while (child) { svg_compute_text_width(child->node, &atts, tr_state); child=child->next; } /*apply justification of all blocks*/ imax=gf_list_count(tr_state->x_anchors); for (i=0; i<imax; i++) { lw=gf_list_get(tr_state->x_anchors, i); svg_apply_text_anchor(tr_state, lw); } /*re-initialize x and y counters for final compute*/ if (atts.text_x) tr_state->count_x = gf_list_count(*atts.text_x); else tr_state->count_x=0; if (atts.text_y) tr_state->count_y = gf_list_count(*atts.text_y); else tr_state->count_y=0; if (atts.text_rotate) tr_state->count_rotate = gf_list_count(*atts.text_rotate); else tr_state->count_rotate=0; tr_state->idx_rotate = 0; tr_state->chunk_index = 0; /*initialize current text position*/ if (!tr_state->text_end_x) { SVG_Coordinate *xc = (atts.text_x ? (SVG_Coordinate *) gf_list_get(*atts.text_x, 0) : NULL); tr_state->text_end_x = (xc ? xc->value : 0); } if (!tr_state->text_end_y) { SVG_Coordinate *yc = (atts.text_y ? (SVG_Coordinate *) gf_list_get(*atts.text_y, 0) : NULL); tr_state->text_end_y = (yc ? yc->value : 0); } /*pass x and y to children*/ tr_state->text_x = atts.text_x; tr_state->text_y = atts.text_y; tr_state->text_rotate = atts.text_rotate; drawable_reset_path(st->drawable); /*switch to bounds mode, and recompute children*/ mode = tr_state->traversing_mode; tr_state->traversing_mode = TRAVERSE_GET_BOUNDS; tr_state->last_char_type = 0; child = ((GF_ParentNode *) text)->children; while (child) { svg_traverse_text_block(child->node, &atts, tr_state, st->spans); child = child->next; } tr_state->traversing_mode = mode; gf_node_dirty_clear(node, 0); drawable_mark_modified(st->drawable, tr_state); st->prev_size = tr_state->svg_props->font_size->value; st->prev_flags = *tr_state->svg_props->font_style; st->prev_anchor = *tr_state->svg_props->text_anchor; while (gf_list_count(tr_state->x_anchors)) { Fixed *f = gf_list_last(tr_state->x_anchors); gf_list_rem_last(tr_state->x_anchors); gf_free(f); } gf_list_del(tr_state->x_anchors); tr_state->x_anchors = NULL; svg_update_bounds(st); } if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) { if (!compositor_svg_is_display_off(tr_state->svg_props)) tr_state->bounds = st->bounds; } else if ((tr_state->traversing_mode == TRAVERSE_SORT) && !compositor_svg_is_display_off(tr_state->svg_props) && (*(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) { ctx = drawable_init_context_svg(st->drawable, tr_state); if (ctx) svg_finalize_sort(ctx, st, tr_state); /*and browse children*/ child = ((GF_ParentNode *) text)->children; while (child) { switch (gf_node_get_tag(child->node)) { case TAG_SVG_tspan: gf_node_traverse(child->node, tr_state); break; case TAG_SVG_switch: gf_node_traverse(child->node, tr_state); break; } child = child->next; } } tr_state->in_svg_text--; tr_state->text_parent = NULL; compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d); memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; }