[FFmpeg-devel] [PATCH] avcodec: add SMC encoder

James Almer jamrial at gmail.com
Sun Aug 15 00:41:56 EEST 2021


On 8/14/2021 1:55 PM, Paul B Mahol wrote:
> +static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
> +                                const AVFrame *frame, int *got_packet)
> +{
> +    SMCContext *s = avctx->priv_data;
> +    const AVFrame *pict = frame;
> +    uint8_t *pal;
> +    int ret;
> +
> +    ret = ff_alloc_packet(avctx, pkt, 8LL * avctx->height * avctx->width);
> +    if (ret < 0)
> +        return ret;
> +
> +    if (avctx->gop_size == 0 || !s->prev_frame->data[0] ||
> +        (avctx->frame_number % avctx->gop_size) == 0) {
> +        s->key_frame = 1;
> +    } else {
> +        s->key_frame = 0;
> +    }
> +
> +    bytestream2_init_writer(&s->pb, pkt->data, pkt->size);
> +
> +    bytestream2_put_be32(&s->pb, 0x00);
> +
> +    if (!s->prev_frame->data[0]) {
> +        s->first_frame = 1;
> +        s->prev_frame->format = pict->format;
> +        s->prev_frame->width = pict->width;
> +        s->prev_frame->height = pict->height;
> +        ret = av_frame_get_buffer(s->prev_frame, 0);

This is unnecessary. You're allocating a buffer you'll not use just so 
for the next frame the !s->prev_frame->data[0] check above will evaluate 
to false.

Get rid of s->first_frame and just look for s->prev_frame->data[0] in 
smc_encode_stream() to know if you need to use a previous frame or not. 
When you process the second one you'll have called av_frame_ref() on 
s->prev_frame at the end of the first, so it will be populated.

> +        if (ret < 0)
> +            return ret;
> +    } else {
> +        s->first_frame = 0;
> +    }
> +
> +    pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
> +    memcpy(pal, frame->data[1], AVPALETTE_SIZE);
> +
> +    smc_encode_stream(s, pict);
> +
> +    av_shrink_packet(pkt, bytestream2_tell_p(&s->pb));
> +
> +    pkt->data[0] = 0x0;
> +
> +    // write chunk length
> +    AV_WB24(pkt->data + 1, pkt->size);
> +
> +    av_frame_unref(s->prev_frame);
> +    ret = av_frame_ref(s->prev_frame, frame);
> +    if (ret < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "cannot add reference\n");
> +        return ret;
> +    }
> +
> +    if (s->key_frame)
> +        pkt->flags |= AV_PKT_FLAG_KEY;
> +
> +    *got_packet = 1;
> +
> +    return 0;
> +}
> +



More information about the ffmpeg-devel mailing list