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";
|
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
|
status_t
|
||||||
oggReader::Sniff(int32 *streamCount)
|
oggReader::Sniff(int32 *streamCount)
|
||||||
{
|
{
|
||||||
TRACE("oggReader::Sniff\n");
|
TRACE("oggReader::Sniff\n");
|
||||||
|
#ifdef STRICT_OGG
|
||||||
|
bool short_page = true;
|
||||||
|
#else
|
||||||
|
bool short_page = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
ogg_page page;
|
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
|
// page sanity checks
|
||||||
if (ogg_page_version(&page) != 0) {
|
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;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
if (ogg_page_continued(&page) != 0) {
|
if (ogg_page_continued(&page) != 0) {
|
||||||
TRACE("oggReader::Sniff: ogg_page_continued: continued page: not ogg\n");
|
TRACE("oggReader::Sniff: ogg_page_continued: continued page: not ogg\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
if (ogg_page_bos(&page) == 0) {
|
#endif STRICT_OGG
|
||||||
TRACE("oggReader::Sniff: ogg_page_bos: not beginning of a bitstream: not ogg\n");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// seems like ogg
|
while (ogg_page_bos(&page) > 0) {
|
||||||
ogg_stream_state stream;
|
if (GetPage(&page,4096,short_page) != B_OK) {
|
||||||
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;
|
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();
|
*streamCount = fStreams.size();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -198,7 +192,8 @@ 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");
|
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
|
*frameCount = -1; // don't know
|
||||||
*duration = -1; // don't know
|
*duration = -1; // don't know
|
||||||
// no info
|
// no info
|
||||||
@@ -219,7 +214,7 @@ oggReader::Seek(void *cookie,
|
|||||||
TRACE("oggReader::Seek: not a PositionIO: not seekable\n");
|
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_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
||||||
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -232,11 +227,28 @@ oggReader::GetNextChunk(void *cookie,
|
|||||||
media_header *mediaHeader)
|
media_header *mediaHeader)
|
||||||
{
|
{
|
||||||
ogg_stream_state * stream = static_cast<ogg_stream_state *>(cookie);
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Reader *
|
Reader *
|
||||||
oggReaderPlugin::NewReader()
|
oggReaderPlugin::NewReader()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
namespace BPrivate { namespace media {
|
namespace BPrivate { namespace media {
|
||||||
|
|
||||||
typedef std::map<int,ogg_stream_state> ogg_stream_map;
|
typedef std::map<int,ogg_stream_state> ogg_stream_map;
|
||||||
|
typedef std::map<int,ogg_packet> ogg_packet_map;
|
||||||
|
|
||||||
class oggReader : public Reader
|
class oggReader : public Reader
|
||||||
{
|
{
|
||||||
@@ -36,8 +37,12 @@ public:
|
|||||||
media_header *mediaHeader);
|
media_header *mediaHeader);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t GetPage(ogg_page * page, int read_size = 4*B_PAGE_SIZE,
|
||||||
|
bool short_page = false);
|
||||||
|
|
||||||
ogg_sync_state fSync;
|
ogg_sync_state fSync;
|
||||||
ogg_stream_map fStreams;
|
ogg_stream_map fStreams;
|
||||||
|
ogg_packet_map fPackets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user