Exemple #1
0
static GF_Err avr_open ( GF_AVRedirect *avr )
{
    assert( avr );
    if ( avr->is_open)
        return GF_OK;
    if (!avr->is_running) {
        avr->is_running = 1;
        gf_th_run(avr->encodingThread, video_encoding_thread_run, avr);
#if REDIRECT_AV_AUDIO_ENABLED
        gf_th_run(avr->audioEncodingThread, audio_encoding_thread_run, avr);
#endif
    }
    return GF_OK;
}
Exemple #2
0
GF_Err gf_term_init_scheduler(GF_Terminal *term, u32 threading_mode)
{
	term->mm_mx = gf_mx_new("MediaManager");
	term->codecs = gf_list_new();

	term->frame_duration = 33;
	switch (threading_mode) {
	case GF_TERM_THREAD_SINGLE:
		term->flags |= GF_TERM_SINGLE_THREAD;
		break;
	case GF_TERM_THREAD_MULTI:
		term->flags |= GF_TERM_MULTI_THREAD;
		break;
	default:
		break;
	}

	if (term->user->init_flags & GF_TERM_NO_DECODER_THREAD)
		return GF_OK;

	term->mm_thread = gf_th_new("MediaManager");
	term->flags |= GF_TERM_RUNNING;
	term->priority = GF_THREAD_PRIORITY_NORMAL;
	gf_th_run(term->mm_thread, MM_Loop, term);
	return GF_OK;
}
Exemple #3
0
GF_Err SDLVid_Setup(struct _video_out *dr, void *os_handle, void *os_display, u32 init_flags)
{
	SDLVID();
	/*we don't allow SDL hack, not stable enough*/
	//if (os_handle) SDLVid_SetHack(os_handle, 1);

	ctx->os_handle = os_handle;
	ctx->is_init = 0;
	ctx->output_3d_type = 0;
	ctx->force_alpha = (init_flags & GF_TERM_WINDOW_TRANSPARENT) ? 1 : 0;

	if (!SDLOUT_InitSDL()) return GF_IO_ERR;

#ifdef	SDL_WINDOW_THREAD
	ctx->sdl_th_state = SDL_STATE_STOPPED;
	gf_th_run(ctx->sdl_th, SDLVid_EventProc, dr);

	while (!ctx->sdl_th_state)
		gf_sleep(10);

	if (ctx->sdl_th_state==SDL_STATE_STOP_REQ) {
		SDLOUT_CloseSDL();
		ctx->sdl_th_state = SDL_STATE_STOPPED;
		return GF_IO_ERR;
	}
#else
	if (!SDLVid_InitializeWindow(ctx, dr)) {
		SDLOUT_CloseSDL();
		return GF_IO_ERR;
	}
#endif

	ctx->is_init = 1;
	return GF_OK;
}
Exemple #4
0
GF_Renderer *gf_sr_new(GF_User *user, Bool self_threaded, GF_Terminal *term)
{
	GF_Renderer *tmp = SR_New(user);
	if (!tmp) return NULL;
	tmp->term = term;

	/**/
	tmp->audio_renderer = gf_sr_ar_load(user);	
	if (!tmp->audio_renderer) GF_USER_MESSAGE(user, "", "NO AUDIO RENDERER", GF_OK);

	gf_mx_p(tmp->mx);

	/*run threaded*/
	if (self_threaded) {
		tmp->VisualThread = gf_th_new();
		gf_th_run(tmp->VisualThread, SR_RenderRun, tmp);
		while (tmp->video_th_state!=1) {
			gf_sleep(10);
			if (tmp->video_th_state==3) {
				gf_mx_v(tmp->mx);
				gf_sr_del(tmp);
				return NULL;
			}
		}
	}

	/*set default size if owning output*/
	if (!tmp->user->os_window_handler) {
		gf_sr_set_size(tmp, 320, 20);
	}

	gf_mx_v(tmp->mx);

	return tmp;
}
Exemple #5
0
void MPEGVS_Start(struct __input_device * dr)
{
	MPEGVSCTX;

	rc->trd = gf_th_new("MPEG-V_IN");
	gf_th_run(rc->trd, ThreadRun, dr);
}
Exemple #6
0
static GF_Err FFD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
{
	FFDemux *ffd = plug->priv;


	if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) {
		if (ffd->audio_st>=0) return GF_OK;
		return GF_NOT_SUPPORTED;
	}

	if (!com->base.on_channel) return GF_NOT_SUPPORTED;

	switch (com->command_type) {
	/*only BIFS/OD work in pull mode (cf ffmpeg_in.h)*/
	case GF_NET_CHAN_SET_PULL:
		return GF_NOT_SUPPORTED;
	case GF_NET_CHAN_INTERACTIVE:
		return ffd->seekable ? GF_OK : GF_NOT_SUPPORTED;
	case GF_NET_CHAN_BUFFER:
		com->buffer.max = com->buffer.min = 0;
		return GF_OK;
	case GF_NET_CHAN_DURATION:
		if (ffd->ctx->duration == AV_NOPTS_VALUE)
			com->duration.duration = -1;
		else
			com->duration.duration = (Double) ffd->ctx->duration / AV_TIME_BASE;
		return GF_OK;
	/*fetch start time*/
	case GF_NET_CHAN_PLAY:
		if (com->play.speed<0) return GF_NOT_SUPPORTED;

		gf_mx_p(ffd->mx);
		ffd->seek_time = (com->play.start_range>=0) ? com->play.start_range : 0;

		if (ffd->audio_ch==com->base.on_channel) ffd->audio_run = 1;
		else if (ffd->video_ch==com->base.on_channel) ffd->video_run = 1;

		/*play on media stream, start thread*/
		if ((ffd->audio_ch==com->base.on_channel) || (ffd->video_ch==com->base.on_channel)) {
			if (ffd->is_running!=1) {
				ffd->is_running = 1;
				gf_th_run(ffd->thread, FFDemux_Run, ffd);
			}
		}
		gf_mx_v(ffd->mx);
		return GF_OK;
	case GF_NET_CHAN_STOP:
		if (ffd->audio_ch==com->base.on_channel) ffd->audio_run = 0;
		else if (ffd->video_ch==com->base.on_channel) ffd->video_run = 0;
		return GF_OK;
	/*note we don't handle PAUSE/RESUME/SET_SPEED, this is automatically handled by the demuxing thread
	through buffer occupancy queries*/

	default:
		return GF_OK;
	}

	return GF_OK;
}
Exemple #7
0
void gf_mse_remove(GF_HTML_SourceBuffer *sb, double start, double end)
{
	sb->remove_start = (u64)(start*sb->timescale);
	sb->remove_end = (u64)(end*sb->timescale);
	{
		GF_Thread *t = gf_th_new(NULL);
		gf_list_add(sb->threads, t);
		gf_th_run(t, gf_mse_source_buffer_remove, sb);
	}
}
Exemple #8
0
/*NOTE: when starting/stoping a decoder we only lock the decoder mutex, NOT the media manager. This
avoids deadlocking in case a system codec waits for the scene graph and the compositor requests
a stop/start on a media*/
void gf_term_start_codec(GF_Codec *codec, Bool is_resume)
{
	GF_CodecCapability cap;
	CodecEntry *ce;
	GF_Terminal *term = codec->odm->term;
	if (!gf_list_count(codec->odm->channels)) return;
	ce = mm_get_codec(term->codecs, codec);
	if (!ce) return;

	/*lock dec*/
	if (ce->mx) gf_mx_p(ce->mx);

	/*clean decoder memory and wait for RAP*/
	if (codec->CB) gf_cm_reset(codec->CB);

	if (!is_resume) {
		cap.CapCode = GF_CODEC_WAIT_RAP;
		gf_codec_set_capability(codec, cap);

		if (codec->decio && (codec->decio->InterfaceType == GF_SCENE_DECODER_INTERFACE)) {
			cap.CapCode = GF_CODEC_SHOW_SCENE;
			cap.cap.valueInt = 1;
			gf_codec_set_capability(codec, cap);
		}
	}

	gf_codec_set_status(codec, GF_ESM_CODEC_PLAY);

	if (!(ce->flags & GF_MM_CE_RUNNING)) {
		ce->flags |= GF_MM_CE_RUNNING;
		if (ce->thread) {
			gf_th_run(ce->thread, RunSingleDec, ce);
			gf_th_set_priority(ce->thread, term->priority);
		} else {
			term->cumulated_priority += ce->dec->Priority+1;
		}
	}


	/*unlock dec*/
	if (ce->mx)
		gf_mx_v(ce->mx);
}
Exemple #9
0
void DD_SetupWindow(GF_VideoOutput *dr, u32 flags)
{
	DDContext *ctx = (DDContext *)dr->opaque;

	if (ctx->os_hwnd) {
		/*override window proc*/
		if (!(flags & GF_TERM_NO_WINDOWPROC_OVERRIDE) ) {
			ctx->orig_wnd_proc = GetWindowLong(ctx->os_hwnd, GWL_WNDPROC);
			SetWindowLong(ctx->os_hwnd, GWL_WNDPROC, (DWORD) DD_WindowProc);
		}
	}
	ctx->switch_res = flags;
	/*create our event thread - since we always have a dedicated window for fullscreen, we need that
	even when a window is passed to us*/
	ctx->th = gf_th_new();
	gf_th_run(ctx->th, DD_WindowThread, dr);
	while (!ctx->th_state) gf_sleep(2);

	if (!the_video_output) the_video_output = dr;
}
Exemple #10
0
GF_DownloadSession *gf_dm_sess_new(GF_DownloadManager *dm, char *url, u32 dl_flags,
									  gf_dm_user_io user_io,
									  void *usr_cbk,
									  GF_Err *e)
{
	GF_DownloadSession *sess;

	*e = GF_OK;
	if (gf_dm_is_local(dm, url)) return NULL;

	if (!gf_dm_can_handle_url(dm, url)) {
		*e = GF_NOT_SUPPORTED;
		return NULL;
	}
	if (!user_io) {
		*e = GF_BAD_PARAM;
		return NULL;
	}


	sess = (GF_DownloadSession *)malloc(sizeof(GF_DownloadSession));
	memset((void *)sess, 0, sizeof(GF_DownloadSession));
	sess->flags = dl_flags;
	sess->user_proc = user_io;
	sess->usr_cbk = usr_cbk;
	sess->dm = dm;
	gf_list_add(dm->sessions, sess);

	*e = gf_dm_setup_from_url(sess, url);
	if (*e) {
		gf_dm_sess_del(sess);
		return NULL;
	}
	if (!(sess->flags & GF_NETIO_SESSION_NOT_THREADED) ) {
		sess->th = gf_th_new();
		sess->mx = gf_mx_new();
		gf_th_run(sess->th, gf_dm_session_thread, sess);
	}
	sess->num_retry = SESSION_RETRY_COUNT;
	return sess;
}
Exemple #11
0
static GF_Err SAF_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
{
	SAFIn *read = (SAFIn *)plug->priv;

	if (!com->base.on_channel) return GF_NOT_SUPPORTED;
	switch (com->command_type) {
	case GF_NET_CHAN_SET_PULL:
		return GF_NOT_SUPPORTED;
	case GF_NET_CHAN_INTERACTIVE:
		return GF_OK;
	case GF_NET_CHAN_BUFFER:
		return GF_OK;
	case GF_NET_CHAN_DURATION:
		com->duration.duration = read->duration;
		return GF_OK;
	case GF_NET_CHAN_PLAY:
		if (!read->nb_playing) {
			read->start_range = (u32) (com->play.start_range*1000);
			read->end_range = (u32) (com->play.end_range*1000);
			/*start demuxer*/
			if ((read->saf_type == SAF_FILE_LOCAL) && (read->run_state!=1)) {
				gf_th_run(read->th, SAF_Run, read);
			}
		}
		read->nb_playing++;
		return GF_OK;
	case GF_NET_CHAN_STOP:
		assert(read->nb_playing);
		read->nb_playing--;
		/*stop demuxer*/
		if (!read->nb_playing && (read->run_state==1)) {
			read->run_state=0;
			while (read->run_state!=2) gf_sleep(2);
		}
		return GF_OK;
	default:
		return GF_OK;
	}
}
Exemple #12
0
void StartHTK(ISPriv *is_dec)
{
	u32 j;
	Bool run;
	ISStack *st;
	run = 0;
	j=0;
	while ((st = gf_list_enum(is_dec->is_nodes, &j))) {
		if (st->is->enabled) {
			run = 1;
			break;
		}
	}
	if (is_dec->htk_running && run) return;
	if (!is_dec->htk_running && !run) return;
	
	is_dec->htk_running = run;
	if (run) {
		HTK_SetDictionary(is_dec->szHTKPath);
		gf_th_run(is_dec->th, RunHTKDec, is_dec);
	}
}
Exemple #13
0
void gf_mse_source_buffer_append_arraybuffer(GF_HTML_SourceBuffer *sb, GF_HTML_ArrayBuffer *buffer)
{
	assert(sb->parser);
	gf_mse_source_buffer_set_update(sb, GF_TRUE);

	buffer->url = (char *)gf_malloc(256);
	sprintf(buffer->url, "gmem://%d@%p", buffer->length, buffer->data);
	buffer->reference_count++;
#ifndef GPAC_DISABLE_ISOM
	buffer->is_init = (gf_isom_probe_file(buffer->url) == 2 ? GF_TRUE : GF_FALSE);
#endif
	GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MSE] Appending segment %s to SourceBuffer %p\n", buffer->url, sb));

	gf_list_add(sb->input_buffer, buffer);
	/* Call the parser (asynchronously) and return */
	/* the updating attribute will be positioned back to 0 when the parser is done */
	{
		GF_Thread *t = gf_th_new(NULL);
		gf_list_add(sb->threads, t);
		gf_th_run(t, gf_mse_parse_segment, sb);
	}
}
Exemple #14
0
static GF_Err SAF_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
{
	char szURL[2048];
	char *ext;
	SAFIn *read = (SAFIn *)plug->priv;
	read->service = serv;

	if (read->dnload) gf_service_download_del(read->dnload);
	read->dnload = NULL;

	strcpy(szURL, url);
	ext = strrchr(szURL, '#');
	if (ext) ext[0] = 0;

	read->needs_connection = 1;
	read->duration = 0;

	read->saf_type = SAF_FILE_LOCAL;
	/*remote fetch*/
	if (strnicmp(url, "file://", 7) && strstr(url, "://")) {
		read->saf_type = SAF_FILE_REMOTE;
		SAF_DownloadFile(plug, (char *) szURL);
		return GF_OK;
	}

	read->stream = gf_f64_open(szURL, "rb");
	if (!read->stream) {
		gf_service_connect_ack(serv, NULL, GF_URL_ERROR);
		return GF_OK;
	}
	SAF_CheckFile(read);
	read->th = gf_th_new("SAFDemux");
	/*start playing for tune-in*/
	gf_th_run(read->th, SAF_Run, read);
	return GF_OK;
}
Exemple #15
0
static GF_Err FM_FAKE_PULL_Connect(GF_HYBMEDIA *self, GF_ClientService *service, const char *url)
{
	u32 i;

	if (!self)
		return GF_BAD_PARAM;

	if (!service)
		return GF_BAD_PARAM;

	self->owner = service;

	/*set audio preloaded data*/
	assert(self->private_data);
	memset(self->private_data, 0, sizeof(FM_FAKE_PULL));
	for (i=0; i<(FM_FAKE_PULL_FRAME_LEN*8)/FM_FAKE_PULL_BITS; i++) {
		if (((2*i)/(FM_FAKE_PULL_CHAN_NUM*100))%2) /*100Hz*/
			*((FM_FAKE_PULL_TYPE*)((FM_FAKE_PULL*)self->private_data)->buffer10+i) = 1 << (FM_FAKE_PULL_BITS-1);
	}

	/*for hybrid scenarios: add an external media*/
	if (1) {
#ifdef EXT_MEDIA_LOAD_THREADED
		GF_Thread **th = &((FM_FAKE_PULL*)self->private_data)->media_th;
		assert(*th == NULL);	//once at a time
		*th = gf_th_new("HYB-FM fake external media load thread");
		gf_th_run(*th, ext_media_load_th, self);
#else
		ext_media_load_th(self);
#endif
		//wait for video to begin as late video creates desynchro.
		//gf_sleep(5000);
	}

	return GF_OK;
}
Exemple #16
0
u32 DemuxThreadStart(HbbtvDemuxer *hbbtv_demuxer){

	return gf_th_run(hbbtv_demuxer->Get_Demux_Thread(),DemuxStart,(void*)hbbtv_demuxer);
}
GF_AbstractTSMuxer * ts_amux_new(GF_AVRedirect * avr, u32 videoBitrateInBitsPerSec, u32 width, u32 height, u32 audioBitRateInBitsPerSec) {
	GF_AbstractTSMuxer * ts = gf_malloc( sizeof(GF_AbstractTSMuxer));
	memset( ts, 0, sizeof( GF_AbstractTSMuxer));
	ts->oc = avformat_alloc_context();
	ts->destination = avr->destination;
	av_register_all();
	ts->oc->oformat = GUESS_FORMAT(NULL, avr->destination, NULL);
	if (!ts->oc->oformat)
		ts->oc->oformat = GUESS_FORMAT("mpegts", NULL, NULL);
	assert( ts->oc->oformat);
#if REDIRECT_AV_AUDIO_ENABLED
	ts->audio_st = av_new_stream(ts->oc, avr->audioCodec->id);
	{
		AVCodecContext * c = ts->audio_st->codec;
		c->codec_id = avr->audioCodec->id;
		c->codec_type = AVMEDIA_TYPE_AUDIO;
		/* put sample parameters */
		c->sample_fmt = SAMPLE_FMT_S16;
		c->bit_rate = audioBitRateInBitsPerSec;
		c->sample_rate = avr->audioSampleRate;
		c->channels = 2;
		c->time_base.num = 1;
		c->time_base.den = 1000;
		// some formats want stream headers to be separate
		if (ts->oc->oformat->flags & AVFMT_GLOBALHEADER)
			c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	}
#endif

	ts->video_st = av_new_stream(ts->oc, avr->videoCodec->id);
	{
		AVCodecContext * c = ts->video_st->codec;
		c->codec_id = avr->videoCodec->id;
		c->codec_type = AVMEDIA_TYPE_VIDEO;

		/* put sample parameters */
		c->bit_rate = videoBitrateInBitsPerSec;
		/* resolution must be a multiple of two */
		c->width = width;
		c->height = height;
		/* time base: this is the fundamental unit of time (in seconds) in terms
		   of which frame timestamps are represented. for fixed-fps content,
		   timebase should be 1/framerate and timestamp increments should be
		   identically 1. */
		c->time_base.den = STREAM_FRAME_RATE;
		c->time_base.num = 1;
		c->gop_size = 12; /* emit one intra frame every twelve frames at most */
		c->pix_fmt = STREAM_PIX_FMT;
		if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
			/* just for testing, we also add B frames */
			c->max_b_frames = 2;
		}
		if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
			/* Needed to avoid using macroblocks in which some coeffs overflow.
			   This does not happen with normal video, it just happens here as
			   the motion of the chroma plane does not match the luma plane. */
			c->mb_decision=2;
		}
		// some formats want stream headers to be separate
		if (ts->oc->oformat->flags & AVFMT_GLOBALHEADER)
			c->flags |= CODEC_FLAG_GLOBAL_HEADER;

	}
	//av_set_pts_info(ts->audio_st, 33, 1, audioBitRateInBitsPerSec);

