⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channel.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / Media terminal sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/terminal_dev.h>#include <gpac/sync_layer.h>#include <gpac/constants.h>#include "media_memory.h"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 %d (nb buffering on clock: %d)\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), ch->clock->Buffering));	}}static void ch_buffer_on(GF_Channel *ch){	/*just in case*/	if (!ch->BufferOn) {		ch->BufferOn = 1;		gf_clock_buffer_on(ch->clock);		GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: buffering on at %d (nb buffering on clock: %d)\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), ch->clock->Buffering));	}}/*reset channel*/static void Channel_Reset(GF_Channel *ch, Bool for_start){	gf_es_lock(ch, 1);	ch->IsClockInit = 0;	ch->au_sn = 0;	ch->pck_sn = 0;	ch->stream_state = 1;	ch->IsRap = 0;	ch->IsEndOfStream = 0;	if (for_start) {		gf_es_lock(ch, 0);		return;	}	ch->ts_offset = 0;	ch->seed_ts = 0;	ch_buffer_off(ch);	if (ch->buffer) free(ch->buffer);	ch->buffer = NULL;	ch->len = ch->allocSize = 0;	gf_db_unit_del(ch->AU_buffer_first);	ch->AU_buffer_first = ch->AU_buffer_last = NULL;	ch->AU_Count = 0;	ch->BufferTime = 0;	ch->NextIsAUStart = 1;	ch->first_au_fetched = 0;	if (ch->AU_buffer_pull) {		ch->AU_buffer_pull->data = NULL;		gf_db_unit_del(ch->AU_buffer_pull);		ch->AU_buffer_pull = NULL;	}	gf_es_lock(ch, 0);}GF_Channel *gf_es_new(GF_ESD *esd){	u32 nbBits;	GF_Channel *tmp;	GF_SAFEALLOC(tmp, GF_Channel);	if (!tmp) return NULL;	tmp->mx = gf_mx_new();	tmp->esd = esd;	tmp->chan_id = (u32) tmp;	tmp->es_state = GF_ESM_ES_SETUP;	nbBits = sizeof(u32) * 8 - esd->slConfig->AUSeqNumLength;	tmp->max_au_sn = 0xFFFFFFFF >> nbBits;	nbBits = sizeof(u32) * 8 - esd->slConfig->packetSeqNumLength;	tmp->max_pck_sn = 0xFFFFFFFF >> nbBits;	tmp->skip_sl = (esd->slConfig->predefined == SLPredef_SkipSL) ? 1 : 0;	/*take care of dummy streams*/	if (!esd->slConfig->timestampResolution) esd->slConfig->timestampResolution = esd->slConfig->timeScale ? esd->slConfig->timeScale : 1000;	if (!esd->slConfig->OCRResolution) esd->slConfig->OCRResolution = esd->slConfig->timestampResolution;	tmp->ts_res = esd->slConfig->timestampResolution;	tmp->ocr_scale = 0;	if (esd->slConfig->OCRResolution) {		tmp->ocr_scale = 1000;		tmp->ocr_scale /= esd->slConfig->OCRResolution;	}	Channel_Reset(tmp, 0);	return tmp;}/*reconfig SL settings for this channel - this is needed by some net services*/void gf_es_reconfig_sl(GF_Channel *ch, GF_SLConfig *slc){	u32 nbBits;		memcpy(ch->esd->slConfig, slc, sizeof(GF_SLConfig));	nbBits = sizeof(u32) * 8 - ch->esd->slConfig->AUSeqNumLength;	ch->max_au_sn = 0xFFFFFFFF >> nbBits;	nbBits = sizeof(u32) * 8 - ch->esd->slConfig->packetSeqNumLength;	ch->max_pck_sn = 0xFFFFFFFF >> nbBits;	ch->skip_sl = (slc->predefined == SLPredef_SkipSL) ? 1 : 0;	/*take care of dummy streams*/	if (!ch->esd->slConfig->timestampResolution) ch->esd->slConfig->timestampResolution = 1000;	if (!ch->esd->slConfig->OCRResolution) ch->esd->slConfig->OCRResolution = ch->esd->slConfig->timestampResolution;	ch->ts_res = ch->esd->slConfig->timestampResolution;	ch->ocr_scale = 0;	if (ch->esd->slConfig->OCRResolution) {		ch->ocr_scale = 1000;		ch->ocr_scale /= ch->esd->slConfig->OCRResolution;	}}/*destroy channel*/void gf_es_del(GF_Channel *ch){	Channel_Reset(ch, 0);	if (ch->AU_buffer_pull) {		ch->AU_buffer_pull->data = NULL;		gf_db_unit_del(ch->AU_buffer_pull);	}	if (ch->ipmp_tool)		gf_modules_close_interface((GF_BaseInterface *) ch->ipmp_tool);	if (ch->mx) gf_mx_del(ch->mx);	free(ch);}Bool gf_es_owns_clock(GF_Channel *ch){	/*if the clock is not in the same namespace (used with dynamic scenes), it's not ours*/	if (gf_list_find(ch->odm->net_service->Clocks, ch->clock)<0) return 0;	return (ch->esd->ESID==ch->clock->clockID) ? 1 : 0;}GF_Err gf_es_start(GF_Channel *ch){	if (!ch) return GF_BAD_PARAM;	switch (ch->es_state) {	case GF_ESM_ES_UNAVAILABLE:	case GF_ESM_ES_SETUP:		return GF_BAD_PARAM;	/*if the channel is already running, don't reset its settings. This only happens in the case of broadcast 	objects started several times by the scene but not stoped at the ODManager level (cf gf_odm_stop)*/	case GF_ESM_ES_RUNNING:		return GF_OK;	default:		break;	}	/*reset clock if we own it*/	if (gf_es_owns_clock(ch)) gf_clock_reset(ch->clock);	/*reset channel*/	Channel_Reset(ch, 1);	/*create pull buffer if needed*/	if (ch->is_pulling && !ch->AU_buffer_pull) ch->AU_buffer_pull = gf_db_unit_new();	/*and start buffering - pull channels always turn off buffering immediately, otherwise 	buffering size is setup by the network service - except InputSensor*/	if ((ch->esd->decoderConfig->streamType != GF_STREAM_INTERACT) || ch->esd->URLString) {		ch_buffer_on(ch);	}	ch->last_au_time = gf_term_get_time(ch->odm->term);	ch->es_state = GF_ESM_ES_RUNNING;	return GF_OK;}GF_Err gf_es_stop(GF_Channel *ch){	if (!ch) return GF_BAD_PARAM;	switch (ch->es_state) {	case GF_ESM_ES_UNAVAILABLE:	case GF_ESM_ES_SETUP:		return GF_BAD_PARAM;	default:		break;	}	ch_buffer_off(ch);	ch->es_state = GF_ESM_ES_CONNECTED;	Channel_Reset(ch, 0);	return GF_OK;}void Channel_WaitRAP(GF_Channel *ch){	ch->pck_sn = 0;	/*if using RAP signal and codec not resilient, wait for rap. If RAP isn't signaled DON'T wait for it :)*/	if (!ch->codec_resilient) ch->stream_state = 2;	if (ch->buffer) free(ch->buffer);	ch->buffer = NULL;	ch->AULength = 0;	ch->au_sn = 0;}void gf_es_map_time(GF_Channel *ch, Bool reset){	gf_mx_p(ch->mx);	if (ch->buffer) free(ch->buffer);	ch->buffer = NULL;	ch->len = ch->allocSize = 0;	if (reset) {		gf_db_unit_del(ch->AU_buffer_first);		ch->AU_buffer_first = ch->AU_buffer_last = NULL;		ch->AU_Count = 0;	} else {		GF_DBUnit *au = ch->AU_buffer_first;		while (au) {			au->DTS = au->CTS = ch->ts_offset;			au = au->next;		}	}	ch->BufferTime = 0;	gf_mx_v(ch->mx);}static Bool Channel_NeedsBuffering(GF_Channel *ch, u32 ForRebuffering){	if (!ch->MaxBuffer || ch->IsEndOfStream) return 0;	/*for rebuffering, check we're not below min buffer*/	if (ForRebuffering) {		if (ch->MinBuffer && (ch->BufferTime <= (s32) ch->MinBuffer)) {			return 1;		}		return 0;	}	/*we're in a broadcast scenario and one of the stream running on this clock has completed its buffering: 	abort all buffering*/	if (ch->clock->no_time_ctrl == 2) return 0;	/*nothing received, buffer needed*/	if (!ch->first_au_fetched && !ch->AU_buffer_first) {		u32 now = gf_term_get_time(ch->odm->term);		/*data timeout (no data sent)*/		if (now > ch->last_au_time + ch->odm->term->net_data_timeout) {			gf_term_message(ch->odm->term, ch->service->url, "Data timeout - aborting buffering", GF_OK); 			ch->MinBuffer = ch->MaxBuffer = 0;			ch->au_duration = 0;			gf_is_buffering_info(ch->odm->parentscene ? ch->odm->parentscene : ch->odm->subscene);			return 0;		} else {			now = ch->odm->term->net_data_timeout + ch->last_au_time - now;			now /= 1000;			if (now != ch->au_duration) {				char szMsg[500];				ch->au_duration = now;				sprintf(szMsg, "Buffering - Waiting for data (%d s)", now);				gf_term_message(ch->odm->term, ch->service->url, szMsg, GF_OK); 			}			return 1;		}	}	/*buffer not filled yet*/	if (ch->BufferTime < (s32) ch->MaxBuffer) {		/*check last AU time*/		u32 now = gf_term_get_time(ch->odm->term);		/*if more than half sec since last AU don't buffer and prevent rebuffering on short streams		this will also work for channels ignoring timing*/		if (now>ch->last_au_time + MAX(ch->BufferTime, 500) ) {			/*this can be safely seen as a stream with very few updates (likely only one)*/			if (!ch->AU_buffer_first && ch->first_au_fetched) ch->MinBuffer = 0;			return 0;		}		return 1;	}	return 0;}static void Channel_UpdateBuffering(GF_Channel *ch, Bool update_info){	if (update_info && ch->MaxBuffer) gf_is_buffering_info(ch->odm->parentscene ? ch->odm->parentscene : ch->odm->subscene);	if (!Channel_NeedsBuffering(ch, 0)) {		ch_buffer_off(ch);		if (ch->MaxBuffer) gf_is_buffering_info(ch->odm->parentscene ? ch->odm->parentscene : ch->odm->subscene);		if (ch->clock->no_time_ctrl) ch->clock->no_time_ctrl = 2;	}}static void Channel_UpdateBufferTime(GF_Channel *ch){	if (!ch->AU_buffer_first) {		ch->BufferTime = 0;	}	else if (ch->skip_sl) {		GF_DBUnit *au;		/*compute buffer size from avg bitrate*/		u32 avg_rate = ch->esd->decoderConfig->avgBitrate;		if (!avg_rate && ch->odm->codec) avg_rate = ch->odm->codec->avg_bit_rate;		if (avg_rate) {			u32 bsize = 0;			au = ch->AU_buffer_first;			while (1) {				bsize += au->dataLength*8;				if (!au->next) break;				au = au->next;			}			ch->BufferTime = 1000*bsize/avg_rate;		} else {			/*we're in the dark, so don't buffer too much (assume 50ms per unit) so that we start decoding asap*/			ch->BufferTime = 50*ch->AU_Count;		}	} else {		s32 bt = ch->AU_buffer_last->DTS - gf_clock_time(ch->clock);		ch->BufferTime = 0;		if (bt>0) ch->BufferTime = (u32) bt;	}	ch->BufferTime += ch->au_duration;}/*dispatch the AU in the DB*/static void Channel_DispatchAU(GF_Channel *ch, u32 duration){	GF_DBUnit *au;	if (!ch->buffer || !ch->len) {		if (ch->buffer) {			free(ch->buffer);			ch->buffer = NULL;		}		return;	}	au = gf_db_unit_new();	if (!au) {		free(ch->buffer);		ch->buffer = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -