[FFmpeg-devel] [PATCH] avcodec: LEAD MCMP decoder

James Almer jamrial at gmail.com
Sat Nov 12 17:33:59 EET 2022


On 11/11/2022 9:39 PM, Peter Ross wrote:
> +static int lead_decode_frame(AVCodecContext *avctx, AVFrame * frame,
> +                             int * got_frame, AVPacket * avpkt)
> +{
> +    LeadContext *s = avctx->priv_data;
> +    const uint8_t * buf = avpkt->data;
> +    int ret, format, yuv20p_half = 0, fields = 1, q, size;
> +    GetBitContext gb;
> +    int16_t dc_pred[3] = {0, 0, 0};
> +    uint16_t dequant[2][64];
> +
> +    if (avpkt->size < 8)
> +        return AVERROR_INVALIDDATA;
> +
> +    format = AV_RL16(buf + 4);
> +    switch(format) {
> +    case 0x1000:
> +        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
> +        break;
> +    case 0x2000:
> +        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
> +        break;
> +    case 0x2006:
> +        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
> +        fields = 2;
> +        break;
> +    case 0x8000:
> +        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
> +        yuv20p_half = 1;

nit: maybe do

switch(format) {
case 0x8000:
     yuv20p_half = 1;
     // fall-through
case 0x1000:
     avctx->pix_fmt = AV_PIX_FMT_YUV420P;
     break;

> +        break;
> +    default:
> +        avpriv_request_sample(avctx, "unsupported format 0x%x", format);
> +        return AVERROR_PATCHWELCOME;
> +    }
> +
> +    q = AV_RL16(buf + 6);
> +    calc_dequant(dequant[0], ff_mjpeg_std_luminance_quant_tbl, q);
> +    calc_dequant(dequant[1], ff_mjpeg_std_chrominance_quant_tbl, q);
> +
> +    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> +        return ret;
> +
> +    frame->key_frame = 1;
> +    frame->pict_type = AV_PICTURE_TYPE_I;

Shouldn't the codec have the prop AV_CODEC_PROP_INTRA_ONLY then? Or do 
some formats not yet supported have inter frames?

[...]

> +    if (yuv20p_half) {
> +        for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
> +            for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
> +                for (int b = 0; b < 4; b++) {
> +                    const VLCElem * dc_vlc = b < 2 ? luma_dc_vlc.table : chroma_dc_vlc.table;
> +                    int dc_bits            = b < 2 ? LUMA_DC_BITS : CHROMA_DC_BITS;
> +                    const VLCElem * ac_vlc = b < 2 ? luma_ac_vlc.table : chroma_ac_vlc.table;
> +                    int ac_bits            = b < 2 ? LUMA_AC_BITS : CHROMA_AC_BITS;
> +                    int plane              = b < 2 ? 0 : b - 1;
> +                    int x, y;
> +
> +                    if (b < 2) {
> +                        y = 16*mb_y + 8*(b >> 1);
> +                        x = 16*mb_x + 8*(b & 1);
> +                    } else {
> +                        y = 8*mb_y;
> +                        x = 8*mb_x;
> +                    }
> +
> +                    ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
> +                        dc_pred + plane, dequant[!(b < 4)],
> +                        frame->data[plane] + y*frame->linesize[plane] + x,
> +                        (b < 2 ? 2 : 1) * frame->linesize[plane]);
> +                    if (ret < 0)
> +                        return ret;
> +
> +                    if (b < 2)
> +                        copy_block8(frame->data[plane] + (y + 1)*frame->linesize[plane] + x,
> +                                    frame->data[plane] + y*frame->linesize[plane] + x,
> +                                    2*frame->linesize[plane], 2*frame->linesize[plane], 8);
> +                }
> +    } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
> +        for (int mb_y = 0; mb_y < avctx->height / 16; mb_y++)
> +            for (int mb_x = 0; mb_x < avctx->width / 16; mb_x++)
> +                for (int b = 0; b < 6; b++) {
> +                    const VLCElem * dc_vlc = b < 4 ? luma_dc_vlc.table : chroma_dc_vlc.table;
> +                    int dc_bits            = b < 4 ? LUMA_DC_BITS : CHROMA_DC_BITS;
> +                    const VLCElem * ac_vlc = b < 4 ? luma_ac_vlc.table : chroma_ac_vlc.table;
> +                    int ac_bits            = b < 4 ? LUMA_AC_BITS : CHROMA_AC_BITS;
> +                    int plane              = b < 4 ? 0 : b - 3;
> +                    int x, y;
> +
> +                    if (b < 4) {
> +                        y = 16*mb_y + 8*(b>>1);
> +                        x = 16*mb_x + 8*(b&1);
> +                    } else {
> +                        y = 8*mb_y;
> +                        x = 8*mb_x;
> +                    }
> +
> +                    ret = decode_block(s, &gb, dc_vlc, dc_bits, ac_vlc, ac_bits,
> +                        dc_pred + plane, dequant[!(b < 4)],
> +                        frame->data[plane] + y*frame->linesize[plane] + x,
> +                        frame->linesize[plane]);
> +                    if (ret < 0)
> +                        return ret;
> +                }

You should be able to combine these two blocks, doing things like b < (4 
 >> yuv20p_half), b - (3 >> yuv20p_half) and such.


More information about the ffmpeg-devel mailing list