On 11/04/2011 02:34 PM, Kostya Shishkov wrote:

> ---
> Yes, it's just a one-game format but it was really nice (and features a
> music video to Eric Idle's song performed by himself).
> 
> REd from https://github.com/scummvm/scummvm/blob/master/engines/tinsel/bmv.cpp
> ---
[...]
> +static const int bmv_dpcm_mults[16] = {
> +    16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 
> 36, 32
> +};
> +
> +static av_cold int bmv_aud_decode_init(AVCodecContext *avctx)
> +{
> +
> +    if (avctx->channels != 2) {
> +        av_log(avctx, AV_LOG_INFO, "invalid number of channels\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
> +
> +    return 0;
> +}
> +
> +static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, int 
> *data_size,
> +                                AVPacket *avpkt)
> +{
> +    const uint8_t *buf = avpkt->data;
> +    int buf_size = avpkt->size;
> +    int blocks = 0, total_blocks, i;
> +    int out_size;
> +    int16_t *output_samples = data;
> +    int scale[2];
> +
> +    if (!buf_size)
> +        return 0;


unnecessary. buf_size will never be 0 unless the codec has
CODEC_CAP_DELAY set.

> +
> +    total_blocks = *buf++;
> +    if (buf_size < total_blocks * 65 + 1) {
> +        av_log(avctx, AV_LOG_ERROR, "expected %d bytes, got %d\n",
> +               total_blocks * 65 + 1, buf_size);
> +        return AVERROR_INVALIDDATA;
> +    }
> +    out_size = total_blocks * 64 * sizeof(*output_samples);
> +    if (*data_size < out_size) {
> +        av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    for (blocks = 0; blocks < total_blocks; blocks++) {
> +        uint8_t code = *buf++;
> +        code = (code >> 1) | (code << 7);
> +        scale[0] = bmv_dpcm_mults[code & 0xF];
> +        scale[1] = bmv_dpcm_mults[code >> 4];
> +        for (i = 0; i < 32; i++) {
> +            *output_samples++ = (scale[0] * (int8_t)*buf++) >> 5;
> +            *output_samples++ = (scale[1] * (int8_t)*buf++) >> 5;


this looks like it could easily overflow. maybe it should use
av_clip_int16()?

> +
> +static int bmv_read_packet(AVFormatContext *s, AVPacket *pkt)
> +{
[...]
> +        if (type & BMV_AUDIO) {
> +            int audio_size = c->packet[1] * 65 + 1;
> +            if (audio_size >= c->size) {
> +                av_log(s, AV_LOG_ERROR, "Reported audio size %d is bigger 
> than packet size (%d)\n",
> +                       audio_size, c->size);
> +                return AVERROR_INVALIDDATA;
> +            }
> +            if (av_new_packet(pkt, audio_size) < 0)
> +                return AVERROR(ENOMEM);
> +            memcpy(pkt->data, c->packet + 1, pkt->size);
> +            pkt->stream_index = 1;
> +            c->get_next = 0;
> +            return pkt->size;


It looks like it should be trivial to calculate the correct packet
duration for audio.

-Justin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to