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

📄 ogg.cpp.svn-base

📁 这是和p2p相关的一份源码
💻 SVN-BASE
字号:
// ------------------------------------------------
// File : mp3.cpp
// Date: 28-may-2003
// Author: giles
//
// (c) 2002-3 peercast.org
// ------------------------------------------------
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.

// This program 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 General Public License for more details.
// ------------------------------------------------

#include "channel.h"
#include "ogg.h"

// ------------------------------------------
void OGGStream::readHeader(Stream &,Channel *)
{
}

// ------------------------------------------
void OGGStream::readEnd(Stream &,Channel *)
{
}

// ------------------------------------------
void OGGStream::readPacket(Stream &in,Channel *ch)
{
	OggPacket ogg;
	ChanPacket pack;

	ogg.read(in);

	if (ogg.isBOS())
		readVorbisHeaders(in,ch,ogg);

	pack.init(ChanPacket::T_DATA,ogg.data,ogg.headLen+ogg.bodyLen,ch->streamPos);

	ch->newPacket(pack);
	ch->checkReadDelay(pack.len);

	ch->streamPos+=pack.len;
}

// -----------------------------------
void OGGStream::readVorbisHeaders(Stream &in,Channel *ch, OggPacket &ogg)
{
	LOG_CHANNEL("Reading OGG Vorbis headers");
		
//	if (!ogg.isVorbisPacket())
//		throw StreamException("Not Vorbis stream");

	ch->headPack.len = 0;

	VorbisPacket vorbis;
	

	int numHeaders = 0;
	
	while (numHeaders < 3)	// ogg vorbis always starts with 3 headers
	{

		// read until we have complete ogg page
		vorbis.bodyLen = 0;
		while (!in.eof())
		{
			if ((vorbis.bodyLen + ogg.bodyLen) >= VorbisPacket::MAX_BODYLEN)
				throw StreamException("Vorbis body too big");

			if (ch->headPack.len+(ogg.bodyLen+ogg.headLen) >= ChanMeta::MAX_DATALEN)
				throw StreamException("OGG packet too big for headMeta");

			// copy complete ogg packet into head packet
			memcpy(&ch->headPack.data[ch->headPack.len],ogg.data,ogg.headLen+ogg.bodyLen);
			ch->headPack.len += ogg.headLen+ogg.bodyLen;

			// add body to vorbis packet
			memcpy(&vorbis.body[vorbis.bodyLen],&ogg.data[ogg.headLen],ogg.bodyLen);
			vorbis.bodyLen += ogg.bodyLen;
		
			// read new ogg packet and check for end of last packet.
			ogg.read(in);
			if (ogg.isNewPacket())
				break;
		}

		MemoryStream vin(vorbis.body,vorbis.bodyLen);

		while (!vin.eof())
		{
			char id[7];

			vin.read(id,7);
			if (memcmp(&id[1],"vorbis",6)!=0)
				throw StreamException("Expected Vorbis packet");

			switch (id[0])
			{
				case 1:	// ident
					LOG_CHANNEL("Vorbis Header: Ident");
					readVorbisIdent(vin,ch->info);
					break;
				case 3: // comment
					LOG_CHANNEL("Vorbis Header: Comment");
					readVorbisComment(vin,ch->info);
					ch->updateMeta();
					break;
				case 5: // setup
					LOG_CHANNEL("Vorbis Header: Setup");
					readVorbisSetup(vin);
					break;
				default:
					throw StreamException("Unknown Vorbis packet while reading headers");
					break;
			}

			numHeaders++;
		}

	}


	ch->headPack.type = ChanPacket::T_HEAD;
	ch->headPack.pos = ch->streamPos;

	ch->streamPos += ch->headPack.len;

	ch->newPacket(ch->headPack);

	LOG_CHANNEL("Got Vorbis headers at %d: total %d bytes",ch->streamPos,ch->headPack.len);

}
// -----------------------------------
void OGGStream::readVorbisIdent(Stream &in, ChanInfo &info)
{
	int ver = in.readLong();
	int chans = in.readChar();
	int rate = in.readLong();
	int brMax = in.readLong();
	int brNom = in.readLong();
	int brLow = in.readLong();

	in.readChar();	// skip blocksize 0+1

	LOG_CHANNEL("OGG Ident: ver=%d, chans=%d, rate=%d, brMax=%d, brNom=%d, brLow=%d",
		ver,chans,rate,brMax,brNom,brLow);

	if (info.bitrate == 0)
	{
		if (brNom > 0)
			info.bitrate = brNom/1000;
		//else
		//	info.bitrate = 0;
	}

	char frame = in.readChar();		// framing bit
	if (!frame)
		throw StreamException("Bad Indent frame");

}

 
// -----------------------------------
void OGGStream::readVorbisSetup(Stream &in)
{
	// skip everything in packet
	int cnt=0;
	while (!in.eof())
	{
		cnt++;
		in.readChar();
	}

	LOG_CHANNEL("Read %d bytes of Vorbis Setup",cnt);
}
// -----------------------------------
void OGGStream::readVorbisComment(Stream &in, ChanInfo &info)
{
	int vLen = in.readLong();	// vendor len

	in.skip(vLen);

	char argBuf[8192];

	info.track.clear();

	int cLen = in.readLong();	// comment len
	for(int i=0; i<cLen; i++)
	{
		int l = in.readLong();
		if (l > sizeof(argBuf))
			throw StreamException("Comment string too long");
		in.read(argBuf,l);
		argBuf[l] = 0;
		LOG_CHANNEL("OGG Comment: %s",argBuf);

		char *arg;
		if ((arg=stristr(argBuf,"ARTIST=")))
			info.track.artist.set(arg+7,String::T_ASCII);
		else if ((arg=stristr(argBuf,"TITLE=")))
			info.track.title.set(arg+6,String::T_ASCII);
		else if ((arg=stristr(argBuf,"GENRE=")))
			info.track.genre.set(arg+6,String::T_ASCII);
		else if ((arg=stristr(argBuf,"CONTACT=")))
			info.track.contact.set(arg+8,String::T_ASCII);
		else if ((arg=stristr(argBuf,"ALBUM=")))
			info.track.album.set(arg+6,String::T_ASCII);
	}

	char frame = in.readChar();		// framing bit
	if (!frame)
		throw StreamException("Bad Comment frame");

//	updateMeta();

}

