[FFmpeg-devel] [FFmpeg-cvslog] avcodec: add Apple Pixlet decoder

Andreas Cadhalpun andreas.cadhalpun at googlemail.com
Sat Dec 24 01:54:59 EET 2016


On 23.12.2016 09:17, Paul B Mahol wrote:
> On 12/23/16, Andreas Cadhalpun <andreas.cadhalpun at googlemail.com> wrote:
>> On 22.12.2016 22:52, Paul B Mahol wrote:
>>> +        xflag = flag + cnt1;
>>> +        yflag = xflag;
>>> +
>>> +        if (flag + cnt1 == 0) {
>>> +            value = 0;
>>> +        } else {
>>> +            xflag &= 1u;
>>> +            tmp = c * ((yflag + 1) >> 1) + (c >> 1);
>>
>> This can overflow.
> 
> And?

That is undefined behavior. It looks like at least a cast to int64_t is missing.

>>> +            value = xflag + (tmp ^ -xflag);
>>> +        }
>>> +
>>> +        i++;
>>> +        dst[j++] = value;
>>> +        if (j == width) {
>>> +            j = 0;
>>> +            dst += stride;
>>> +        }
>>> +        state += d * yflag - (d * state >> 8);
>>
>> This can overflow, too.
> 
> And?

Same as above.

>> [...]
>>> +static void postprocess_chroma(AVFrame *frame, int w, int h, int depth)
>>> +{
>>> +    uint16_t *dstu = (uint16_t *)frame->data[1];
>>> +    uint16_t *dstv = (uint16_t *)frame->data[2];
>>> +    int16_t *srcu  = (int16_t *)frame->data[1];
>>> +    int16_t *srcv  = (int16_t *)frame->data[2];
>>> +    ptrdiff_t strideu = frame->linesize[1] / 2;
>>> +    ptrdiff_t stridev = frame->linesize[2] / 2;
>>> +    const int add = 1 << (depth - 1);
>>> +    const int shift = 16 - depth;
>>> +    int i, j;
>>> +
>>> +    for (j = 0; j < h; j++) {
>>> +        for (i = 0; i < w; i++) {
>>> +            dstu[i] = (add + srcu[i]) << shift;
>>> +            dstv[i] = (add + srcv[i]) << shift;
>>
>> These result in undefined shifts, since the value to be shifted can be
>> negative.
> 
> OK.

Making add unsigned would fix that.

>>> +        }
>>> +        dstu += strideu;
>>> +        dstv += stridev;
>>> +        srcu += strideu;
>>> +        srcv += stridev;
>>> +    }
>>> +}
>>> +
>>> +static int decode_plane(AVCodecContext *avctx, int plane, AVPacket
>>> *avpkt, AVFrame *frame)
>>> +{
>>> +    PixletContext *ctx = avctx->priv_data;
>>> +    ptrdiff_t stride = frame->linesize[plane] / 2;
>>> +    unsigned shift = plane > 0;
>>> +    int16_t *dst;
>>> +    int i, ret;
>>> +
>>> +    for (i = ctx->levels - 1; i >= 0; i--) {
>>> +        ctx->scaling[plane][H][i] = 1000000. /
>>> sign_extend(bytestream2_get_be32(&ctx->gb), 32);
>>> +        ctx->scaling[plane][V][i] = 1000000. /
>>> sign_extend(bytestream2_get_be32(&ctx->gb), 32);
>>
>> Here the denominators can be zero.
> 
> And?

That is undefined behavior.

>>> +    *got_frame = 1;
>>> +
>>> +    return pktsize;
>>
>> Since this is a video decoder, this should always return the full
>> avpkt->size.
> 
> Wrong. It returns what it consumes.

Video decoders are expected to consume the full packet and the new decoding API does that.
So not returning the full packet size results in a behavior difference between the new
and the old API, which is bad. Why would you want that?

Best regards,
Andreas



More information about the ffmpeg-devel mailing list