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

📄 main.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
			muxer->last_br_time = now;			muxer->pck_sent=0;		}	}	return ret;}typedef struct{	GF_ISOFile *mp4;	u32 track, sample_number, sample_count;	GF_ISOSample *sample;} GF_ESIMP4;static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param){	GF_ESIMP4 *priv = (GF_ESIMP4 *)ifce->input_udta;	if (!priv) return GF_BAD_PARAM;	switch (act_type) {	case GF_ESI_INPUT_DATA_FLUSH:		return GF_OK;	case GF_ESI_INPUT_DATA_PULL:	{		GF_ESIPacket *pck = (GF_ESIPacket *)param;		if (!priv->sample) {			priv->sample = gf_isom_get_sample(priv->mp4, priv->track, priv->sample_number+1, NULL);		}		if (!priv->sample) return GF_IO_ERR;		pck->dts = priv->sample->DTS;		pck->cts = priv->sample->DTS + priv->sample->CTS_Offset;		pck->data_len = priv->sample->dataLength;		pck->data = priv->sample->data;		pck->flags = GF_ESI_DATA_AU_START | GF_ESI_DATA_AU_END;		if (priv->sample->IsRAP) pck->flags |= GF_ESI_DATA_AU_RAP;	}		return GF_OK;	case GF_ESI_INPUT_DATA_RELEASE:		if (priv->sample) {			gf_isom_sample_del(&priv->sample);			priv->sample_number++;			if (priv->sample_number==priv->sample_count) 				ifce->caps |= GF_ESI_STREAM_IS_OVER;		}		return GF_OK;	case GF_ESI_INPUT_DESTROY:		free(priv);		ifce->input_udta = NULL;		return GF_OK;	default:		return GF_BAD_PARAM;	}}static void fill_isom_es_ifce(GF_ESInterface *ifce, GF_ISOFile *mp4, u32 track_num){	GF_ESIMP4 *priv;	char _lan[4];	GF_DecoderConfig *dcd;	u64 avg_rate;	GF_SAFEALLOC(priv, GF_ESIMP4);	priv->mp4 = mp4;	priv->track = track_num;	priv->sample_count = gf_isom_get_sample_count(mp4, track_num);	memset(ifce, 0, sizeof(GF_ESInterface));	ifce->caps = GF_ESI_AU_PULL_CAP;	ifce->stream_id = gf_isom_get_track_id(mp4, track_num);	dcd = gf_isom_get_decoder_config(mp4, track_num, 1);	ifce->stream_type = dcd->streamType;	ifce->object_type_indication = dcd->objectTypeIndication;	gf_odf_desc_del((GF_Descriptor *)dcd);	gf_isom_get_media_language(mp4, track_num, _lan);	ifce->lang = GF_4CC(_lan[0],_lan[1],_lan[2],' ');	ifce->timescale = gf_isom_get_media_timescale(mp4, track_num);	ifce->duration = gf_isom_get_media_timescale(mp4, track_num);	avg_rate = gf_isom_get_media_data_size(mp4, track_num);	avg_rate *= ifce->timescale * 8;	avg_rate /= gf_isom_get_media_duration(mp4, track_num);	if (gf_isom_has_time_offset(mp4, track_num)) ifce->caps |= GF_ESI_SIGNAL_DTS;	ifce->bit_rate = (u32) avg_rate;	ifce->duration = (Double) (s64) gf_isom_get_media_duration(mp4, track_num);	ifce->duration /= ifce->timescale;	ifce->input_ctrl = mp4_input_ctrl;	ifce->input_udta = priv;}typedef struct{	/*RTP channel*/	GF_RTPChannel *rtp_ch;	/*depacketizer*/	GF_RTPDepacketizer *depacketizer;	GF_ESIPacket pck;	GF_ESInterface *ifce;} GF_ESIRTP;static GF_Err rtp_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param){	u32 size, PayloadStart;	GF_Err e;	GF_RTPHeader hdr;	char buffer[8000];	GF_ESIRTP *rtp = (GF_ESIRTP*)ifce->input_udta;	if (!ifce->input_udta) return GF_BAD_PARAM;	switch (act_type) {	case GF_ESI_INPUT_DATA_FLUSH:		/*flush rtp channel*/		while (1) {			size = gf_rtp_read_rtp(rtp->rtp_ch, buffer, 8000);			if (!size) break;			e = gf_rtp_decode_rtp(rtp->rtp_ch, buffer, size, &hdr, &PayloadStart);			if (e) return e;			gf_rtp_depacketizer_process(rtp->depacketizer, &hdr, buffer + PayloadStart, size - PayloadStart);		}		/*flush rtcp channel*/		while (1) {			size = gf_rtp_read_rtcp(rtp->rtp_ch, buffer, 8000);			if (!size) break;			e = gf_rtp_decode_rtcp(rtp->rtp_ch, buffer, size);			if (e == GF_EOS) ifce->caps |= GF_ESI_STREAM_IS_OVER;		}		return GF_OK;	case GF_ESI_INPUT_DESTROY:		gf_rtp_depacketizer_del(rtp->depacketizer);		gf_rtp_del(rtp->rtp_ch);		free(rtp);		ifce->input_udta = NULL;		return GF_OK;	}	return GF_OK;}static void rtp_sl_packet_cbk(void *udta, char *payload, u32 size, GF_SLHeader *hdr, GF_Err e){	GF_ESIRTP *rtp = (GF_ESIRTP*)udta;	rtp->pck.data = payload;	rtp->pck.data_len = size;	rtp->pck.dts = hdr->decodingTimeStamp;	rtp->pck.cts = hdr->compositionTimeStamp;	rtp->pck.flags = 0;	if (hdr->compositionTimeStampFlag) rtp->pck.flags |= GF_ESI_DATA_HAS_CTS;	if (hdr->decodingTimeStampFlag) rtp->pck.flags |= GF_ESI_DATA_HAS_DTS;	if (hdr->randomAccessPointFlag) rtp->pck.flags |= GF_ESI_DATA_AU_RAP;	if (hdr->accessUnitStartFlag) rtp->pck.flags |= GF_ESI_DATA_AU_START;	if (hdr->accessUnitEndFlag) rtp->pck.flags |= GF_ESI_DATA_AU_END;	rtp->ifce->output_ctrl(rtp->ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &rtp->pck);}void fill_rtp_es_ifce(GF_ESInterface *ifce, GF_SDPMedia *media, GF_SDPInfo *sdp){	u32 i;	GF_Err e;	GF_X_Attribute*att;	GF_ESIRTP *rtp;	GF_RTPMap*map;	GF_SDPConnection *conn;	GF_RTSPTransport trans;	/*check connection*/	conn = sdp->c_connection;	if (!conn) conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0);	/*check payload type*/	map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0);	GF_SAFEALLOC(rtp, GF_ESIRTP);	memset(ifce, 0, sizeof(GF_ESInterface));	rtp->rtp_ch = gf_rtp_new();	i=0;	while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &i))) {		if (!stricmp(att->Name, "mpeg4-esid") && att->Value) ifce->stream_id = atoi(att->Value);	}	memset(&trans, 0, sizeof(GF_RTSPTransport));	trans.Profile = media->Profile;	trans.source = conn ? conn->host : sdp->o_address;	trans.IsUnicast = gf_sk_is_multicast_address(trans.source) ? 0 : 1;	if (!trans.IsUnicast) {		trans.port_first = media->PortNumber;		trans.port_last = media->PortNumber + 1;		trans.TTL = conn ? conn->TTL : 0;	} else {		trans.client_port_first = media->PortNumber;		trans.client_port_last = media->PortNumber + 1;	}	if (gf_rtp_setup_transport(rtp->rtp_ch, &trans, NULL) != GF_OK) {		gf_rtp_del(rtp->rtp_ch);		fprintf(stdout, "Cannot initialize RTP transport\n");		return;	}	/*setup depacketizer*/	rtp->depacketizer = gf_rtp_depacketizer_new(media, rtp_sl_packet_cbk, rtp);	if (!rtp->depacketizer) {		gf_rtp_del(rtp->rtp_ch);		fprintf(stdout, "Cannot create RTP depacketizer\n");		return;	}	/*setup channel*/	gf_rtp_setup_payload(rtp->rtp_ch, map);	ifce->input_udta = rtp;	ifce->input_ctrl = rtp_input_ctrl;	rtp->ifce = ifce;	ifce->object_type_indication = rtp->depacketizer->sl_map.ObjectTypeIndication;	ifce->stream_type = rtp->depacketizer->sl_map.StreamType;	ifce->timescale = gf_rtp_get_clockrate(rtp->rtp_ch);	/*DTS signaling is only supported for MPEG-4 visual*/	if (rtp->depacketizer->sl_map.DTSDeltaLength) ifce->caps |= GF_ESI_SIGNAL_DTS;	gf_rtp_depacketizer_reset(rtp->depacketizer, 1);	e = gf_rtp_initialize(rtp->rtp_ch, 0x100000ul, 0, 0, 10, 200, NULL);	if (e!=GF_OK) {		gf_rtp_del(rtp->rtp_ch);		fprintf(stdout, "Cannot initialize RTP channel: %s\n", gf_error_to_string(e));		return;	}	fprintf(stdout, "RTP interface initialized\n");}#define MAX_MUX_SRC_PROG	100typedef struct{	GF_ISOFile *mp4;	u32 nb_streams, pcr_idx;	GF_ESInterface streams[40];} M2TSProgram;Bool open_program(M2TSProgram *prog, const char *src){	GF_SDPInfo *sdp;	u32 i;	GF_Err e;	memset(prog, 0, sizeof(M2TSProgram));	/* Open ISO file  */	if (gf_isom_probe_file(src)) {		prog->mp4 = gf_isom_open(src, GF_ISOM_OPEN_READ, 0);		prog->nb_streams = gf_isom_get_track_count(prog->mp4); 		for (i=0; i<prog->nb_streams; i++) {			fill_isom_es_ifce(&prog->streams[i], prog->mp4, i+1);			/*get first visual stream as PCR*/			if (!prog->pcr_idx && (gf_isom_get_media_type(prog->mp4, i+1) == GF_ISOM_MEDIA_VISUAL) && (gf_isom_get_sample_count(prog->mp4, i+1)>1) ) {				prog->pcr_idx = i+1;			}		}		if (prog->pcr_idx) prog->pcr_idx-=1;		return 1;	}	/*open SDP file*/	if (strstr(src, ".sdp")) {		char *sdp_buf;		u32 sdp_size;		FILE *_sdp = fopen(src, "rt");		if (!_sdp) {			fprintf(stderr, "Error opening %s - no such file\n", src);			return 0;		}		fseek(_sdp, 0, SEEK_END);		sdp_size = ftell(_sdp);		fseek(_sdp, 0, SEEK_SET);		sdp_buf = (char*)malloc(sizeof(char)*sdp_size);		memset(sdp_buf, 0, sizeof(char)*sdp_size);		fread(sdp_buf, sdp_size, 1, _sdp);		fclose(_sdp);		sdp = gf_sdp_info_new();		e = gf_sdp_info_parse(sdp, sdp_buf, sdp_size);		free(sdp_buf);		if (e) {			fprintf(stderr, "Error opening %s : %s\n", src, gf_error_to_string(e));			gf_sdp_info_del(sdp);			return 0;		}		prog->nb_streams = gf_list_count(sdp->media_desc);		for (i=0; i<prog->nb_streams; i++) {			GF_SDPMedia *media = gf_list_get(sdp->media_desc, i);			fill_rtp_es_ifce(&prog->streams[i], media, sdp);			if (!prog->pcr_idx && (prog->streams[i].stream_type == GF_STREAM_VISUAL)) {				prog->pcr_idx = i+1;			}		}		if (prog->pcr_idx) prog->pcr_idx-=1;		gf_sdp_info_del(sdp);		return 2;	} else {		fprintf(stderr, "Error opening %s - not a supported input media, skipping.\n", src);		return 0;	}}int main(int argc, char **argv){	const char *ts_pck;	GF_Err e;	u32 res;	Bool real_time=0;	M2TS_Mux *muxer;	u32 i, j, mux_rate, nb_progs, cur_pid;	char *ts_out = NULL;	FILE *ts_file;	GF_Socket *ts_udp;	GF_RTPChannel *ts_rtp;	GF_RTSPTransport tr;	GF_RTPHeader hdr;	u16 port = 1234;	u32 output_type;	M2TSProgram progs[MAX_MUX_SRC_PROG];	output_type = 0;	ts_file = NULL;	ts_udp = NULL;	ts_rtp = NULL;	ts_out = NULL;	nb_progs = 0;	mux_rate = 0;	for (i=1; i<argc; i++) {		char *arg = argv[i];		if (arg[0]=='-') {			if (!strnicmp(arg, "-rate=", 6)) mux_rate = 1024*atoi(arg+6);			else if (!strnicmp(arg, "-prog=", 6)) {				memset(&progs[nb_progs], 0, sizeof(M2TSProgram));				res = open_program(&progs[nb_progs], arg+6);				if (res) {					nb_progs++;					if (res==2) real_time=1;				}			}		}		/*output*/		else {			if (!strnicmp(arg, "rtp://", 6) || !strnicmp(arg, "udp://", 6)) {				char *sep = strchr(arg+6, ':');				output_type = (arg[0]=='r') ? 1 : 2;				real_time=1;				if (sep) {					port = atoi(sep+1);					sep[0]=0;					ts_out = strdup(arg);					sep[0]=':';				} else {					ts_out = strdup(arg+6);				}			} 			else if (!strnicmp(arg, "udp://", 6)) {				output_type = 1;				ts_out = arg;				real_time=1;			} else {				output_type = 0;				ts_out = strdup(arg);			}		}	}	if (!nb_progs || !ts_out) {		usage();		return 0;	}	gf_log_set_level(GF_LOG_DEBUG);	gf_log_set_tools(GF_LOG_RTP);//	gf_log_set_tools(GF_LOG_CONTAINER);	gf_sys_init();	GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("What a FGucking test!!\n"));	muxer = m2ts_mux_new(mux_rate, real_time);	/* Open mpeg2ts file*/	switch(output_type) {	case 0:		ts_file = fopen(ts_out, "wb");		if (!ts_file ) {			fprintf(stderr, "Error opening %s\n", ts_out);			goto exit;		}		break;	case 1:		ts_udp = gf_sk_new(GF_SOCK_TYPE_UDP);		if (gf_sk_is_multicast_address((char *)ts_out)) {			e = gf_sk_setup_multicast(ts_udp, (char *)ts_out, port, 0, 0, NULL);		} else {			e = gf_sk_bind(ts_udp, port, (char *)ts_out, port, GF_SOCK_REUSE_PORT);		}		if (e) {			fprintf(stdout, "Error inhitializing UDP socket: %s\n", gf_error_to_string(e));			goto exit;		}		break;	case 2:		ts_rtp = gf_rtp_new();		gf_rtp_set_ports(ts_rtp, port);		tr.IsUnicast = gf_sk_is_multicast_address((char *)ts_out) ? 0 : 1;		tr.Profile="RTP/AVP";		tr.destination = (char *)ts_out;		tr.source = "0.0.0.0";		tr.IsRecord = 0;		tr.Append = 0;		tr.SSRC = rand();		tr.port_first = port;		tr.port_last = port+1;		if (tr.IsUnicast) {			tr.client_port_first = port;			tr.client_port_last = port+1;		} else {			tr.source = (char *)ts_out;		}		res = gf_rtp_setup_transport(ts_rtp, &tr, (char *)ts_out);		if (res !=0) {			fprintf(stdout, "Cannot setup RTP transport info\n");			goto exit;		}		res = gf_rtp_initialize(ts_rtp, 0, 1, 1500, 0, 0, NULL);		if (res !=0) {			fprintf(stdout, "Cannot initialize RTP sockets\n");			goto exit;		}		memset(&hdr, 0, sizeof(GF_RTPHeader));		hdr.Version = 2;		hdr.PayloadType = 33;	/*MP2T*/		hdr.SSRC = tr.SSRC;		hdr.Marker = 0;		break;	}		cur_pid = 100;	for (i=0; i<nb_progs; i++) {		M2TS_Mux_Program *program = m2ts_mux_program_add(muxer, i+1, cur_pid);		for (j=0; j<progs[i].nb_streams; j++) {			m2ts_program_stream_add(program, &progs[i].streams[j], cur_pid+j+1, (progs[i].pcr_idx==j) ? 1 : 0);		}		cur_pid += progs[i].nb_streams;		while (cur_pid % 10)			cur_pid ++;	}	m2ts_mux_update_config(muxer, 1);	while (1) {		u32 ts;		u32 status;		/*flush all packets*/		switch (output_type) {		case 0:			while ((ts_pck = m2ts_mux_process(muxer, &status)) != NULL) {				fwrite(ts_pck, 1, 188, ts_file); 				if (status>=GF_M2TS_STATE_PADDING) break;			}			break;		case 1:			while ((ts_pck = m2ts_mux_process(muxer, &status)) != NULL) {				e = gf_sk_send(ts_udp, (char*)ts_pck, 188); 				if (e) 					fprintf(stdout, "Error %s sending UDP packet\n", gf_error_to_string(e));				if (status>=GF_M2TS_STATE_PADDING) break;			}			break;		case 2:			while ((ts_pck = m2ts_mux_process(muxer, &status)) != NULL) {				hdr.SequenceNumber++;				/*muxer clock at 90k*/				ts = muxer->time.sec*90000 + muxer->time.nanosec*9/100000;				/*FIXME - better discontinuity check*/				hdr.Marker = (ts < hdr.TimeStamp) ? 1 : 0;				hdr.TimeStamp = ts;				e = gf_rtp_send_packet(ts_rtp, &hdr, 0, 0, (char*)ts_pck, 188);				if (e) 					fprintf(stdout, "Error %s sending RTP packet\n", gf_error_to_string(e));				if (status>=GF_M2TS_STATE_PADDING) break;			}			break;		}		if (real_time) {			/*abort*/			if (gf_prompt_has_input()) {				char c = gf_prompt_get_char();				if (c == 'q') break;			}			fprintf(stdout, "M2TS: time %d - TS time %d - avg bitrate %d\r", gf_m2ts_get_sys_clock(muxer), gf_m2ts_get_ts_clock(muxer), muxer->avg_br);		} else {			if (status==GF_M2TS_STATE_EOS) 				break;		}	}exit:	if (ts_file) fclose(ts_file);	if (ts_udp) gf_sk_del(ts_udp);	if (ts_rtp) gf_rtp_del(ts_rtp);	if (ts_out) free(ts_out);	m2ts_mux_del(muxer);		for (i=0; i<nb_progs; i++) {		for (j=0; j<progs[i].nb_streams; j++) {			progs[i].streams[j].input_ctrl(&progs[i].streams[j], GF_ESI_INPUT_DESTROY, NULL);		}		if (progs[i].mp4) gf_isom_close(progs[i].mp4);	}	gf_sys_close();	return 1;}

⌨️ 快捷键说明

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