// -----------------------------------
bool OggPacket::isBOS()
{
	return (data[5] & 0x02) != 0;
}
// -----------------------------------
bool OggPacket::isNewPacket()
{
	return (data[5] & 0x01) == 0;
}
// -----------------------------------
void OggPacket::read(Stream &in)
{
	// skip until we get OGG capture pattern
	bool gotOgg=false;
	while (!gotOgg)
	{
		if (in.readChar() == 'O')
			if (in.readChar() == 'g')
				if (in.readChar() == 'g')
					if (in.readChar() == 'S')
						gotOgg = true;
		if (!gotOgg)
			LOG_CHANNEL("Skipping OGG packet");
	}



	memcpy(&data[0],"OggS",4);

	in.read(&data[4],27-4);

	int numSegs = data[26];
	bodyLen = 0;

	// read segment table
	in.read(&data[27],numSegs);
	for(int i=0; i<numSegs; i++)
		bodyLen += data[27+i];

	if (bodyLen >= MAX_BODYLEN)		
		throw StreamException("OGG body too big");

	headLen = 27+numSegs;

	if (headLen > MAX_HEADERLEN)
		throw StreamException("OGG header too big");

	in.read(&data[headLen],bodyLen);



	#if 0
		LOG_DEBUG("OGG Packet - page %d, id = %x - %s %s %s - %d segs, %d bytes",
			*(unsigned int *)&data[18],
			*(unsigned int *)&data[14],
			data[5]&0x1?"cont":"new",
			data[5]&0x2?"bos":"",
			data[5]&0x4?"eos":"",
			numSegs,
			headLen+bodyLen);
	#endif

}

⌨️ 快捷键说明

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