int main(int argc, char *argv[]) {
    /*perform simple round-trip using page reader and writer*/

    BitstreamReader *reader = br_open(stdin, BS_LITTLE_ENDIAN);
    BitstreamWriter *writer = bw_open(stdout, BS_LITTLE_ENDIAN);
    struct ogg_page page;

    do {
        ogg_status result;
        if ((result = read_ogg_page(reader, &page)) == OGG_OK) {
            write_ogg_page(writer, &page);
        } else {
            fprintf(stderr, "*** Error: %s", ogg_strerror(result));
            goto error;
        }
    } while (!page.header.stream_end);

    reader->close(reader);
    writer->close(writer);
    return 0;

error:
    reader->close(reader);
    writer->close(writer);
    return 1;
}
Example #2
0
int main(int argc, char *argv[]) {
    FILE *f = fopen(argv[1], "rb");
    OggReader *reader = oggreader_open(f);
    BitstreamReader *packet = bs_substream_new(BS_LITTLE_ENDIAN);
    ogg_status result;

    do {
        result = oggreader_next_packet(reader, packet);
        if (result < 0) {
            fprintf(stderr, "Error : %s\n", ogg_error(result));
        } else if (result == OGG_OK) {
            printf("packet size %u\n", packet->input.substream->buffer_size);
        }
    } while (result == OGG_OK);

    packet->close(packet);
    oggreader_close(reader);
    fclose(f);
    return 0;
}
Example #3
0
int
flacdec_read_metadata(BitstreamReader *bitstream,
                      struct flac_STREAMINFO *streaminfo,
                      a_obj *seektable,
                      int *channel_mask)
{
    BitstreamReader *comment = br_substream_new(BS_LITTLE_ENDIAN);

    enum {
        fL =  0x1,
        fR =  0x2,
        fC =  0x4,
        LFE = 0x8,
        bL =  0x10,
        bR =  0x20,
        bC =  0x100,
        sL =  0x200,
        sR =  0x400
    };

    if (!setjmp(*br_try(bitstream))) {
        unsigned last_block;

        if (bitstream->read(bitstream, 32) != 0x664C6143u) {
#ifndef STANDALONE
            PyErr_SetString(PyExc_ValueError, "not a FLAC file");
#endif
            br_etry(bitstream);
            comment->close(comment);
            return 1;
        }

        do {
            last_block = bitstream->read(bitstream, 1);
            const unsigned block_type = bitstream->read(bitstream, 7);
            const unsigned block_length = bitstream->read(bitstream, 24);

            switch (block_type) {
            case 0:   /*STREAMINFO*/
                streaminfo->minimum_block_size =
                    bitstream->read(bitstream, 16);
                streaminfo->maximum_block_size =
                    bitstream->read(bitstream, 16);
                streaminfo->minimum_frame_size =
                    bitstream->read(bitstream, 24);
                streaminfo->maximum_frame_size =
                    bitstream->read(bitstream, 24);
                streaminfo->sample_rate =
                    bitstream->read(bitstream, 20);
                streaminfo->channels =
                    bitstream->read(bitstream, 3) + 1;
                streaminfo->bits_per_sample =
                    bitstream->read(bitstream, 5) + 1;
                streaminfo->total_samples =
                    bitstream->read_64(bitstream, 36);

                bitstream->read_bytes(bitstream, streaminfo->md5sum, 16);

                /*default channel mask based on channel count*/
                switch (streaminfo->channels) {
                case 1:
                    *channel_mask = fC;
                    break;
                case 2:
                    *channel_mask = fL | fR;
                    break;
                case 3:
                    *channel_mask = fL | fR | fC;
                    break;
                case 4:
                    *channel_mask = fL | fR | bL | bR;
                    break;
                case 5:
                    *channel_mask = fL | fR | fC | bL | bR;
                    break;
                case 6:
                    *channel_mask = fL | fR | fC | LFE | bL | bR;
                    break;
                case 7:
                    *channel_mask = fL | fR | fC | LFE | bC | sL | sR;
                    break;
                case 8:
                    *channel_mask = fL | fR | fC | LFE | bL | bR | sL | sR;
                    break;
                default:
                    /*shouldn't be able to happen*/
                    *channel_mask = 0;
                    break;
                }
                break;
            case 3: /*SEEKTABLE*/
                {
                    unsigned seekpoints = block_length / 18;
                    seektable->reset_for(seektable, seekpoints);

                    for (; seekpoints > 0; seekpoints--) {
                        struct flac_SEEKPOINT seekpoint;
                        seekpoint.sample_number =
                            bitstream->read_64(bitstream, 64);
                        seekpoint.byte_offset =
                            bitstream->read_64(bitstream, 64);
                        seekpoint.samples =
                            bitstream->read(bitstream, 16);
                        seektable->append(seektable, &seekpoint);
                    }
                }
                break;
            case 4: /*VORBIS_COMMENT*/
                {
                    /*Vorbis comment's channel mask - if any -
                      overrides default one from channel count */

                    br_substream_reset(comment);
                    bitstream->substream_append(bitstream,
                                                comment,
                                                block_length);

                    flacdec_read_vorbis_comment(comment,
                                                streaminfo->channels,
                                                channel_mask);
                }
                break;
            default:  /*all other blocks*/
                bitstream->skip(bitstream, block_length * 8);
                break;
            }
        } while (!last_block);

        br_etry(bitstream);
        comment->close(comment);
        return 0;
    } else {
#ifndef STANDALONE
        PyErr_SetString(PyExc_IOError, "EOF while reading metadata");
#endif
        br_etry(bitstream);
        comment->close(comment);
        return 1;
    }
}
Example #4
0
int main(int argc, char* argv[]) {
    FILE* ogg_file;
    OggReader* ogg_stream = NULL;
    BitstreamReader* packet = NULL;
    struct flac_STREAMINFO streaminfo;
    uint16_t header_packets;
    a_int* residuals = NULL;
    a_int* qlp_coeffs = NULL;
    aa_int* subframe_data = NULL;
    a_int* framelist_data = NULL;
    ogg_status result;
    uint16_t crc16 = 0;

    FrameList_int_to_char_converter converter;
    unsigned pcm_size;
    unsigned output_data_size = 1;
    uint8_t* output_data = NULL;

    audiotools__MD5Context md5;
    unsigned char stream_md5sum[16];
    const static unsigned char blank_md5sum[16] = {0, 0, 0, 0, 0, 0, 0, 0,
                                                   0, 0, 0, 0, 0, 0, 0, 0};

    if (argc < 2) {
        fprintf(stderr, "*** Usage: %s <file.oga>\n", argv[0]);
        return 1;
    }

    /*open input file for reading*/
    if ((ogg_file = fopen(argv[1], "rb")) == NULL) {
        fprintf(stderr, "*** %s: %s\n", argv[1], strerror(errno));
        return 1;
    } else {
        /*open bitstream and setup temporary arrays/buffers*/
        ogg_stream = oggreader_open(ogg_file);
        packet = br_substream_new(BS_BIG_ENDIAN);
        subframe_data = aa_int_new();
        residuals = a_int_new();
        qlp_coeffs = a_int_new();
        framelist_data = a_int_new();
        output_data = malloc(output_data_size);
    }

    /*the first packet should be the FLAC's STREAMINFO*/
    if ((result = oggreader_next_packet(ogg_stream, packet)) == OGG_OK) {
        if (!oggflac_read_streaminfo(packet, &streaminfo, &header_packets)) {
            goto error;
        } else {
            converter = FrameList_get_int_to_char_converter(
                streaminfo.bits_per_sample, 0, 1);
        }
    } else {
        fprintf(stderr, "*** Error: %s\n", ogg_strerror(result));
        goto error;
    }

    /*skip subsequent header packets*/
    for (; header_packets > 0; header_packets--) {
        if ((result = oggreader_next_packet(ogg_stream, packet)) != OGG_OK) {
            fprintf(stderr, "*** Error: %s\n", ogg_strerror(result));
            goto error;
        }
    }

    /*initialize the output MD5 sum*/
    audiotools__MD5Init(&md5);

    /*add callback for CRC16 calculation*/
    br_add_callback(packet, (bs_callback_f)flac_crc16, &crc16);

    /*decode the next FrameList from the stream*/
    result = oggreader_next_packet(ogg_stream, packet);

    while (result != OGG_STREAM_FINISHED) {
        if (result == OGG_OK) {
            flac_status flac_status;
            struct flac_frame_header frame_header;
            unsigned channel;

            subframe_data->reset(subframe_data);

            if (!setjmp(*br_try(packet))) {
                /*read frame header*/
                if ((flac_status =
                     flacdec_read_frame_header(packet,
                                               &streaminfo,
                                               &frame_header)) != OK) {
                    fprintf(stderr, "*** Error: %s\n",
                            FlacDecoder_strerror(flac_status));
                    br_etry(packet);
                    goto error;
                }

                /*read 1 subframe per channel*/
                for (channel = 0;
                     channel < frame_header.channel_count;
                     channel++)
                    if ((flac_status = flacdec_read_subframe(
                        packet,
                        qlp_coeffs,
                        residuals,
                        frame_header.block_size,
                        flacdec_subframe_bits_per_sample(&frame_header,
                                                         channel),
                        subframe_data->append(subframe_data))) != OK) {
                        fprintf(stderr, "*** Error: %s\n",
                                FlacDecoder_strerror(flac_status));
                        br_etry(packet);
                        goto error;
                    }

                br_etry(packet);
            } else {
                br_etry(packet);
                fprintf(stderr, "*** I/O Error reading FLAC frame\n");
                goto error;
            }

            /*handle difference channels, if any*/
            flacdec_decorrelate_channels(frame_header.channel_assignment,
                                         subframe_data,
                                         framelist_data);

            /*check CRC-16*/
            packet->byte_align(packet);
            packet->read(packet, 16);
            if (crc16 != 0) {
                fprintf(stderr, "*** Error: invalid checksum in frame\n");
                goto error;
            }

            /*turn FrameList into string of output*/
            pcm_size = (streaminfo.bits_per_sample / 8) * framelist_data->len;
            if (pcm_size > output_data_size) {
                output_data_size = pcm_size;
                output_data = realloc(output_data, output_data_size);
            }
            FrameList_samples_to_char(output_data,
                                      framelist_data->_,
                                      converter,
                                      framelist_data->len,
                                      streaminfo.bits_per_sample);

            /*update MD5 sum*/
            audiotools__MD5Update(&md5, output_data, pcm_size);

            /*output string to stdout*/
            fwrite(output_data, sizeof(unsigned char), pcm_size, stdout);

            result = oggreader_next_packet(ogg_stream, packet);
        } else {
            /*some error reading Ogg stream*/
            fprintf(stderr, "*** Error: %s\n", ogg_strerror(result));
            goto error;
        }
    }

    /*Ogg stream is finished so verify stream's MD5 sum*/
    audiotools__MD5Final(stream_md5sum, &md5);

    if (!((memcmp(streaminfo.md5sum, blank_md5sum, 16) == 0) ||
          (memcmp(stream_md5sum, streaminfo.md5sum, 16) == 0))) {
        fprintf(stderr, "*** MD5 mismatch at end of stream\n");
        goto error;
    }

    /*close streams, temporary buffers*/
    oggreader_close(ogg_stream);
    packet->close(packet);
    subframe_data->del(subframe_data);
    residuals->del(residuals);
    qlp_coeffs->del(qlp_coeffs);
    framelist_data->del(framelist_data);
    free(output_data);

    return 0;

error:
    oggreader_close(ogg_stream);
    packet->close(packet);
    subframe_data->del(subframe_data);
    residuals->del(residuals);
    qlp_coeffs->del(qlp_coeffs);
    framelist_data->del(framelist_data);
    free(output_data);

    return 1;
}
Example #5
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
}