#ifndef AVIO_FLAG_WRITE
	/* set the output parameters (must be done even if no
	   parameters). */
	if (av_set_parameters(ts->oc, NULL) < 0) {
		fprintf(stderr, "Invalid output format parameters\n");
		return NULL;
	}
#endif

	dump_format(ts->oc, 0, avr->destination, 1);
	GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[AVRedirect] DUMPING to %s...\n", ts->destination));

#if (LIBAVCODEC_VERSION_MAJOR<55)
	if (avcodec_open(ts->video_st->codec, avr->videoCodec) < 0) {
#else
	if (avcodec_open2(ts->video_st->codec, avr->videoCodec, NULL) < 0) {
#endif
		GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] failed to open video codec\n"));
		return NULL;
	}
#if REDIRECT_AV_AUDIO_ENABLED
#if (LIBAVCODEC_VERSION_MAJOR<55)
	if (avcodec_open(ts->audio_st->codec, avr->audioCodec) < 0) {
#else
	if (avcodec_open2(ts->audio_st->codec, avr->audioCodec, NULL) < 0) {
#endif
		GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] failed to open audio codec\n"));
		return NULL;
	}
	ts->audioMx = gf_mx_new("TS_AudioMx");
#endif
	ts->videoMx = gf_mx_new("TS_VideoMx");
	ts->tsEncodingThread = gf_th_new("ts_interleave_thread_run");
	ts->encode = 1;
	ts->audioPackets = NULL;
	ts->videoPackets = NULL;
	gf_th_run(ts->tsEncodingThread, ts_interleave_thread_run, ts);
	return ts;
}

