[FFmpeg-devel] [PATCH] EA ADPCM R1, R2 and R3

Michael Niedermayer michaelni
Sat Oct 20 20:11:58 CEST 2007


Hi

On Sat, Oct 20, 2007 at 03:42:35PM +0200, Aurelien Jacobs wrote:
> Hi,
> 
> Attached patch adds support for EA ADPCM R1, R2 and R3.
> It's based on the patch from Peter Ross.
> I intend to apply it soon.
> 
> Aurel

[...]
> @@ -637,9 +638,12 @@
>  {
>      ADPCMContext *c = avctx->priv_data;
>  
> -    if(avctx->channels > 2U){
> +    if ((avctx->channels > 2
> +         && avctx->codec->id != CODEC_ID_ADPCM_EA_R1
> +         && avctx->codec->id != CODEC_ID_ADPCM_EA_R2
> +         && avctx->codec->id != CODEC_ID_ADPCM_EA_R3)
> +        || avctx->channels > 6)
>          return -1;
> -    }

this is wrong, channels is signed so it must be 2U not 2

also this is not the most readable way to check this especially if more
codecs get added ...


>  
>      c->channel = 0;
>      c->status[0].predictor = c->status[1].predictor = 0;
> @@ -1182,6 +1186,78 @@
>              }
>          }
>          break;
> +    case CODEC_ID_ADPCM_EA_R1:
> +    case CODEC_ID_ADPCM_EA_R2:
> +    case CODEC_ID_ADPCM_EA_R3: {
> +        /* channel numbering
> +           2chan: 0=fl, 1=fr
> +           4chan: 0=fl, 1=rl, 2=fr, 3=rr
> +           6chan: 0=fl, 1=c,  2=fr, 3=rl,  4=rr, 5=sub */
> +        const int big_endian = avctx->codec->id == CODEC_ID_ADPCM_EA_R3;
> +        unsigned int channel;
> +        uint16_t *samplesC;
> +        uint8_t *srcC;
> +
> +        samples_in_chunk = (big_endian ? bytestream_get_be32(&src)
> +                                       : bytestream_get_le32(&src)) / 28;
> +
> +        for (channel=0; channel<avctx->channels; channel++) {
> +            srcC = src + (big_endian ? bytestream_get_be32(&src)
> +                                     : bytestream_get_le32(&src))
> +                       + (avctx->channels-channel-1) * 4;
> +            samplesC = samples + channel;
> +
> +            if (avctx->codec->id == CODEC_ID_ADPCM_EA_R1) {
> +                current_left_sample  = (int16_t)bytestream_get_le16(&srcC);
> +                previous_left_sample = (int16_t)bytestream_get_le16(&srcC);
> +            } else {
> +                current_left_sample  = c->status[channel].predictor;
> +                previous_left_sample = c->status[channel].prev_sample;
> +            }
> +
> +            for (count1=0; count1<samples_in_chunk; count1++) {
> +                if (*srcC == 0xEE) {  /* only seen in R2 and R3 */
> +                    srcC++;
> +                    current_left_sample  = (int16_t)bytestream_get_be16(&srcC);
> +                    previous_left_sample = (int16_t)bytestream_get_be16(&srcC);
> +
> +                    for (count2=0; count2<28; count2++) {
> +                        *samplesC = (int16_t)bytestream_get_be16(&srcC);
> +                        samplesC += avctx->channels;
> +                    }

completely missing checks for array bounds, this should be exploitable


> +                } else {
> +                    coeff1l = ea_adpcm_table[ (*srcC>>4) & 0x0F     ];
> +                    coeff2l = ea_adpcm_table[((*srcC>>4) & 0x0F) + 4];
> +                    shift_left = (*srcC++ & 0x0F) + 8;
> +
> +                    for (count2=0; count2<28; count2++) {
> +                        if (count2 & 1)
> +                            next_left_sample = ((*srcC++&0x0F)<<28)>>shift_left;
> +                        else
> +                            next_left_sample = ((*srcC  &0xF0)<<24)>>shift_left;

this code doesnt seem to be executed with just the left channel so why
is it called left?


> +
> +                        next_left_sample += (current_left_sample  * coeff1l) +
> +                                            (previous_left_sample * coeff2l);
> +                        next_left_sample = av_clip_int16(next_left_sample >> 8);
> +
> +                        previous_left_sample = current_left_sample;
> +                        current_left_sample  = next_left_sample;

> +                        *samplesC = (int16_t)current_left_sample;

senseless cast

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Breaking DRM is a little like attempting to break through a door even
though the window is wide open and the only thing in the house is a bunch
of things you dont want and which you would get tomorrow for free anyway
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20071020/78ea3f10/attachment.pgp>



More information about the ffmpeg-devel mailing list