return FALSE;
}
+ t->StreamSize = reader->Size(reader->Context);
+
+ t->Position = 0;
+
t->Setup = QV_CreateDecoderSetup();
if (t->Setup == NULL) {
return FALSE;
}
if (header.StreamSerialNumber != t->StreamSerialNumber) {
+ if (!QO_OggReader_SkipPayload(reader)) {
+ return FALSE;
+ }
+
continue;
}
/* */
+BOOL QO_OggVorbisReader_DetectSamples(
+ QO_OggVorbisReader_t* t,
+ INT64* samples)
+{
+ QO_OggReader_t* reader = &(t->Reader);
+
+ INT64 psz = reader->Size / 2;
+
+ INT64 pos = t->StreamSize;
+ if (pos >= psz) {
+ pos -= psz;
+ }
+ pos &= ~(psz - 1);
+
+ *samples = 0;
+
+ if (!QO_OggReader_Seek(reader, pos)) {
+ return FALSE;
+ }
+
+ for (; ; ) {
+ QO_OggHeader_t header;
+
+ if (!QO_OggReader_ReadHeader(reader, &header)) {
+ return FALSE;
+ }
+
+ if (!QO_OggReader_SkipPayload(reader)) {
+ return FALSE;
+ }
+
+ if (header.StreamSerialNumber == t->StreamSerialNumber &&
+ (header.HeaderType & HT_EOS) != 0) {
+ *samples = header.GranulePosition;
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* */
+
+BOOL QO_OggVorbisReader_QuerySampleRange(
+ QO_OggVorbisReader_t* t,
+ INT64 pos,
+ QO_OggVorbisRange_t* range)
+{
+ QO_OggHeader_t header;
+
+ QO_OggReader_t* reader = &(t->Reader);
+
+ SIZE_T sz = reader->Size / 2;
+
+ INT64 start = -1;
+ INT64 end = -1;
+
+ range->Start = 0;
+ range->End = 0;
+
+ QV_ResetDecoderChecker(t->Decoder);
+
+ if (!QO_OggReader_Seek(reader, pos)) {
+ return FALSE;
+ }
+
+ /* printf("S: %04X\n", reader->Pointer); */
+
+ for (; ; ) {
+ if (reader->Pointer >= sz) {
+ /* printf("E: %04X\n", reader->Pointer); */
+ break;
+ }
+
+ for (; ; ) {
+ if (!QO_OggReader_ReadHeader(reader, &header)) {
+ return FALSE;
+ }
+
+ if (header.StreamSerialNumber == t->StreamSerialNumber) {
+ if (!QO_OggReader_ReadPayload(reader)) {
+ return FALSE;
+ }
+ break;
+ }
+
+ if (!QO_OggReader_SkipPayload(reader)) {
+ return FALSE;
+ }
+ }
+
+ if (reader->Packets > 0) {
+ INT32 i, samples = 0;
+
+ UINT8* pb = reader->PacketsBuffer;
+
+ if ((pb[0] & 1) != 0) { /* Skip Header Packet */
+ continue;
+ }
+
+ for (i = 0; i < reader->Packets; i++) {
+ INT32 s = 0;
+ if (!QV_CheckDecoderChecker(t->Decoder, pb, reader->PacketsSize[i], &s)) {
+ return FALSE;
+ }
+
+ pb += reader->PacketsSize[i];
+
+ samples += s;
+ }
+
+ if (start < 0) {
+ start = header.GranulePosition - samples;
+ }
+
+ end = header.GranulePosition;
+ }
+ }
+
+ range->Start = start;
+ range->End = end;
+
+ return TRUE;
+}
+
+/* */
+
+BOOL QO_OggVorbisReader_SeekPage(
+ QO_OggVorbisReader_t* t,
+ INT64 pos)
+{
+ QO_OggHeader_t header;
+
+ QO_OggReader_t* reader = &(t->Reader);
+
+ QV_ResetDecoderChecker(t->Decoder);
+ QV_ResetDecoder(t->Decoder);
+
+ if (!QO_OggReader_Seek(reader, pos)) {
+ return FALSE;
+ }
+
+ for (; ; ) {
+ for (; ; ) {
+ if (!QO_OggReader_ReadHeader(reader, &header)) {
+ return FALSE;
+ }
+
+ if (header.StreamSerialNumber == t->StreamSerialNumber) {
+ if (!QO_OggReader_ReadPayload(reader)) {
+ return FALSE;
+ }
+ break;
+ }
+
+ if (!QO_OggReader_SkipPayload(reader)) {
+ return FALSE;
+ }
+ }
+
+ if (reader->Packets > 0) {
+ INT32 i, samples = 0;
+
+ UINT8* pb = reader->PacketsBuffer;
+
+ if ((pb[0] & 1) != 0) { /* Skip Header Packet */
+ continue;
+ }
+
+ for (i = 0; i < reader->Packets; i++) {
+ INT32 s = 0;
+ if (!QV_CheckDecoderChecker(t->Decoder, pb, reader->PacketsSize[i], &s)) {
+ return FALSE;
+ }
+
+ pb += reader->PacketsSize[i];
+
+ samples += s;
+ }
+
+ t->Position = header.GranulePosition - samples;
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* */
+
QO_OggReader_t Reader;
+ INT64 StreamSize;
+
+ INT64 Position;
+
UINT32 StreamSerialNumber;
UINT32 PageSequenceNumber;
BOOL QO_OggVorbisReader_Setup(
QO_OggVorbisReader_t* t);
+BOOL QO_OggVorbisReader_DetectSamples(
+ QO_OggVorbisReader_t* t,
+ INT64* samples);
+
+/* */
+
+struct QO_OggVorbisRange {
+
+ INT64 Start;
+ INT64 End;
+
+}; /* QO_OggVorbisRange */
+
+typedef struct QO_OggVorbisRange QO_OggVorbisRange_t;
+
+BOOL QO_OggVorbisReader_QuerySampleRange(
+ QO_OggVorbisReader_t* t,
+ INT64 pos,
+ QO_OggVorbisRange_t* range);
+
+/* */
+
+BOOL QO_OggVorbisReader_SeekPage(
+ QO_OggVorbisReader_t* t,
+ INT64 pos);
+
/* */