/** -- * * \return -1 on error * \return 0 on end of file * \return 1 on successful page read */ static int get_page(mm_file *mf, ogg_page *pg) { const int bufsize = 8192; char *p = NULL; int n = 0; int res = 0; assert(mf); while (0 == (res = ogg_sync_pageout(&mf->sync, pg))) { p = ogg_sync_buffer(&mf->sync, bufsize); if (!p) { ERROR1("ogg buffer synchronization failed"); return -1; } if (0 == (n = fread(p, 1, bufsize, mf->file))) { return (feof(mf->file)) ? 0 : -1; } if (ogg_sync_wrote(&mf->sync, n)) { ERROR1("buffer overflow in ogg_sync_wrote"); return -1; } } /* XXX: following may segfault if non-ogg file is read */ if (res < 0 || ogg_page_version(pg) != 0) { return -1; } return 1; }
static PyObject * py_ogg_ogg_page_version(PyObject *self, PyObject *args) { int size; int c_out; ogg_page * og; PyArg_ParseTuple(args, "s#", &og, &size); c_out = ogg_page_version(og); return Py_BuildValue("i", c_out); };
//---------------------------Start readOGGPacket-----------------------------------// HRESULT VorbisPropertyHandler::readOGGPacket (IStream *pStream, ogg_page &page, ogg_sync_state &syncstate, ogg_stream_state &streamstate, ogg_packet &packet) { oLOG ("VorbisPropertyHandler::readOGGPacket ()" << std::endl); ULONG length = 0L; do { while (ogg_sync_pageout(&syncstate, &page) != 1) { char* buffer; V_ASSERT_N (buffer = ogg_sync_buffer (&syncstate, 4096) ); H_ASSERT_ (pStream->Read (buffer, 4096, &length) ); if (length == 0) { // End of file break; } V_ASSERT_ (ogg_sync_wrote (&syncstate, length) ); } //oLOG ("VorbisPropertyHandler::readOGGPacket: " << page.header_len << std::endl); streamstate.serialno = ogg_page_serialno (&page); V_ASSERT_ (ogg_stream_pagein (&streamstate, &page) ); #ifdef DEBUG print_header (&page); g_oLog << "VorbisPropertyHandler::readOGGPacket: " << page.header_len << std::endl; g_oLog << "VorbisPropertyHandler::readOGGPacket: " << ogg_page_version (&page) << std::endl; g_oLog << "VorbisPropertyHandler::readOGGPacket: " << (char)page.header[0] << (char)page.header[1] << (char)page.header[2] << (char)page.header[3] << (int)page.header[4] << (int)page.header[5] << std::endl; #endif int ret = ogg_stream_packetout (&streamstate, &packet); if (ret == 0) continue; // Need more data to be able to complete the packet else return ret; } while (true); }
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ unsigned char *header=og->header; unsigned char *body=og->body; long bodysize=og->body_len; int segptr=0; int version=ogg_page_version(og); int continued=ogg_page_continued(og); int bos=ogg_page_bos(og); int eos=ogg_page_eos(og); ogg_int64_t granulepos=ogg_page_granulepos(og); int serialno=ogg_page_serialno(og); long pageno=ogg_page_pageno(og); int segments=header[26]; /* clean up 'returned data' */ { long lr=os->lacing_returned; long br=os->body_returned; /* body data */ if(br){ os->body_fill-=br; if(os->body_fill) memmove(os->body_data,os->body_data+br,os->body_fill); os->body_returned=0; } if(lr){ /* segment table */ if(os->lacing_fill-lr){ memmove(os->lacing_vals,os->lacing_vals+lr, (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); memmove(os->granule_vals,os->granule_vals+lr, (os->lacing_fill-lr)*sizeof(*os->granule_vals)); } os->lacing_fill-=lr; os->lacing_packet-=lr; os->lacing_returned=0; } } /* check the serial number */ if(serialno!=os->serialno)return(-1); if(version>0)return(-1); _os_lacing_expand(os,segments+1); /* are we in sequence? */ if(pageno!=os->pageno){ int i; /* unroll previous partial packet (if any) */ for(i=os->lacing_packet;i<os->lacing_fill;i++) os->body_fill-=os->lacing_vals[i]&0xff; os->lacing_fill=os->lacing_packet; /* make a note of dropped data in segment table */ if(os->pageno!=-1){ os->lacing_vals[os->lacing_fill++]=0x400; os->lacing_packet++; } /* are we a 'continued packet' page? If so, we'll need to skip some segments */ if(continued){ bos=0; for(;segptr<segments;segptr++){ int val=header[27+segptr]; body+=val; bodysize-=val; if(val<255){ segptr++; break; } } } } if(bodysize){ _os_body_expand(os,bodysize); memcpy(os->body_data+os->body_fill,body,bodysize); os->body_fill+=bodysize; } { int saved=-1; while(segptr<segments){ int val=header[27+segptr]; os->lacing_vals[os->lacing_fill]=val; os->granule_vals[os->lacing_fill]=-1; if(bos){ os->lacing_vals[os->lacing_fill]|=0x100; bos=0; } if(val<255)saved=os->lacing_fill; os->lacing_fill++; segptr++; if(val<255)os->lacing_packet=os->lacing_fill; } /* set the granulepos on the last granuleval of the last full packet */ if(saved!=-1){ os->granule_vals[saved]=granulepos; } } if(eos){ os->e_o_s=1; if(os->lacing_fill>0) os->lacing_vals[os->lacing_fill-1]|=0x200; } os->pageno=pageno+1; return(0); }
int main () { ogg_sync_state oy; /* sync and verify incoming physical bitstream */ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ struct stream *st = NULL; int r; char *buffer; int bytes; int eos = 0; int i; int bufferSize = 4096; r = ogg_sync_init(&oy); /* Now we can read pages */ assert(r == 0); while (1) { /* we repeat if the bitstream is chained */ /* submit a 4k block to the libogg sync layer */ buffer = ogg_sync_buffer(&oy, bufferSize); bytes = fread(buffer, 1, bufferSize, stdin); if (bytes == 0) { fprintf(stderr, "Got stdin EOF.\n"); r = 0; break; } r = ogg_sync_wrote(&oy, bytes); assert(r == 0); /* Get the first page. */ r = ogg_sync_pageout(&oy, &og); if (r == 0) { fprintf(stderr, "Need more data.\n"); continue; } else if (r < 1) { /* have we simply run out of data? If so, we're done. */ if (bytes < bufferSize) break; /* error case. Must not be Vorbis data */ fprintf(stderr, "Input does not appear to be an Ogg bitstream.\n"); r = 1; break; } assert(r == 1); /* Get the serial number and set up the rest of decode. */ /* serialno first; use it to set up a logical stream */ int serialno = ogg_page_serialno(&og); int packets = ogg_page_packets(&og); fprintf(stderr, "version: %d\n", ogg_page_version(&og)); fprintf(stderr, "continued: %d\n", ogg_page_continued(&og)); fprintf(stderr, "pageno: %ld\n", ogg_page_pageno(&og)); fprintf(stderr, "serialno: %d\n", serialno); fprintf(stderr, "packets: %d\n", packets); fprintf(stderr, "granulepos: %lld\n", ogg_page_granulepos(&og)); fprintf(stderr, "eos: %d\n", ogg_page_eos(&og)); fprintf(stderr, "bos: %d\n", ogg_page_bos(&og)); /* we need to get the correct "ogg_stream_state" struct based on the serialno */ struct stream *s = st; while (1) { if (s == NULL) { fprintf(stderr, "creating struct stream for %d\n", serialno); s = malloc(sizeof(struct stream)); s->next = NULL; s->serialno = serialno; ogg_stream_init(&s->os, serialno); if (st == NULL) { st = s; } else { /* have to set "s" to the last element of the "st" linked list */ struct stream *t = st; while (1) { if (t->next == NULL) { t->next = s; break; } else { t = t->next; } } } break; } if (s->serialno == serialno) { break; } s = s->next; } assert(s->serialno == serialno); fprintf(stderr, "using struct stream %d\n", s->serialno); /* holy shit that sucked... */ if (ogg_stream_pagein(&s->os, &og) < 0) { /* error; stream version mismatch perhaps */ fprintf(stderr, "Error reading page of Ogg bitstream data.\n"); r = 1; break; } /* iterate though the "packets" in the page */ for (i=0; i<packets; i++) { fprintf(stderr, " Reading packet %d.\n", i); r = ogg_stream_packetout(&s->os, &op); fprintf(stderr, " Reading packet result %d.\n", r); if (r != 1) { /* no page? must not be vorbis */ fprintf(stderr, " Error reading packet.\n"); r = 1; break; } /** * At this point, you'd pass the raw packet data to the vorbis decoder or * whatever your destination is.... */ fprintf(stderr, " bytes: %ld\n", op.bytes); fprintf(stderr, " b_o_s: %ld\n", op.b_o_s); fprintf(stderr, " e_o_s: %ld\n", op.e_o_s); fprintf(stderr, " granulepos: %lld\n", op.granulepos); fprintf(stderr, " packetno: %lld\n", op.packetno); } fprintf(stderr, "\n"); } /* OK, clean up the framer */ ogg_sync_clear(&oy); fprintf(stderr,"\nDone.\n"); return r; }
// the main page reading hook (stream friendly) ssize_t OggReader::ReadPage(bool first_page) { // TRACE("OggReader::ReadPage\n"); int read_size = (first_page ? 4096 : 4*B_PAGE_SIZE); BAutolock autolock(fSyncLock); ogg_page page; retry: int result = ogg_sync_pageout(&fSync, &page); // first read leftovers 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: no data\n"); return B_LAST_BUFFER_ERROR; } if (bytes < 0) { TRACE("OggReader::GetPage: Read: error\n"); return bytes; } 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 (first_page && (result != 1)) { TRACE("OggReader::GetPage: short first page not found: error\n"); return B_ERROR; } } if (result == -1) { TRACE("OggReader::GetPage: ogg_sync_pageout: not synced: error\n"); return B_ERROR; } if (ogg_page_version(&page) != 0) { TRACE("OggReader::GetPage: ogg_page_version: error in page encoding: error\n"); return B_ERROR; } long serialno = ogg_page_serialno(&page); bool new_serialno = fTracks.find(serialno) == fTracks.end(); if (new_serialno) { // this is an unknown serialno if (ogg_page_bos(&page) == 0) { TRACE("OggReader::GetPage: non-bos page with unknown serialno\n"); #ifdef STRICT_OGG return B_ERROR; #else // silently discard non-bos packets with unknown serialno goto retry; #endif } #ifdef STRICT_OGG if (ogg_page_continued(&page) != 0) { TRACE("oggReader::GetPage: ogg_page_continued: continued page: not ogg\n"); return B_ERROR; } #endif //STRICT_OGG // this is a beginning of stream page ogg_stream_state stream; if (ogg_stream_init(&stream, serialno) != 0) { TRACE("oggReader::GetPage: ogg_stream_init failed?: error\n"); return B_ERROR; } if (ogg_stream_pagein(&stream, &page) != 0) { TRACE("oggReader::GetPage: ogg_stream_pagein: failed: error\n"); return B_ERROR; } ogg_packet packet; if (ogg_stream_packetout(&stream, &packet) != 1) { #ifdef STRICT_OGG return B_ERROR; #endif //STRICT_OGG } if (fSeekable) { fTracks[serialno] = OggSeekable::makeOggSeekable(fSeekable, &fSeekableLock, serialno, packet); } else { class Interface : public StreamInterface { private: OggReader * reader; public: Interface(OggReader * reader) { this->reader = reader; } virtual ssize_t ReadPage() { return reader->ReadPage(); } }; fTracks[serialno] = OggStream::makeOggStream(new Interface(this), serialno, packet); } fCookies.push_back(serialno); } // this check ensures that we only push the initial pages into OggSeekables. if (!fSeekable || new_serialno) { status_t status = fTracks[serialno]->AddPage(fPosition, page); if (status != B_OK) { return status; } fPosition += page.header_len + page.body_len; } return page.header_len + page.body_len; }