Example #1
0
Bool gf_term_lock_codec(GF_Codec *codec, Bool lock, Bool trylock)
{
	Bool res = 1;
	CodecEntry *ce;
	GF_Terminal *term = codec->odm->term;

	ce = mm_get_codec(term->codecs, codec);
	if (!ce) return 0;

	if (ce->mx) {
		if (lock) {
			if (trylock) {
				res = gf_mx_try_lock(ce->mx);
			} else {
				res = gf_mx_p(ce->mx);
			}
		}
		else gf_mx_v(ce->mx);
	}
	else {
		if (lock) {
			if (trylock) {
				res = gf_mx_try_lock(term->mm_mx);
			} else {
				res = gf_mx_p(term->mm_mx);
			}
		}
		else gf_mx_v(term->mm_mx);
	}
	return res;
}
Example #2
0
void gf_term_remove_codec(GF_Terminal *term, GF_Codec *codec)
{
	u32 i;
	Bool locked;
	CodecEntry *ce;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Unregistering codec %s\n", codec->decio ? codec->decio->module_name : "RAW"));

	/*cf note above*/
	locked = gf_mx_try_lock(term->mm_mx);

	i=0;
	while ((ce = (CodecEntry*)gf_list_enum(term->codecs, &i))) {
		if (ce->dec != codec) continue;

		if (ce->thread) {
			if (ce->flags & GF_MM_CE_RUNNING) {
				ce->flags &= ~GF_MM_CE_RUNNING;
				while (! (ce->flags & GF_MM_CE_DEAD)) gf_sleep(10);
				ce->flags &= ~GF_MM_CE_DEAD;
			}
			gf_th_del(ce->thread);
			gf_mx_del(ce->mx);
		}
		if (locked) {
			gf_free(ce);
			gf_list_rem(term->codecs, i-1);
		} else {
			ce->flags |= GF_MM_CE_DISCARDED;
		}
		break;
	}
	if (locked) gf_mx_v(term->mm_mx);
	return;
}
Example #3
0
GF_EXPORT
void gf_sc_texture_destroy(GF_TextureHandler *txh)
{
	GF_Compositor *compositor = txh->compositor;
	Bool lock = gf_mx_try_lock(compositor->mx);

	gf_sc_texture_release(txh);
	if (txh->is_open) gf_sc_texture_stop(txh);
	gf_list_del_item(txh->compositor->textures, txh);

	if (lock) gf_mx_v(compositor->mx);
}
Example #4
0
void gf_term_stop_codec(GF_Codec *codec, Bool is_pause)
{
	GF_CodecCapability cap;
	Bool locked = 0;
	CodecEntry *ce;
	GF_Terminal *term = codec->odm->term;
	ce = mm_get_codec(term->codecs, codec);
	if (!ce) return;

	if (ce->mx) gf_mx_p(ce->mx);
	/*We must make sure:
		1- media codecs are synchrounously stop otherwise we could destroy the composition memory while
	the codec writes to it
		2- prevent deadlock for other codecs waiting for the scene graph
	*/
	else if (codec->CB) {
		locked = 1;
		gf_mx_p(term->mm_mx);
	} else {
		locked = gf_mx_try_lock(term->mm_mx);
	}

	if (!is_pause) {
		cap.CapCode = GF_CODEC_ABORT;
		cap.cap.valueInt = 0;
		gf_codec_set_capability(codec, cap);

		if (codec->decio && codec->odm->mo && (codec->odm->mo->flags & GF_MO_DISPLAY_REMOVE) ) {
			cap.CapCode = GF_CODEC_SHOW_SCENE;
			cap.cap.valueInt = 0;
			gf_codec_set_capability(codec, cap);
			codec->odm->mo->flags &= ~GF_MO_DISPLAY_REMOVE;
		}
	}

	/*set status directly and don't touch CB state*/
	codec->Status = GF_ESM_CODEC_STOP;
	/*don't wait for end of thread since this can be triggered within the decoding thread*/
	if (ce->flags & GF_MM_CE_RUNNING) {
		ce->flags &= ~GF_MM_CE_RUNNING;
		if (!ce->thread)
			term->cumulated_priority -= codec->Priority+1;
	}
	if (codec->CB) gf_cm_abort_buffering(codec->CB);

	if (ce->mx) gf_mx_v(ce->mx);
	/*cf note above*/
	else if (locked) gf_mx_v(term->mm_mx);
}
Example #5
0
GF_EXPORT
void gf_term_download_del(GF_DownloadSession * sess)
{
	Bool locked;
	GF_ClientService *serv;
	if (!sess) return;
	serv = (GF_ClientService *)gf_dm_sess_get_private(sess);

	/*avoid sending data back to user*/
	gf_dm_sess_abort(sess);

	locked = gf_mx_try_lock(serv->term->media_queue_mx);

	/*unregister from service*/
	gf_list_del_item(serv->dnloads, sess);

	/*same as service: this may be called in the downloader thread (typically when download fails)
	so we must queue the downloader and let the term delete it later on*/
	gf_list_add(serv->term->net_services_to_remove, sess);

	if (locked)
		gf_term_lock_media_queue(serv->term, 0);
}
Example #6
0
GF_Err gf_sr_set_size(GF_Renderer *sr, u32 NewWidth, u32 NewHeight)
{
	Bool lock_ok;
	if (!NewWidth || !NewHeight) {
		sr->override_size_flags &= ~2;
		return GF_OK;
	}
	/*EXTRA CARE HERE: the caller (user app) is likely a different thread than the renderer one, and depending on window 
	manager we may get called here as a result of a message sent to user but not yet returned */
	lock_ok = gf_mx_try_lock(sr->mx);
	
	sr->new_width = NewWidth;
	sr->new_height = NewHeight;
	sr->msg_type |= GF_SR_CFG_SET_SIZE;
	
	/*if same size only request for video setup */
	if ((sr->width == NewWidth) && (sr->height == NewHeight) ) 
		sr->msg_type |= GF_SR_CFG_WINDOWSIZE_NOTIF;
	
	if (lock_ok) gf_sr_lock(sr, 0);

	return GF_OK;
}
Example #7
0
void gf_term_add_codec(GF_Terminal *term, GF_Codec *codec)
{
	u32 i, count;
	Bool locked;
	Bool threaded;
	CodecEntry *cd;
	CodecEntry *ptr, *next;
	GF_CodecCapability cap;
	assert(codec);

	GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Registering codec %s\n", codec->decio ? codec->decio->module_name : "RAW"));

	/*caution: the mutex can be grabbed by a decoder waiting for a mutex owned by the calling thread
	this happens when several scene codecs are running concurently and triggering play/pause on media*/
	locked = gf_mx_try_lock(term->mm_mx);

	cd = mm_get_codec(term->codecs, codec);
	if (cd) goto exit;

	GF_SAFEALLOC(cd, CodecEntry);
	cd->dec = codec;
	if (!cd->dec->Priority)
		cd->dec->Priority = 1;

	/*we force audio codecs to be threaded in free mode, so that we avoid waiting in the audio renderer if another decoder is locking the main mutex
	this can happen when the audio decoder is running late*/
	if (codec->type==GF_STREAM_AUDIO) {
		threaded = 1;
	} else {
		cap.CapCode = GF_CODEC_WANTS_THREAD;
		cap.cap.valueInt = 0;
		gf_codec_get_capability(codec, &cap);
		threaded = cap.cap.valueInt;
	}

	if (threaded) cd->flags |= GF_MM_CE_REQ_THREAD;


	if (term->flags & GF_TERM_MULTI_THREAD) {
		if ((codec->type==GF_STREAM_AUDIO) || (codec->type==GF_STREAM_VISUAL)) threaded = 1;
	} else if (term->flags & GF_TERM_SINGLE_THREAD) {
		threaded = 0;
	}
	if (codec->flags & GF_ESM_CODEC_IS_RAW_MEDIA)
		threaded = 0;

	if (threaded) {
		cd->thread = gf_th_new(cd->dec->decio->module_name);
		cd->mx = gf_mx_new(cd->dec->decio->module_name);
		cd->flags |= GF_MM_CE_THREADED;
		gf_list_add(term->codecs, cd);
		goto exit;
	}

	//add codec 1- per priority 2- per type, audio being first
	//priorities inherits from Systems (5bits) so range from 0 to 31
	//we sort from MAX to MIN
	count = gf_list_count(term->codecs);
	for (i=0; i<count; i++) {
		ptr = (CodecEntry*)gf_list_get(term->codecs, i);
		if (ptr->flags & GF_MM_CE_THREADED) continue;

		//higher priority, continue
		if (ptr->dec->Priority > codec->Priority) continue;

		//same priority, put audio first
		if (ptr->dec->Priority == codec->Priority) {
			//we insert audio (0x05) before video (0x04)
			if (ptr->dec->type < codec->type) {
				gf_list_insert(term->codecs, cd, i);
				goto exit;
			}
			//same prior, same type: insert after
			if (ptr->dec->type == codec->type) {
				if (i+1==count) {
					gf_list_add(term->codecs, cd);
				} else {
					gf_list_insert(term->codecs, cd, i+1);
				}
				goto exit;
			}
			//we insert video (0x04) after audio (0x05) if next is not audio
			//last one
			if (i+1 == count) {
				gf_list_add(term->codecs, cd);
				goto exit;
			}
			next = (CodecEntry*)gf_list_get(term->codecs, i+1);
			//# priority level, insert
			if ((next->flags & GF_MM_CE_THREADED) || (next->dec->Priority != codec->Priority)) {
				gf_list_insert(term->codecs, cd, i+1);
				goto exit;
			}
			//same priority level and at least one after : continue
			continue;
		}
		gf_list_insert(term->codecs, cd, i);
		goto exit;
	}
	//if we got here, first in list
	gf_list_add(term->codecs, cd);

exit:
	if (locked) gf_mx_v(term->mm_mx);
	return;
}
Example #8
0
/*dispatch the AU in the DB*/
static void Channel_DispatchAU(GF_Channel *ch, u32 duration)
{
	u32 time;
	GF_DBUnit *au;

	if (!ch->buffer || !ch->len) {
		if (ch->buffer) {
			gf_free(ch->buffer);
			ch->buffer = NULL;
		}
		return;
	}

	au = gf_db_unit_new();
	if (!au) {
		gf_free(ch->buffer);
		ch->buffer = NULL;
		ch->len = 0;
		return;
	}

	au->CTS = ch->CTS;
	au->DTS = ch->DTS;
	if (ch->IsRap) au->flags |= GF_DB_AU_RAP;
	if (ch->CTS_past_offset) {
		au->CTS = ch->CTS_past_offset;
		au->flags |= GF_DB_AU_CTS_IN_PAST;
		ch->CTS_past_offset = 0;
	}
	if (ch->no_timestamps) {
		au->flags |= GF_DB_AU_NO_TIMESTAMPS;
		ch->no_timestamps=0;
	}
	au->data = ch->buffer;
	au->dataLength = ch->len;
	au->PaddingBits = ch->padingBits;

	ch->IsRap = 0;
	ch->padingBits = 0;
	au->next = NULL;
	ch->buffer = NULL;

	if (ch->len + ch->media_padding_bytes != ch->allocSize) {
		au->data = (char*)gf_realloc(au->data, sizeof(char) * (au->dataLength + ch->media_padding_bytes));
	}
	if (ch->media_padding_bytes) memset(au->data + au->dataLength, 0, sizeof(char)*ch->media_padding_bytes);
	
	ch->len = ch->allocSize = 0;

	gf_es_lock(ch, 1);

	if (ch->service && ch->service->cache) {
		GF_SLHeader slh;
		memset(&slh, 0, sizeof(GF_SLHeader));
		slh.accessUnitEndFlag = slh.accessUnitStartFlag = 1;
		slh.compositionTimeStampFlag = slh.decodingTimeStampFlag = 1;
		slh.decodingTimeStamp = ch->net_dts;
		slh.compositionTimeStamp = ch->net_cts;
		slh.randomAccessPointFlag = (au->flags & GF_DB_AU_RAP) ? 1 : 0;
		ch->service->cache->Write(ch->service->cache, ch, au->data, au->dataLength, &slh);
	}

	if (!ch->AU_buffer_first) {
		ch->AU_buffer_first = au;
		ch->AU_buffer_last = au;
		ch->AU_Count = 1;
	} else {
		if (ch->AU_buffer_last->DTS<=au->DTS) {
			ch->AU_buffer_last->next = au;
			ch->AU_buffer_last = ch->AU_buffer_last->next;
		}
		/*enable deinterleaving only for audio channels (some video transport may not be able to compute DTS, cf MPEG1-2/RTP)
		HOWEVER, we must recompute a monotone increasing DTS in case the decoder does perform frame reordering
		in which case the DTS is used for presentation time!!*/
		else if (ch->esd->decoderConfig->streamType!=GF_STREAM_AUDIO) {
#if 0
			GF_DBUnit *au_prev, *ins_au;
			u32 DTS;
#endif
			au->DTS = 0;
			/*append AU*/
			ch->AU_buffer_last->next = au;
			ch->AU_buffer_last = ch->AU_buffer_last->next;

#if 0
			GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] Media deinterleaving OD %d ch %d\n", ch->esd->ESID, ch->odm->OD->objectDescriptorID));

			DTS = au->DTS;
			au_prev = ch->AU_buffer_first;
			/*locate first AU in buffer with DTS greater than new unit CTS*/
			while (au_prev->next && (au_prev->DTS < DTS) ) au_prev = au_prev->next;
			/*remember insertion point*/
			ins_au = au_prev;
			/*shift all following frames DTS*/
			while (au_prev->next) {
				au_prev->next->DTS = au_prev->DTS;
				au_prev = au_prev->next;
			}
			/*and apply*/
			ins_au->DTS = DTS;
#endif
		} else {
			GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] Audio deinterleaving OD %d ch %d\n", ch->esd->ESID, ch->odm->OD->objectDescriptorID));
			/*de-interleaving of AUs*/
			if (ch->AU_buffer_first->DTS > au->DTS) {
				au->next = ch->AU_buffer_first;
				ch->AU_buffer_first = au;
			} else {
				GF_DBUnit *au_prev = ch->AU_buffer_first;
				while (au_prev->next && au_prev->next->DTS<au->DTS) {
					au_prev = au_prev->next;
				}
				assert(au_prev);
				if (au_prev->next->DTS==au->DTS) {
					gf_free(au->data);
					gf_free(au);
				} else {
					au->next = au_prev->next;
					au_prev->next = au;
				}
			}
		}
		ch->AU_Count += 1;
	}

	Channel_UpdateBufferTime(ch);
	ch->au_duration = 0;
	if (duration) ch->au_duration = (u32) ((u64)1000 * duration / ch->ts_res);

	GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d - Dispatch AU DTS %d - CTS %d - size %d time %d Buffer %d Nb AUs %d - First AU relative timing %d\n", ch->esd->ESID, au->DTS, au->CTS, au->dataLength, gf_clock_real_time(ch->clock), ch->BufferTime, ch->AU_Count, ch->AU_buffer_first ? ch->AU_buffer_first->DTS - gf_clock_time(ch->clock) : 0 ));

	/*little optimisation: if direct dispatching is possible, try to decode the AU
	we must lock the media scheduler to avoid deadlocks with other codecs accessing the scene or 
	media resources*/
	if (ch->dispatch_after_db) {
		u32 retry = 100;
		u32 current_frame;
		GF_Terminal *term = ch->odm->term;
		ch_buffer_off(ch);

		gf_es_lock(ch, 0);
		if (gf_mx_try_lock(term->mm_mx)) {
			switch (ch->esd->decoderConfig->streamType) {
			case GF_STREAM_OD:
				gf_codec_process(ch->odm->subscene->od_codec, 100);
				break;
			case GF_STREAM_SCENE:
				if (ch->odm->codec) 
					gf_codec_process(ch->odm->codec, 100);
				else
					gf_codec_process(ch->odm->subscene->scene_codec, 100);
				break;
			}
			gf_mx_v(term->mm_mx);
		}
		gf_es_lock(ch, 1);

		current_frame = term->compositor->frame_number;
		/*wait for initial setup to complete before giving back the hand to the caller service*/
		while (retry) {
			/*Scene bootstrap: if the scene is attached, wait for first frame to complete so that initial PLAY on
			objects can be evaluated*/
			if (term->compositor->scene && (term->compositor->frame_number==current_frame) ) {
				retry--;
				gf_sleep(1);
				continue;
			}
			/*Media bootstrap: wait for all pending requests on media objects are processed*/
			if (gf_list_count(term->media_queue)) {
				retry--;
				gf_sleep(1);
				continue;
			}
			break;
		}
	}

	time = gf_term_get_time(ch->odm->term);
	if (ch->BufferOn) {
		ch->last_au_time = time;
		Channel_UpdateBuffering(ch, 1);
	} else {
		/*trigger the data progress every 500 ms*/
		if (ch->last_au_time + 500 > time) {
			gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_PROGRESS);
			ch->last_au_time = time;
		}
	}

	gf_es_lock(ch, 0);
}
Example #9
0
/*special handling of decoders not using ESM*/
static GF_Err PrivateScene_Process(GF_Codec *codec, u32 TimeAvailable)
{
	Bool resume_clock;
	u32 now;
	GF_Channel *ch;
	GF_Scene *scene_locked;
	GF_SceneDecoder *sdec = (GF_SceneDecoder *)codec->decio;
	GF_Err e = GF_OK;

	/*muting systems codec means we don't decode until mute is off - likely there will be visible however
	there is no other way to decode system AUs without modifying the content, which is what mute is about on visual...*/
	if (codec->Muted) return GF_OK;

	if (codec->Status == GF_ESM_CODEC_EOS) {
		gf_term_stop_codec(codec);
		return GF_OK;
	}

	scene_locked = codec->odm->subscene ? codec->odm->subscene : codec->odm->parentscene;

	ch = (GF_Channel*)gf_list_get(codec->inChannels, 0);
	if (!ch) return GF_OK;
	resume_clock = 0;
	/*init channel clock*/
	if (!ch->IsClockInit) {
		Bool started;
		/*signal seek*/
		if (!gf_mx_try_lock(scene_locked->root_od->term->compositor->mx)) return GF_OK;
		gf_es_init_dummy(ch);

		sdec->ProcessData(sdec, NULL, 0, ch->esd->ESID, -1, GF_CODEC_LEVEL_NORMAL);
		gf_mx_v(scene_locked->root_od->term->compositor->mx);
		started = gf_clock_is_started(ch->clock);
		/*let's be nice to the scene loader (that usually involves quite some parsing), pause clock while
		parsing*/
		gf_clock_pause(ch->clock);
		codec->last_unit_dts = 0;
		if (!started) return GF_OK;
	}

	codec->odm->current_time = codec->last_unit_cts = gf_clock_time(codec->ck);

	/*lock scene*/
	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[PrivateDec] Codec %s Processing at %d\n", sdec->module_name , codec->odm->current_time));

	if (!gf_mx_try_lock(scene_locked->root_od->term->compositor->mx)) return GF_OK;
	now = gf_term_get_time(codec->odm->term);
	e = sdec->ProcessData(sdec, NULL, 0, ch->esd->ESID, codec->odm->current_time, GF_CODEC_LEVEL_NORMAL);
	now = gf_term_get_time(codec->odm->term) - now;
	codec->last_unit_dts ++;
	/*resume on error*/
	if (e && (codec->last_unit_dts<2) ) {
		gf_clock_resume(ch->clock);
		codec->last_unit_dts = 2;
	}
	/*resume clock on 2nd decode (we assume parsing is done in 2 steps, one for first frame display, one for complete parse)*/
	else if (codec->last_unit_dts==2) {
		gf_clock_resume(ch->clock);
	}

	codec_update_stats(codec, 0, now);

	gf_mx_v(scene_locked->root_od->term->compositor->mx);

	if (e==GF_EOS) {
		/*first end of stream, evaluate duration*/
		//if (!codec->odm->duration) gf_odm_set_duration(codec->odm, ch, codec->odm->current_time);
		gf_es_on_eos(ch);
		return GF_OK;
	}
	return e;
}
Example #10
0
static GF_Err SystemCodec_Process(GF_Codec *codec, u32 TimeAvailable)
{
	GF_DBUnit *AU;
	GF_Channel *ch;
	u32 now, obj_time, mm_level, au_time, cts;
	GF_Scene *scene_locked;
	Bool check_next_unit;
	GF_SceneDecoder *sdec = (GF_SceneDecoder *)codec->decio;
	GF_Err e = GF_OK;

	scene_locked = NULL;

	/*for resync, if needed - the logic behind this is that there is no composition memory on sytems codecs so
	"frame dropping" is done by preventing the compositor from redrawing after an update and decoding following AU
	so that the compositor is always woken up once all late systems AUs are decoded. This flag is overriden when
	seeking*/
	check_next_unit = (codec->odm->term->flags & GF_TERM_SYSDEC_RESYNC) ? 1 : 0;

check_unit:

	/*muting systems codec means we don't decode until mute is off - likely there will be visible however
	there is no other way to decode system AUs without modifying the content, which is what mute is about on visual...*/
	if (codec->Muted) goto exit;

	/*fetch next AU in DTS order for this codec*/
	Decoder_GetNextAU(codec, &ch, &AU);

	/*no active channel return*/
	if (!AU || !ch) {
		/*if the codec is in EOS state, move to STOP*/
		if (codec->Status == GF_ESM_CODEC_EOS) {
			GF_CodecCapability cap;
			cap.CapCode = GF_CODEC_MEDIA_NOT_OVER;
			cap.cap.valueInt = 0;
			sdec->GetCapabilities(codec->decio, &cap);
			if (!cap.cap.valueInt) {
				gf_term_stop_codec(codec);
				if ((codec->type==GF_STREAM_OD) && (codec->nb_dec_frames==1)) {
					/*this is just by safety, since seeking is only allowed when a single clock is present
					in the scene*/
					if (gf_list_count(codec->odm->net_service->Clocks)==1)
						codec->odm->subscene->static_media_ressources=1;
				}
			}
		}
		goto exit;
	}

#ifndef GPAC_DISABLE_VRML
	if (ch && ch->odm->media_ctrl && !ch->odm->media_ctrl->media_speed)
		goto exit;
#endif

	/*get the object time*/
	obj_time = gf_clock_time(codec->ck);

	/*clock is not started*/
//	if (ch->first_au_fetched && !gf_clock_is_started(ch->clock)) goto exit;

	/*check timing based on the input channel and main FPS*/
	if (AU->DTS > obj_time /*+ codec->odm->term->half_frame_duration*/) goto exit;

	cts = AU->CTS;
	/*in cases where no CTS was set for the BIFS (which may be interpreted as "now", although not compliant), use the object clock*/
	if (AU->flags & GF_DB_AU_NO_TIMESTAMPS) au_time = obj_time;
	/*case where CTS is in the past (carousels) */
	else if (AU->flags & GF_DB_AU_CTS_IN_PAST) {
		au_time = - (s32) AU->CTS;
		cts = AU->DTS;
	}
	/*regular case, SFTime will be from CTS (since DTS == CTS)*/
	else au_time = AU->DTS;

	/*check seeking and update timing - do NOT use the base layer, since BIFS streams may depend on other
	streams not on the same clock*/
	if (codec->last_unit_cts == cts) {
		/*seeking for systems is done by not releasing the graph until seek is done*/
		check_next_unit = 1;
		mm_level = GF_CODEC_LEVEL_SEEK;

	}
	/*set system stream timing*/
	else {
		codec->last_unit_cts = AU->CTS;
		/*we're droping the frame*/
		if (scene_locked) codec->nb_droped ++;
		mm_level = GF_CODEC_LEVEL_NORMAL;
	}

	/*lock scene*/
	if (!scene_locked) {
		scene_locked = codec->odm->subscene ? codec->odm->subscene : codec->odm->parentscene;
		if (!gf_mx_try_lock(scene_locked->root_od->term->compositor->mx)) 
			return GF_OK;
		/*if terminal is paused, force step-mode: it won't hurt in regular pause/play and ensures proper frame dumping*/
		if (codec->odm->term->play_state) codec->odm->term->compositor->step_mode=1;
	}

	/*current media time for system objects is the clock time, since the media is likely to have random
	updates in time*/
	codec->odm->current_time = gf_clock_time(codec->ck);

	now = gf_term_get_time(codec->odm->term);
	e = sdec->ProcessData(sdec, AU->data, AU->dataLength, ch->esd->ESID, au_time, mm_level);
	now = gf_term_get_time(codec->odm->term) - now;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] ODM%d#CH%d at %d decoded AU TS %d in %d ms\n", sdec->module_name, codec->odm->OD->objectDescriptorID, ch->esd->ESID, codec->odm->current_time, AU->CTS, now));

	codec_update_stats(codec, AU->dataLength, now);
	codec->prev_au_size = AU->dataLength;

	/*destroy this AU*/
	gf_es_drop_au(ch);

	if (e) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SysDec] Codec %s AU CTS %d Decode error %s\n", sdec->module_name , cts, gf_error_to_string(e) ));
		if (e<0) ch->stream_state = 2;
		goto exit;
	}

	/*in broadcast mode, generate a scene if none is available*/
	if (codec->ck->no_time_ctrl) {
		GF_Scene *scene = codec->odm->subscene ? codec->odm->subscene : codec->odm->parentscene;

		/*static OD resources (embedded in ESD) in broadcast mode, reset time*/
		if (codec->flags & GF_ESM_CODEC_IS_STATIC_OD) gf_clock_reset(codec->ck);
		/*generate a temp scene if none is in place*/
		if (scene->graph_attached != 1) {
			Bool prev_dyn = scene->is_dynamic_scene;
			scene->is_dynamic_scene = 1;
			gf_scene_regenerate(scene);
			scene->graph_attached = 2;
			scene->is_dynamic_scene = prev_dyn;
			GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[Decoder] Got OD resources before scene - generating temporary scene\n"));
		}
	}

	/*if no release restart*/
	if (check_next_unit) goto check_unit;

