ogg_status oggreader_read_page_header(BitstreamReader *ogg_stream, struct ogg_page_header *header) { int i; struct bs_callback callback; if (!setjmp(*br_try(ogg_stream))) { if ((header->magic_number = ogg_stream->read(ogg_stream, 32)) != 0x5367674F) { br_etry(ogg_stream); return OGG_INVALID_MAGIC_NUMBER; } if ((header->version = ogg_stream->read(ogg_stream, 8)) != 0) { br_etry(ogg_stream); return OGG_INVALID_STREAM_VERSION; } header->type = ogg_stream->read(ogg_stream, 8); header->granule_position = ogg_stream->read_64(ogg_stream, 64); header->bitstream_serial_number = ogg_stream->read(ogg_stream, 32); header->page_sequence_number = ogg_stream->read(ogg_stream, 32); /*the checksum field is *not* checksummed itself, naturally those 4 bytes are treated as 0*/ br_pop_callback(ogg_stream, &callback); header->checksum = ogg_stream->read(ogg_stream, 32); br_push_callback(ogg_stream, &callback); br_call_callbacks(ogg_stream, 0); br_call_callbacks(ogg_stream, 0); br_call_callbacks(ogg_stream, 0); br_call_callbacks(ogg_stream, 0); header->page_segment_count = ogg_stream->read(ogg_stream, 8); header->segment_length_total = 0; for (i = 0; i < header->page_segment_count; i++) { header->page_segment_lengths[i] = ogg_stream->read(ogg_stream, 8); header->segment_length_total += header->page_segment_lengths[i]; } br_etry(ogg_stream); return OGG_OK; } else { br_etry(ogg_stream); return OGG_PREMATURE_EOF; } }
flac_status flacdec_read_frame_header(BitstreamReader *bitstream, struct flac_STREAMINFO *streaminfo, struct flac_frame_header *header) { unsigned block_size_bits; unsigned sample_rate_bits; uint8_t crc8 = 0; br_add_callback(bitstream, (bs_callback_f)flac_crc8, &crc8); /*read and verify sync code*/ if (bitstream->read(bitstream, 14) != 0x3FFE) { return ERR_INVALID_SYNC_CODE; } /*read and verify reserved bit*/ if (bitstream->read(bitstream, 1) != 0) { return ERR_INVALID_RESERVED_BIT; } header->blocking_strategy = bitstream->read(bitstream, 1); block_size_bits = bitstream->read(bitstream, 4); sample_rate_bits = bitstream->read(bitstream, 4); header->channel_assignment = bitstream->read(bitstream, 4); switch (header->channel_assignment) { case 0x8: case 0x9: case 0xA: header->channel_count = 2; break; default: header->channel_count = header->channel_assignment + 1; break; } switch (bitstream->read(bitstream, 3)) { case 0: header->bits_per_sample = streaminfo->bits_per_sample; break; case 1: header->bits_per_sample = 8; break; case 2: header->bits_per_sample = 12; break; case 4: header->bits_per_sample = 16; break; case 5: header->bits_per_sample = 20; break; case 6: header->bits_per_sample = 24; break; default: return ERR_INVALID_BITS_PER_SAMPLE; } bitstream->read(bitstream, 1); /*padding*/ header->frame_number = read_utf8(bitstream); switch (block_size_bits) { case 0x0: header->block_size = streaminfo->maximum_block_size; break; case 0x1: header->block_size = 192; break; case 0x2: header->block_size = 576; break; case 0x3: header->block_size = 1152; break; case 0x4: header->block_size = 2304; break; case 0x5: header->block_size = 4608; break; case 0x6: header->block_size = bitstream->read(bitstream, 8) + 1; break; case 0x7: header->block_size = bitstream->read(bitstream, 16) + 1; break; case 0x8: header->block_size = 256; break; case 0x9: header->block_size = 512; break; case 0xA: header->block_size = 1024; break; case 0xB: header->block_size = 2048; break; case 0xC: header->block_size = 4096; break; case 0xD: header->block_size = 8192; break; case 0xE: header->block_size = 16384; break; case 0xF: header->block_size = 32768; break; } switch (sample_rate_bits) { case 0x0: header->sample_rate = streaminfo->sample_rate; break; case 0x1: header->sample_rate = 88200; break; case 0x2: header->sample_rate = 176400; break; case 0x3: header->sample_rate = 192000; break; case 0x4: header->sample_rate = 8000; break; case 0x5: header->sample_rate = 16000; break; case 0x6: header->sample_rate = 22050; break; case 0x7: header->sample_rate = 24000; break; case 0x8: header->sample_rate = 32000; break; case 0x9: header->sample_rate = 44100; break; case 0xA: header->sample_rate = 48000; break; case 0xB: header->sample_rate = 96000; break; case 0xC: header->sample_rate = bitstream->read(bitstream, 8) * 1000; break; case 0xD: header->sample_rate = bitstream->read(bitstream, 16); break; case 0xE: header->sample_rate = bitstream->read(bitstream, 16) * 10; break; case 0xF: return ERR_INVALID_SAMPLE_RATE; } /*check for valid CRC-8 value*/ bitstream->read(bitstream, 8); br_pop_callback(bitstream, NULL); if (crc8 != 0) return ERR_INVALID_FRAME_CRC; /*Once we've read everything, ensure the values are compatible with STREAMINFO.*/ if (streaminfo->sample_rate != header->sample_rate) { return ERR_SAMPLE_RATE_MISMATCH; } if (streaminfo->channels != header->channel_count) { return ERR_CHANNEL_COUNT_MISMATCH; } if (streaminfo->bits_per_sample != header->bits_per_sample) { return ERR_BITS_PER_SAMPLE_MISMATCH; } if (header->block_size > streaminfo->maximum_block_size) { return ERR_MAXIMUM_BLOCK_SIZE_EXCEEDED; } return OK; }
PyObject* FlacDecoder_read(decoders_FlacDecoder* self, PyObject *args) { uint16_t crc16 = 0; int channel; struct flac_frame_header frame_header; PyObject* framelist; PyThreadState *thread_state; flac_status error; if (self->closed) { PyErr_SetString(PyExc_ValueError, "cannot read closed stream"); return NULL; } self->subframe_data->reset(self->subframe_data); /*if all samples have been read, return an empty FrameList*/ if (self->stream_finalized) { return empty_FrameList(self->audiotools_pcm, self->streaminfo.channels, self->streaminfo.bits_per_sample); } if (self->remaining_samples < 1) { self->stream_finalized = 1; if (FlacDecoder_verify_okay(self)) { return empty_FrameList(self->audiotools_pcm, self->streaminfo.channels, self->streaminfo.bits_per_sample); } else { PyErr_SetString(PyExc_ValueError, "MD5 mismatch at end of stream"); return NULL; } } thread_state = PyEval_SaveThread(); if (!setjmp(*br_try(self->bitstream))) { /*add callback for CRC16 calculation*/ br_add_callback(self->bitstream, (bs_callback_f)flac_crc16, &crc16); /*read frame header*/ if ((error = flacdec_read_frame_header(self->bitstream, &(self->streaminfo), &frame_header)) != OK) { br_pop_callback(self->bitstream, NULL); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error)); br_etry(self->bitstream); return NULL; } /*read 1 subframe per channel*/ for (channel = 0; channel < frame_header.channel_count; channel++) if ((error = flacdec_read_subframe( self->bitstream, self->qlp_coeffs, self->residuals, (unsigned int)MIN(frame_header.block_size, self->remaining_samples), flacdec_subframe_bits_per_sample(&frame_header, channel), self->subframe_data->append(self->subframe_data))) != OK) { br_pop_callback(self->bitstream, NULL); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error)); br_etry(self->bitstream); return NULL; } /*handle difference channels, if any*/ flacdec_decorrelate_channels(frame_header.channel_assignment, self->subframe_data, self->framelist_data); /*check CRC-16*/ self->bitstream->byte_align(self->bitstream); self->bitstream->read(self->bitstream, 16); br_pop_callback(self->bitstream, NULL); if (crc16 != 0) { PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, "invalid checksum in frame"); br_etry(self->bitstream); return NULL; } /*decrement remaining samples*/ self->remaining_samples -= frame_header.block_size; } else { /*handle I/O error during read*/ br_pop_callback(self->bitstream, NULL); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_IOError, "EOF reading frame"); br_etry(self->bitstream); return NULL; } br_etry(self->bitstream); PyEval_RestoreThread(thread_state); framelist = array_i_to_FrameList(self->audiotools_pcm, self->framelist_data, frame_header.channel_count, frame_header.bits_per_sample); if (framelist != NULL) { /*update MD5 sum*/ if (FlacDecoder_update_md5sum(self, framelist) == OK) /*return pcm.FrameList Python object*/ return framelist; else { Py_DECREF(framelist); return NULL; } } else { return NULL; } }
static PyObject* FlacDecoder_offsets(decoders_FlacDecoder* self, PyObject *args) { int channel; struct flac_frame_header frame_header; flac_status error; PyObject* offsets = PyList_New(0); PyObject* offset_pair; unsigned long long total_offset = 0; unsigned samples; unsigned long long offset; br_add_callback(self->bitstream, (bs_callback_f)increment_offset, &total_offset); while (self->remaining_samples > 0) { self->subframe_data->reset(self->subframe_data); offset = total_offset; if (!setjmp(*br_try(self->bitstream))) { /*read frame header*/ if ((error = flacdec_read_frame_header(self->bitstream, &(self->streaminfo), &frame_header)) != OK) { PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error)); goto error; } samples = frame_header.block_size; /*read 1 subframe per channel*/ for (channel = 0; channel < frame_header.channel_count; channel++) if ((error = flacdec_read_subframe( self->bitstream, self->qlp_coeffs, self->residuals, (unsigned int)MIN(frame_header.block_size, self->remaining_samples), flacdec_subframe_bits_per_sample(&frame_header, channel), self->subframe_data->append(self->subframe_data))) != OK) { PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error)); goto error; } /*read CRC-16*/ self->bitstream->byte_align(self->bitstream); self->bitstream->read(self->bitstream, 16); /*decrement remaining samples*/ self->remaining_samples -= frame_header.block_size; /*add offset pair to our list*/ offset_pair = Py_BuildValue("(K, I)", offset, samples); PyList_Append(offsets, offset_pair); Py_DECREF(offset_pair); } else { /*handle I/O error during read*/ PyErr_SetString(PyExc_IOError, "EOF reading frame"); goto error; } br_etry(self->bitstream); } self->stream_finalized = 1; br_pop_callback(self->bitstream, NULL); return offsets; error: Py_XDECREF(offsets); br_etry(self->bitstream); br_pop_callback(self->bitstream, NULL); return NULL; }