pcm_reader_t *caf_open(pcm_io_context_t *io,
                       aacenc_tag_callback_t tag_callback, void *tag_ctx)
{
    caf_reader_t *reader = 0;
    int64_t data_length;
    unsigned bpf;

    if ((reader = calloc(1, sizeof(caf_reader_t))) == 0)
        return 0;
    memcpy(&reader->io, io, sizeof(pcm_io_context_t));
    reader->tag_callback = tag_callback;
    reader->tag_ctx = tag_ctx;
    memcpy(reader->chanmap, "\000\001\002\003\004\005\006\007", 8);

    if (caf_parse(reader, &data_length) < 0) {
        free(reader);
        return 0;
    }
    bpf = reader->sample_format.bytes_per_frame;

    /* CAF uses -1 to indicate "unknown size" */
    if (data_length < 0 || data_length % bpf)
        reader->length = INT64_MAX;
    else
        reader->length = data_length / bpf;

    if (reader->length == INT64_MAX) {
        if (pcm_seek(&reader->io, 0, SEEK_END) >= 0) {
            int64_t size = pcm_tell(&reader->io);
            if (size > 0)
                reader->length = (size - reader->data_offset) / bpf;
            pcm_seek(&reader->io, reader->data_offset, SEEK_SET);
        }
    }
    reader->vtbl = &caf_vtable;
    return (pcm_reader_t *)reader;
}
pcm_reader_t *caf_open(pcm_io_context_t *io,
                       aacenc_tag_callback_t tag_callback, void *tag_ctx)
{
    caf_reader_t *reader = 0;
    int64_t data_length;
    unsigned bpf;

    if ((reader = calloc(1, sizeof(caf_reader_t))) == 0)
        return 0;
    memcpy(&reader->io, io, sizeof(pcm_io_context_t));
    reader->tag_callback = tag_callback;
    reader->tag_ctx = tag_ctx;
    memcpy(reader->chanmap, "\000\001\002\003\004\005\006\007", 8);

    if (caf_parse(reader, &data_length) < 0) {
        free(reader);
        return 0;
    }
    bpf = reader->sample_format.bytes_per_frame;

     
    if (data_length < 0 || data_length % bpf)
        reader->length = INT64_MAX;
    else
        reader->length = data_length / bpf;

    if (reader->length == INT64_MAX) {
        if (pcm_seek(&reader->io, 0, SEEK_END) >= 0) {
            int64_t size = pcm_tell(&reader->io);
            if (size > 0)
                reader->length = (size - reader->data_offset) / bpf;
            pcm_seek(&reader->io, reader->data_offset, SEEK_SET);
        }
    }
    reader->vtbl = &caf_vtable;
    return (pcm_reader_t *)reader;
}