static int read_audio_packet(DVDA_Packet_Reader* packets, DVDA_Packet* packet, struct bs_buffer* packet_data) { if (packets->total_sectors) { BitstreamReader* reader = packets->reader; struct bs_buffer* buffer = reader->input.substream; buf_reset(buffer); if (!read_sector(packets->sectors, buffer)) { if (buf_window_size(buffer) == 0) { return 0; } if (!setjmp(*br_try(reader))) { unsigned sync_bytes; unsigned pad[6]; unsigned PTS_high; unsigned PTS_mid; unsigned PTS_low; unsigned SCR_extension; unsigned bitrate; unsigned stuffing_count; int audio_packet_found = 0; /*read pack header*/ reader->parse(reader, "32u 2u 3u 1u 15u 1u 15u 1u 9u 1u 22u 2u 5p 3u", &sync_bytes, &(pad[0]), &PTS_high, &(pad[1]), &PTS_mid, &(pad[2]), &PTS_low, &(pad[3]), &SCR_extension, &(pad[4]), &bitrate, &(pad[5]), &stuffing_count); if (sync_bytes != 0x000001BA) { br_etry(reader); return 1; } if ((pad[0] != 1) || (pad[1] != 1) || (pad[2] != 1) || (pad[3] != 1) || (pad[4] != 1) || (pad[5] != 3)) { br_etry(reader); return 1; } for (; stuffing_count; stuffing_count--) { reader->skip(reader, 8); } /*read packets from sector until sector is empty*/ while (buf_window_size(buffer) > 0) { unsigned start_code; unsigned stream_id; unsigned packet_length; reader->parse(reader, "24u 8u 16u", &start_code, &stream_id, &packet_length); if (start_code != 0x000001) { br_etry(reader); return 1; } if (stream_id == 0xBD) { /*audio packets are forwarded to packet*/ unsigned pad1_size; unsigned pad2_size; reader->parse(reader, "16p 8u", &pad1_size); reader->skip_bytes(reader, pad1_size); reader->parse(reader, "8u 8u 8p 8u", &(packet->codec_ID), &(packet->CRC), &pad2_size); if (packet->codec_ID == 0xA0) { /*PCM*/ reader->parse(reader, "16u 8p 4u 4u 4u 4u 8p 8u 8p 8u", &(packet->PCM.first_audio_frame), &(packet->PCM.group_1_bps), &(packet->PCM.group_2_bps), &(packet->PCM.group_1_rate), &(packet->PCM.group_2_rate), &(packet->PCM.channel_assignment), &(packet->PCM.CRC)); reader->skip_bytes(reader, pad2_size - 9); } else { /*probably MLP*/ reader->skip_bytes(reader, pad2_size); } packet_length -= 3 + pad1_size + 4 + pad2_size; buf_reset(packet_data); while (packet_length) { static uint8_t buffer[4096]; const unsigned to_read = MIN(packet_length, 4096); reader->read_bytes(reader, buffer, to_read); buf_write(packet_data, buffer, to_read); packet_length -= to_read; } audio_packet_found = 1; } else { /*other packets are ignored*/ reader->skip_bytes(reader, packet_length); } } /*return success if an audio packet was read*/ br_etry(reader); if (audio_packet_found) { return 0; } else { return 1; } } else { /*error reading sector*/ br_etry(reader); return 1; } } else { /*error reading sector*/ return 1; } } else { /*no more sectors, so return EOF*/ return 0; } }
static PyObject* DVDA_Title_next_track(decoders_DVDA_Title *self, PyObject *args) { unsigned PTS_ticks; DVDA_Packet next_packet; struct bs_buffer* packet_data = self->packet_data; unsigned i; if (!PyArg_ParseTuple(args, "I", &PTS_ticks)) return NULL; /*ensure previous track has been exhausted, if any*/ if (self->pcm_frames_remaining) { PyErr_SetString(PyExc_ValueError, "current track has not been exhausted"); return NULL; } /*read the next packet*/ if (read_audio_packet(self->packet_reader, &next_packet, packet_data)) { PyErr_SetString(PyExc_IOError, "I/O error reading initialization packet"); return NULL; } #else int DVDA_Title_next_track(decoders_DVDA_Title *self, unsigned PTS_ticks) { DVDA_Packet next_packet; struct bs_buffer* packet_data = self->packet_data; unsigned i; if (self->pcm_frames_remaining) { fprintf(stderr, "current track has not been exhausted\n"); return 0; } if (read_audio_packet(self->packet_reader, &next_packet, packet_data)) { fprintf(stderr, "I/O error reading initialization packet\n"); return 0; } #endif if (next_packet.codec_ID == PCM_CODEC_ID) { /*if the packet is PCM, initialize Title's stream attributes (bits-per-sample, sample rate, channel assignment/mask) with values taken from the first packet*/ /*PCM stores stream attributes in the second padding block*/ self->bits_per_sample = dvda_bits_per_sample(next_packet.PCM.group_1_bps); self->sample_rate = dvda_sample_rate(next_packet.PCM.group_1_rate); self->channel_assignment = next_packet.PCM.channel_assignment; self->channel_count = dvda_channel_count(next_packet.PCM.channel_assignment); self->channel_mask = dvda_channel_mask(next_packet.PCM.channel_assignment); self->frame_codec = PCM; init_aobpcm_decoder(&(self->pcm_decoder), self->bits_per_sample, self->channel_count); buf_extend(packet_data, self->frames); } else if (next_packet.codec_ID == MLP_CODEC_ID) { /*if the packet is MLP, check if the first frame starts with a major sync*/ enum {PACKET_DATA}; BitstreamReader* r = br_open_buffer(packet_data, BS_BIG_ENDIAN); r->mark(r, PACKET_DATA); if (!setjmp(*br_try(r))) { unsigned sync_words; unsigned stream_type; r->parse(r, "32p 24u 8u", &sync_words, &stream_type); if ((sync_words == 0xF8726F) && (stream_type == 0xBB)) { /*if so, discard any unconsumed packet data and initialize Title's stream attributes with values taken from the major sync*/ unsigned group_1_bps; unsigned group_2_bps; unsigned group_1_rate; unsigned group_2_rate; r->parse(r, "4u 4u 4u 4u 11p 5u 48p", &group_1_bps, &group_2_bps, &group_1_rate, &group_2_rate, &(self->channel_assignment)); self->bits_per_sample = dvda_bits_per_sample(group_1_bps); self->sample_rate = dvda_sample_rate(group_1_rate); self->channel_count = dvda_channel_count(self->channel_assignment); self->channel_mask = dvda_channel_mask(self->channel_assignment); self->frame_codec = MLP; self->mlp_decoder->major_sync_read = 0; r->rewind(r, PACKET_DATA); r->unmark(r, PACKET_DATA); br_etry(r); r->close(r); buf_reset(self->frames); buf_extend(packet_data, self->frames); } else { /*if not, append packet data to any unconsumed data and leave Title's stream attributes as they were*/ r->rewind(r, PACKET_DATA); r->unmark(r, PACKET_DATA); br_etry(r); r->close(r); buf_extend(packet_data, self->frames); } } else { /*if I/O error reading major sync, append packet data to any unconsumed data and leave Title's stream attributes as they were*/ r->rewind(r, PACKET_DATA); r->unmark(r, PACKET_DATA); br_etry(r); r->close(r); buf_extend(packet_data, self->frames); } } else { #ifndef STANDALONE PyErr_SetString(PyExc_ValueError, "unknown codec ID"); return NULL; #else return 0; #endif } /*convert PTS ticks to PCM frames based on sample rate*/ self->pcm_frames_remaining = (unsigned)round((double)PTS_ticks * (double)self->sample_rate / (double)PTS_PER_SECOND); /*initalize codec's framelist with the proper number of channels*/ if (self->codec_framelist->len != self->channel_count) { self->codec_framelist->reset(self->codec_framelist); for (i = 0; i < self->channel_count; i++) self->codec_framelist->append(self->codec_framelist); } #ifndef STANDALONE Py_INCREF(Py_None); return Py_None; #else return 1; #endif }