static int wv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    WVContext *wc = s->priv_data;
    int ret;
    int off;
    int64_t pos;
    uint32_t block_samples;

    if (avio_feof(s->pb))
        return AVERROR_EOF;
    if (wc->block_parsed) {
        if ((ret = wv_read_block_header(s, s->pb)) < 0)
            return ret;
    }

    pos = wc->pos;
    if (av_new_packet(pkt, wc->header.blocksize + WV_HEADER_SIZE) < 0)
        return AVERROR(ENOMEM);
    memcpy(pkt->data, wc->block_header, WV_HEADER_SIZE);
    ret = avio_read(s->pb, pkt->data + WV_HEADER_SIZE, wc->header.blocksize);
    if (ret != wc->header.blocksize) {
        av_packet_unref(pkt);
        return AVERROR(EIO);
    }
    while (!(wc->header.flags & WV_FLAG_FINAL_BLOCK)) {
        if ((ret = wv_read_block_header(s, s->pb)) < 0) {
            av_packet_unref(pkt);
            return ret;
        }

        off = pkt->size;
        if ((ret = av_grow_packet(pkt, WV_HEADER_SIZE + wc->header.blocksize)) < 0) {
            av_packet_unref(pkt);
            return ret;
        }
        memcpy(pkt->data + off, wc->block_header, WV_HEADER_SIZE);

        ret = avio_read(s->pb, pkt->data + off + WV_HEADER_SIZE, wc->header.blocksize);
        if (ret != wc->header.blocksize) {
            av_packet_unref(pkt);
            return (ret < 0) ? ret : AVERROR_EOF;
        }
    }
    pkt->stream_index = 0;
    pkt->pos          = pos;
    wc->block_parsed  = 1;
    pkt->pts          = wc->header.block_idx;
    block_samples     = wc->header.samples;
    if (block_samples > INT32_MAX)
        av_log(s, AV_LOG_WARNING,
               "Too many samples in block: %"PRIu32"\n", block_samples);
    else
        pkt->duration = block_samples;

    return 0;
}