void ts_amux_del(GF_AbstractTSMuxer * muxerToDelete) {
	if (!muxerToDelete)
		return;
	muxerToDelete->encode = 0;
	gf_sleep(100);
	gf_th_stop(muxerToDelete->tsEncodingThread);
	muxerToDelete->tsEncodingThread = NULL;
#if REDIRECT_AV_AUDIO_ENABLED
	gf_mx_del(muxerToDelete->audioMx);
	muxerToDelete->audioMx = NULL;
#endif
	gf_mx_del(muxerToDelete->videoMx);
	muxerToDelete->videoMx = NULL;
	if (muxerToDelete->video_st) {
		avcodec_close(muxerToDelete->video_st->codec);
		muxerToDelete->video_st = NULL;
	}
#if REDIRECT_AV_AUDIO_ENABLED
	if (muxerToDelete->audio_st) {
		avcodec_close(muxerToDelete->audio_st->codec);
		muxerToDelete->audio_st = NULL;
	}
#endif
	/* write the trailer, if any.  the trailer must be written
	 * before you close the CodecContexts open when you wrote the
	 * header; otherwise write_trailer may try to use memory that
	 * was freed on av_codec_close() */
	if (muxerToDelete->oc) {
		u32 i;
		/* free the streams */
		for (i = 0; i < muxerToDelete->oc->nb_streams; i++) {
			av_freep(&muxerToDelete->oc->streams[i]->codec);
			av_freep(&muxerToDelete->oc->streams[i]);
		}

		/* free the stream */
		av_free(muxerToDelete->oc);
		muxerToDelete->oc = NULL;
	}
}

