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 ;
|
||||
|
||||
SubDirHdrs $(SUBDIR) libogg ogg ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) libogg ] ;
|
||||
|
||||
Addon ogg : media plugins :
|
||||
OggReaderPlugin.cpp
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
oggReader::oggReader()
|
||||
{
|
||||
TRACE("oggReader::oggReader\n");
|
||||
ogg_stream_init(&fOggStreamState,(int)this);
|
||||
ogg_sync_init(&fOggSyncState);
|
||||
ogg_sync_init(&fSync);
|
||||
}
|
||||
|
||||
|
||||
oggReader::~oggReader()
|
||||
{
|
||||
ogg_stream_destroy(&fOggStreamState);
|
||||
ogg_sync_destroy(&fOggSyncState);
|
||||
ogg_sync_destroy(&fSync);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,47 +40,116 @@ status_t
|
||||
oggReader::Sniff(int32 *streamCount)
|
||||
{
|
||||
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;
|
||||
buffer = ogg_sync_buffer(&sync,4096);
|
||||
bytes = fSeekableSource->Read(buffer,4096);
|
||||
ogg_sync_pageout(&fSync,&page); // clear the buffer
|
||||
|
||||
char * buffer = ogg_sync_buffer(&fSync,4096);
|
||||
ssize_t bytes = Source()->Read(buffer,4096);
|
||||
if (bytes < 4096) {
|
||||
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;
|
||||
}
|
||||
ogg_sync_wrote(&sync,bytes);
|
||||
if (bytesogg_sync_pageout(&sync,&page) != 1) {
|
||||
TRACE("oggReader::Sniff: ogg_sync_pageout error: not ogg\n");
|
||||
ogg_sync_destroy(&sync);
|
||||
switch ((int)ogg_sync_pageout(&fSync,&page)) {
|
||||
case -1:
|
||||
TRACE("oggReader::Sniff: ogg_sync_pageout: not synced: not ogg\n");
|
||||
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;
|
||||
}
|
||||
// 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
|
||||
// TODO: count the streams
|
||||
*streamCount = 1;
|
||||
|
||||
/* ogg_stream_state stream;
|
||||
ogg_stream_init(&stream,ogg_page_serial_no(&page);
|
||||
|
||||
ogg_stream_pagein(&stream,&page);
|
||||
ogg_packet packet;
|
||||
ogg_stream_packetout(&stream,&packet);*/
|
||||
|
||||
ogg_stream_state 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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_AUDIO
|
||||
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
||||
mff->family = B_OGG_FORMAT_FAMILY;
|
||||
mff->family = B_MISC_FORMAT_FAMILY;
|
||||
mff->version = 100;
|
||||
strcpy(mff->mime_type, "application/ogg");
|
||||
strcpy(mff->file_extension, "ogg");
|
||||
|
||||
// uint8 header[4];
|
||||
// Source()->ReadAt(fDataStart, header, sizeof(header));
|
||||
strcpy(mff->short_name, "Ogg");
|
||||
strcpy(mff->short_name, "Ogg");
|
||||
strcpy(mff->pretty_name, "Ogg bitstream");
|
||||
}
|
||||
|
||||
@@ -106,9 +170,17 @@ status_t
|
||||
oggReader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||
{
|
||||
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
|
||||
*cookie = data;
|
||||
*cookie = (void*)(&i->second);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -125,6 +197,13 @@ status_t
|
||||
oggReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -134,10 +213,15 @@ oggReader::Seek(void *cookie,
|
||||
uint32 seekTo,
|
||||
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;
|
||||
}
|
||||
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||
|
||||
|
||||
ogg_sync_reset
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -147,6 +231,9 @@ oggReader::GetNextChunk(void *cookie,
|
||||
void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
|
||||
#include "ReaderPlugin.h"
|
||||
#include "ogg/ogg.h"
|
||||
#include <map>
|
||||
|
||||
namespace BPrivate { namespace media {
|
||||
|
||||
typedef std::map<int,ogg_stream_state> ogg_stream_map;
|
||||
|
||||
class oggReader : public Reader
|
||||
{
|
||||
public:
|
||||
@@ -32,12 +35,9 @@ public:
|
||||
void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader);
|
||||
|
||||
BPositionIO *Source() { return fSeekableSource; }
|
||||
|
||||
private:
|
||||
BPositionIO * fSeekableSource;
|
||||
ogg_stream_state fOggStreamState;
|
||||
ogg_sync_state fOggSyncState;
|
||||
ogg_sync_state fSync;
|
||||
ogg_stream_map fStreams;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user