#include "oggstat.h" using namespace std; /* Most of this code has been blatently copied from ogginfo, a testing program that comes with vorbis-tools package on the xiph cvs server. It has been stripped down and altered to work correctly (hopefully). */ // checks the beginning headers to make sure it's not corrupt or missing. // initializes vorbis_info struct as well as others. int vorb::test_header (FILE * fp, ogg_sync_state * oy, ogg_stream_state * os, vorbis_info * vi, vorbis_comment * vc, long *serialno) { ogg_page og; ogg_packet op; char *buffer; int bytes; int i, result; buffer = ogg_sync_buffer (oy, 4096); bytes = fread (buffer, 1, 4096, fp); ogg_sync_wrote (oy, bytes); vorbis_info_init (vi); if (ogg_sync_pageout (oy, &og) != 1) return -1; *serialno = ogg_page_serialno (&og); ogg_stream_init (os, *serialno); vorbis_comment_init (vc); if (ogg_stream_pagein (os, &og) < 0) return 0; if (ogg_stream_packetout (os, &op) != 1) return 0; if (vorbis_synthesis_headerin (vi, vc, &op) < 0) return 0; i = 0; while (i < 2) { while (i < 2) { result = ogg_sync_pageout (oy, &og); if (result == 0) break; /* Need more data */ if (result == 1) { ogg_stream_pagein (os, &og); while (i < 2) { result = ogg_stream_packetout (os, &op); if (result == 0) break; if (result < 0) return 0; vorbis_synthesis_headerin (vi, vc, &op); i++; } } } buffer = ogg_sync_buffer (oy, 4096); bytes = fread (buffer, 1, 4096, fp); ogg_sync_wrote (oy, bytes); if (bytes == 0 && i < 2) return 0; } return 1; } // Runs through the packets and grabs info, hopefully handling any errors found. void vorb::scan_ogg (FILE * fp, int len, statistic * mp3info2) { int header_state = -1; /* Assume the worst */ int stream_state = -1; ogg_sync_state oy; ogg_stream_state os; vorbis_info vi; vorbis_comment vc; ogg_page og; ogg_packet op; ogg_int64_t bits = 0; ogg_int64_t final_granulepos = 0; int bytes; int blocksize = 0; char *buffer; int eos = 0; int eof = 0; int result; long serialno; if (!fp) exit (0); ogg_sync_init (&oy); /* Now we can read pages */ while (!eof) { bits = 0; // calls the test header function which makes sure everything is okydokey if ((header_state = test_header (fp, &oy, &os, &vi, &vc, &serialno)) == 1) { result = 0; while (!eos) { while (!eos) { result = ogg_sync_pageout (&oy, &og); if (result == 0) break; /* need more data */ if (result < 0) break; /* missing or corrupt data at this page position */ else { if (ogg_stream_pagein (&os, &og) < 0) exit (-1); while (1) { result = ogg_stream_packetout (&os, &op); if (result == 0) break; /* need more data */ if (result < 0) break; blocksize = vorbis_packet_blocksize (&vi, &op); mp3info2->addBit((int)((( (double) vi.rate / (double) blocksize) * (double)op.bytes*16) / 1000)); } if (ogg_page_eos (&og)) eos = 1; } } if (!eos) { buffer = ogg_sync_buffer (&oy, 4096); bytes = fread (buffer, 1, 4096, fp); bits += 8 * bytes; ogg_sync_wrote (&oy, bytes); if (bytes == 0) eos = 1; } } final_granulepos = ogg_page_granulepos (&og); stream_state = ogg_page_eos (&og); } eof = feof (fp); } // shutting everything down ogg_stream_clear (&os); vorbis_comment_clear (&vc); vorbis_info_clear (&vi); ogg_sync_clear (&oy); } // gets the size and sets up the dynamic array for holding all the packet bitrates. void vorb::statfile (statistic * mp3info2) { FILE *fp; struct stat buf; int len; stat (mp3info2->getName().c_str(), &buf); len = buf.st_size; mp3info2->setSize((double) len / 1024); // this is broken i think. if ((fp = fopen (mp3info2->getName().c_str(), "rb"))) { scan_ogg (fp, len, mp3info2); // open file then after scanning, close it fclose (fp); } } extern "C" input* createi() { return new vorb; } extern "C" void destroyi(input* tempIn) { delete tempIn; }