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

📄 ogg_in.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / XIPH.org 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 "ogg_in.h"#include <ogg/ogg.h>typedef struct {	u32 streamType;	/*MPEG-4 streamType*/	u32 num_init_headers;	u32 sample_rate, bitrate;	u32 theora_kgs;	Float frame_rate;	u32 frame_rate_base;	u32 type;} OGGInfo;typedef struct{	ogg_stream_state os;	u32 serial_no;	/*DSI for ogg in mp4 - cf constants.h*/	char *dsi;	u32 dsi_len;	OGGInfo info;	Bool got_headers;	s64 seek_granule, last_granule;	Bool is_running;	u32 parse_headers;	LPNETCHANNEL ch;	u16 ESID;	Bool eos_detected, map_time;	u32 ogg_ts;	GF_VorbisParser vp;} OGGStream;typedef struct{	GF_ClientService *service;	GF_Thread *demuxer;	GF_List *streams;	FILE *ogfile;	u32 file_size;	Bool is_remote, is_inline;	u32 nb_playing, kill_demux, do_seek, service_type, init_remain, bos_done;	/*ogg ogfile state*/    ogg_sync_state oy;		OGGStream *resync_stream;	Bool has_video, has_audio, is_single_media;	Double dur;	u32 data_buffer_ms;	Bool needs_connection;	Double start_range, end_range;	/*file downloader*/	GF_DownloadSession * dnload;	Bool is_live;	u32 tune_in_time;} OGGReader;void OGG_EndOfFile(OGGReader *read){	OGGStream *st;	u32 i=0;	while ((st = gf_list_enum(read->streams, &i))) {		gf_term_on_sl_packet(read->service, st->ch, NULL, 0, NULL, GF_EOS);	}}#define OGG_BUFFER_SIZE 4096static Bool OGG_ReadPage(OGGReader *read, ogg_page *oggpage){	char buf[OGG_BUFFER_SIZE];	GF_Err e;	/*remote file, check if we use cache*/	if (read->is_remote) {		u32 total_size, status;		e = gf_dm_sess_get_stats(read->dnload, NULL, NULL, &total_size, NULL, NULL, &status);		/*not ready*/		if ((e<GF_OK) || (status > GF_NETIO_DATA_EXCHANGE)) return 0;		if (status == GF_NETIO_DATA_EXCHANGE) {			if (!total_size && !read->is_live) {				read->is_live = 1;				read->tune_in_time = gf_sys_clock();			}			else if (!read->is_live  && !read->ogfile) {				const char *szCache = gf_dm_sess_get_cache_name(read->dnload);				if (!szCache) return 0;				read->ogfile = fopen((char *) szCache, "rb");				if (!read->ogfile) return 0;			}		}	}    while (ogg_sync_pageout(&read->oy, oggpage ) != 1 ) {        char *buffer;		u32 bytes;				if (read->ogfile) {			if (feof(read->ogfile)) {				OGG_EndOfFile(read);				return 0;			}			bytes = fread(buf, 1, OGG_BUFFER_SIZE, read->ogfile);		} else {			e = gf_dm_sess_fetch_data(read->dnload, buf, OGG_BUFFER_SIZE, &bytes);			if (e) return 0;		}		if (!bytes) return 0;		buffer = ogg_sync_buffer(&read->oy, bytes);		memcpy(buffer, buf, bytes);        ogg_sync_wrote(&read->oy, bytes);    }    return 1;}static OGGStream *OGG_FindStreamForPage(OGGReader *read, ogg_page *oggpage){	u32 i, count;	count = gf_list_count(read->streams);	for (i=0; i<count; i++) {		OGGStream *st = gf_list_get(read->streams, i);        if (ogg_stream_pagein(&st->os, oggpage) == 0) return st;	}	return NULL;}static GF_ObjectDescriptor *OGG_GetOD(OGGStream *st){	GF_ObjectDescriptor *od;	GF_ESD *esd;	od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);	od->objectDescriptorID = (st->info.streamType==GF_STREAM_AUDIO) ? 3 : 2;	esd = gf_odf_desc_esd_new(0);	esd->decoderConfig->streamType = st->info.streamType;	esd->decoderConfig->objectTypeIndication = GPAC_OGG_MEDIA_OTI;	esd->decoderConfig->avgBitrate = st->info.bitrate;	esd->ESID = st->ESID;	esd->slConfig->useTimestampsFlag = 1;	esd->slConfig->useAccessUnitEndFlag = esd->slConfig->useAccessUnitStartFlag = 1;	esd->slConfig->timestampResolution = st->info.sample_rate ? st->info.sample_rate : (u32) (1000*st->info.frame_rate);	if (st->info.sample_rate) esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;	else esd->slConfig->useRandomAccessPointFlag = 1;	esd->decoderConfig->decoderSpecificInfo->dataLength = st->dsi_len;	esd->decoderConfig->decoderSpecificInfo->data = (char *) malloc(sizeof(char) * st->dsi_len);	memcpy(esd->decoderConfig->decoderSpecificInfo->data, st->dsi, sizeof(char) * st->dsi_len);	gf_list_add(od->ESDescriptors, esd);	return od;}u64 OGG_GranuleToTime(OGGInfo *cfg, s64 granule){	if (cfg->sample_rate) {		return granule;	}	if (cfg->frame_rate) {		s64 iframe = granule>>cfg->theora_kgs;		s64 pframe = granule - (iframe<<cfg->theora_kgs);		pframe += iframe;		pframe *= cfg->frame_rate_base;		return (u64) (pframe / cfg->frame_rate);	}	return 0;}Double OGG_GranuleToMediaTime(OGGInfo *cfg, s64 granule){	Double t = (Double) (s64) OGG_GranuleToTime(cfg, granule);	if (cfg->sample_rate) t /= cfg->sample_rate;	else t /= cfg->frame_rate_base;	return t;}static void OGG_GetStreamInfo(ogg_packet *oggpacket, OGGInfo *info) {	oggpack_buffer opb;	memset(info, 0, sizeof(OGGInfo));	/*vorbis*/	if ((oggpacket->bytes >= 7) && !strncmp(&oggpacket->packet[1], "vorbis", 6)) {		info->streamType = GF_STREAM_AUDIO;		oggpack_readinit(&opb, oggpacket->packet, oggpacket->bytes);		oggpack_adv( &opb, 88);		oggpack_adv( &opb, 8);	/*nb chan*/		info->sample_rate = oggpack_read(&opb, 32);		oggpack_adv( &opb, 32);	/*max rate*/		info->bitrate = oggpack_read(&opb, 32);		info->num_init_headers = 3;		info->type = OGG_VORBIS;	}	/*speex*/	else if ((oggpacket->bytes >= 7) && !strncmp(&oggpacket->packet[0], "Speex", 5)) {		info->streamType = GF_STREAM_AUDIO;		oggpack_readinit(&opb, oggpacket->packet, oggpacket->bytes);		oggpack_adv(&opb, 224);		oggpack_adv(&opb, 32);		oggpack_adv( &opb, 32);		info->sample_rate = oggpack_read(&opb, 32);		info->type = OGG_SPEEX;		info->num_init_headers = 1;	}	/*flac*/	else if ((oggpacket->bytes >= 4) && !strncmp(&oggpacket->packet[0], "fLaC", 4)) {		info->streamType = GF_STREAM_AUDIO;		info->type = 3;		info->num_init_headers = OGG_FLAC;	}	/*theora*/	else if ((oggpacket->bytes >= 7) && !strncmp(&oggpacket->packet[1], "theora", 6)) {		GF_BitStream *bs;		u32 fps_numerator, fps_denominator, keyframe_freq_force;		info->streamType = GF_STREAM_VISUAL;		info->type = OGG_THEORA;		bs = gf_bs_new(oggpacket->packet, oggpacket->bytes, GF_BITSTREAM_READ);		gf_bs_read_int(bs, 56);		gf_bs_read_int(bs, 8); /* major version num */		gf_bs_read_int(bs, 8); /* minor version num */		gf_bs_read_int(bs, 8); /* subminor version num */		gf_bs_read_int(bs, 16) /*<< 4*/; /* width */		gf_bs_read_int(bs, 16) /*<< 4*/; /* height */		gf_bs_read_int(bs, 24); /* frame width */		gf_bs_read_int(bs, 24); /* frame height */		gf_bs_read_int(bs, 8); /* x offset */		gf_bs_read_int(bs, 8); /* y offset */		fps_numerator = gf_bs_read_u32(bs);		fps_denominator = gf_bs_read_u32(bs);		gf_bs_read_int(bs, 24); /* aspect_numerator */		gf_bs_read_int(bs, 24); /* aspect_denominator */		gf_bs_read_int(bs, 8); /* colorspace */		gf_bs_read_int(bs, 24);/* bitrate */		gf_bs_read_int(bs, 6); /* quality */		keyframe_freq_force = 1 << gf_bs_read_int(bs, 5);		info->theora_kgs = 0;		keyframe_freq_force--;		while (keyframe_freq_force) {			info->theora_kgs ++;			keyframe_freq_force >>= 1;		}	    info->frame_rate = ((Float)fps_numerator) / fps_denominator;		info->num_init_headers = 3;		gf_bs_del(bs);		info->frame_rate_base = fps_denominator;	}}static void OGG_ResetupStream(OGGReader *read, OGGStream *st, ogg_page *oggpage){	ogg_stream_clear(&st->os);	ogg_stream_init(&st->os, st->serial_no);	ogg_stream_pagein(&st->os, oggpage);	st->parse_headers = st->info.num_init_headers;		if (st->info.sample_rate) {		st->seek_granule = (s64) (read->start_range * st->info.sample_rate);	} else if (st->info.frame_rate) {		s64 seek = (s64) (read->start_range * st->info.frame_rate) - 1;		if (seek<0) seek=0;		st->seek_granule = (seek)<<st->info.theora_kgs;	}	st->last_granule = -1;}static void OGG_NewStream(OGGReader *read, ogg_page *oggpage){	ogg_packet oggpacket;	u32 serial_no, i;	OGGStream *st;	/*reannounce of stream (caroussel in live streams) - until now I don't think icecast uses this*/	serial_no = ogg_page_serialno(oggpage);	i=0;	while ((st = gf_list_enum(read->streams, &i))) {		if (st->serial_no==serial_no) {			OGG_ResetupStream(read, st, oggpage);			return;		}	}	/*look if we have the same stream defined (eg, reuse first stream dead with same header page)*/	i=0;	while ((st = gf_list_enum(read->streams, &i))) {		if (st->eos_detected) {			ogg_stream_state os;			ogg_stream_init(&os, serial_no);			ogg_stream_pagein(&os, oggpage);			ogg_stream_packetpeek(&os, &oggpacket);			if (st->dsi && !memcmp(st->dsi, oggpacket.packet, oggpacket.bytes)) {				ogg_stream_clear(&os);				st->serial_no = serial_no;				OGG_ResetupStream(read, st, oggpage);				return;			}			ogg_stream_clear(&os);			/*nope streams are different, signal eos on this one*/			gf_term_on_sl_packet(read->service, st->ch, NULL, 0, NULL, GF_EOS);		}	}	GF_SAFEALLOC(st, OGGStream);    st->serial_no = serial_no;    ogg_stream_init(&st->os, st->serial_no);	ogg_stream_pagein(&st->os, oggpage);		ogg_stream_packetpeek(&st->os, &oggpacket);	OGG_GetStreamInfo(&oggpacket, &st->info);	/*check we don't discard audio or visual streams*/	if ( ((read->service_type==1) && (st->info.streamType==GF_STREAM_AUDIO))		|| ((read->service_type==2) && (st->info.streamType==GF_STREAM_VISUAL)) )	{	    ogg_stream_clear(&st->os);		free(st);		return;	}	gf_list_add(read->streams, st);	st->ESID = 2 + gf_list_count(read->streams);	st->parse_headers = st->info.num_init_headers;	if (st->parse_headers) read->init_remain++;		if (st->info.sample_rate) {		st->seek_granule = (s64) (read->start_range * st->info.sample_rate);	} else if (st->info.frame_rate) {		s64 seek = (s64) (read->start_range * st->info.frame_rate) - 1;		if (seek<0) seek=0;		st->seek_granule = (seek)<<st->info.theora_kgs;	}	st->last_granule = -1;	if (st->info.streamType==GF_STREAM_VISUAL) {		read->has_video = 1;	} else {		read->has_audio = 1;	}	if (st->got_headers && read->is_inline) gf_term_add_media(read->service, (GF_Descriptor*) OGG_GetOD(st), 0);}void OGG_SignalEndOfStream(OGGReader *read, OGGStream *st){	if (st->eos_detected) {		gf_term_on_sl_packet(read->service, st->ch, NULL, 0, NULL, GF_EOS);		ogg_stream_clear(&st->os);	}}GFINLINE void OGG_SendPackets(OGGReader *read, OGGStream *st, ogg_packet *oggpacket){	GF_SLHeader slh;	memset(&slh, 0, sizeof(GF_SLHeader));	if (st->info.type==OGG_VORBIS) {		slh.accessUnitEndFlag = slh.accessUnitStartFlag = 1;		slh.randomAccessPointFlag = 1;		slh.compositionTimeStampFlag = 1;		slh.compositionTimeStamp = st->ogg_ts;		gf_term_on_sl_packet(read->service, st->ch, oggpacket->packet, oggpacket->bytes, &slh, GF_OK);		st->ogg_ts += gf_vorbis_check_frame(&st->vp, oggpacket->packet, oggpacket->bytes);	}	else if (st->info.type==OGG_THEORA) {		oggpack_buffer opb;		oggpackB_readinit(&opb, oggpacket->packet, oggpacket->bytes);		/*new frame*/		if (oggpackB_read(&opb, 1) == 0) {			slh.accessUnitStartFlag = slh.accessUnitEndFlag = 1;			/*add packet*/			slh.randomAccessPointFlag = oggpackB_read(&opb, 1) ? 0 : 1;			slh.compositionTimeStampFlag = 1;			slh.compositionTimeStamp = st->ogg_ts;			gf_term_on_sl_packet(read->service, st->ch, oggpacket->packet, oggpacket->bytes, &slh, GF_OK);			st->ogg_ts += 1000;		}	}}void OGG_Process(OGGReader *read){	OGGStream *st;    ogg_packet oggpacket;	ogg_page oggpage;	if (read->resync_stream) {		st = read->resync_stream;		read->resync_stream = NULL;		goto process_stream;	}	if (!OGG_ReadPage(read, &oggpage)) {		return;	}	if (ogg_page_bos(&oggpage)) {		OGG_NewStream(read, &oggpage);		return;	}	st = OGG_FindStreamForPage(read, &oggpage);	if (!st) {		if (!read->bos_done && read->is_live) {			u32 now = gf_sys_clock();			if (now-read->tune_in_time > 1000) {				gf_term_on_message(read->service, GF_OK, "Waiting for tune in...");				read->tune_in_time = now;			}		}		return;	}	if (ogg_page_eos(&oggpage)) 		st->eos_detected = 1;	if (st->parse_headers && !st->got_headers) {		while (ogg_stream_packetout(&st->os, &oggpacket ) > 0 ) {			GF_BitStream *bs;			if (st->info.type==OGG_VORBIS)				gf_vorbis_parse_header(&st->vp, oggpacket.packet, oggpacket.bytes);			bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);			if (st->dsi) {				gf_bs_write_data(bs, st->dsi, st->dsi_len);				free(st->dsi);				st->dsi = NULL;				st->dsi_len=0;			}			gf_bs_write_u16(bs, oggpacket.bytes);			gf_bs_write_data(bs, oggpacket.packet, oggpacket.bytes);			gf_bs_get_content(bs, (unsigned char **)&st->dsi, &st->dsi_len);			gf_bs_del(bs);			st->parse_headers--;			if (!st->parse_headers) {				st->got_headers = 1;				if (read->is_inline) 					gf_term_add_media(read->service, (GF_Descriptor*) OGG_GetOD(st), 0);				break;			}		}		if (!st->got_headers) return;		assert(read->init_remain);		read->init_remain--;		if (!read->init_remain) read->bos_done = 1;		return;	}	/*from here we should have passed all headers*/	if (read->init_remain) return;

⌨️ 快捷键说明

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