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

📄 timedtext_in.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / 3GPP/MPEG4 timed text module * *  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/modules/service.h>#include <gpac/modules/codec.h>#include <gpac/constants.h>#ifndef GPAC_READ_ONLY#include <gpac/media_tools.h>typedef struct{	GF_ClientService *service;	Bool od_done;	Bool needs_connection;	u32 status;	LPNETCHANNEL ch;	GF_SLHeader sl_hdr;	GF_ISOFile *mp4;	char *szFile;	u32 tt_track;	GF_ISOSample *samp;	u32 samp_num;	u32 start_range;	/*file downloader*/	GF_DownloadSession * dnload;} TTIn;static Bool TTIn_CanHandleURL(GF_InputService *plug, const char *url){	char *sExt;	sExt = strrchr(url, '.');	if (!sExt) return 0;	if (gf_term_check_extension(plug, "x-subtitle/srt", "srt", "SRT SubTitles", sExt)) return 1;	if (gf_term_check_extension(plug, "x-subtitle/sub", "sub", "SUB SubTitles", sExt)) return 1;	if (gf_term_check_extension(plug, "x-subtitle/ttxt", "ttxt", "3GPP TimedText", sExt)) return 1;	return 0;}static Bool TTIn_is_local(const char *url){	if (!strnicmp(url, "file://", 7)) return 1;	if (strstr(url, "://")) return 0;	return 1;}static GF_ESD *tti_get_esd(TTIn *tti){	return gf_media_map_esd(tti->mp4, tti->tt_track);}static void tti_setup_object(TTIn *tti){	GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);	GF_ESD *esd = tti_get_esd(tti);	od->objectDescriptorID = esd->ESID;	gf_list_add(od->ESDescriptors, esd);	gf_term_add_media(tti->service, (GF_Descriptor *)od, 0);}GF_Err TTIn_LoadFile(GF_InputService *plug, const char *url, Bool is_cache){	GF_Err e;	GF_MediaImporter import;	char szFILE[GF_MAX_PATH];	TTIn *tti = (TTIn *)plug->priv;	const char *cache_dir = gf_modules_get_option((GF_BaseInterface *)plug, "General", "CacheDirectory");		if (cache_dir && strlen(cache_dir)) {		if (cache_dir[strlen(cache_dir)-1] != GF_PATH_SEPARATOR) {			sprintf(szFILE, "%s%csrt_%d_mp4", cache_dir, GF_PATH_SEPARATOR, (u32) tti);		} else {			sprintf(szFILE, "%ssrt_%d_mp4", cache_dir, (u32) tti);		}	} else {		sprintf(szFILE, "%d_temp_mp4", (u32) tti);	}	tti->mp4 = gf_isom_open(szFILE, GF_ISOM_OPEN_WRITE, NULL);	if (!tti->mp4) return gf_isom_last_error(NULL);	tti->szFile = strdup(szFILE);	memset(&import, 0, sizeof(GF_MediaImporter));	import.dest = tti->mp4;	/*override layout from sub file*/	import.flags = GF_IMPORT_SKIP_TXT_BOX;	import.in_name = (char *) url;		e = gf_media_import(&import);	if (!e) {		tti->tt_track = 1;		gf_isom_text_set_streaming_mode(tti->mp4, 1);	}	return e;}void TTIn_NetIO(void *cbk, GF_NETIO_Parameter *param){	GF_Err e;	const char *szCache;	GF_InputService *plug = (GF_InputService *)cbk;	TTIn *tti = (TTIn *) plug->priv;	gf_term_download_update_stats(tti->dnload);	e = param->error;	/*done*/	if (param->msg_type==GF_NETIO_DATA_TRANSFERED) {		szCache = gf_dm_sess_get_cache_name(tti->dnload);		if (!szCache) e = GF_IO_ERR;		else {			e = TTIn_LoadFile(plug, szCache, 1);		}	} 	else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) 		return;	/*OK confirm*/	if (tti->needs_connection) {		tti->needs_connection = 0;		gf_term_on_connect(tti->service, NULL, e);		if (!e) tti_setup_object(tti);	}}void TTIn_download_file(GF_InputService *plug, char *url){	TTIn *tti = (TTIn *) plug->priv;	tti->needs_connection = 1;	tti->dnload = gf_term_download_new(tti->service, url, 0, TTIn_NetIO, plug);	if (!tti->dnload) {		tti->needs_connection = 0;		gf_term_on_connect(tti->service, NULL, GF_NOT_SUPPORTED);	}	/*service confirm is done once fetched*/}static GF_Err TTIn_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url){	GF_Err e;	TTIn *tti = (TTIn *)plug->priv;	tti->service = serv;	if (tti->dnload) gf_term_download_del(tti->dnload);	tti->dnload = NULL;	/*remote fetch*/	if (!TTIn_is_local(url)) {		TTIn_download_file(plug, (char *) url);		return GF_OK;	}	e = TTIn_LoadFile(plug, url, 0);	gf_term_on_connect(serv, NULL, e);	if (!e) tti_setup_object(tti);	return GF_OK;}static GF_Err TTIn_CloseService(GF_InputService *plug){	TTIn *tti = (TTIn *)plug->priv;	if (tti->samp) gf_isom_sample_del(&tti->samp);	if (tti->mp4) gf_isom_delete(tti->mp4);	tti->mp4 = NULL;	if (tti->szFile) {		gf_delete_file(tti->szFile);		free(tti->szFile);		tti->szFile = NULL;	}	if (tti->dnload) gf_term_download_del(tti->dnload);	tti->dnload = NULL;	gf_term_on_disconnect(tti->service, NULL, GF_OK);	return GF_OK;}static GF_Descriptor *TTIn_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url){	TTIn *tti = (TTIn *)plug->priv;	/*visual object*/	if (expect_type==GF_MEDIA_OBJECT_TEXT) {		GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);		GF_ESD *esd = tti_get_esd(tti);		od->objectDescriptorID = esd->ESID;		gf_list_add(od->ESDescriptors, esd);		return (GF_Descriptor *) od;	}	return NULL;}static GF_Err TTIn_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream){	u32 ES_ID;	GF_Err e;	TTIn *tti = (TTIn *)plug->priv;	e = GF_SERVICE_ERROR;	if (tti->ch==channel) goto exit;	e = GF_STREAM_NOT_FOUND;	ES_ID = 0;	if (strstr(url, "ES_ID")) sscanf(url, "ES_ID=%d", &ES_ID);	if (ES_ID==1) {		tti->ch = channel;		e = GF_OK;	}exit:	gf_term_on_connect(tti->service, channel, e);	return e;}static GF_Err TTIn_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel){	TTIn *tti = (TTIn *)plug->priv;	GF_Err e = GF_STREAM_NOT_FOUND;	if (tti->ch == channel) {		tti->ch = NULL;		e = GF_OK;	}	gf_term_on_disconnect(tti->service, channel, e);	return GF_OK;}static GF_Err TTIn_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com){	TTIn *tti = (TTIn *)plug->priv;	if (!com->base.on_channel) return GF_NOT_SUPPORTED;	switch (com->command_type) {	case GF_NET_CHAN_SET_PADDING:		gf_isom_set_sample_padding(tti->mp4, tti->tt_track, com->pad.padding_bytes);		return GF_OK;	case GF_NET_CHAN_DURATION:		com->duration.duration = (Double) (s64) gf_isom_get_media_duration(tti->mp4, tti->tt_track);		com->duration.duration /= gf_isom_get_media_timescale(tti->mp4, tti->tt_track);		return GF_OK;	case GF_NET_CHAN_PLAY:		tti->start_range = (com->play.start_range>0) ? (u32) (com->play.start_range * 1000) : 0;		if (tti->ch == com->base.on_channel) {			tti->samp_num = 0;			if (tti->samp) gf_isom_sample_del(&tti->samp);		}		return GF_OK;	case GF_NET_CHAN_STOP:		return GF_OK;	default:		return GF_OK;	}}static GF_Err TTIn_ChannelGetSLP(GF_InputService *plug, LPNETCHANNEL channel, char **out_data_ptr, u32 *out_data_size, GF_SLHeader *out_sl_hdr, Bool *sl_compressed, GF_Err *out_reception_status, Bool *is_new_data){	TTIn *tti = (TTIn *)plug->priv;	*out_reception_status = GF_OK;	*sl_compressed = 0;	*is_new_data = 0;	memset(&tti->sl_hdr, 0, sizeof(GF_SLHeader));	tti->sl_hdr.randomAccessPointFlag = 1;	tti->sl_hdr.compositionTimeStampFlag = 1;	tti->sl_hdr.accessUnitStartFlag = tti->sl_hdr.accessUnitEndFlag = 1;	/*fetching es data*/	if (tti->ch == channel) {		if (tti->samp_num>=gf_isom_get_sample_count(tti->mp4, tti->tt_track)) {			*out_reception_status = GF_EOS;			return GF_OK;		}		if (!tti->samp) {			u32 di;			if (tti->start_range) {				u32 di;				*out_reception_status = gf_isom_get_sample_for_movie_time(tti->mp4, tti->tt_track, tti->start_range, &di, GF_ISOM_SEARCH_SYNC_BACKWARD, &tti->samp, &tti->samp_num);				tti->start_range = 0;			} else {				tti->samp = gf_isom_get_sample(tti->mp4, tti->tt_track, tti->samp_num+1, &di);			}			if (!tti->samp) {				*out_reception_status = GF_CORRUPTED_DATA;				return GF_OK;			}			*is_new_data = 1;		}		tti->sl_hdr.compositionTimeStamp = tti->sl_hdr.decodingTimeStamp = tti->samp->DTS;		*out_data_ptr = tti->samp->data;		*out_data_size = tti->samp->dataLength;		*out_sl_hdr = tti->sl_hdr;		return GF_OK;	}	return GF_STREAM_NOT_FOUND;}static GF_Err TTIn_ChannelReleaseSLP(GF_InputService *plug, LPNETCHANNEL channel){	TTIn *tti = (TTIn *)plug->priv;	if (tti->ch == channel) {		if (!tti->samp) return GF_BAD_PARAM;		gf_isom_sample_del(&tti->samp);		tti->samp = NULL;		tti->samp_num++;		return GF_OK;	}	return GF_OK;}void *NewTTReader(){	TTIn *priv;	GF_InputService *plug;	GF_SAFEALLOC(plug, GF_InputService);	GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC SubTitle Reader", "gpac distribution")	plug->CanHandleURL = TTIn_CanHandleURL;	plug->CanHandleURLInService = NULL;	plug->ConnectService = TTIn_ConnectService;	plug->CloseService = TTIn_CloseService;	plug->GetServiceDescriptor = TTIn_GetServiceDesc;	plug->ConnectChannel = TTIn_ConnectChannel;	plug->DisconnectChannel = TTIn_DisconnectChannel;	plug->ChannelGetSLP = TTIn_ChannelGetSLP;	plug->ChannelReleaseSLP = TTIn_ChannelReleaseSLP;	plug->ServiceCommand = TTIn_ServiceCommand;	GF_SAFEALLOC(priv, TTIn);	plug->priv = priv;	return plug;}void DeleteTTReader(void *ifce){	GF_InputService *plug = (GF_InputService *) ifce;	TTIn *tti = (TTIn *)plug->priv;	free(tti);	free(plug);}#endif

⌨️ 快捷键说明

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