Exemple #1
0
static void cb_set_buffer_off(GF_CompositionMemory *cb)
{
	gf_clock_buffer_off(cb->odm->codec->ck);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] CB Buffering done 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));

	gf_term_service_media_event(cb->odm->parentscene->root_od, GF_EVENT_MEDIA_CANPLAY);
}
Exemple #2
0
GF_Err gf_codec_process_raw_media_pull(GF_Codec *codec, u32 TimeAvailable)
{
	GF_Channel *ch;
	GF_DBUnit *db;
	if (codec->ck && codec->ck->Paused) {
		u32 i;
		for (i=0; i<gf_list_count(codec->odm->channels); i++) {
			ch = gf_list_get(codec->odm->channels, i);
			if (ch->BufferOn) {
				ch->BufferOn = 0;
				gf_clock_buffer_off(ch->clock);
			}
		}
		if (codec->CB)
			gf_cm_abort_buffering(codec->CB);
	}

	/*this will pull the next AU from the service */
	Decoder_GetNextAU(codec, &ch, &db);
	if (!db) return GF_OK;

	/*dispatch raw media - this call is blocking untill the cu has been consumed */
	gf_es_dispatch_raw_media_au(ch, db->data, db->dataLength, db->CTS);

	/*release AU from service*/
	gf_term_channel_release_sl_packet(ch->service, ch);
	return GF_OK;
}
Exemple #3
0
void gf_es_dispatch_raw_media_au(GF_Channel *ch, char *payload, u32 payload_size, u32 cts)
{
	GF_CompositionMemory *cb;
	GF_CMUnit *cu;
	if (!payload || !ch->odm->codec->CB) return;
	if (!ch->odm->codec->CB->no_allocation) return;

	cb = ch->odm->codec->CB;
	cu = gf_cm_lock_input(cb, cts, 1);
	if (cu) {
		u32 size = 0;
		assert(cu->RenderedLength==0);
		if (cb->UnitSize >= payload_size) {
			cu->data = payload;
			size = payload_size;
			cu->TS = cts;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched to CB - TS %d ms\n", ch->odm->OD->objectDescriptorID, cu->TS));
		}
		gf_cm_unlock_input(cb, cu, size, 1);

		if (ch->BufferOn) {
			ch->BufferOn = 0;
			gf_clock_buffer_off(ch->clock);
			gf_cm_abort_buffering(cb);
		}
		/*since the CB is a simple pointer to the input frame, wait until it is released before getting 
		back to the caller module*/
		if (size) {
			gf_sema_wait(ch->odm->raw_frame_sema);
			assert(cb->output->dataLength == 0);
		}
	}
}
Exemple #4
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);
}
Exemple #5
0
void gf_cm_abort_buffering(GF_CompositionMemory *cb)
{
	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));
	}
}
Exemple #6
0
static void ch_buffer_off(GF_Channel *ch)
{
	/*just in case*/
	if (ch->BufferOn) {
		ch->BufferOn = 0;
		gf_clock_buffer_off(ch->clock);
		GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: buffering off at STB %d (OTB %d) (nb buffering on clock: %d)\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), gf_clock_time(ch->clock), ch->clock->Buffering));
	}
}
Exemple #7
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);

}
Exemple #8
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);
}
Exemple #9
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);
}
Exemple #10
0
void gf_es_dispatch_raw_media_au(GF_Channel *ch, char *payload, u32 payload_size, u32 cts)
{
	u32 now;
	GF_CompositionMemory *cb;
	GF_CMUnit *cu;
	if (!payload || !ch->odm->codec->CB) return;
	if (!ch->odm->codec->CB->no_allocation) return;

	now = gf_clock_real_time(ch->clock);
	if (cts + ch->MinBuffer < now) {
		if (ch->MinBuffer && (ch->is_raw_channel==2)) {
			ch->clock->clock_init = 0;
			gf_clock_set_time(ch->clock, cts);
			GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched at OTB %d but frame TS is %d ms - adjusting clock\n", ch->odm->OD->objectDescriptorID, now, cts));
		} else {
			GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched at OTB %d but frame TS is %d ms - DROPPING\n", ch->odm->OD->objectDescriptorID, now, cts));
		}
		return;
	}

	cb = ch->odm->codec->CB;
	cu = gf_cm_lock_input(cb, cts, 1);
	if (cu) {
		u32 size = 0;
		assert(cu->RenderedLength==0);
		if (cb->UnitSize >= payload_size) {
			cu->data = payload;
			size = payload_size;
			cu->TS = cts;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched to CB - TS %d ms - OTB %d ms - OTB_drift %d ms\n", ch->odm->OD->objectDescriptorID, cu->TS, gf_clock_real_time(ch->clock), gf_clock_time(ch->clock) ));
		}
		gf_cm_unlock_input(cb, cu, size, 1);

		if (ch->BufferOn) {
			ch->BufferOn = 0;
			gf_clock_buffer_off(ch->clock);
			gf_cm_abort_buffering(cb);
		}
		/*since the CB is a simple pointer to the input frame, wait until it is released before getting 
		back to the caller module*/
		if (size) {
			gf_sema_wait(ch->odm->raw_frame_sema);
			assert(cb->output->dataLength == 0);
		}
	}
}
Exemple #11
0
GF_Err gf_codec_process_private_media(GF_Codec *codec, u32 TimeAvailable)
{
	
	if (codec->ck && codec->ck->Paused) {
		u32 i;
		for (i=0; i<gf_list_count(codec->odm->channels); i++) {
			GF_Channel *ch = gf_list_get(codec->odm->channels, i);
			if (ch->BufferOn) {
				ch->BufferOn = 0;
				gf_clock_buffer_off(ch->clock);
			}
		}
		if (codec->CB) 
			gf_cm_abort_buffering(codec->CB);
	}
	return GF_OK;
}
Exemple #12
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);
}
Exemple #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);
}
Exemple #14
0
/*access to the first available CU for rendering
this is a blocking call since input may change the output (temporal scalability)*/
GF_CMUnit *gf_cm_get_output(GF_CompositionMemory *cb)
{
	/*if paused or stop or buffering, do nothing*/
	switch (cb->Status) {
	case CB_BUFFER:
	case CB_STOP:
		/*only visual buffers deliver data when buffering or stop*/
		if (cb->odm->codec->type != GF_STREAM_VISUAL) return NULL;
		break;
	case CB_BUFFER_DONE:
		//For non-visual output move to play state upon fetch
		if (cb->odm->codec->type != GF_STREAM_VISUAL)
			cb->Status = CB_PLAY;
		break;
	//we always deliver in pause, up to the caller to decide to consume or not the frame
	case CB_PAUSE:
		break;
	}

	/*no output*/
	if (!cb->UnitCount || !cb->output->dataLength) {
		if ((cb->Status != CB_STOP) && cb->HasSeenEOS && (cb->odm && cb->odm->codec)) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Switching composition memory to stop state - time %d\n", cb->odm->OD->objectDescriptorID, (u32) cb->odm->media_stop_time));

			if ((cb->Status==CB_BUFFER_DONE) && (cb->odm->codec->type == GF_STREAM_VISUAL) ){
				gf_clock_buffer_off(cb->odm->codec->ck);
			}
			cb->Status = CB_STOP;
			cb->odm->media_current_time = (u32) cb->odm->media_stop_time;
#ifndef GPAC_DISABLE_VRML
			/*force update of media time*/
			mediasensor_update_timing(cb->odm, 1);
#endif
			gf_odm_signal_eos(cb->odm);
		}
		return NULL;
	}

	/*update the timing*/
	if ((cb->Status != CB_STOP) && cb->odm && cb->odm->codec) {
		if (cb->odm->codec->ck->has_media_time_shift) {
			cb->odm->media_current_time = cb->output->TS + cb->odm->codec->ck->media_time_at_init - cb->odm->codec->ck->init_time;
		} else {
			cb->odm->media_current_time = cb->output->TS;
		}

		/*handle visual object - EOS if no more data (we keep the last CU for rendering, so check next one)*/
		if (cb->HasSeenEOS && (cb->odm->codec->type == GF_STREAM_VISUAL) && (!cb->output->next->dataLength || (cb->Capacity==1))) {
			GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Switching composition memory to stop state - time %d\n", cb->odm->OD->objectDescriptorID, (u32) cb->odm->media_stop_time));
			if (cb->Status==CB_BUFFER_DONE) {
				gf_clock_buffer_off(cb->odm->codec->ck);
			}
			cb->Status = CB_STOP;
			cb->odm->media_current_time = (u32) cb->odm->media_stop_time;
#ifndef GPAC_DISABLE_VRML
			/*force update of media time*/
			mediasensor_update_timing(cb->odm, 1);
#endif
			gf_odm_signal_eos(cb->odm);
		}
	}
	if (cb->output->sender_ntp) {
		cb->LastRenderedNTPDiff = gf_net_get_ntp_diff_ms(cb->output->sender_ntp);
		cb->LastRenderedNTP = cb->output->sender_ntp;
	}

	return cb->output;
}