[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