static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
                                   MatroskaTrack *track,
                                   AVStream *st,
                                   uint8_t *data, int size,
                                   uint64_t timecode,
                                   int64_t pos)
{
    int a = st->codec->block_align;
    int sps = track->audio.sub_packet_size;
    int cfs = track->audio.coded_framesize;
    int h = track->audio.sub_packet_h;
    int y = track->audio.sub_packet_cnt;
    int w = track->audio.frame_size;
    int x;

    if (!track->audio.pkt_cnt) {
        if (track->audio.sub_packet_cnt == 0)
            track->audio.buf_timecode = timecode;
        if (st->codec->codec_id == AV_CODEC_ID_RA_288) {
            if (size < cfs * h / 2) {
                av_log(matroska->ctx, AV_LOG_ERROR,
                       "Corrupt int4 RM-style audio packet size\n");
                return AVERROR_INVALIDDATA;
            }
            for (x=0; x<h/2; x++)
                memcpy(track->audio.buf+x*2*w+y*cfs,
                       data+x*cfs, cfs);
        } else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
            if (size < w) {
                av_log(matroska->ctx, AV_LOG_ERROR,
                       "Corrupt sipr RM-style audio packet size\n");
                return AVERROR_INVALIDDATA;
            }
            memcpy(track->audio.buf + y*w, data, w);
        } else {
            if (size < sps * w / sps) {
                av_log(matroska->ctx, AV_LOG_ERROR,
                       "Corrupt generic RM-style audio packet size\n");
                return AVERROR_INVALIDDATA;
            }
            for (x=0; x<w/sps; x++)
                memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
        }

        if (++track->audio.sub_packet_cnt >= h) {
            if (st->codec->codec_id == AV_CODEC_ID_SIPR)
                ff_rm_reorder_sipr_data(track->audio.buf, h, w);
            track->audio.sub_packet_cnt = 0;
            track->audio.pkt_cnt = h*w / a;
        }
    }

    while (track->audio.pkt_cnt) {
        AVPacket *pkt = NULL;
        if (!(pkt = av_mallocz(sizeof(AVPacket))) || av_new_packet(pkt, a) < 0){
            av_free(pkt);
            return AVERROR(ENOMEM);
        }
        memcpy(pkt->data, track->audio.buf
               + a * (h*w / a - track->audio.pkt_cnt--), a);
        pkt->pts = track->audio.buf_timecode;
        track->audio.buf_timecode = AV_NOPTS_VALUE;
        pkt->pos = pos;
        pkt->stream_index = st->index;
        dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
    }

    return 0;
}