static PyObject* TrackReader_read(dvda_TrackReader *self, PyObject *args) { int pcm_frames; unsigned requested_pcm_frames; unsigned received_pcm_frames; pcm_FrameList *framelist; const unsigned channel_count = dvda_channel_count(self->reader); const unsigned bits_per_sample = dvda_bits_per_sample(self->reader); /*if closed, raise ValueError*/ if (self->closed) { PyErr_SetString(PyExc_ValueError, "unable to read closed stream"); return NULL; } if (!PyArg_ParseTuple(args, "i", &pcm_frames)) { return NULL; } /*restrict requested number of PCM frames to a reasonable value*/ requested_pcm_frames = MIN(MAX(pcm_frames, 1), 1 << 20); /*grab empty FrameList and make a buffer for it*/ if ((framelist = new_FrameList(self->audiotools_pcm, channel_count, bits_per_sample, requested_pcm_frames)) == NULL) { return NULL; } /*perform read to FrameList's buffer*/ received_pcm_frames = dvda_read(self->reader, requested_pcm_frames, framelist->samples); /*fill in remaining FrameList parameters*/ framelist->frames = received_pcm_frames; /*return FrameList*/ return (PyObject*)framelist; }
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_bits_per_sample(dvda_TrackReader *self, void *closure) { return Py_BuildValue("I", dvda_bits_per_sample(self->reader)); }