Пример #1
0
/*Reset composition memory. Note we don't reset the content of each frame since it would lead to green frames 
when using bitmap (visual), where data is not cached*/
void gf_cm_reset(GF_CompositionMemory *cb)
{
	GF_CMUnit *cu;

	gf_odm_lock(cb->odm, 1);
	cu = cb->input;
	cu->RenderedLength = 0;
	if (cu->dataLength && cb->odm->raw_frame_sema)  {
		cu->dataLength = 0;
		gf_sema_notify(cb->odm->raw_frame_sema, 1);
	}
	
	cu->dataLength = 0;
	cu->TS = 0;
	cu = cu->next;
	while (cu != cb->input) {
		cu->RenderedLength = 0;
		cu->TS = 0;
		cu->dataLength = 0;
		cu = cu->next;
	}
	cb->UnitCount = 0;
	cb->HasSeenEOS = 0;

	if (cb->odm->mo) cb->odm->mo->timestamp = 0;

	cb->output = cb->input;
	gf_odm_lock(cb->odm, 0);
}
Пример #2
0
void gf_cm_unlock_input(GF_CompositionMemory *cb, u32 TS, u32 NbBytes)
{
	GF_CMUnit *cu;

	/*nothing dispatched, ignore*/
	if (!NbBytes) return;
	gf_odm_lock(cb->odm, 1);

	/*insert/swap this CU*/
	cu = LocateAndOrderUnit(cb, TS);

	if (cu) {
		/*if the CU already has data, this is spatial scalability so same num buffers*/
		if (!cu->dataLength) cb->UnitCount += 1;
		cu->dataLength = NbBytes;
		cu->RenderedLength = 0;

		/*turn off buffering - this must be done now rather than when fetching first output frame since we're not 
		sure output is fetched (Switch node, ...)*/
		if ( (cb->Status == CB_BUFFER) && (cb->UnitCount >= cb->Capacity) ) {
			/*done with buffering, signal to the clock (ONLY ONCE !)*/
			cb->Status = CB_BUFFER_DONE;
			gf_clock_buffer_off(cb->odm->codec->ck);
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ODM%d: buffering off at %d (nb buffering on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
		} 

		/*since a new CU is here notify the renderer*/
		if ((cb->odm->codec->type==GF_STREAM_VISUAL) && cb->odm->mo && cb->odm->mo->num_open) {
			gf_term_invalidate_renderer(cb->odm->term);
		}
	}
	gf_odm_lock(cb->odm, 0);
}
Пример #3
0
/*resize buffers (blocking)*/
void gf_cm_resize(GF_CompositionMemory *cb, u32 newCapacity)
{
	GF_CMUnit *cu;
	if (!newCapacity) return;

	/*lock buffer*/
	gf_odm_lock(cb->odm, 1);
	cu = cb->input;

	cb->UnitSize = newCapacity;
	if (!cb->no_allocation) {
		my_large_gf_free(cu->data);
		cu->data = (char*) my_large_alloc(newCapacity);
	} else {
		cu->data = NULL;
		if (cu->dataLength && cb->odm->raw_frame_sema) {
			cu->dataLength = 0;
			gf_sema_notify(cb->odm->raw_frame_sema, 1);
		}
	}
	cu = cu->next;
	while (cu != cb->input) {
		if (!cb->no_allocation) {
			my_large_gf_free(cu->data);
			cu->data = (char*) my_large_alloc(newCapacity);
		} else {
			cu->data = NULL;
		}
		cu = cu->next;
	}

	gf_odm_lock(cb->odm, 0);
}
Пример #4
0
void gf_cm_reset_timing(GF_CompositionMemory *cb)
{
	GF_CMUnit *cu = cb->input;

	gf_odm_lock(cb->odm, 1);
	cu->TS = 0;
	cu = cu->next;
	while (cu != cb->input) {
		cu->TS = 0;
		cu = cu->next;
	}
	if (cb->odm->mo) cb->odm->mo->timestamp = 0;
	gf_odm_lock(cb->odm, 0);
}
Пример #5
0
void gf_cm_set_status(GF_CompositionMemory *cb, u32 Status)
{
	if (cb->Status == Status)
		return;

	gf_odm_lock(cb->odm, 1);
	/*if we're asked for play, trigger on buffering*/
	if (Status == CB_PLAY) {
		switch (cb->Status) {
		case CB_STOP:
			if (cb->odm->disable_buffer_at_next_play) {
				cb->Status = CB_BUFFER_DONE;
			} else {
				cb->Status = CB_BUFFER;
				gf_clock_buffer_on(cb->odm->codec->ck);
				GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] CB status changed - ODM%d: buffering on at OTB %d (STB %d) (nb wait on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_clock_time(cb->odm->codec->ck),gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
			}
			break;
		case CB_PAUSE:
			cb->Status = CB_PLAY;
			break;
		/*this should never happen (calling play while already buffering ...)*/
		case CB_BUFFER:
			cb->LastRenderedTS = 0;
			break;
		default:
			cb->Status = Status;
			break;
		}
	} else {
		cb->LastRenderedTS = 0;
		if (cb->Status == CB_BUFFER) {
			gf_clock_buffer_off(cb->odm->codec->ck);
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] CB status changed - ODM%d: buffering off at OTB %u (STB %d) (nb wait on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_clock_time(cb->odm->codec->ck), gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
		}
		if (Status == CB_STOP) {
			gf_cm_reset(cb);
			cb->LastRenderedTS = 0;
		}
		cb->Status = Status;
		if (Status==CB_BUFFER) {
			gf_clock_buffer_on(cb->odm->codec->ck);
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] CB status changed - ODM%d: buffering on at OTB %d (STB %d) (nb wait on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_clock_time(cb->odm->codec->ck), gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
		}
	}

	gf_odm_lock(cb->odm, 0);

}
Пример #6
0
void gf_cm_unlock_input(GF_CompositionMemory *cb, GF_CMUnit *cu, u32 cu_size, Bool codec_reordering)
{
	/*nothing dispatched, ignore*/
	if (!cu_size || (!cu->data && !cu->frame && !cb->pY) ) {
		if (cu->frame) {
			cu->frame->Release(cu->frame);
			cu->frame = NULL;
		}
		cu->dataLength = 0;
		cu->TS = 0;
		return;
	}
	gf_odm_lock(cb->odm, 1);
//		assert(cu->frame);

	if (codec_reordering) {
		cb->input = cb->input->next;
	} else {
		cu = gf_cm_reorder_unit(cb, cu, codec_reordering);
		assert(cu);
	}

	if (cu) {
		/*FIXME - if the CU already has data, this is spatial scalability so same num buffers*/
		if (!cu->dataLength) cb->UnitCount += 1;
		cu->dataLength = cu_size;
		cu->RenderedLength = 0;

		/*turn off buffering for audio - this must be done now rather than when fetching first output frame since we're not
		sure output is fetched (Switch node, ...)*/
		if ( (cb->Status == CB_BUFFER) && (cb->UnitCount >= cb->Capacity) ) {
			/*done with buffering*/
			cb->Status = CB_BUFFER_DONE;
			
			//for audio, turn off buffering now. For video, we will wait for the first frame to be drawn
			if (cb->odm->codec->type == GF_STREAM_AUDIO)
				cb_set_buffer_off(cb);
		}

		//new FPS regulation doesn't need this signaling
#if 0
		/*since a new CU is here notify the compositor*/
		if ((cb->odm->codec->type==GF_STREAM_VISUAL) && cb->odm->mo && cb->odm->mo->num_open) {
			gf_term_invalidate_compositor(cb->odm->term);
		}
#endif
	}
	gf_odm_lock(cb->odm, 0);
}
Пример #7
0
void gf_cm_set_eos(GF_CompositionMemory *cb)
{
	gf_odm_lock(cb->odm, 1);
	/*we may have a pb if the stream is so short that the EOS is signaled 
	while we're buffering. In this case we shall turn the clock on and 
	keep a trace of the EOS notif*/
	if (cb->Status == CB_BUFFER) {
		cb->Status = CB_BUFFER_DONE;
		gf_clock_buffer_off(cb->odm->codec->ck);
		GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ODM%d: buffering off at %d (nb buffering on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
	}
	cb->HasSeenEOS = 1;
	gf_term_invalidate_renderer(cb->odm->term);
	gf_odm_lock(cb->odm, 0);
}
Пример #8
0
void gf_cm_del(GF_CompositionMemory *cb)
{
	gf_odm_lock(cb->odm, 1);
	/*may happen when CB is destroyed right after creation in case*/
	if (cb->Status == CB_BUFFER) {
		gf_clock_buffer_off(cb->odm->codec->ck);
		GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ODM%d: buffering off at %d (nb buffering on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
	}
	
	/*break the loop and destroy*/
	cb->input->prev->next = NULL;
	gf_cm_unit_del(cb->input);
	gf_odm_lock(cb->odm, 0);
	free(cb);
}
Пример #9
0
void gf_cm_unlock_input(GF_CompositionMemory *cb, GF_CMUnit *cu, u32 cu_size, Bool codec_reordering)
{
	/*nothing dispatched, ignore*/
	if (!cu_size) {
		cu->dataLength = 0;
		cu->TS = 0;
		return;
	}
	gf_odm_lock(cb->odm, 1);

	if (cu->TS < cb->input->TS)
		cu = cu;


	if (codec_reordering) {
		cb->input = cb->input->next;
	} else {
		cu = gf_cm_reorder_unit(cb, cu, codec_reordering);
		assert(cu);
	}

	if (cu) {
		/*FIXME - if the CU already has data, this is spatial scalability so same num buffers*/
		if (!cu->dataLength) cb->UnitCount += 1;
		cu->dataLength = cu_size;
		cu->RenderedLength = 0;

		/*turn off buffering - this must be done now rather than when fetching first output frame since we're not 
		sure output is fetched (Switch node, ...)*/
		if ( (cb->Status == CB_BUFFER) && (cb->UnitCount >= cb->Capacity) ) {
			/*done with buffering, signal to the clock (ONLY ONCE !)*/
			cb->Status = CB_BUFFER_DONE;
			gf_clock_buffer_off(cb->odm->codec->ck);
			cb->odm->codec->ck->data_timeout = 0;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ODM%d: buffering off at %d (nb buffering on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));

			gf_term_service_media_event(cb->odm->parentscene->root_od, GF_EVENT_MEDIA_CANPLAY);
		} 

		/*since a new CU is here notify the compositor*/
		if ((cb->odm->codec->type==GF_STREAM_VISUAL) && cb->odm->mo && cb->odm->mo->num_open) {
			gf_term_invalidate_compositor(cb->odm->term);
		}
	}
	gf_odm_lock(cb->odm, 0);
}
Пример #10
0
/*resize buffers (blocking)*/
void gf_cm_reinit(GF_CompositionMemory *cb, u32 UnitSize, u32 Capacity)
{
	GF_CMUnit *cu, *prev;
	u32 i;
	if (!Capacity || !UnitSize) return;

	gf_odm_lock(cb->odm, 1);
	if (cb->input){
	  /*break the loop and destroy*/
	  cb->input->prev->next = NULL;
	  gf_cm_unit_del(cb->input, cb->no_allocation);
	  cb->input = NULL;
	}

	cu = NULL;
	cb->Capacity = Capacity;
	cb->UnitSize = UnitSize;

	prev = NULL;
	i = 1;
	while (Capacity) {
		cu = gf_cm_unit_new();
		if (!prev) {
			cb->input = cu;
		} else {
			prev->next = cu;
			cu->prev = prev;
		}
		cu->dataLength = 0;
		if (cb->no_allocation) {
			cu->data = NULL;
		} else {
			cu->data = (char*)my_large_alloc(UnitSize);
		}
		prev = cu;
		Capacity --;
		i++;
	}
	cu->next = cb->input;
	cb->input->prev = cu;
	cb->output = cb->input;
	gf_odm_lock(cb->odm, 0);
}
Пример #11
0
/*resize buffers (blocking)*/
void gf_cm_resize(GF_CompositionMemory *cb, u32 newCapacity)
{
	GF_CMUnit *cu;
	if (!newCapacity) return;

	/*lock buffer*/
	gf_odm_lock(cb->odm, 1);
	cu = cb->input;

	cb->UnitSize = newCapacity;
	/*don't touch any existing memory (it may happen on the fly with audio)*/
	cu->data = (char*)realloc(cu->data, sizeof(char)*newCapacity);
	cu = cu->next;
	while (cu != cb->input) {
		cu->data = (char*)realloc(cu->data, sizeof(char)*newCapacity);
		cu = cu->next;
	}

	gf_odm_lock(cb->odm, 0);
}
Пример #12
0
void gf_mo_unload_xlink_resource(GF_Node *node, GF_MediaObject *mo)
{
	if (!mo) return;
	if (!gf_odm_lock_mo(mo)) return;
	if (!mo->odm->subscene) {
		gf_odm_lock(mo->odm, 0);
		return;
	}
	if (mo->num_open) {
		mo->num_open--;
		if (!mo->num_open) {
			/*do we simply stop the associated document or unload it??? to check*/
//			gf_mo_stop(mo);
			gf_odm_disconnect(mo->odm, 2);
			return;
		}
	}

	/*ODM may be destroyed at this point !!*/
	if (mo->odm) gf_odm_lock(mo->odm, 0);
}
Пример #13
0
void gf_cm_set_eos(GF_CompositionMemory *cb)
{
	gf_odm_lock(cb->odm, 1);
	/*we may have a pb if the stream is so short that the EOS is signaled
	while we're buffering. In this case we shall turn the clock on and
	keep a trace of the EOS notif*/
	if (cb->Status == CB_BUFFER) {
		cb->Status = CB_BUFFER_DONE;
		gf_clock_buffer_off(cb->odm->codec->ck);
		GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] CB EOS - ODM%d: buffering off at OTB %u (STB %d) (nb wait on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_clock_time(cb->odm->codec->ck), gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
	}
	cb->HasSeenEOS = 1;

	//in bench mode eos cannot be signaled through flush of composition memory since it is always empty - do it here
	if (cb->odm->term->bench_mode==2) {
		cb->Status = CB_STOP;
		gf_odm_signal_eos(cb->odm);
	}

	gf_term_invalidate_compositor(cb->odm->term);
	gf_odm_lock(cb->odm, 0);
}
Пример #14
0
/*re-orders units in case of temporal scalability. Blocking call as it may change the output unit too*/
static GF_CMUnit *gf_cm_reorder_unit(GF_CompositionMemory *cb, GF_CMUnit *unit, Bool codec_reordering)
{
	GF_CMUnit *cu;
#if NO_TEMPORAL_SCALABLE
	cu = cb->input;
	cb->input = cb->input->next;
	return cu;
#else
	/*lock the buffer since we may move pointers*/
	gf_odm_lock(cb->odm, 1);

	/*1- unit is next on time axis (no temporal scalability)*/
	if (!cb->input->dataLength || cb->input->TS < unit->TS) {

		if (unit != cb->input) {
			/*remove unit from the list*/
			unit->prev->next = unit->next;
			unit->next->prev = unit->prev;

			/*insert unit after input*/
			unit->prev = cb->input;
			unit->next = cb->input->next;
			unit->next->prev = unit;
			unit->prev->next = unit;
		}
		/*set input to our unit*/
		cb->input = unit;
		goto exit;
	}
	/*2- unit is before our last delivered input - temporal scalability*/
	cu = cb->input;
	while (1) {

		if (cu->TS > unit->TS) {
			/*we have a unit after this one that has been consumed - discard our unit*/
			if (!cu->dataLength) {
				unit = NULL;
				goto exit;
			}
			/*previous unit is the active one - check one further*/
			if (cu->prev == unit) {
				if (!unit->prev->dataLength || (unit->prev->TS < unit->TS)) 
					break;
			} 
			/*no previous unit or our unit is just after the previous unit*/
			else if (!cu->prev->dataLength || (cu->prev->TS < unit->TS)) {
				break;
			}
			/*otherwise need to go one further*/
		}

		/*go on*/
		cu = cu->prev;
		/*done (should never happen)*/
		if (cu == cb->input) 
			goto exit;
	}
	
	/*remove unit from the list*/
	unit->prev->next = unit->next;
	unit->next->prev = unit->prev;

	/*insert active before cu*/
	unit->next = cu;
	unit->prev = cu->prev;
	unit->next->prev = unit;
	unit->prev->next = unit;
	GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("Swapping CU buffer\n"));
	
exit:

	/*perform sanity check on output ordering*/
	if (unit) {
		/*if no more output reset to our min*/
		if (!cb->output->dataLength) {
			cb->output = cb->input;
			while (1) {
				if (!cb->output->prev->dataLength) break;
				cb->output = cb->output->prev;
			}
		}
		/*otherwise we just inserted a CU that should be the next one to be consumed*/
		else if (cb->output->TS > unit->TS) {
			cb->output = unit;
		}

	}

	//check_temporal(cb);
	/*unlock the buffer*/
	gf_odm_lock(cb->odm, 0);
	return unit;
#endif
}