exit:
	if (scene_locked) {
		gf_mx_v(scene_locked->root_od->term->compositor->mx);
	}
	return e;
}
Example #11
0
void gf_term_stop_codec(GF_Codec *codec, Bool is_pause)
{
	GF_CodecCapability cap;
	Bool locked = 0;
	CodecEntry *ce;
	GF_Terminal *term = codec->odm->term;
	ce = mm_get_codec(term->codecs, codec);
	if (!ce) return;

	if (ce->mx) gf_mx_p(ce->mx);
	/*We must make sure:
		1- media codecs are synchrounously stop otherwise we could destroy the composition memory while
	the codec writes to it
		2- prevent deadlock for other codecs waiting for the scene graph
	*/
	else if (codec->CB) {
		locked = 1;
		gf_mx_p(term->mm_mx);
	} else {
		locked = gf_mx_try_lock(term->mm_mx);
	}

	if (!is_pause) {
		cap.CapCode = GF_CODEC_ABORT;
		cap.cap.valueInt = 0;
		gf_codec_set_capability(codec, cap);

		if (codec->decio && codec->odm->mo && (codec->odm->mo->flags & GF_MO_DISPLAY_REMOVE) ) {
			cap.CapCode = GF_CODEC_SHOW_SCENE;
			cap.cap.valueInt = 0;
			gf_codec_set_capability(codec, cap);
			codec->odm->mo->flags &= ~GF_MO_DISPLAY_REMOVE;
		}
	}

	/*for audio codec force CB to stop state to discard any pending AU. Not doing so would lead to a wrong estimation of the clock drift
	when resuming the object*/
	if (codec->type==GF_STREAM_AUDIO) {
		gf_codec_set_status(codec, GF_ESM_CODEC_STOP);
	}
	//if video is in a dynamic scene, reset the CB if user stop (eg codec was not in EOS). Otherwise (bifs,svg) we may want to keep the last decoded image
	else if ((codec->Status<GF_ESM_CODEC_EOS) && codec->odm && codec->odm->parentscene && codec->odm->parentscene->is_dynamic_scene && codec->CB && (codec->CB->Capacity>1)) {
		gf_codec_set_status(codec, GF_ESM_CODEC_STOP);
	}
	/*otherwise set status directly and don't touch CB state*/
	else {
		codec->Status = GF_ESM_CODEC_STOP;
	}

	/*don't wait for end of thread since this can be triggered within the decoding thread*/
	if (ce->flags & GF_MM_CE_RUNNING) {
		ce->flags &= ~GF_MM_CE_RUNNING;
		if (!ce->thread)
			term->cumulated_priority -= codec->Priority+1;
	}
	if (codec->CB) gf_cm_abort_buffering(codec->CB);

	if (ce->mx) gf_mx_v(ce->mx);
	/*cf note above*/
	else if (locked) gf_mx_v(term->mm_mx);
}
Example #12
0
void MPEGVSensorCallback( void* ptr, const char* data)
{
	GF_BitStream *bs;
	char *buf;
	u32 buf_size;
	float x, y, z, a, b;
    struct __input_device * dr = (struct __input_device *)ptr;
	MPEGVSCTX;

    if (!gf_mx_try_lock(rc->mx))
        return;

	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);

	if ( rc->sensorIOSType == SENSOR_ACCELEROMETER
			|| rc->sensorIOSType == SENSOR_GYROSCOPE
			//|| rc->sensorIOSType == 3
			|| rc->sensorIOSType == SENSOR_MAGNETOMETER )
	{
		sscanf(data, "%f;%f;%f;", &x, &y, &z);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_float(bs, x);
		gf_bs_write_float(bs, y);
		gf_bs_write_float(bs, z);
	}
	else
	if ( rc->sensorIOSType == 5
			|| rc->sensorIOSType == 6 )
	{
		sscanf(data, "%f;", &x);

		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_float(bs, x);
	}
	else
	if ( rc->sensorIOSType == 11 )
	{
		sscanf(data, "%f;%f;%f;", &x, &y, &z);

		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_float(bs, x);
		gf_bs_write_float(bs, y);
		gf_bs_write_float(bs, z);
		/*gf_bs_write_float(bs, q);*/
	}
	else
	if ( rc->sensorIOSType == SENSOR_GPS )
	{
		sscanf(data, "%f;%f;%f;%f;%f;", &x, &y, &z, &a, &b);

		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_float(bs, x);
		gf_bs_write_float(bs, y);
		gf_bs_write_float(bs, z);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_float(bs, a);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_float(bs, b);
		/*gf_bs_write_float(bs, q);*/
	}

	gf_bs_align(bs);
	gf_bs_get_content(bs, &buf, &buf_size);
	gf_bs_del(bs);

	dr->DispatchFrame(dr, (u8*)buf, buf_size);
	gf_free(buf);

    gf_mx_v(rc->mx);
}
Example #13
0
static Bool gf_sr_on_event_ex(GF_Renderer *sr , GF_Event *event, Bool from_user)
{
	/*not assigned yet*/
	if (!sr || !sr->visual_renderer) return 0;
	/*we're reconfiguring the video output, cancel all messages*/
	if (sr->msg_type & GF_SR_IN_RECONFIG) return 0;

	switch (event->type) {
	case GF_EVENT_REFRESH:
		if (!sr->draw_next_frame) sr->draw_next_frame = 2;
		break;
	case GF_EVENT_VIDEO_SETUP:
		gf_sr_reset_graphics(sr);
		break;
	case GF_EVENT_SIZE:
		/*resize message from plugin: if we own the output, resize*/
		if (!sr->user->os_window_handler) {
			/*EXTRA CARE HERE: the caller (video output) is likely a different thread than the renderer one, and the
			renderer may be locked on the video output (flush or whatever)!!
			*/
			Bool lock_ok = gf_mx_try_lock(sr->mx);
			sr->new_width = event->size.width;
			sr->new_height = event->size.height;
			sr->msg_type |= GF_SR_CFG_SET_SIZE;
			if (lock_ok) gf_sr_lock(sr, 0);
		}
		/*otherwise let the user decide*/
		else {
			GF_USER_SENDEVENT(sr->user, event);
		}
		break;

	case GF_EVENT_KEYDOWN:
	case GF_EVENT_KEYUP:
		switch (event->key.key_code) {
		case GF_KEY_SHIFT: 
			if (event->type==GF_EVENT_KEYDOWN) {
				sr->key_states |= GF_KEY_MOD_SHIFT; 
			} else {
				sr->key_states &= ~GF_KEY_MOD_SHIFT; 
			}
			break;
		case GF_KEY_CONTROL: 
			if (event->type==GF_EVENT_KEYDOWN) {
				sr->key_states |= GF_KEY_MOD_CTRL; 
			} else {
				sr->key_states &= ~GF_KEY_MOD_CTRL; 
			}
			break;
		case GF_KEY_ALT: 
			if (event->type==GF_EVENT_KEYDOWN) {
				sr->key_states |= GF_KEY_MOD_ALT;
			} else {
				sr->key_states &= ~GF_KEY_MOD_ALT;
			}
			break;
		}
		event->key.flags |= sr->key_states;
		/*key sensor*/
		if (sr->term && (sr->interaction_level & GF_INTERACT_INPUT_SENSOR) ) {
			gf_term_keyboard_input(sr->term, event->key.key_code, event->key.hw_code, (event->type==GF_EVENT_KEYUP) ? 1 : 0);
		}		
		return SR_UserInputIntern(sr, event, from_user);

	case GF_EVENT_TEXTINPUT:
		if (sr->term && (sr->interaction_level & GF_INTERACT_INPUT_SENSOR) )
			gf_term_string_input(sr->term , event->character.unicode_char);
		return SR_UserInputIntern(sr, event, from_user);
	/*switch fullscreen off!!!*/
	case GF_EVENT_SHOWHIDE:
		gf_sr_set_option(sr, GF_OPT_FULLSCREEN, !sr->fullscreen);
		break;

	case GF_EVENT_SET_CAPTION:
		sr->video_out->ProcessEvent(sr->video_out, event);
		break;

	case GF_EVENT_MOUSEMOVE:
		event->mouse.button = 0;
	case GF_EVENT_MOUSEDOWN:
	case GF_EVENT_MOUSEUP:
	case GF_EVENT_MOUSEWHEEL:
		event->mouse.key_states = sr->key_states;
		return SR_UserInputIntern(sr, event, from_user);

	/*when we process events we don't forward them to the user*/
	default:
		GF_USER_SENDEVENT(sr->user, event);
		break;
	}
	return 1;
}