oggstream.java
来自「java语言开发的P2P流媒体系统」· Java 代码 · 共 238 行
JAVA
238 行
/*
* P2P-Radio - Peer to peer streaming system
* Project homepage: http://p2p-radio.sourceforge.net/
* Copyright (C) 2003-2004 Michael Kaufmann <hallo@michael-kaufmann.ch>
*
* ---------------------------------------------------------------------------
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ---------------------------------------------------------------------------
*/
package p2pradio.sources.ogg;
import p2pradio.*;
import p2pradio.packets.*;
import java.io.*;
import java.util.*;
public class OggStream
{
public static byte[] readVorbisHeader(OggPage firstPage, InputStream input, Metadata metadata) throws IOException, OggException
{
// The raw data of all the pages that belong to the header
byte[] pagesData = new byte[PacketFactory.STREAM_PACKET_MAX_SIZE - DataPacket.getMaxLength()];
int pagesSize = 0;
boolean firstPacketOfSet = true;
// Comment header
byte[] commentData = new byte[PacketFactory.STREAM_PACKET_MAX_SIZE - DataPacket.getMaxLength()];
int commentSize = 0;
boolean readingCommentHeader = true;
// Setup header
boolean readingSetupHeader = false;
// Read the identification header
OggPage identificationHeader = firstPage;
if (!identificationHeader.isBeginOfLogicalBitstream())
{
throw new OggException(Messages.getString("OggStream.NOT_BEGINNING_OF_A_STREAM")); //$NON-NLS-1$
}
if (identificationHeader.data.length != 58)
{
throw new OggException(Messages.getString("OggStream.WRONG_IDENTIFICATION_HEADER_SIZE")); //$NON-NLS-1$
}
LinkedList packets = identificationHeader.oggPackets;
if (packets.size() != 1)
{
throw new OggException(Messages.getString("OggStream.INVALID_IDENTIFICATION_HEADER")); //$NON-NLS-1$
}
OggPacket packet = (OggPacket)packets.getFirst();
if (!packet.isVorbisPacket() || (packet.getVorbisPacketType() != OggPacket.VORBIS_IDENTIFICATION_HEADER) || (packet.isContinuedInNextPage()))
{
throw new OggException(Messages.getString("OggStream.INVALID_IDENTIFICATION_HEADER")); //$NON-NLS-1$
}
pagesSize = identificationHeader.data.length;
System.arraycopy(identificationHeader.data, 0, pagesData, 0, pagesSize);
// Read the comment and setup headers
OggPage nextPage;
do
{
nextPage = new OggPage(input);
if (pagesSize + nextPage.data.length > pagesData.length)
{
throw new OggException(Messages.getString("OggStream.HEADER_IS_TOO_LONG")); //$NON-NLS-1$
}
// Copy page
System.arraycopy(nextPage.data, 0, pagesData, pagesSize, nextPage.data.length);
pagesSize += nextPage.data.length;
// Look at all packets in the current page
Iterator iterator = nextPage.oggPackets.iterator();
while(iterator.hasNext())
{
packet = (OggPacket)iterator.next();
if (firstPacketOfSet)
{
if (readingCommentHeader)
{
if (!packet.isVorbisPacket() || (packet.getVorbisPacketType() != OggPacket.VORBIS_COMMENT_HEADER))
{
throw new OggException(Messages.getString("OggStream.INVALID_COMMENT_HEADER")); //$NON-NLS-1$
}
}
else if (readingSetupHeader)
{
if (!packet.isVorbisPacket() || (packet.getVorbisPacketType() != OggPacket.VORBIS_SETUP_HEADER))
{
throw new OggException(Messages.getString("OggStream.INVALID_SETUP_HEADER")); //$NON-NLS-1$
}
}
else
{
// Yet another packet was found
throw new OggException(Messages.getString("OggStream.INVALID_PACKET_IN_HEADER")); //$NON-NLS-1$
}
firstPacketOfSet = false;
}
if (readingCommentHeader)
{
// Copy the part of the comment header
System.arraycopy(packet.parent.data, packet.dataStartPos, commentData, commentSize, packet.dataLength);
commentSize += packet.dataLength;
}
if (!packet.isContinuedInNextPage())
{
firstPacketOfSet = true;
if (readingCommentHeader)
{
readingCommentHeader = false;
readingSetupHeader = true;
}
else if (readingSetupHeader)
{
readingSetupHeader = false;
}
}
}
}
while (readingCommentHeader || readingSetupHeader);
readCommentHeader(commentData, metadata);
// Create a new array with the exact size
byte[] pagesDataResult = new byte[pagesSize];
System.arraycopy(pagesData, 0, pagesDataResult, 0, pagesSize);
return pagesDataResult;
}
public static void readCommentHeader(byte[] commentHeader, Metadata metadata) throws OggException
{
try
{
// Skip the marker byte and the "vorbis" signature
int readPos = 7;
// Skip the vendor string
readPos += 4 + getInt(commentHeader, readPos);
int numberOfEntries = getInt(commentHeader, readPos);
readPos += 4;
String artist = null;
String title = null;
for (int i=0; i < numberOfEntries; i++)
{
int length = getInt(commentHeader, readPos);
readPos += 4;
String entry = new String(commentHeader, readPos, length, "UTF-8"); //$NON-NLS-1$
readPos += length;
// It's possible that there are more than one artists
// in the comment header. Only look at the first artist
if (artist == null)
{
if (entry.toUpperCase().startsWith("ARTIST=")) //$NON-NLS-1$
{
artist = entry.substring(7);
}
}
if (title == null)
{
if (entry.toUpperCase().startsWith("TITLE=")) //$NON-NLS-1$
{
title = entry.substring(6);
}
}
}
// Check the framing bit
if ((commentHeader[readPos] & 0x01) == 0)
{
throw new OggException(Messages.getString("OggStream.INVALID_COMMENT_HEADER")); //$NON-NLS-1$
}
if ((title != null) && (title.length() != 0))
{
if ((artist != null) && (artist.length() != 0))
{
metadata.setSongTitle(artist + " - " + title); //$NON-NLS-1$
}
else
{
metadata.setSongTitle(title);
}
}
}
catch (Exception e)
{
e.printStackTrace();
throw new OggException(Messages.getString("OggStream.INVALID_COMMENT_HEADER")); //$NON-NLS-1$
}
}
private static int getInt(byte[] array, int offset)
{
int ch1 = (array[offset + 0] & 0xff);
int ch2 = (array[offset + 1] & 0xff);
int ch3 = (array[offset + 2] & 0xff);
int ch4 = (array[offset + 3] & 0xff);
return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24));
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?