Bool ts_encode_audio_frame(GF_AbstractTSMuxer * ts, uint8_t * data, int encoded, u64 pts) {
	AVPacketList *pl;
	AVPacket * pkt;
	if (!ts->encode)
		return 1;
	pl = gf_malloc(sizeof(AVPacketList));
	pl->next = NULL;
	pkt = &(pl->pkt);
	av_init_packet(pkt);
	assert( ts->audio_st);
	assert( ts->audio_st->codec);
	pkt->flags = 0;
	if (ts->audio_st->codec->coded_frame) {
		if (ts->audio_st->codec->coded_frame->key_frame)
			pkt->flags = AV_PKT_FLAG_KEY;
		if (ts->audio_st->codec->coded_frame->pts != AV_NOPTS_VALUE) {
			pkt->pts = av_rescale_q(ts->audio_st->codec->coded_frame->pts, ts->audio_st->codec->time_base, ts->audio_st->time_base);
		} else {
			if (pts == AV_NOPTS_VALUE)
				pkt->pts = AV_NOPTS_VALUE;
			else {
				pkt->pts = av_rescale_q(pts, ts->audio_st->codec->time_base, ts->audio_st->time_base);
			}
		}
	} else {
		if (pts == AV_NOPTS_VALUE)
			pkt->pts = AV_NOPTS_VALUE;
		else
			pkt->pts = av_rescale_q(pts, ts->audio_st->codec->time_base, ts->audio_st->time_base);
	}
	pkt->stream_index= ts->audio_st->index;
	pkt->data = data;
	pkt->size = encoded;
	//fprintf(stderr, "AUDIO PTS="LLU" was: "LLU" (%p)\n", pkt->pts, pts, pl);
	gf_mx_p(ts->audioMx);
	if (!ts->audioPackets)
		ts->audioPackets = pl;
	else {
		AVPacketList * px = ts->audioPackets;
		while (px->next)
			px = px->next;
		px->next = pl;
	}
	gf_mx_v(ts->audioMx);
	return 0;
}

