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 }
static PyObject* TrackReader_sample_rate(dvda_TrackReader *self, void *closure) { return Py_BuildValue("I", dvda_sample_rate(self->reader)); }