ogg reader plugin based on mp3
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5663 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0380884167
commit
1c828415cf
14
src/add-ons/media/plugins/ogg/Jamfile
Normal file
14
src/add-ons/media/plugins/ogg/Jamfile
Normal file
@ -0,0 +1,14 @@
|
||||
SubDir OBOS_TOP src add-ons media plugins ogg ;
|
||||
|
||||
UsePrivateHeaders media ;
|
||||
|
||||
SubDirHdrs $(SUBDIR) libogg ogg ;
|
||||
|
||||
Addon ogg : media plugins :
|
||||
OggReaderPlugin.cpp
|
||||
: false : libogg.a
|
||||
;
|
||||
|
||||
LinkSharedOSLibs ogg : be libmedia.so ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons media plugins ogg libogg ;
|
874
src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp
Normal file
874
src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp
Normal file
@ -0,0 +1,874 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <DataIO.h>
|
||||
#include <ByteOrder.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <MediaFormats.h>
|
||||
#include "OggReaderPlugin.h"
|
||||
|
||||
#define TRACE_THIS 1
|
||||
#if TRACE_THIS
|
||||
#define TRACE printf
|
||||
#else
|
||||
#define TRACE ((void)0)
|
||||
#endif
|
||||
|
||||
// bit_rate_table[mpeg_version_index][layer_index][bitrate_index]
|
||||
static const int bit_rate_table[4][4][16] =
|
||||
{
|
||||
{ // mpeg version 2.5
|
||||
{ }, // undefined layer
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, // layer 3
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, // layer 2
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 } // layer 1
|
||||
},
|
||||
{ // undefined version
|
||||
{ },
|
||||
{ },
|
||||
{ },
|
||||
{ }
|
||||
},
|
||||
{ // mpeg version 2
|
||||
{ },
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 },
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 },
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }
|
||||
},
|
||||
{ // mpeg version 1
|
||||
{ },
|
||||
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 },
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 },
|
||||
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}
|
||||
}
|
||||
};
|
||||
|
||||
// b_mpeg_id_table[mpeg_version_index][layer_index]
|
||||
static const int32 b_mpeg_id_table[4][4] =
|
||||
{
|
||||
{ 0, B_MPEG_2_5_AUDIO_LAYER_3, B_MPEG_2_5_AUDIO_LAYER_2, B_MPEG_2_5_AUDIO_LAYER_1 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, B_MPEG_2_AUDIO_LAYER_3, B_MPEG_2_AUDIO_LAYER_2, B_MPEG_2_AUDIO_LAYER_1 },
|
||||
{ 0, B_MPEG_1_AUDIO_LAYER_3, B_MPEG_1_AUDIO_LAYER_2, B_MPEG_1_AUDIO_LAYER_1 },
|
||||
};
|
||||
|
||||
// frame_rate_table[mpeg_version_index][sampling_rate_index]
|
||||
static const int frame_rate_table[4][4] =
|
||||
{
|
||||
{ 11025, 12000, 8000, 0}, // mpeg version 2.5
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 22050, 24000, 16000, 0}, // mpeg version 2
|
||||
{ 44100, 48000, 32000, 0} // mpeg version 1
|
||||
};
|
||||
|
||||
// name_table[mpeg_version_index][layer_index]
|
||||
static const char * name_table[4][4] =
|
||||
{
|
||||
{ 0, "MPEG 2.5 Audio Layer 3", "MPEG 2.5 Audio Layer 2", "MPEG 2.5 Audio Layer 1" },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, "MPEG 2 Audio Layer 3", "MPEG 2 Audio Layer 2", "MPEG 2 Audio Layer 1" },
|
||||
{ 0, "MPEG 1 Audio Layer 3", "MPEG 1 Audio Layer 2", "MPEG 1 Audio Layer 1" },
|
||||
};
|
||||
|
||||
// frame_sample_count_table[layer_index]
|
||||
static const int frame_sample_count_table[4] = { 0, 1152, 1152, 384 };
|
||||
|
||||
static const int MAX_CHUNK_SIZE = 5200;
|
||||
|
||||
struct mp3data
|
||||
{
|
||||
int64 position;
|
||||
char * chunkBuffer;
|
||||
|
||||
int64 duration; // usec
|
||||
|
||||
int32 framesPerFrame; // PCM frames in each mpeg frame
|
||||
int64 frameCount; // PCM frames
|
||||
int32 frameRate;
|
||||
int64 framePosition;
|
||||
|
||||
media_format format;
|
||||
};
|
||||
|
||||
struct oggReader::xing_vbr_info
|
||||
{
|
||||
int32 frameRate;
|
||||
int64 encodedFramesCount;
|
||||
int64 byteCount;
|
||||
int32 vbrScale;
|
||||
bool hasSeekpoints;
|
||||
uint8 seekpoints[100];
|
||||
|
||||
int64 duration; // usec
|
||||
int64 frameCount; // PCM frames
|
||||
};
|
||||
|
||||
struct oggReader::fhg_vbr_info
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
oggReader::oggReader()
|
||||
: fXingVbrInfo(0),
|
||||
fFhgVbrInfo(0)
|
||||
{
|
||||
TRACE("oggReader::oggReader\n");
|
||||
}
|
||||
|
||||
|
||||
oggReader::~oggReader()
|
||||
{
|
||||
delete fXingVbrInfo;
|
||||
delete fFhgVbrInfo;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
oggReader::Copyright()
|
||||
{
|
||||
return "mp3 reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen";
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
oggReader::Sniff(int32 *streamCount)
|
||||
{
|
||||
TRACE("oggReader::Sniff\n");
|
||||
|
||||
fSeekableSource = dynamic_cast<BPositionIO *>(Reader::Source());
|
||||
if (!fSeekableSource) {
|
||||
TRACE("oggReader::Sniff: non seekable sources not supported\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fFileSize = Source()->Seek(0, SEEK_END);
|
||||
|
||||
TRACE("oggReader::Sniff: file size is %Ld bytes\n", fFileSize);
|
||||
|
||||
if (!IsMp3File()) {
|
||||
TRACE("oggReader::Sniff: non recognized as mp3 file\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE("oggReader::Sniff: looks like an mp3 file\n");
|
||||
|
||||
if (!ParseFile()) {
|
||||
TRACE("oggReader::Sniff: parsing file failed\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
*streamCount = 1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
oggReader::GetFileFormatInfo(media_file_format *mff)
|
||||
{
|
||||
mff->capabilities = media_file_format::B_READABLE
|
||||
| media_file_format::B_KNOWS_ENCODED_AUDIO
|
||||
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
||||
mff->family = B_MPEG_FORMAT_FAMILY;
|
||||
mff->version = 100;
|
||||
strcpy(mff->mime_type, "audio/mpeg");
|
||||
strcpy(mff->file_extension, "mp3");
|
||||
|
||||
uint8 header[4];
|
||||
Source()->ReadAt(fDataStart, header, sizeof(header));
|
||||
int mpeg_version_index = (header[1] >> 3) & 0x03;
|
||||
int layer_index = (header[1] >> 1) & 0x03;
|
||||
strcpy(mff->short_name, name_table[mpeg_version_index][layer_index]);
|
||||
strcpy(mff->pretty_name, name_table[mpeg_version_index][layer_index]);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
oggReader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||
{
|
||||
TRACE("oggReader::AllocateCookie\n");
|
||||
|
||||
mp3data *data = new mp3data;
|
||||
data->chunkBuffer = new char[MAX_CHUNK_SIZE];
|
||||
data->position = 0;
|
||||
|
||||
uint8 header[4];
|
||||
Source()->ReadAt(fDataStart, header, sizeof(header));
|
||||
int mpeg_version_index = (header[1] >> 3) & 0x03;
|
||||
int layer_index = (header[1] >> 1) & 0x03;
|
||||
|
||||
int bit_rate;
|
||||
int frame_size;
|
||||
|
||||
if (fXingVbrInfo && fXingVbrInfo->frameCount != -1 && fXingVbrInfo->duration != -1) {
|
||||
TRACE("oggReader::AllocateCookie: using timing info from VBR header\n");
|
||||
bit_rate = (fXingVbrInfo->byteCount * 8 * 1000000) / fXingVbrInfo->duration; // average bit rate
|
||||
frame_size = fXingVbrInfo->byteCount / fXingVbrInfo->encodedFramesCount; // average frame size
|
||||
data->duration = fXingVbrInfo->duration;
|
||||
data->frameCount = fXingVbrInfo->frameCount;
|
||||
data->frameRate = fXingVbrInfo->frameRate;
|
||||
} else {
|
||||
TRACE("oggReader::AllocateCookie: assuming CBR, calculating timing info from file\n");
|
||||
int sampling_rate_index = (header[2] >> 2) & 0x03;
|
||||
int bitrate_index = (header[2] >> 4) & 0x0f;
|
||||
int samples_per_chunk = frame_sample_count_table[layer_index];
|
||||
bit_rate = 1000 * bit_rate_table[mpeg_version_index][layer_index][bitrate_index];
|
||||
frame_size = GetFrameLength(header);
|
||||
data->frameRate = frame_rate_table[mpeg_version_index][sampling_rate_index];
|
||||
data->frameCount = samples_per_chunk * (fDataSize / frame_size);
|
||||
data->duration = (data->frameCount * 1000000) / data->frameRate;
|
||||
}
|
||||
|
||||
TRACE("oggReader::AllocateCookie: frameRate %ld, frameCount %Ld, duration %.6f\n",
|
||||
data->frameRate, data->frameCount, data->duration / 1000000.0);
|
||||
|
||||
data->framePosition = 0;
|
||||
data->framesPerFrame = frame_sample_count_table[layer_index];
|
||||
|
||||
// BMediaFormats formats;
|
||||
media_format_description description;
|
||||
description.family = B_MPEG_FORMAT_FAMILY;
|
||||
description.u.mpeg.id = b_mpeg_id_table[mpeg_version_index][layer_index];
|
||||
// formats.GetFormatFor(description, &data->format);
|
||||
|
||||
_get_format_for_description(&data->format, description);
|
||||
|
||||
// data->format.u.encoded_audio.encoding = media_encoded_audio_format::B_ANY;
|
||||
data->format.u.encoded_audio.bit_rate = bit_rate;
|
||||
data->format.u.encoded_audio.frame_size = frame_size;
|
||||
// data->format.u.encoded_audio.output.frame_rate = data->frameRate;
|
||||
// data->format.u.encoded_audio.output.channel_count = 2;
|
||||
|
||||
// store the cookie
|
||||
*cookie = data;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
oggReader::FreeCookie(void *cookie)
|
||||
{
|
||||
TRACE("oggReader::FreeCookie\n");
|
||||
mp3data *data = reinterpret_cast<mp3data *>(cookie);
|
||||
delete [] data->chunkBuffer;
|
||||
delete data;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
oggReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
||||
media_format *format, void **infoBuffer, int32 *infoSize)
|
||||
{
|
||||
mp3data *data = reinterpret_cast<mp3data *>(cookie);
|
||||
|
||||
*frameCount = data->frameCount;
|
||||
*duration = data->duration;
|
||||
*format = data->format;
|
||||
*infoBuffer = 0;
|
||||
*infoSize = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
oggReader::Seek(void *cookie,
|
||||
uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time)
|
||||
{
|
||||
if (!fSeekableSource)
|
||||
return B_ERROR;
|
||||
|
||||
mp3data *data = reinterpret_cast<mp3data *>(cookie);
|
||||
int64 pos;
|
||||
|
||||
// this isn't very accurate
|
||||
|
||||
if (seekTo & B_MEDIA_SEEK_TO_FRAME) {
|
||||
pos = fXingVbrInfo ? XingSeekPoint(100.0 * *frame / (float)data->frameCount) : -1;
|
||||
if (pos < 0)
|
||||
pos = (*frame * fDataSize) / data->frameCount;
|
||||
TRACE("oggReader::Seek to frame %Ld, pos %Ld\n", *frame, pos);
|
||||
*time = (*frame * data->duration) / data->frameCount;
|
||||
TRACE("oggReader::Seek newtime %Ld\n", *time);
|
||||
} else if (seekTo & B_MEDIA_SEEK_TO_TIME) {
|
||||
pos = fXingVbrInfo ? XingSeekPoint(100.0 * *time / (float)data->duration) : -1;
|
||||
if (pos < 0)
|
||||
pos = (*time * fDataSize) / data->duration;
|
||||
TRACE("oggReader::Seek to time %Ld, pos %Ld\n", *time, pos);
|
||||
*frame = (*time * data->frameCount) / data->duration;
|
||||
TRACE("oggReader::Seek newframe %Ld\n", *frame);
|
||||
} else {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// We ignore B_MEDIA_SEEK_CLOSEST_FORWARD, B_MEDIA_SEEK_CLOSEST_BACKWARD
|
||||
|
||||
uint8 buffer[16000];
|
||||
if (pos > fDataSize - 16000)
|
||||
pos = fDataSize - 16000;
|
||||
if (pos < 0)
|
||||
pos = 0;
|
||||
int64 size = fDataSize - pos;
|
||||
if (size > 16000)
|
||||
size = 16000;
|
||||
if (size != Source()->ReadAt(fDataStart + pos, buffer, size)) {
|
||||
TRACE("oggReader::Seek: unexpected read error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
int32 end = size - 4;
|
||||
int32 ofs;
|
||||
for (ofs = 0; ofs < end; ofs++) {
|
||||
if (buffer[ofs] != 0xff) // quick check
|
||||
continue;
|
||||
if (IsValidStream(&buffer[ofs], size - ofs))
|
||||
break;
|
||||
}
|
||||
if (ofs == end) {
|
||||
TRACE("oggReader::Seek: couldn't synchronize\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
data->position = pos + ofs;
|
||||
|
||||
data->framePosition = *frame; // this is not exact
|
||||
|
||||
TRACE("oggReader::Seek: synchronized at position %Ld\n", data->position);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
oggReader::GetNextChunk(void *cookie,
|
||||
void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
mp3data *data = reinterpret_cast<mp3data *>(cookie);
|
||||
|
||||
int64 maxbytes = fDataSize - data->position;
|
||||
if (maxbytes < 4)
|
||||
return B_ERROR;
|
||||
|
||||
mediaHeader->start_time = (data->framePosition * 1000000) / data->frameRate;
|
||||
mediaHeader->file_pos = data->position;
|
||||
|
||||
if (4 != Source()->ReadAt(fDataStart + data->position, data->chunkBuffer, 4)) {
|
||||
TRACE("oggReader::GetNextChunk: unexpected read error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
data->position += 4;
|
||||
maxbytes -= 4;
|
||||
|
||||
int size = GetFrameLength(data->chunkBuffer) - 4;
|
||||
if (size <= 0) {
|
||||
TRACE("oggReader::GetNextChunk: invalid frame encountered\n");
|
||||
// try to synchronize again here!
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (size > maxbytes)
|
||||
size = maxbytes;
|
||||
|
||||
if (size != Source()->ReadAt(fDataStart + data->position, data->chunkBuffer + 4, size)) {
|
||||
TRACE("oggReader::GetNextChunk: unexpected read error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
data->position += size;
|
||||
|
||||
data->framePosition += data->framesPerFrame;
|
||||
|
||||
*chunkBuffer = data->chunkBuffer;
|
||||
*chunkSize = size + 4;
|
||||
|
||||
if (*chunkSize > MAX_CHUNK_SIZE) {
|
||||
printf("oggReader: chunk buffer overrun, read %ld bytes into %d bytes buffer\n", *chunkSize, MAX_CHUNK_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
oggReader::ParseFile()
|
||||
{
|
||||
// Since we already know that this is an mp3 file,
|
||||
// detect the real (mp3 audio) data start and end
|
||||
// and find VBR or other headers and tags
|
||||
|
||||
const int32 search_size = 16384;
|
||||
const int32 padding_size = 128; // Get???Length() functions need some bytes to look into
|
||||
int64 offset;
|
||||
int32 size;
|
||||
uint8 buf[search_size];
|
||||
|
||||
fDataStart = -1;
|
||||
|
||||
for (offset = 0; offset < fFileSize; ) {
|
||||
int64 maxsize = fFileSize - offset;
|
||||
size = (search_size < maxsize) ? search_size : maxsize;
|
||||
|
||||
if (size != Source()->ReadAt(offset, buf, size)) {
|
||||
TRACE("oggReaderPlugin::ParseFile reading %ld bytes at offset %Ld failed\n", size, offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
int skip_bytes = 0;
|
||||
|
||||
// since the various Get???Length() functions need to check a few bytes
|
||||
// (10 for ID3V2, about 40 for VBR), we stop searching before buffer end
|
||||
int32 end = size - padding_size;
|
||||
for (int32 pos = 0; pos < end; ) {
|
||||
int hdr_length;
|
||||
|
||||
// A Xing or Fraunhofer VBR header is embedded into a valid
|
||||
// mp3 frame that contains silence. We need to first check
|
||||
// for these headers before we can search for the start of a stream.
|
||||
|
||||
hdr_length = GetXingVbrLength(&buf[pos]);
|
||||
if (hdr_length > 0) {
|
||||
TRACE("oggReaderPlugin::ParseFile found a Xing VBR header of %d bytes at position %Ld\n", hdr_length, offset + pos);
|
||||
ParseXingVbrHeader(offset + pos);
|
||||
goto skip_header;
|
||||
}
|
||||
|
||||
hdr_length = GetInfoCbrLength(&buf[pos]);
|
||||
if (hdr_length > 0) {
|
||||
TRACE("oggReaderPlugin::ParseFile found a Info CBR header of %d bytes at position %Ld\n", hdr_length, offset + pos);
|
||||
goto skip_header;
|
||||
}
|
||||
|
||||
hdr_length = GetFraunhoferVbrLength(&buf[pos]);
|
||||
if (hdr_length > 0) {
|
||||
TRACE("oggReaderPlugin::ParseFile found a Fraunhofer VBR header of %d bytes at position %Ld\n", hdr_length, offset + pos);
|
||||
ParseFraunhoferVbrHeader(offset + pos);
|
||||
goto skip_header;
|
||||
}
|
||||
|
||||
hdr_length = GetLameVbrLength(&buf[pos]);
|
||||
if (hdr_length > 0) {
|
||||
TRACE("oggReaderPlugin::ParseFile found a Lame VBR header of %d bytes at position %Ld\n", hdr_length, offset + pos);
|
||||
goto skip_header;
|
||||
}
|
||||
|
||||
hdr_length = GetId3v2Length(&buf[pos]);
|
||||
if (hdr_length > 0) {
|
||||
TRACE("oggReaderPlugin::ParseFile found a ID3V2 header of %d bytes at position %Ld\n", hdr_length, offset + pos);
|
||||
goto skip_header;
|
||||
}
|
||||
|
||||
if (IsValidStream(&buf[pos], size - pos)) {
|
||||
fDataStart = offset + pos;
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
continue;
|
||||
|
||||
skip_header:
|
||||
int skip_max = end - pos;
|
||||
skip_bytes = (skip_max < hdr_length) ? skip_max : hdr_length;
|
||||
pos += skip_bytes;
|
||||
skip_bytes = hdr_length - skip_bytes;
|
||||
}
|
||||
if (fDataStart != -1)
|
||||
break;
|
||||
|
||||
if (skip_bytes) {
|
||||
offset += skip_bytes;
|
||||
skip_bytes = 0;
|
||||
} else {
|
||||
offset += (search_size - padding_size);
|
||||
}
|
||||
}
|
||||
|
||||
fDataSize = fFileSize - fDataStart;
|
||||
|
||||
TRACE("found mp3 audio data at file position %Ld, maximum data length is %Ld\n", fDataStart, fDataSize);
|
||||
|
||||
// search for a ID3 V1 tag
|
||||
offset = fFileSize - 128;
|
||||
size = 128;
|
||||
if (offset > 0) {
|
||||
if (size != Source()->ReadAt(offset, buf, size)) {
|
||||
TRACE("oggReaderPlugin::ParseFile reading %ld bytes at offset %Ld failed\n", size, offset);
|
||||
return false;
|
||||
}
|
||||
if (buf[0] == 'T'&& buf[1] == 'A' && buf[2] == 'G') {
|
||||
TRACE("oggReaderPlugin::ParseFile found a ID3V1 header of 128 bytes at position %Ld\n", offset);
|
||||
fDataSize -= 128;
|
||||
}
|
||||
}
|
||||
|
||||
// search for a lyrics tag
|
||||
// maximum size is 5100 bytes, and a 128 byte ID3V1 tag is always appended
|
||||
// starts with "LYRICSBEGIN", end with "LYRICS200" or "LYRICSEND"
|
||||
offset = fFileSize - 5300;
|
||||
size = 5300;
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
size = fFileSize;
|
||||
}
|
||||
if (size != Source()->ReadAt(offset, buf, size)) {
|
||||
TRACE("oggReaderPlugin::ParseFile reading %ld bytes at offset %Ld failed\n", size, offset);
|
||||
return false;
|
||||
}
|
||||
for (int pos = 0; pos < size; pos++) {
|
||||
if (buf[pos] != 'L')
|
||||
continue;
|
||||
if (0 == memcmp(&buf[pos], "LYRICSBEGIN", 11)) {
|
||||
TRACE("oggReaderPlugin::ParseFile found a Lyrics header at position %Ld\n", offset + pos);
|
||||
fDataSize = offset + pos + fDataStart;
|
||||
}
|
||||
}
|
||||
|
||||
// might search for APE tags, too
|
||||
|
||||
TRACE("found mp3 audio data at file position %Ld, data length is %Ld\n", fDataStart, fDataSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
oggReader::GetXingVbrLength(uint8 *header)
|
||||
{
|
||||
int h_id = (header[1] >> 3) & 1;
|
||||
int h_mode = (header[3] >> 6) & 3;
|
||||
uint8 *xing_header;
|
||||
|
||||
// determine offset of header
|
||||
if(h_id) // mpeg1
|
||||
xing_header = (h_mode != 3) ? (header + 36) : (header + 21);
|
||||
else // mpeg2
|
||||
xing_header = (h_mode != 3) ? (header + 21) : (header + 13);
|
||||
|
||||
if (xing_header[0] != 'X') return -1;
|
||||
if (xing_header[1] != 'i') return -1;
|
||||
if (xing_header[2] != 'n') return -1;
|
||||
if (xing_header[3] != 'g') return -1;
|
||||
|
||||
return GetFrameLength(header);
|
||||
}
|
||||
|
||||
int
|
||||
oggReader::GetInfoCbrLength(uint8 *header)
|
||||
{
|
||||
int h_id = (header[1] >> 3) & 1;
|
||||
int h_mode = (header[3] >> 6) & 3;
|
||||
uint8 *info_header;
|
||||
|
||||
// determine offset of header
|
||||
if(h_id) // mpeg1
|
||||
info_header = (h_mode != 3) ? (header + 36) : (header + 21);
|
||||
else // mpeg2
|
||||
info_header = (h_mode != 3) ? (header + 21) : (header + 13);
|
||||
|
||||
if (info_header[0] != 'I') return -1;
|
||||
if (info_header[1] != 'n') return -1;
|
||||
if (info_header[2] != 'f') return -1;
|
||||
if (info_header[3] != 'o') return -1;
|
||||
|
||||
return GetFrameLength(header);
|
||||
}
|
||||
|
||||
void
|
||||
oggReader::ParseXingVbrHeader(int64 pos)
|
||||
{
|
||||
static const int sr_table[2][4] = { { 22050, 24000, 16000, 0 }, { 44100, 48000, 32000, 0 } };
|
||||
static const int FRAMES_FLAG = 0x0001;
|
||||
static const int BYTES_FLAG = 0x0002;
|
||||
static const int TOC_FLAG = 0x0004;
|
||||
static const int VBR_SCALE_FLAG = 0x0008;
|
||||
uint8 header[200];
|
||||
uint8 *xing_header;
|
||||
|
||||
Source()->ReadAt(pos, header, sizeof(header));
|
||||
|
||||
int layer_index = (header[1] >> 1) & 3;
|
||||
int h_id = (header[1] >> 3) & 1;
|
||||
int h_sr_index = (header[2] >> 2) & 3;
|
||||
int h_mode = (header[3] >> 6) & 3;
|
||||
|
||||
// determine offset of header
|
||||
if(h_id) // mpeg1
|
||||
xing_header = (h_mode != 3) ? (header + 36) : (header + 21);
|
||||
else // mpeg2
|
||||
xing_header = (h_mode != 3) ? (header + 21) : (header + 13);
|
||||
|
||||
xing_header += 4; // skip ID
|
||||
|
||||
int flags = B_BENDIAN_TO_HOST_INT32(*(uint32 *)xing_header);
|
||||
xing_header += 4;
|
||||
|
||||
if (fXingVbrInfo) {
|
||||
TRACE("oggReader::ParseXingVbrHeader: Error, already found a header\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fXingVbrInfo = new xing_vbr_info;
|
||||
|
||||
fXingVbrInfo->frameRate = sr_table[h_id][h_sr_index];
|
||||
if (flags & FRAMES_FLAG) {
|
||||
fXingVbrInfo->encodedFramesCount = (int64)(uint32)B_BENDIAN_TO_HOST_INT32(*(uint32 *)xing_header);
|
||||
xing_header += 4;
|
||||
} else {
|
||||
fXingVbrInfo->encodedFramesCount = -1;
|
||||
}
|
||||
|
||||
if (flags & BYTES_FLAG) {
|
||||
fXingVbrInfo->byteCount = (int64)(uint32)B_BENDIAN_TO_HOST_INT32(*(uint32 *)xing_header);
|
||||
xing_header += 4;
|
||||
} else {
|
||||
fXingVbrInfo->byteCount = -1;
|
||||
}
|
||||
|
||||
if (flags & TOC_FLAG) {
|
||||
fXingVbrInfo->hasSeekpoints = true;
|
||||
memcpy(fXingVbrInfo->seekpoints, xing_header, 100);
|
||||
xing_header += 100;
|
||||
} else {
|
||||
fXingVbrInfo->hasSeekpoints = false;
|
||||
}
|
||||
|
||||
if (flags & VBR_SCALE_FLAG) {
|
||||
fXingVbrInfo->vbrScale = B_BENDIAN_TO_HOST_INT32(*(uint32 *)xing_header);
|
||||
xing_header += 4;
|
||||
} else {
|
||||
fXingVbrInfo->vbrScale = -1;
|
||||
}
|
||||
|
||||
// mpeg frame (chunk) size is is constant and always 384 samples (frames) for
|
||||
// Layer I and 1152 samples for Layer II and Layer III
|
||||
if (fXingVbrInfo->encodedFramesCount != -1) {
|
||||
fXingVbrInfo->frameCount = fXingVbrInfo->encodedFramesCount * frame_sample_count_table[layer_index];
|
||||
fXingVbrInfo->duration = (fXingVbrInfo->frameCount * 1000000) / fXingVbrInfo->frameRate;
|
||||
} else {
|
||||
fXingVbrInfo->duration = -1;
|
||||
fXingVbrInfo->frameCount = -1;
|
||||
}
|
||||
|
||||
TRACE("oggReader::ParseXingVbrHeader: %Ld encoded frames, %Ld bytes, %s seekpoints, vbrscale %ld\n",
|
||||
fXingVbrInfo->encodedFramesCount, fXingVbrInfo->byteCount,
|
||||
fXingVbrInfo->hasSeekpoints ? "has" : "no", fXingVbrInfo->vbrScale);
|
||||
TRACE("oggReader::ParseXingVbrHeader: frameRate %ld, frameCount %Ld, duration %.6f\n",
|
||||
fXingVbrInfo->frameRate, fXingVbrInfo->frameCount, fXingVbrInfo->duration / 1000000.0);
|
||||
}
|
||||
|
||||
int64
|
||||
oggReader::XingSeekPoint(float percent)
|
||||
{
|
||||
if (!fXingVbrInfo || !fXingVbrInfo->hasSeekpoints || fXingVbrInfo->byteCount == -1)
|
||||
return -1;
|
||||
|
||||
int a;
|
||||
int64 point;
|
||||
float fa, fb, fx;
|
||||
|
||||
if (percent < 0.0f)
|
||||
percent = 0.0f;
|
||||
if (percent > 100.0f)
|
||||
percent = 100.0f;
|
||||
|
||||
a = (int)percent;
|
||||
if (a > 99)
|
||||
a = 99;
|
||||
fa = fXingVbrInfo->seekpoints[a];
|
||||
if (a < 99)
|
||||
fb = fXingVbrInfo->seekpoints[a + 1];
|
||||
else
|
||||
fb = 256.0f;
|
||||
|
||||
fx = fa + (fb - fa) * (percent - a);
|
||||
|
||||
point = (int64)((1.0f / 256.0f) * fx * fXingVbrInfo->byteCount);
|
||||
TRACE("oggReader::XingSeekPoint for %.8f%% is %Ld\n", percent, point);
|
||||
return point;
|
||||
}
|
||||
|
||||
int
|
||||
oggReader::GetLameVbrLength(uint8 *header)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
oggReader::GetFraunhoferVbrLength(uint8 *header)
|
||||
{
|
||||
if (header[0] != 0xff) return -1;
|
||||
if (header[36] != 'V') return -1;
|
||||
if (header[37] != 'B') return -1;
|
||||
if (header[38] != 'R') return -1;
|
||||
if (header[39] != 'I') return -1;
|
||||
|
||||
return GetFrameLength(header);
|
||||
}
|
||||
|
||||
void
|
||||
oggReader::ParseFraunhoferVbrHeader(int64 pos)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
oggReader::GetId3v2Length(uint8 *buffer)
|
||||
{
|
||||
if ((buffer[0] == 'I') && /* magic */
|
||||
(buffer[1] == 'D') &&
|
||||
(buffer[2] == '3') &&
|
||||
(buffer[3] != 0xff) && (buffer[4] != 0xff) && /* version */
|
||||
/* flags */
|
||||
(!(buffer[6] & 0x80)) && (!(buffer[7] & 0x80)) && /* the MSB in each byte in size is 0, to avoid */
|
||||
(!(buffer[8] & 0x80)) && (!(buffer[9] & 0x80))) { /* making a buggy mpeg header */
|
||||
return ((buffer[6] << 21)|(buffer[7] << 14)|(buffer[8] << 7)|(buffer[9])) + 10;
|
||||
}
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
bool
|
||||
oggReader::IsMp3File()
|
||||
{
|
||||
// avoid detecting mp3 in a container format like AVI or mov
|
||||
|
||||
// To detect an mp3 file, we seek into the middle,
|
||||
// and search for a valid sequence of 3 frame headers.
|
||||
// A mp3 frame has a maximum length of 2881 bytes, we
|
||||
// load a block of 16kB and use it to search.
|
||||
|
||||
const int32 search_size = 16384;
|
||||
int64 offset;
|
||||
int32 size;
|
||||
uint8 buf[search_size];
|
||||
|
||||
size = 8;
|
||||
offset = 0;
|
||||
if (size != Source()->ReadAt(offset, buf, size)) {
|
||||
TRACE("oggReaderPlugin::IsMp3File reading %ld bytes at offset %Ld failed\n", size, offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
// avoid reading some common formats that might have an embedded mp3 stream
|
||||
// RIFF, AVI or WAV
|
||||
if (buf[0] == 'R' && buf[1] == 'I' && buf[2] == 'F' && buf[3] == 'F')
|
||||
return false;
|
||||
// Ogg Vorbis
|
||||
if (buf[0] == 'O' && buf[1] == 'g' && buf[2] == 'g' && buf[3] == 'S')
|
||||
return false;
|
||||
// Real Media
|
||||
if (buf[0] == '.' && buf[1] == 'R' && buf[2] == 'M' && buf[3] == 'F')
|
||||
return false;
|
||||
// Quicktime
|
||||
if (buf[4] == 'm' && buf[5] == 'o' && buf[6] == 'o' && buf[7] == 'v')
|
||||
return false;
|
||||
// ASF 1 (first few bytes of GUID)
|
||||
if (buf[0] == 0x30 && buf[1] == 0x26 && buf[2] == 0xb2 && buf[3] == 0x75
|
||||
&& buf[4] == 0x8e && buf[5] == 0x66 && buf[6] == 0xcf && buf[7] == 0x11)
|
||||
return false;
|
||||
// ASF 2.0 (first few bytes of GUID)
|
||||
if (buf[0] == 0xd1 && buf[1] == 0x29 && buf[2] == 0xe2 && buf[3] == 0xd6
|
||||
&& buf[4] == 0xda && buf[5] == 0x35 && buf[6] == 0xd1 && buf[7] == 0x11)
|
||||
return false;
|
||||
|
||||
// search for a valid mpeg audio frame header
|
||||
// sequence in the middle of the file
|
||||
size = search_size;
|
||||
offset = fFileSize / 2 - search_size / 2;
|
||||
if (size > fFileSize) {
|
||||
size = fFileSize;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
TRACE("searching for mp3 frame headers at %Ld in %ld bytes\n", offset, size);
|
||||
|
||||
if (size != Source()->ReadAt(offset, buf, size)) {
|
||||
TRACE("oggReaderPlugin::IsMp3File reading %ld bytes at offset %Ld failed\n", size, offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 end = size - 4;
|
||||
for (int32 pos = 0; pos < end; pos++) {
|
||||
if (buf[pos] != 0xff) // quick check
|
||||
continue;
|
||||
if (IsValidStream(&buf[pos], size - pos))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
oggReader::IsValidStream(uint8 *buffer, int size)
|
||||
{
|
||||
// check 3 consecutive frame headers to make sure
|
||||
// that the length encoded in the header is correct,
|
||||
// and also that mpeg version and layer do not change
|
||||
int length1 = GetFrameLength(buffer);
|
||||
if (length1 < 0 || (length1 + 4) > size)
|
||||
return false;
|
||||
int version_index1 = (buffer[1] >> 3) & 0x03;
|
||||
int layer_index1 = (buffer[1] >> 1) & 0x03;
|
||||
int length2 = GetFrameLength(buffer + length1);
|
||||
if (length2 < 0 || (length1 + length2 + 4) > size)
|
||||
return false;
|
||||
int version_index2 = (buffer[length1 + 1] >> 3) & 0x03;
|
||||
int layer_index2 = (buffer[length1 + 1] >> 1) & 0x03;
|
||||
if (version_index1 != version_index2 || layer_index1 != layer_index1)
|
||||
return false;
|
||||
int length3 = GetFrameLength(buffer + length1 + length2);
|
||||
if (length3 < 0)
|
||||
return false;
|
||||
int version_index3 = (buffer[length1 + length2 + 1] >> 3) & 0x03;
|
||||
int layer_index3 = (buffer[length1 + length2 + 1] >> 1) & 0x03;
|
||||
if (version_index2 != version_index3 || layer_index2 != layer_index3)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
oggReader::GetFrameLength(void *header)
|
||||
{
|
||||
uint8 *h = (uint8 *)header;
|
||||
|
||||
if (h[0] != 0xff)
|
||||
return -1;
|
||||
if ((h[1] & 0xe0) != 0xe0)
|
||||
return -1;
|
||||
|
||||
int mpeg_version_index = (h[1] >> 3) & 0x03;
|
||||
int layer_index = (h[1] >> 1) & 0x03;
|
||||
int bitrate_index = (h[2] >> 4) & 0x0f;
|
||||
int sampling_rate_index = (h[2] >> 2) & 0x03;
|
||||
int padding = (h[2] >> 1) & 0x01;
|
||||
/* no interested in the other bits */
|
||||
|
||||
int bitrate = bit_rate_table[mpeg_version_index][layer_index][bitrate_index];
|
||||
int framerate = frame_rate_table[mpeg_version_index][sampling_rate_index];
|
||||
|
||||
if (!bitrate || !framerate)
|
||||
return -1;
|
||||
|
||||
int length;
|
||||
if (layer_index == 3) // layer 1
|
||||
length = ((144 * 1000 * bitrate) / framerate) + (padding * 4);
|
||||
else // layer 2 & 3
|
||||
length = ((144 * 1000 * bitrate) / framerate) + padding;
|
||||
|
||||
#if 0
|
||||
TRACE("%s %s, %s crc, bit rate %d, frame rate %d, padding %d, frame length %d\n",
|
||||
mpeg_version_index == 0 ? "mpeg 2.5" : (mpeg_version_index == 2 ? "mpeg 2" : "mpeg 1"),
|
||||
layer_index == 3 ? "layer 1" : (layer_index == 2 ? "layer 2" : "layer 3"),
|
||||
(h[1] & 0x01) ? "no" : "has",
|
||||
bitrate, framerate, padding, length);
|
||||
#endif
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
Reader *
|
||||
oggReaderPlugin::NewReader()
|
||||
{
|
||||
return new oggReader;
|
||||
}
|
||||
|
||||
|
||||
MediaPlugin *
|
||||
instantiate_plugin()
|
||||
{
|
||||
return new oggReaderPlugin;
|
||||
}
|
82
src/add-ons/media/plugins/ogg/OggReaderPlugin.h
Normal file
82
src/add-ons/media/plugins/ogg/OggReaderPlugin.h
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef _OGG_READER_PLUGIN_H
|
||||
#define _OGG_READER_PLUGIN_H
|
||||
|
||||
#include "ReaderPlugin.h"
|
||||
|
||||
namespace BPrivate { namespace media {
|
||||
|
||||
class oggReader : public Reader
|
||||
{
|
||||
public:
|
||||
oggReader();
|
||||
~oggReader();
|
||||
|
||||
const char *Copyright();
|
||||
|
||||
status_t Sniff(int32 *streamCount);
|
||||
|
||||
void GetFileFormatInfo(media_file_format *mff);
|
||||
|
||||
status_t AllocateCookie(int32 streamNumber, void **cookie);
|
||||
status_t FreeCookie(void *cookie);
|
||||
|
||||
status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
||||
media_format *format, void **infoBuffer, int32 *infoSize);
|
||||
|
||||
status_t Seek(void *cookie,
|
||||
uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time);
|
||||
|
||||
status_t GetNextChunk(void *cookie,
|
||||
void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader);
|
||||
|
||||
BPositionIO *Source() { return fSeekableSource; }
|
||||
|
||||
private:
|
||||
bool ParseFile();
|
||||
bool IsMp3File();
|
||||
|
||||
// checks if the buffer contains a valid ogg stream, length should be
|
||||
bool IsValidStream(uint8 *buffer, int size);
|
||||
|
||||
int GetFrameLength(void *header);
|
||||
int GetXingVbrLength(uint8 *header);
|
||||
int GetFraunhoferVbrLength(uint8 *header);
|
||||
int GetLameVbrLength(uint8 *header);
|
||||
int GetId3v2Length(uint8 *header);
|
||||
int GetInfoCbrLength(uint8 *header);
|
||||
|
||||
bool FindData();
|
||||
|
||||
void ParseXingVbrHeader(int64 pos);
|
||||
void ParseFraunhoferVbrHeader(int64 pos);
|
||||
|
||||
int64 XingSeekPoint(float percent);
|
||||
|
||||
private:
|
||||
BPositionIO * fSeekableSource;
|
||||
int64 fFileSize;
|
||||
|
||||
int64 fDataStart;
|
||||
int64 fDataSize;
|
||||
|
||||
struct xing_vbr_info;
|
||||
struct fhg_vbr_info;
|
||||
|
||||
xing_vbr_info * fXingVbrInfo;
|
||||
fhg_vbr_info * fFhgVbrInfo;
|
||||
};
|
||||
|
||||
|
||||
class oggReaderPlugin : public ReaderPlugin
|
||||
{
|
||||
public:
|
||||
Reader *NewReader();
|
||||
};
|
||||
|
||||
} } // namespace BPrivate::media
|
||||
|
||||
using namespace BPrivate::media;
|
||||
|
||||
#endif
|
28
src/add-ons/media/plugins/ogg/libogg/COPYING
Normal file
28
src/add-ons/media/plugins/ogg/libogg/COPYING
Normal file
@ -0,0 +1,28 @@
|
||||
Copyright (c) 2002, Xiph.Org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.Org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
6
src/add-ons/media/plugins/ogg/libogg/Jamfile
Normal file
6
src/add-ons/media/plugins/ogg/libogg/Jamfile
Normal file
@ -0,0 +1,6 @@
|
||||
SubDir OBOS_TOP src add-ons media plugins ogg libogg ;
|
||||
|
||||
StaticLibrary ogg :
|
||||
bitwise.c
|
||||
framing.c
|
||||
;
|
452
src/add-ons/media/plugins/ogg/libogg/bitwise.c
Normal file
452
src/add-ons/media/plugins/ogg/libogg/bitwise.c
Normal file
@ -0,0 +1,452 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: packing variable sized words into an octet stream
|
||||
last mod: $Id: bitwise.c,v 1.1 2003/12/13 20:12:32 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* We're 'LSb' endian; if we write a word but read individual bits,
|
||||
then we'll read the lsb first */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#define BUFFER_INCREMENT 256
|
||||
|
||||
static unsigned long mask[]=
|
||||
{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
|
||||
0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
|
||||
0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
|
||||
0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
|
||||
0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
|
||||
0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
|
||||
0x3fffffff,0x7fffffff,0xffffffff };
|
||||
|
||||
void oggpack_writeinit(oggpack_buffer *b){
|
||||
memset(b,0,sizeof(*b));
|
||||
b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
|
||||
b->buffer[0]='\0';
|
||||
b->storage=BUFFER_INCREMENT;
|
||||
}
|
||||
|
||||
void oggpack_writetrunc(oggpack_buffer *b,long bits){
|
||||
long bytes=bits>>3;
|
||||
bits-=bytes*8;
|
||||
b->ptr=b->buffer+bytes;
|
||||
b->endbit=bits;
|
||||
b->endbyte=bytes;
|
||||
*b->ptr|=mask[bits];
|
||||
}
|
||||
|
||||
void oggpack_writealign(oggpack_buffer *b){
|
||||
int bits=8-b->endbit;
|
||||
if(bits<8)
|
||||
oggpack_write(b,0,bits);
|
||||
}
|
||||
|
||||
void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
|
||||
unsigned char *ptr=(unsigned char *)source;
|
||||
|
||||
long bytes=bits/8;
|
||||
bits-=bytes*8;
|
||||
|
||||
if(b->endbit){
|
||||
int i;
|
||||
/* unaligned copy. Do it the hard way. */
|
||||
for(i=0;i<bytes;i++)
|
||||
oggpack_write(b,(long)(ptr[i]),8);
|
||||
}else{
|
||||
/* aligned block copy */
|
||||
if(b->endbyte+bytes+1>=b->storage){
|
||||
b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
|
||||
b->buffer=_ogg_realloc(b->buffer,b->storage);
|
||||
b->ptr=b->buffer+b->endbyte;
|
||||
}
|
||||
|
||||
memmove(b->ptr,source,bytes);
|
||||
b->ptr+=bytes;
|
||||
b->buffer+=bytes;
|
||||
*b->ptr=0;
|
||||
|
||||
}
|
||||
if(bits)
|
||||
oggpack_write(b,(long)(ptr[bytes]),bits);
|
||||
}
|
||||
|
||||
void oggpack_reset(oggpack_buffer *b){
|
||||
b->ptr=b->buffer;
|
||||
b->buffer[0]=0;
|
||||
b->endbit=b->endbyte=0;
|
||||
}
|
||||
|
||||
void oggpack_writeclear(oggpack_buffer *b){
|
||||
_ogg_free(b->buffer);
|
||||
memset(b,0,sizeof(*b));
|
||||
}
|
||||
|
||||
void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
|
||||
memset(b,0,sizeof(*b));
|
||||
b->buffer=b->ptr=buf;
|
||||
b->storage=bytes;
|
||||
}
|
||||
|
||||
/* Takes only up to 32 bits. */
|
||||
void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
|
||||
if(b->endbyte+4>=b->storage){
|
||||
b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
|
||||
b->storage+=BUFFER_INCREMENT;
|
||||
b->ptr=b->buffer+b->endbyte;
|
||||
}
|
||||
|
||||
value&=mask[bits];
|
||||
bits+=b->endbit;
|
||||
|
||||
b->ptr[0]|=value<<b->endbit;
|
||||
|
||||
if(bits>=8){
|
||||
b->ptr[1]=value>>(8-b->endbit);
|
||||
if(bits>=16){
|
||||
b->ptr[2]=value>>(16-b->endbit);
|
||||
if(bits>=24){
|
||||
b->ptr[3]=value>>(24-b->endbit);
|
||||
if(bits>=32){
|
||||
if(b->endbit)
|
||||
b->ptr[4]=value>>(32-b->endbit);
|
||||
else
|
||||
b->ptr[4]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b->endbyte+=bits/8;
|
||||
b->ptr+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
}
|
||||
|
||||
/* Read in bits without advancing the bitptr; bits <= 32 */
|
||||
long oggpack_look(oggpack_buffer *b,int bits){
|
||||
unsigned long ret;
|
||||
unsigned long m=mask[bits];
|
||||
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte+4>=b->storage){
|
||||
/* not the main path */
|
||||
if(b->endbyte*8+bits>b->storage*8)return(-1);
|
||||
}
|
||||
|
||||
ret=b->ptr[0]>>b->endbit;
|
||||
if(bits>8){
|
||||
ret|=b->ptr[1]<<(8-b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->ptr[2]<<(16-b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->ptr[3]<<(24-b->endbit);
|
||||
if(bits>32 && b->endbit)
|
||||
ret|=b->ptr[4]<<(32-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(m&ret);
|
||||
}
|
||||
|
||||
long oggpack_look1(oggpack_buffer *b){
|
||||
if(b->endbyte>=b->storage)return(-1);
|
||||
return((b->ptr[0]>>b->endbit)&1);
|
||||
}
|
||||
|
||||
void oggpack_adv(oggpack_buffer *b,int bits){
|
||||
bits+=b->endbit;
|
||||
b->ptr+=bits/8;
|
||||
b->endbyte+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
}
|
||||
|
||||
void oggpack_adv1(oggpack_buffer *b){
|
||||
if(++(b->endbit)>7){
|
||||
b->endbit=0;
|
||||
b->ptr++;
|
||||
b->endbyte++;
|
||||
}
|
||||
}
|
||||
|
||||
/* bits <= 32 */
|
||||
long oggpack_read(oggpack_buffer *b,int bits){
|
||||
unsigned long ret;
|
||||
unsigned long m=mask[bits];
|
||||
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte+4>=b->storage){
|
||||
/* not the main path */
|
||||
ret=-1UL;
|
||||
if(b->endbyte*8+bits>b->storage*8)goto overflow;
|
||||
}
|
||||
|
||||
ret=b->ptr[0]>>b->endbit;
|
||||
if(bits>8){
|
||||
ret|=b->ptr[1]<<(8-b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->ptr[2]<<(16-b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->ptr[3]<<(24-b->endbit);
|
||||
if(bits>32 && b->endbit){
|
||||
ret|=b->ptr[4]<<(32-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret&=m;
|
||||
|
||||
overflow:
|
||||
|
||||
b->ptr+=bits/8;
|
||||
b->endbyte+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
long oggpack_read1(oggpack_buffer *b){
|
||||
unsigned long ret;
|
||||
|
||||
if(b->endbyte>=b->storage){
|
||||
/* not the main path */
|
||||
ret=-1UL;
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
ret=(b->ptr[0]>>b->endbit)&1;
|
||||
|
||||
overflow:
|
||||
|
||||
b->endbit++;
|
||||
if(b->endbit>7){
|
||||
b->endbit=0;
|
||||
b->ptr++;
|
||||
b->endbyte++;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
long oggpack_bytes(oggpack_buffer *b){
|
||||
return(b->endbyte+(b->endbit+7)/8);
|
||||
}
|
||||
|
||||
long oggpack_bits(oggpack_buffer *b){
|
||||
return(b->endbyte*8+b->endbit);
|
||||
}
|
||||
|
||||
unsigned char *oggpack_get_buffer(oggpack_buffer *b){
|
||||
return(b->buffer);
|
||||
}
|
||||
|
||||
/* Self test of the bitwise routines; everything else is based on
|
||||
them, so they damned well better be solid. */
|
||||
|
||||
#ifdef _V_SELFTEST
|
||||
#include <stdio.h>
|
||||
|
||||
static int ilog(unsigned int v){
|
||||
int ret=0;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
oggpack_buffer o;
|
||||
oggpack_buffer r;
|
||||
|
||||
void report(char *in){
|
||||
fprintf(stderr,"%s",in);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
|
||||
long bytes,i;
|
||||
unsigned char *buffer;
|
||||
|
||||
oggpack_reset(&o);
|
||||
for(i=0;i<vals;i++)
|
||||
oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
|
||||
buffer=oggpack_get_buffer(&o);
|
||||
bytes=oggpack_bytes(&o);
|
||||
if(bytes!=compsize)report("wrong number of bytes!\n");
|
||||
for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
|
||||
for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
|
||||
report("wrote incorrect value!\n");
|
||||
}
|
||||
oggpack_readinit(&r,buffer,bytes);
|
||||
for(i=0;i<vals;i++){
|
||||
int tbit=bits?bits:ilog(b[i]);
|
||||
if(oggpack_look(&r,tbit)==-1)
|
||||
report("out of data!\n");
|
||||
if(oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
|
||||
report("looked at incorrect value!\n");
|
||||
if(tbit==1)
|
||||
if(oggpack_look1(&r)!=(b[i]&mask[tbit]))
|
||||
report("looked at single bit incorrect value!\n");
|
||||
if(tbit==1){
|
||||
if(oggpack_read1(&r)!=(b[i]&mask[tbit]))
|
||||
report("read incorrect single bit value!\n");
|
||||
}else{
|
||||
if(oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
|
||||
report("read incorrect value!\n");
|
||||
}
|
||||
}
|
||||
if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
|
||||
}
|
||||
|
||||
int main(void){
|
||||
unsigned char *buffer;
|
||||
long bytes,i;
|
||||
static unsigned long testbuffer1[]=
|
||||
{18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
|
||||
567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
|
||||
int test1size=43;
|
||||
|
||||
static unsigned long testbuffer2[]=
|
||||
{216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
|
||||
1233432,534,5,346435231,14436467,7869299,76326614,167548585,
|
||||
85525151,0,12321,1,349528352};
|
||||
int test2size=21;
|
||||
|
||||
static unsigned long large[]=
|
||||
{2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
|
||||
1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
|
||||
85525151,0,12321,1,2146528352};
|
||||
|
||||
static unsigned long testbuffer3[]=
|
||||
{1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,
|
||||
0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
|
||||
int test3size=56;
|
||||
|
||||
int onesize=33;
|
||||
static int one[]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
|
||||
34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
|
||||
223,4};
|
||||
|
||||
int twosize=6;
|
||||
static int two[]={61,255,255,251,231,29};
|
||||
|
||||
int threesize=54;
|
||||
static int three[]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
|
||||
142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
|
||||
58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
|
||||
100,52,4,14,18,86,77,1};
|
||||
|
||||
int foursize=38;
|
||||
static int four[]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
|
||||
132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
|
||||
28,2,133,0,1};
|
||||
|
||||
int fivesize=45;
|
||||
static int five[]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
|
||||
241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
|
||||
84,75,159,2,1,0,132,192,8,0,0,18,22};
|
||||
|
||||
int sixsize=7;
|
||||
static int six[]={17,177,170,242,169,19,148};
|
||||
|
||||
/* Test read/write together */
|
||||
/* Later we test against pregenerated bitstreams */
|
||||
oggpack_writeinit(&o);
|
||||
|
||||
fprintf(stderr,"\nSmall preclipped packing: ");
|
||||
cliptest(testbuffer1,test1size,0,one,onesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nNull bit call: ");
|
||||
cliptest(testbuffer3,test3size,0,two,twosize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nLarge preclipped packing: ");
|
||||
cliptest(testbuffer2,test2size,0,three,threesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\n32 bit preclipped packing: ");
|
||||
oggpack_reset(&o);
|
||||
for(i=0;i<test2size;i++)
|
||||
oggpack_write(&o,large[i],32);
|
||||
buffer=oggpack_get_buffer(&o);
|
||||
bytes=oggpack_bytes(&o);
|
||||
oggpack_readinit(&r,buffer,bytes);
|
||||
for(i=0;i<test2size;i++){
|
||||
if(oggpack_look(&r,32)==-1)report("out of data. failed!");
|
||||
if(oggpack_look(&r,32)!=large[i]){
|
||||
fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpack_look(&r,32),large[i],
|
||||
oggpack_look(&r,32),large[i]);
|
||||
report("read incorrect value!\n");
|
||||
}
|
||||
oggpack_adv(&r,32);
|
||||
}
|
||||
if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nSmall unclipped packing: ");
|
||||
cliptest(testbuffer1,test1size,7,four,foursize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nLarge unclipped packing: ");
|
||||
cliptest(testbuffer2,test2size,17,five,fivesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nSingle bit unclipped packing: ");
|
||||
cliptest(testbuffer3,test3size,1,six,sixsize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nTesting read past end: ");
|
||||
oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
|
||||
for(i=0;i<64;i++){
|
||||
if(oggpack_read(&r,1)!=0){
|
||||
fprintf(stderr,"failed; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(oggpack_look(&r,1)!=-1 ||
|
||||
oggpack_read(&r,1)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
|
||||
if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
|
||||
fprintf(stderr,"failed 2; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(oggpack_look(&r,18)!=0 ||
|
||||
oggpack_look(&r,18)!=0){
|
||||
fprintf(stderr,"failed 3; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(oggpack_look(&r,19)!=-1 ||
|
||||
oggpack_look(&r,19)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(oggpack_look(&r,32)!=-1 ||
|
||||
oggpack_look(&r,32)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr,"ok.\n\n");
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif /* _V_SELFTEST */
|
||||
|
||||
#undef BUFFER_INCREMENT
|
10
src/add-ons/media/plugins/ogg/libogg/config_types.h
Normal file
10
src/add-ons/media/plugins/ogg/libogg/config_types.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef __CONFIG_TYPES_H__
|
||||
#define __CONFIG_TYPES_H__
|
||||
|
||||
/* these are filled in by configure */
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
|
||||
#endif
|
1746
src/add-ons/media/plugins/ogg/libogg/framing.c
Normal file
1746
src/add-ons/media/plugins/ogg/libogg/framing.c
Normal file
File diff suppressed because it is too large
Load Diff
184
src/add-ons/media/plugins/ogg/libogg/ogg/ogg.h
Normal file
184
src/add-ons/media/plugins/ogg/libogg/ogg/ogg.h
Normal file
@ -0,0 +1,184 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: toplevel libogg include
|
||||
last mod: $Id: ogg.h,v 1.1 2003/12/13 20:12:32 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
#define _OGG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
typedef struct {
|
||||
long endbyte;
|
||||
int endbit;
|
||||
|
||||
unsigned char *buffer;
|
||||
unsigned char *ptr;
|
||||
long storage;
|
||||
} oggpack_buffer;
|
||||
|
||||
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
long header_len;
|
||||
unsigned char *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
|
||||
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream **********************************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *body_data; /* bytes from packet bodies */
|
||||
long body_storage; /* storage elements allocated */
|
||||
long body_fill; /* elements stored; fill mark */
|
||||
long body_returned; /* elements of fill returned */
|
||||
|
||||
|
||||
int *lacing_vals; /* The values that will go to the segment table */
|
||||
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo */
|
||||
long lacing_storage;
|
||||
long lacing_fill;
|
||||
long lacing_packet;
|
||||
long lacing_returned;
|
||||
|
||||
unsigned char header[282]; /* working space for header encode */
|
||||
int header_fill;
|
||||
|
||||
int e_o_s; /* set when we have buffered the last packet in the
|
||||
logical bitstream */
|
||||
int b_o_s; /* set after we've written the initial page
|
||||
of a logical bitstream */
|
||||
long serialno;
|
||||
long pageno;
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a seperate abstraction
|
||||
layer) also knows about the gap */
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
} ogg_stream_state;
|
||||
|
||||
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *packet;
|
||||
long bytes;
|
||||
long b_o_s;
|
||||
long e_o_s;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a seperate abstraction
|
||||
layer) also knows about the gap */
|
||||
} ogg_packet;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int storage;
|
||||
int fill;
|
||||
int returned;
|
||||
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
} ogg_sync_state;
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||
|
||||
extern void oggpack_writeinit(oggpack_buffer *b);
|
||||
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpack_writealign(oggpack_buffer *b);
|
||||
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpack_reset(oggpack_buffer *b);
|
||||
extern void oggpack_writeclear(oggpack_buffer *b);
|
||||
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_look1(oggpack_buffer *b);
|
||||
extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpack_adv1(oggpack_buffer *b);
|
||||
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read1(oggpack_buffer *b);
|
||||
extern long oggpack_bytes(oggpack_buffer *b);
|
||||
extern long oggpack_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||
|
||||
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
|
||||
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||
|
||||
extern int ogg_sync_init(ogg_sync_state *oy);
|
||||
extern int ogg_sync_clear(ogg_sync_state *oy);
|
||||
extern int ogg_sync_reset(ogg_sync_state *oy);
|
||||
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||
|
||||
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
|
||||
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
|
||||
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||
|
||||
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_clear(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||
extern int ogg_stream_eos(ogg_stream_state *os);
|
||||
|
||||
extern void ogg_page_checksum_set(ogg_page *og);
|
||||
|
||||
extern int ogg_page_version(ogg_page *og);
|
||||
extern int ogg_page_continued(ogg_page *og);
|
||||
extern int ogg_page_bos(ogg_page *og);
|
||||
extern int ogg_page_eos(ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(ogg_page *og);
|
||||
extern int ogg_page_serialno(ogg_page *og);
|
||||
extern long ogg_page_pageno(ogg_page *og);
|
||||
extern int ogg_page_packets(ogg_page *og);
|
||||
|
||||
extern void ogg_packet_clear(ogg_packet *op);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OGG_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
84
src/add-ons/media/plugins/ogg/libogg/ogg/os_types.h
Normal file
84
src/add-ons/media/plugins/ogg/libogg/ogg/os_types.h
Normal file
@ -0,0 +1,84 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
||||
last mod: $Id: os_types.h,v 1.1 2003/12/13 20:12:32 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OS_TYPES_H
|
||||
#define _OS_TYPES_H
|
||||
|
||||
/* make it easy on the folks that want to compile the libs with a
|
||||
different malloc than stdlib */
|
||||
#define _ogg_malloc malloc
|
||||
#define _ogg_calloc calloc
|
||||
#define _ogg_realloc realloc
|
||||
#define _ogg_free free
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# ifndef __GNUC__
|
||||
/* MSVC/Borland */
|
||||
typedef __int64 ogg_int64_t;
|
||||
typedef __int32 ogg_int32_t;
|
||||
typedef unsigned __int32 ogg_uint32_t;
|
||||
typedef __int16 ogg_int16_t;
|
||||
# else
|
||||
/* Cygwin */
|
||||
#include <_G_config.h>
|
||||
typedef _G_int64_t ogg_int64_t;
|
||||
typedef _G_int32_t ogg_int32_t;
|
||||
typedef _G_uint32_t ogg_uint32_t;
|
||||
typedef _G_int16_t ogg_int16_t;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 ogg_int16_t;
|
||||
typedef SInt32 ogg_int32_t;
|
||||
typedef UInt32 ogg_uint32_t;
|
||||
typedef SInt64 ogg_int64_t;
|
||||
|
||||
#elif defined(__MACOSX__) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef u_int32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef u_int32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short ogg_int16_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
|
||||
#else
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <ogg/config_types.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _OS_TYPES_H */
|
Loading…
Reference in New Issue
Block a user