Bool ts_encode_video_frame(GF_AbstractTSMuxer* ts, uint8_t* data, int encoded) {
	AVPacketList *pl;
	AVPacket * pkt;
	if (!ts->encode)
		return 1;
	pl = gf_malloc(sizeof(AVPacketList));
	pl->next = NULL;
	pkt = &(pl->pkt);

	av_init_packet(pkt);

	if (ts->video_st->codec->coded_frame->pts != AV_NOPTS_VALUE) {
		//pkt->pts= av_rescale_q(ts->video_st->codec->coded_frame->pts, ts->video_st->codec->time_base, ts->video_st->time_base);
		pkt->pts = ts->video_st->codec->coded_frame->pts * ts->video_st->time_base.den / ts->video_st->time_base.num / 1000;
		//pkt->pts = ts->video_st->codec->coded_frame->pts;
	}
	if (ts->video_st->codec->coded_frame->key_frame)
		pkt->flags |= AV_PKT_FLAG_KEY;
	pkt->stream_index= ts->video_st->index;
	pkt->data= data;
	pkt->size= encoded;
	//fprintf(stderr, "VIDEO PTS="LLU" was: "LLU" (%p)\n", pkt->pts, ts->video_st->codec->coded_frame->pts, pl);
	gf_mx_p(ts->videoMx);
	if (!ts->videoPackets)
		ts->videoPackets = pl;
	else {
		AVPacketList * px = ts->videoPackets;
		while (px->next)
			px = px->next;
		px->next = pl;
	}
	gf_mx_v(ts->videoMx);
	return 0;
}
Exemple #18
0
GF_Err RP_ConnectServiceEx(GF_InputService *plug, GF_ClientService *serv, const char *url, Bool skip_migration)
{
	char *session_cache;
	RTSPSession *sess;
	RTPClient *priv = (RTPClient *)plug->priv;

	/*store user address*/
	priv->service = serv;

	if (priv->dnload) gf_term_download_del(priv->dnload);
	priv->dnload = NULL;

	GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Opening service %s\n", url));

	/*load preferences*/
	RT_LoadPrefs(plug, priv);

	/*start thread*/
	gf_th_run(priv->th, RP_Thread, priv);

	if (!skip_migration) {
		session_cache = (char *) gf_modules_get_option((GF_BaseInterface *) plug, "Streaming", "SessionMigrationFile");
		if (session_cache && session_cache[0]) {
			FILE *f = gf_f64_open(session_cache, "rb");
			if (f) {
				fclose(f);
				GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Restarting RTSP session from %s\n", session_cache));
				RP_FetchSDP(priv, (char *) session_cache, NULL, (char *) url);
				return GF_OK;
			}
			if (!strncmp(session_cache, "http://", 7)) {
				GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Restarting RTSP session from %s\n", session_cache));
				RP_FetchSDP(priv, (char *) session_cache, NULL, (char *) url);
				return GF_OK;
			}
		}
	}


	/*local or remote SDP*/
	if (strstr(url, "data:application/sdp") || (strnicmp(url, "rtsp", 4) && strstr(url, ".sdp")) ) {
		RP_FetchSDP(priv, (char *) url, NULL, NULL);
		return GF_OK;
	}

	/*rtsp and rtsp over udp*/
	if (!strnicmp(url, "rtsp://", 7) || !strnicmp(url, "rtspu://", 8)) {
		char *the_url = gf_strdup(url);
		char *the_ext = strrchr(the_url, '#');
		if (the_ext) {
			if (!stricmp(the_ext, "#audio")) priv->media_type = GF_MEDIA_OBJECT_AUDIO;
			else if (!stricmp(the_ext, "#video")) priv->media_type = GF_MEDIA_OBJECT_VIDEO;
			the_ext[0] = 0;
		}
		sess = RP_NewSession(priv, (char *) the_url);
		gf_free(the_url);
		if (!sess) {
			gf_term_on_connect(serv, NULL, GF_NOT_SUPPORTED);
		} else {
			RP_Describe(sess, 0, NULL);
		}
		return GF_OK;
	}

	/*direct RTP (no control) or embedded data - this means the service is attached to a single channel (no IOD)
	reply right away*/
	gf_term_on_connect(serv, NULL, GF_OK);
	RP_SetupObjects(priv);
	return GF_OK;
}
Exemple #19
0
static void OCV_Start(struct __input_device *ifce)
{
	GF_OpenCV *ocv = (GF_OpenCV*)ifce->udta;
	ocv->running = 1;
	gf_th_run(ocv->th, OCV_Run, ifce);
}
Exemple #20
0
GF_AbstractTSMuxer * ts_amux_new(GF_AVRedirect * avr, u32 videoBitrateInBitsPerSec, u32 width, u32 height, u32 audioBitRateInBitsPerSec) {
    GF_AbstractTSMuxer * ts = gf_malloc( sizeof(GF_AbstractTSMuxer));
    memset( ts, 0, sizeof( GF_AbstractTSMuxer));
    ts->oc = avformat_alloc_context();
    ts->destination = avr->destination;
    av_register_all();
    ts->oc->oformat = GUESS_FORMAT(NULL, avr->destination, NULL);
    if (!ts->oc->oformat)
        ts->oc->oformat = GUESS_FORMAT("mpegts", NULL, NULL);
    assert( ts->oc->oformat);
#if REDIRECT_AV_AUDIO_ENABLED
    ts->audio_st = av_new_stream(ts->oc, avr->audioCodec->id);
    {
        AVCodecContext * c = ts->audio_st->codec;
        c->codec_id = avr->audioCodec->id;
        c->codec_type = AVMEDIA_TYPE_AUDIO;
        /* put sample parameters */
        c->sample_fmt = SAMPLE_FMT_S16;
        c->bit_rate = audioBitRateInBitsPerSec;
        c->sample_rate = avr->audioSampleRate;
        c->channels = 2;
        c->time_base.num = 1;
        c->time_base.den = 1000;
        // some formats want stream headers to be separate
        if (ts->oc->oformat->flags & AVFMT_GLOBALHEADER)
            c->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }
#endif

    ts->video_st = av_new_stream(ts->oc, avr->videoCodec->id);
    {
        AVCodecContext * c = ts->video_st->codec;
        c->codec_id = avr->videoCodec->id;
        c->codec_type = AVMEDIA_TYPE_VIDEO;

        /* put sample parameters */
        c->bit_rate = videoBitrateInBitsPerSec;
        /* resolution must be a multiple of two */
        c->width = width;
        c->height = height;
        /* time base: this is the fundamental unit of time (in seconds) in terms
           of which frame timestamps are represented. for fixed-fps content,
           timebase should be 1/framerate and timestamp increments should be
           identically 1. */
        c->time_base.den = STREAM_FRAME_RATE;
        c->time_base.num = 1;
        c->gop_size = 12; /* emit one intra frame every twelve frames at most */
        c->pix_fmt = STREAM_PIX_FMT;
        if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
            /* just for testing, we also add B frames */
            c->max_b_frames = 2;
        }
        if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
            /* Needed to avoid using macroblocks in which some coeffs overflow.
               This does not happen with normal video, it just happens here as
               the motion of the chroma plane does not match the luma plane. */
            c->mb_decision=2;
        }
        // some formats want stream headers to be separate
        if (ts->oc->oformat->flags & AVFMT_GLOBALHEADER)
            c->flags |= CODEC_FLAG_GLOBAL_HEADER;

    }
    //av_set_pts_info(ts->audio_st, 33, 1, audioBitRateInBitsPerSec);

#ifndef AVIO_FLAG_WRITE
	/* set the output parameters (must be done even if no
       parameters). */
    if (av_set_parameters(ts->oc, NULL) < 0) {
        fprintf(stderr, "Invalid output format parameters\n");
        return NULL;
    }
#endif

	dump_format(ts->oc, 0, avr->destination, 1);
    GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[AVRedirect] DUMPING to %s...\n", ts->destination));

    if (avcodec_open(ts->video_st->codec, avr->videoCodec) < 0) {
        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] failed to open video codec\n"));
        return NULL;
    }
#if REDIRECT_AV_AUDIO_ENABLED
    if (avcodec_open(ts->audio_st->codec, avr->audioCodec) < 0) {
        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] failed to open audio codec\n"));
        return NULL;
    }
    ts->audioMx = gf_mx_new("TS_AudioMx");
