compilable, missing seek, getnextchunk
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5757 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,7 +2,7 @@ SubDir OBOS_TOP src add-ons media plugins ogg ;
|
|||||||
|
|
||||||
UsePrivateHeaders media ;
|
UsePrivateHeaders media ;
|
||||||
|
|
||||||
SubDirHdrs $(SUBDIR) libogg ogg ;
|
SubDirHdrs [ FDirName $(SUBDIR) libogg ] ;
|
||||||
|
|
||||||
Addon ogg : media plugins :
|
Addon ogg : media plugins :
|
||||||
OggReaderPlugin.cpp
|
OggReaderPlugin.cpp
|
||||||
|
|||||||
@@ -19,15 +19,13 @@
|
|||||||
oggReader::oggReader()
|
oggReader::oggReader()
|
||||||
{
|
{
|
||||||
TRACE("oggReader::oggReader\n");
|
TRACE("oggReader::oggReader\n");
|
||||||
ogg_stream_init(&fOggStreamState,(int)this);
|
ogg_sync_init(&fSync);
|
||||||
ogg_sync_init(&fOggSyncState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
oggReader::~oggReader()
|
oggReader::~oggReader()
|
||||||
{
|
{
|
||||||
ogg_stream_destroy(&fOggStreamState);
|
ogg_sync_destroy(&fSync);
|
||||||
ogg_sync_destroy(&fOggSyncState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -42,47 +40,116 @@ status_t
|
|||||||
oggReader::Sniff(int32 *streamCount)
|
oggReader::Sniff(int32 *streamCount)
|
||||||
{
|
{
|
||||||
TRACE("oggReader::Sniff\n");
|
TRACE("oggReader::Sniff\n");
|
||||||
|
|
||||||
fSeekableSource = dynamic_cast<BPositionIO *>(Reader::Source());
|
|
||||||
if (!fSeekableSource) {
|
|
||||||
TRACE("oggReader::Sniff: not a BPositionIO\n");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
fSeekableSource->Seek(0,SEEK_SET);
|
|
||||||
|
|
||||||
ogg_sync_state sync;
|
|
||||||
ogg_sync_init(&sync);
|
|
||||||
char * buffer = 0;
|
|
||||||
ssize_t bytes = 0;
|
|
||||||
ogg_page page;
|
ogg_page page;
|
||||||
buffer = ogg_sync_buffer(&sync,4096);
|
ogg_sync_pageout(&fSync,&page); // clear the buffer
|
||||||
bytes = fSeekableSource->Read(buffer,4096);
|
|
||||||
|
char * buffer = ogg_sync_buffer(&fSync,4096);
|
||||||
|
ssize_t bytes = Source()->Read(buffer,4096);
|
||||||
if (bytes < 4096) {
|
if (bytes < 4096) {
|
||||||
TRACE("oggReader::Sniff: Read: not enough: not ogg\n");
|
TRACE("oggReader::Sniff: Read: not enough: not ogg\n");
|
||||||
ogg_sync_destroy(&sync);
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_sync_wrote(&fSync,bytes) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_wrote failed?: bail\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
ogg_sync_wrote(&sync,bytes);
|
switch ((int)ogg_sync_pageout(&fSync,&page)) {
|
||||||
if (bytesogg_sync_pageout(&sync,&page) != 1) {
|
case -1:
|
||||||
TRACE("oggReader::Sniff: ogg_sync_pageout error: not ogg\n");
|
TRACE("oggReader::Sniff: ogg_sync_pageout: not synced: not ogg\n");
|
||||||
ogg_sync_destroy(&sync);
|
return B_ERROR;
|
||||||
|
case 0:
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_pageout: need more data: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
case 1:
|
||||||
|
TRACE("oggReader::Sniff: looks like a valid ogg page\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_pageout: unexpected result: bail\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
// page sanity checks
|
||||||
|
if (ogg_page_version(&page) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_version: error in page encoding: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_page_continued(&page) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_page_continued: continued page: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_page_bos(&page) == 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_page_bos: not beginning of a bitstream: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// seems like ogg
|
// seems like ogg
|
||||||
// TODO: count the streams
|
ogg_stream_state stream;
|
||||||
*streamCount = 1;
|
if (ogg_stream_init(&stream,ogg_page_serialno(&page)) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_stream_init: failed: bail\n");
|
||||||
/* ogg_stream_state stream;
|
return B_ERROR;
|
||||||
ogg_stream_init(&stream,ogg_page_serial_no(&page);
|
}
|
||||||
|
if (ogg_stream_pagein(&stream,&page) != 0) {
|
||||||
ogg_stream_pagein(&stream,&page);
|
TRACE("oggReader::Sniff: ogg_stream_pagein: failed: bail\n");
|
||||||
ogg_packet packet;
|
return B_ERROR;
|
||||||
ogg_stream_packetout(&stream,&packet);*/
|
}
|
||||||
|
fStreams[ogg_page_serialno(&page)] = stream;
|
||||||
|
while (true) {
|
||||||
|
buffer = ogg_sync_buffer(&fSync,4096);
|
||||||
|
bytes = Source()->Read(buffer,4096);
|
||||||
|
if (bytes < 4096) {
|
||||||
|
TRACE("oggReader::Sniff: Read: not enough: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_sync_wrote(&fSync,bytes) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_wrote failed?: bail\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
int result = ogg_sync_pageout(&fSync,&page);
|
||||||
|
if (result == -1) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_pageout: not synced: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
} else if (result == 0) {
|
||||||
|
// need more data to complete an ogg page
|
||||||
|
} else if (result == 1) {
|
||||||
|
// valid ogg page
|
||||||
|
if (ogg_page_version(&page) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_version: error in page encoding: not ogg\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_page_bos(&page) == 0) {
|
||||||
|
// not start of stream
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// new stream
|
||||||
|
if (ogg_stream_init(&stream,ogg_page_serialno(&page)) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_stream_init: failed: bail\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_stream_pagein(&stream,&page) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_stream_pagein: failed: bail\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
// we don't check for unique-ness of start pages. we accept duplication.
|
||||||
|
fStreams[ogg_page_serialno(&page)] = stream;
|
||||||
|
} else {
|
||||||
|
TRACE("oggReader::Sniff: ogg_sync_pageout: unexpected result: bail\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// last page needs to be put into the right stream
|
||||||
|
ogg_stream_map::iterator i = fStreams.find(ogg_page_serialno(&page));
|
||||||
|
if (i == fStreams.end()) {
|
||||||
|
// the next page doesn't belong to any existing stream?
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
if (ogg_stream_pagein(&i->second,&page) != 0) {
|
||||||
|
TRACE("oggReader::Sniff: ogg_stream_pagein: failed: bail\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
*streamCount = fStreams.size();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
oggReader::GetFileFormatInfo(media_file_format *mff)
|
oggReader::GetFileFormatInfo(media_file_format *mff)
|
||||||
{
|
{
|
||||||
@@ -90,14 +157,11 @@ oggReader::GetFileFormatInfo(media_file_format *mff)
|
|||||||
| media_file_format::B_KNOWS_ENCODED_VIDEO
|
| media_file_format::B_KNOWS_ENCODED_VIDEO
|
||||||
| media_file_format::B_KNOWS_ENCODED_AUDIO
|
| media_file_format::B_KNOWS_ENCODED_AUDIO
|
||||||
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
||||||
mff->family = B_OGG_FORMAT_FAMILY;
|
mff->family = B_MISC_FORMAT_FAMILY;
|
||||||
mff->version = 100;
|
mff->version = 100;
|
||||||
strcpy(mff->mime_type, "application/ogg");
|
strcpy(mff->mime_type, "application/ogg");
|
||||||
strcpy(mff->file_extension, "ogg");
|
strcpy(mff->file_extension, "ogg");
|
||||||
|
strcpy(mff->short_name, "Ogg");
|
||||||
// uint8 header[4];
|
|
||||||
// Source()->ReadAt(fDataStart, header, sizeof(header));
|
|
||||||
strcpy(mff->short_name, "Ogg");
|
|
||||||
strcpy(mff->pretty_name, "Ogg bitstream");
|
strcpy(mff->pretty_name, "Ogg bitstream");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,9 +170,17 @@ status_t
|
|||||||
oggReader::AllocateCookie(int32 streamNumber, void **cookie)
|
oggReader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||||
{
|
{
|
||||||
TRACE("oggReader::AllocateCookie\n");
|
TRACE("oggReader::AllocateCookie\n");
|
||||||
|
ogg_stream_map::iterator i = fStreams.begin();
|
||||||
|
while (streamNumber > 0) {
|
||||||
|
if (i == fStreams.end()) {
|
||||||
|
TRACE("oggReader::AllocateCookie: invalid streamNumber: bail\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
streamNumber--;
|
||||||
|
}
|
||||||
// store the cookie
|
// store the cookie
|
||||||
*cookie = data;
|
*cookie = (void*)(&i->second);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +197,13 @@ status_t
|
|||||||
oggReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
oggReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
||||||
media_format *format, void **infoBuffer, int32 *infoSize)
|
media_format *format, void **infoBuffer, int32 *infoSize)
|
||||||
{
|
{
|
||||||
|
TRACE("oggReader::GetStreamInfo\n");
|
||||||
|
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||||
|
*frameCount = -1; // don't know
|
||||||
|
*duration = -1; // don't know
|
||||||
|
// no info
|
||||||
|
*infoBuffer = 0;
|
||||||
|
*infoSize = 0;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,10 +213,15 @@ oggReader::Seek(void *cookie,
|
|||||||
uint32 seekTo,
|
uint32 seekTo,
|
||||||
int64 *frame, bigtime_t *time)
|
int64 *frame, bigtime_t *time)
|
||||||
{
|
{
|
||||||
if (!fSeekableSource)
|
TRACE("oggReader::Seek\n");
|
||||||
|
BPositionIO * input = dynamic_cast<BPositionIO *>(Source());
|
||||||
|
if (input == 0) {
|
||||||
|
TRACE("oggReader::Seek: not a PositionIO: not seekable\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||||
|
|
||||||
|
|
||||||
ogg_sync_reset
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +231,9 @@ oggReader::GetNextChunk(void *cookie,
|
|||||||
void **chunkBuffer, int32 *chunkSize,
|
void **chunkBuffer, int32 *chunkSize,
|
||||||
media_header *mediaHeader)
|
media_header *mediaHeader)
|
||||||
{
|
{
|
||||||
|
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||||
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
|
|
||||||
#include "ReaderPlugin.h"
|
#include "ReaderPlugin.h"
|
||||||
#include "ogg/ogg.h"
|
#include "ogg/ogg.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace BPrivate { namespace media {
|
namespace BPrivate { namespace media {
|
||||||
|
|
||||||
|
typedef std::map<int,ogg_stream_state> ogg_stream_map;
|
||||||
|
|
||||||
class oggReader : public Reader
|
class oggReader : public Reader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -32,12 +35,9 @@ public:
|
|||||||
void **chunkBuffer, int32 *chunkSize,
|
void **chunkBuffer, int32 *chunkSize,
|
||||||
media_header *mediaHeader);
|
media_header *mediaHeader);
|
||||||
|
|
||||||
BPositionIO *Source() { return fSeekableSource; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BPositionIO * fSeekableSource;
|
ogg_sync_state fSync;
|
||||||
ogg_stream_state fOggStreamState;
|
ogg_stream_map fStreams;
|
||||||
ogg_sync_state fOggSyncState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user