From 439271f08483f7d9144b05700d4dc77d2b86bfe9 Mon Sep 17 00:00:00 2001 From: shatty Date: Fri, 26 Dec 2003 08:15:36 +0000 Subject: [PATCH] getnextchunk git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5758 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/plugins/ogg/OggReaderPlugin.cpp | 200 ++++++++++-------- .../media/plugins/ogg/OggReaderPlugin.h | 5 + 2 files changed, 111 insertions(+), 94 deletions(-) diff --git a/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp b/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp index e4a0f3a942..70b82a674d 100644 --- a/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp +++ b/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp @@ -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(cookie); +// ogg_stream_state * stream = static_cast(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(cookie); +// ogg_stream_state * stream = static_cast(cookie); return B_OK; @@ -232,11 +227,28 @@ oggReader::GetNextChunk(void *cookie, media_header *mediaHeader) { ogg_stream_state * stream = static_cast(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() { diff --git a/src/add-ons/media/plugins/ogg/OggReaderPlugin.h b/src/add-ons/media/plugins/ogg/OggReaderPlugin.h index 206a62c5a9..224d49a15c 100644 --- a/src/add-ons/media/plugins/ogg/OggReaderPlugin.h +++ b/src/add-ons/media/plugins/ogg/OggReaderPlugin.h @@ -8,6 +8,7 @@ namespace BPrivate { namespace media { typedef std::map ogg_stream_map; +typedef std::map 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; };