#endif
    ts->videoMx = gf_mx_new("TS_VideoMx");
    ts->tsEncodingThread = gf_th_new("ts_interleave_thread_run");
    ts->encode = 1;
    ts->audioPackets = NULL;
    ts->videoPackets = NULL;
    gf_th_run(ts->tsEncodingThread, ts_interleave_thread_run, ts);
    return ts;
}
Exemple #21
0
void gf_term_set_threading(GF_Terminal *term, u32 mode)
{
	u32 i;
	Bool thread_it, restart_it;
	CodecEntry *ce;

	switch (mode) {
	case GF_TERM_THREAD_SINGLE:
		if (term->flags & GF_TERM_SINGLE_THREAD) return;
		term->flags &= ~GF_TERM_MULTI_THREAD;
		term->flags |= GF_TERM_SINGLE_THREAD;
		break;
	case GF_TERM_THREAD_MULTI:
		if (term->flags & GF_TERM_MULTI_THREAD) return;
		term->flags &= ~GF_TERM_SINGLE_THREAD;
		term->flags |= GF_TERM_MULTI_THREAD;
		break;
	default:
		if (!(term->flags & (GF_TERM_MULTI_THREAD | GF_TERM_SINGLE_THREAD) ) ) return;
		term->flags &= ~GF_TERM_SINGLE_THREAD;
		term->flags &= ~GF_TERM_MULTI_THREAD;
		break;
	}

	gf_mx_p(term->mm_mx);


	i=0;
	while ((ce = (CodecEntry*)gf_list_enum(term->codecs, &i))) {
		thread_it = 0;
		/*free mode, decoder wants threading - do */
		if ((mode == GF_TERM_THREAD_FREE) && (ce->flags & GF_MM_CE_REQ_THREAD)) thread_it = 1;
		else if (mode == GF_TERM_THREAD_MULTI) thread_it = 1;

		if (thread_it && (ce->flags & GF_MM_CE_THREADED)) continue;
		if (!thread_it && !(ce->flags & GF_MM_CE_THREADED)) continue;

		restart_it = 0;
		if (ce->flags & GF_MM_CE_RUNNING) {
			restart_it = 1;
			ce->flags &= ~GF_MM_CE_RUNNING;
		}

		if (ce->flags & GF_MM_CE_THREADED) {
			/*wait for thread to die*/
			while (!(ce->flags & GF_MM_CE_DEAD)) gf_sleep(1);
			ce->flags &= ~GF_MM_CE_DEAD;
			gf_th_del(ce->thread);
			ce->thread = NULL;
			gf_mx_del(ce->mx);
			ce->mx = NULL;
			ce->flags &= ~GF_MM_CE_THREADED;
		} else {
			term->cumulated_priority -= ce->dec->Priority+1;
		}

		if (thread_it) {
			ce->flags |= GF_MM_CE_THREADED;
			ce->thread = gf_th_new(ce->dec->decio->module_name);
			ce->mx = gf_mx_new(ce->dec->decio->module_name);
		}

		if (restart_it) {
			ce->flags |= GF_MM_CE_RUNNING;
			if (ce->thread) {
				gf_th_run(ce->thread, RunSingleDec, ce);
				gf_th_set_priority(ce->thread, term->priority);
			} else {
				term->cumulated_priority += ce->dec->Priority+1;
			}
		}
	}
	gf_mx_v(term->mm_mx);
}
Exemple #22
0
int main(int argc, char **argv)
{
	/* The ISO progressive reader */
	ISOProgressiveReader reader;
	/* Error indicator */
	GF_Err e;
	/* input file to be read in the data buffer */
	FILE *input;
	/* number of bytes read from the file at each read operation */
	u32 read_bytes;
	/* number of bytes read from the file (total) */
	u64 total_read_bytes;
	/* size of the input file */
	u64 file_size;
	/* number of bytes required to finish the current ISO Box reading (not used here)*/
	u64 missing_bytes;
	/* Thread used to run the ISO parsing in */
	GF_Thread *reading_thread;
	/* Return value for the program */
	int ret = 0;

	/* Usage */
	if (argc != 2) {
		fprintf(stdout, "Usage: %s filename\n", argv[0]);
		return 1;
	}

	/* Initializing GPAC framework */
	/* Enables GPAC memory tracking in debug mode only */
#if defined(DEBUG) || defined(_DEBUG)
	gf_sys_init(GF_MemTrackerSimple);
	gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING);
	gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_INFO);
#else
	gf_sys_init(GF_MemTrackerNone);
	gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING);
#endif

	/* This is an input file to read data from. Could be replaced by any other method to retrieve the data (e.g. JavaScript, socket, ...)*/
	input = gf_fopen(argv[1], "rb");
	if (!input) {
		fprintf(stdout, "Could not open file %s for reading.\n", argv[1]);
		gf_sys_close();
		return 1;
	}

	gf_fseek(input, 0, SEEK_END);
	file_size = gf_ftell(input);
	gf_fseek(input, 0, SEEK_SET);

	/* Initializing the progressive reader */
	memset(&reader, 0, sizeof(ISOProgressiveReader));
	reading_thread = gf_th_new("ISO reading thread");
	reader.mutex = gf_mx_new("ISO Segment");
	reader.do_run = GF_TRUE;
	/* we want to parse the first track */
	reader.track_id = 1;
	/* start the async parsing */
	gf_th_run(reading_thread, iso_progressive_read_thread, &reader);

	/* start the data reading */
	reader.data_size = BUFFER_BLOCK_SIZE;
	reader.data = (u8 *)gf_malloc(reader.data_size);
	reader.valid_data_size = 0;
	total_read_bytes = 0;
	while (1) {
		/* block the parser until we are done manipulating the data buffer */
		gf_mx_p(reader.mutex);

		if (reader.valid_data_size + BUFFER_BLOCK_SIZE > MAX_BUFFER_SIZE) {
			/* regulate the reader to limit the max buffer size and let some time to the parser to release buffer data */
			fprintf(stdout, "Buffer full (%d/%d)- waiting to read next data \r", reader.valid_data_size, reader.data_size);
			gf_mx_v(reader.mutex);
			//gf_sleep(10);
		} else {
			/* make sure we have enough space in the buffer to read the next bloc of data */
			if (reader.valid_data_size + BUFFER_BLOCK_SIZE > reader.data_size) {
				reader.data = (u8 *)gf_realloc(reader.data, reader.data_size + BUFFER_BLOCK_SIZE);
				reader.data_size += BUFFER_BLOCK_SIZE;
			}

			/* read the next bloc of data and update the data buffer url */
			read_bytes = fread(reader.data+reader.valid_data_size, 1, BUFFER_BLOCK_SIZE, input);
			total_read_bytes += read_bytes;
			fprintf(stdout, "Read "LLD" bytes of "LLD" bytes from input file %s (buffer status: %5d/%5d)\r", total_read_bytes, file_size, argv[1], reader.valid_data_size, reader.data_size);
			if (read_bytes) {
				reader.valid_data_size += read_bytes;
				sprintf(reader.data_url, "gmem://%d@%p", reader.valid_data_size, reader.data);
			} else {
				/* end of file we can quit */
				gf_mx_v(reader.mutex);
				break;
			}

			/* if the file is not yet opened (no movie), open it in progressive mode (to update its data later on) */
			if (!reader.movie) {
				/* let's initialize the parser */
				e = gf_isom_open_progressive(reader.data_url, 0, 0, &reader.movie, &missing_bytes);
				if (reader.movie) {
					gf_isom_set_single_moof_mode(reader.movie, GF_TRUE);
				}
				/* we can let parser try to work now */
				gf_mx_v(reader.mutex);

				if ((e == GF_OK || e == GF_ISOM_INCOMPLETE_FILE) && reader.movie) {
					/* nothing to do, this is normal */
				} else {
					fprintf(stdout, "Error opening fragmented mp4 in progressive mode: %s (missing "LLD" bytes)\n", gf_error_to_string(e), missing_bytes);
					ret = 1;
					goto exit;
				}
			} else {
				/* let inform the parser that the buffer has been updated with new data */
				e = gf_isom_refresh_fragmented(reader.movie, &missing_bytes, reader.data_url);

				/* we can let parser try to work now */
				gf_mx_v(reader.mutex);

				if (e != GF_OK && e != GF_ISOM_INCOMPLETE_FILE) {
					fprintf(stdout, "Error refreshing fragmented mp4: %s (missing "LLD" bytes)\n", gf_error_to_string(e), missing_bytes);
					ret = 1;
					goto exit;
				}
			}

			//gf_sleep(1);
		}
	}

