getnextchunk
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5758 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -35,116 +35,110 @@ oggReader::Copyright()
|
||||
return "ogg reader, " B_UTF8_COPYRIGHT " by Andrew Bachmann";
|
||||
}
|
||||
|
||||
status_t
|
||||
oggReader::GetPage(ogg_page * page, int read_size, bool short_page)
|
||||
{
|
||||
ogg_sync_pageout(&fSync,page); // clear the buffer
|
||||
int result = 0;
|
||||
while (result == 0) {
|
||||
char * buffer = ogg_sync_buffer(&fSync,read_size);
|
||||
ssize_t bytes = Source()->Read(buffer,read_size);
|
||||
if (bytes < 0) {
|
||||
TRACE("oggReader::GetPage: Read: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (ogg_sync_wrote(&fSync,bytes) != 0) {
|
||||
TRACE("oggReader::GetPage: ogg_sync_wrote failed?: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
result = ogg_sync_pageout(&fSync,page);
|
||||
if (short_page && (result != 0)) {
|
||||
TRACE("oggReader::GetPage: short page not found: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
if (result == -1) {
|
||||
TRACE("oggReader::GetPage: ogg_sync_pageout: not synced: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
#ifdef STRICT_OGG
|
||||
if (ogg_page_version(page) != 0) {
|
||||
TRACE("oggReader::GetPage: ogg_page_version: error in page encoding: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
#endif
|
||||
long serialno = ogg_page_serialno(page);
|
||||
if (fStreams.find(serialno) == fStreams.end()) {
|
||||
// this is an unknown serialno
|
||||
if (ogg_page_bos(page) == 0) {
|
||||
TRACE("oggReader::GetPage: non-bos packet with unknown serialno\n");
|
||||
#ifdef STRICT_OGG
|
||||
return B_ERROR;
|
||||
#endif
|
||||
}
|
||||
ogg_stream_state stream;
|
||||
fStreams[serialno] = stream;
|
||||
if (ogg_stream_init(&fStreams[serialno],serialno) != 0) {
|
||||
TRACE("oggReader::GetPage: ogg_stream_init failed?: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
} else if (ogg_page_bos(page) > 0) {
|
||||
TRACE("oggReader::GetPage: bos packet with duplicate serialno\n");
|
||||
#ifdef STRICT_OGG
|
||||
return B_ERROR;
|
||||
#else
|
||||
if (ogg_stream_destroy(&fStreams[serialno]) != 0) {
|
||||
TRACE("oggReader::GetPage: ogg_stream_destroy failed?: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (ogg_stream_init(&fStreams[serialno],serialno) != 0) {
|
||||
TRACE("oggReader::GetPage: ogg_stream_init failed?: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (ogg_stream_pagein(&fStreams[serialno],page) != 0) {
|
||||
TRACE("oggReader::Sniff: ogg_stream_pagein: failed: error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
oggReader::Sniff(int32 *streamCount)
|
||||
{
|
||||
TRACE("oggReader::Sniff\n");
|
||||
#ifdef STRICT_OGG
|
||||
bool short_page = true;
|
||||
#else
|
||||
bool short_page = false;
|
||||
#endif
|
||||
|
||||
ogg_page page;
|
||||
ogg_sync_pageout(&fSync,&page); // clear the buffer
|
||||
if (GetPage(&page,4096,short_page) != B_OK) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
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");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (ogg_sync_wrote(&fSync,bytes) != 0) {
|
||||
TRACE("oggReader::Sniff: ogg_sync_wrote failed?: bail\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
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");
|
||||
TRACE("oggReader::Sniff: ogg_page_version: error in page encoding: not ogg\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
#ifdef STRICT_OGG
|
||||
if (ogg_page_bos(&page) == 0) {
|
||||
TRACE("oggReader::Sniff: ogg_page_bos: not beginning of a bitstream: 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;
|
||||
}
|
||||
#endif STRICT_OGG
|
||||
|
||||
// seems like ogg
|
||||
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");
|
||||
while (ogg_page_bos(&page) > 0) {
|
||||
if (GetPage(&page,4096,short_page) != B_OK) {
|
||||
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;
|
||||
@@ -198,7 +192,8 @@ 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);
|
||||
// ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||
memset(format, 0, sizeof(*format));
|
||||
*frameCount = -1; // don't know
|
||||
*duration = -1; // don't know
|
||||
// no info
|
||||
@@ -219,7 +214,7 @@ oggReader::Seek(void *cookie,
|
||||
TRACE("oggReader::Seek: not a PositionIO: not seekable\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||
// ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||
|
||||
|
||||
return B_OK;
|
||||
@@ -232,11 +227,28 @@ oggReader::GetNextChunk(void *cookie,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||
|
||||
while (ogg_stream_packetpeek(stream,NULL) != 1) {
|
||||
ogg_page page;
|
||||
do {
|
||||
if (GetPage(&page) != B_OK) {
|
||||
return B_ERROR;
|
||||
}
|
||||
} while (ogg_page_serialno(&page) != stream->serialno);
|
||||
}
|
||||
if (fPackets.find(stream->serialno) == fPackets.end()) {
|
||||
ogg_packet packet;
|
||||
fPackets[stream->serialno] = packet;
|
||||
}
|
||||
if (ogg_stream_packetout(stream,&fPackets[stream->serialno]) != 1) {
|
||||
return B_ERROR;
|
||||
}
|
||||
*chunkBuffer = (void*)&fPackets[stream->serialno];
|
||||
*chunkSize = sizeof(ogg_packet);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Reader *
|
||||
oggReaderPlugin::NewReader()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
namespace BPrivate { namespace media {
|
||||
|
||||
typedef std::map<int,ogg_stream_state> ogg_stream_map;
|
||||
typedef std::map<int,ogg_packet> ogg_packet_map;
|
||||
|
||||
class oggReader : public Reader
|
||||
{
|
||||
@@ -36,8 +37,12 @@ public:
|
||||
media_header *mediaHeader);
|
||||
|
||||
private:
|
||||
status_t GetPage(ogg_page * page, int read_size = 4*B_PAGE_SIZE,
|
||||
bool short_page = false);
|
||||
|
||||
ogg_sync_state fSync;
|
||||
ogg_stream_map fStreams;
|
||||
ogg_packet_map fPackets;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user