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