exit:
	/* stop the parser */
	reader.do_run = GF_FALSE;
	gf_th_stop(reading_thread);

	/* clean structures */
	gf_th_del(reading_thread);
	gf_mx_del(reader.mutex);
	gf_free(reader.data);
	gf_isom_close(reader.movie);
	gf_fclose(input);
	gf_sys_close();

	return ret;
}
Exemple #23
0
GF_AudioRenderer *gf_sc_ar_load(GF_User *user)
{
	const char *sOpt;
	u32 i, count;
	u32 num_buffers, total_duration;
	GF_Err e;
	GF_AudioRenderer *ar;
	ar = (GF_AudioRenderer *) gf_malloc(sizeof(GF_AudioRenderer));
	memset(ar, 0, sizeof(GF_AudioRenderer));

	num_buffers = total_duration = 0;
	sOpt = gf_cfg_get_key(user->config, "Audio", "ForceConfig");
	if (sOpt && !stricmp(sOpt, "yes")) {
		sOpt = gf_cfg_get_key(user->config, "Audio", "NumBuffers");
		num_buffers = sOpt ? atoi(sOpt) : 6;
		sOpt = gf_cfg_get_key(user->config, "Audio", "TotalDuration");
		total_duration = sOpt ? atoi(sOpt) : 400;
	}

	sOpt = gf_cfg_get_key(user->config, "Audio", "NoResync");
	ar->disable_resync = (sOpt && !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
	sOpt = gf_cfg_get_key(user->config, "Audio", "DisableMultiChannel");
	ar->disable_multichannel = (sOpt && !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;

	ar->mixer = gf_mixer_new(ar);
	ar->user = user;

	sOpt = gf_cfg_get_key(user->config, "Audio", "Volume");
	ar->volume = sOpt ? atoi(sOpt) : 75;
	sOpt = gf_cfg_get_key(user->config, "Audio", "Pan");
	ar->pan = sOpt ? atoi(sOpt) : 50;

	if (! (user->init_flags & GF_TERM_NO_AUDIO) ) {

		/*get a prefered compositor*/
		sOpt = gf_cfg_get_key(user->config, "Audio", "DriverName");
		if (sOpt) {
			ar->audio_out = (GF_AudioOutput *) gf_modules_load_interface_by_name(user->modules, sOpt, GF_AUDIO_OUTPUT_INTERFACE);
			if (!ar->audio_out) {
				ar->audio_out = NULL;
				sOpt = NULL;
			}
		}
		if (!ar->audio_out) {
			GF_AudioOutput *raw_out = NULL;
			count = gf_modules_get_count(ar->user->modules);
			for (i=0; i<count; i++) {
				ar->audio_out = (GF_AudioOutput *) gf_modules_load_interface(ar->user->modules, i, GF_AUDIO_OUTPUT_INTERFACE);
				if (!ar->audio_out) continue;

				//in enum mode, only use raw out if everything else failed ...
				if (!stricmp(ar->audio_out->module_name, "Raw Audio Output")) {
					raw_out = ar->audio_out;
					ar->audio_out = NULL;
					continue;
				}
				GF_LOG(GF_LOG_DEBUG, GF_LOG_AUDIO, ("[AudioRender] Audio output module %s loaded\n", ar->audio_out->module_name));
				/*check that's a valid audio compositor*/
				if ((ar->audio_out->SelfThreaded && ar->audio_out->SetPriority) || ar->audio_out->WriteAudio) {
					/*remember the module we use*/
					gf_cfg_set_key(user->config, "Audio", "DriverName", ar->audio_out->module_name);
					break;
				}
				gf_modules_close_interface((GF_BaseInterface *)ar->audio_out);
				ar->audio_out = NULL;
			}
			if (raw_out) {
				if (ar->audio_out) gf_modules_close_interface((GF_BaseInterface *)raw_out);
				else ar->audio_out = raw_out;
			}
		}

		/*if not init we run with a NULL audio compositor*/
		if (ar->audio_out) {
			ar->audio_out->FillBuffer = gf_ar_fill_output;
			ar->audio_out->audio_renderer = ar;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_AUDIO, ("[AudioRender] Setting up audio module %s\n", ar->audio_out->module_name));
			e = ar->audio_out->Setup(ar->audio_out, ar->user->os_window_handler, num_buffers, total_duration);


			/*load main audio filter*/
			gf_afc_load(&ar->filter_chain, user, (char*)gf_cfg_get_key(user->config, "Audio", "Filter"));


			if (e != GF_OK) {
				GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("Could not setup audio out %s\n", ar->audio_out->module_name));
				gf_modules_close_interface((GF_BaseInterface *)ar->audio_out);
				ar->audio_out = NULL;
			} else {
				if (!ar->audio_out->SelfThreaded) {
					ar->th = gf_th_new("AudioRenderer");
					gf_th_run(ar->th, gf_ar_proc, ar);
				} else {
					gf_ar_setup_output_format(ar);
					if (ar->audio_out->SetPriority) ar->audio_out->SetPriority(ar->audio_out, GF_THREAD_PRIORITY_REALTIME);
				}
			}
		}
		if (!ar->audio_out) {
			gf_cfg_set_key(user->config, "Audio", "DriverName", "No Audio Output Available");
		} else {
			if (user->init_flags & GF_TERM_USE_AUDIO_HW_CLOCK)
				ar->clock_use_audio_out = GF_TRUE;
		}
	}
	/*init compositor timer*/
	ar->start_time = gf_sys_clock_high_res();
	ar->current_time = 0;
	return ar;
}
Exemple #24
0
static void WII_Start(struct __input_device *ifce)
{
	GF_WiiMote *wii = (GF_WiiMote *)ifce->udta;
	wii->running = 1;
	gf_th_run(wii->th, WII_Run, ifce);
}
Exemple #25
0
int main (const int argc, const char** argv)
{
	GF_Err e;
	Bool run;

	/* location of the configuration file: 0 wait for config on a socket, 1 use the given file */
	u32 config_flag;	
	char config_file_name[MAX_BUF];

	int dest_port;
	unsigned short tcp_port = 0;
	/* Should be fine on WIFI network */
	unsigned short mtu_size = 1492;
	int debug = 0;
	TCP_Input *tcp_conf = NULL;
	GF_Thread *tcp_thread;
	GF_Err th_err_tcp;

	GF_Err th_err_rap;
	RAP_Input *rap_conf;
	GF_Thread *rap_thread;

	CONF_Data *conf;	
	GF_Config *gf_config_file;
	GF_Err res;
	
	GF_Socket *UDP_feedback_socket;
	u32 socketType_for_updates;
	
	PNC_CallbackData * data;
	GF_RTPChannel * chan;
	GF_RTPHeader hdr;
	u32 timer = -1;
	
	GF_Mutex *carrousel_mutex;	
	char sdp_fmt[5000];
	tcp_thread = NULL;
	
	/* init gpac lib */
	gf_sys_init();
	gf_log_set_level(GF_LOG_ERROR);
	gf_log_set_tools(GF_LOG_NETWORK|GF_LOG_RTP|GF_LOG_SCENE|GF_LOG_PARSER|GF_LOG_AUTHOR|GF_LOG_CODING|GF_LOG_SCRIPT);
	
	GF_SAFEALLOC(conf, CONF_Data);
		
	tcp_port = config_flag = 0;
	socketType_for_updates = GF_SOCK_TYPE_UDP;
	if (command_line_parsing(argc, argv, &tcp_port, config_file_name, (int *) &config_flag, &mtu_size, &debug, &socketType_for_updates)){
		print_usage();
		return -1;
	}
	setDebugMode( debug );
	gf_config_file = NULL;
	if (config_flag == 1)
	{
		char *cfg_path;
		char *cfg_fname;
		char *tmp;
		
		cfg_fname = config_file_name;
		cfg_path = config_file_name;
		tmp = strrchr(cfg_fname, GF_PATH_SEPARATOR);
		if (tmp) {
			cfg_fname = tmp+1;
			tmp[0] = 0;
		} else {
			cfg_path = ".";
		}
		gf_config_file = gf_cfg_new(cfg_path, cfg_fname);	
		if (!gf_config_file) {
			fprintf(stderr, "Cannot open config file %s\n", config_file_name);
			return -1;
		} else {
			dprintf(DEBUG_broadcaster, "Using config file %s.\n", config_file_name);
		}
		if (parse_config(gf_config_file, conf, debug)) return -1;
		tcp_port = atoi(conf->config_input_port);
	}
	else
	{
		GF_SAFEALLOC(tcp_conf, TCP_Input);
		tcp_conf->config_flag = &config_flag;
		tcp_conf->RAPtimer = &timer;
		tcp_conf->port = tcp_port;
		tcp_conf->config = conf;
		tcp_thread = gf_th_new("TCPInterface");

		/* Starting the thread which will write the received config in a temporary file */
		th_err_tcp = gf_th_run(tcp_thread, tcp_server, tcp_conf);
		
		fprintf(stdout, "Waiting for configuration on port %d...\n", tcp_conf->port);

		while(config_flag == 0) { 
			gf_sleep(1000); 
		}
		fprintf(stdout, "Configuration File received. Starting Streaming ...\n");
	}
	
	timer = atoi(conf->rap_timer);
	dest_port = atoi(conf->dest_port);
	res = PNC_InitRTP(&chan, (char *)conf->dest_ip, dest_port, mtu_size);
 	if (res != 0) {
		fprintf(stderr, "Cannot initialize RTP output (error: %d)\n", res); 
		exit(1);
	} 

	carrousel_mutex = gf_mx_new("Carrousel");
	data = PNC_Init_SceneGenerator(chan, &hdr, (char *) conf->scene_init_file,
								   socketType_for_updates, (u16) atoi(conf->modif_input_port), debug); 
	if (!data) {
		fprintf(stderr, "Cannot initialize Scene Generator\n"); 
		exit(1);
	}
	data->carrousel_mutex = carrousel_mutex;
	data->RAPsent = 1;
	
	UDP_feedback_socket = gf_sk_new(GF_SOCK_TYPE_UDP);
	e = gf_sk_bind(UDP_feedback_socket, NULL, (u16)atoi(conf->feedback_port), (char*)conf->feedback_ip, (u16)atoi(conf->feedback_port), 0);
	if (e) {
		fprintf(stderr, "Cannot bind socket for bitrate feedback information (%s)\n", gf_error_to_string(e));
	} else {
		e = gf_sk_set_block_mode(UDP_feedback_socket, 1);
		if (e) {
			fprintf(stderr, "Cannot set feedback socket block mode (%s)\n", gf_error_to_string(e));
		}
	}
	data->feedback_socket = UDP_feedback_socket;

	PNC_InitPacketiser(data, sdp_fmt, mtu_size); 
	PNC_SendInitScene(data);

	GF_SAFEALLOC(rap_conf, RAP_Input);
	rap_conf->RAPtimer = &timer;
	rap_conf->carrousel_mutex = carrousel_mutex;
	rap_conf->data = data;
	rap_thread = gf_th_new("RAPGenerator");
	th_err_rap = gf_th_run(rap_thread, RAP_send, rap_conf);

	sdp_generator(data, (char *)conf->dest_ip, sdp_fmt);
	
	run = 1;
	while (run)
	{
		GF_Err e = PNC_processBIFSGenerator(data); 
		if (e) {
			fprintf(stderr, "Cannot Process BIFS data (%s)\n", gf_error_to_string(e));
			break;
		}

		if (has_input()) {
			char c = get_a_char();
			switch (c) {
			case 'q':
				run = 0;
				break;
			}
		}
		gf_sleep(10);
	}

	/* waiting for termination of the RAP thread */
	rap_conf->status = 0;
	while (rap_conf->status != 2)
		gf_sleep(0);
	gf_free(rap_conf);
	gf_th_del(rap_thread);

	/* waiting for termination of the TCP listening thread */
	if (tcp_conf) {
		tcp_conf->status = 0;
		while (tcp_conf->status != 2)
			gf_sleep(0);
		gf_free(tcp_conf);
		gf_th_del(tcp_thread);
	}

	PNC_Close_SceneGenerator(data);
	
	gf_free(conf);
	
	if (gf_config_file)
		gf_cfg_del(gf_config_file);

	gf_mx_del(carrousel_mutex);
	gf_sys_close();
	return 0;
}