[libav-api] UYV to RGB artifacts

Christophe Gimenez christophe.gimenez at gmail.com
Sat Mar 18 18:56:14 CET 2017


Hello everybody, I'm new to the mailing list and discovering libav.

3 days long I've been struggling to code a small experimental app that
pretends to transform RGB24 pixels buffers (provided by the framework I
use, which is OpenFramework) to a h264 file.

I've almost reached the finish line, but still have a problem : the encoded
h264 has some color artifacts. You can see one frame here, for example :
http://pasteboard.co/KYNkeOoFm.png

1) I'm on Raspbian, compiled my own version of libav. I can assure that
there is no "mix" between this libav and the system's one. Included files,
linked libraries are from the libav I've compiled.
I used libav 12.

2) below are my app relevant sections, without error checking - Can you see
something wrong ?
I tried everything I could.
Thanks in advance for your help...

INIT METHOD EXCERPT
    avcodec_register_all();

    codec = avcodec_find_encoder(codec_id);

    c = avcodec_alloc_context3(codec);
    c->bit_rate = 400000;
    c->width = width;
    c->height = height;
    c->time_base = (AVRational){1, 25};
    c->framerate = (AVRational){25, 1};
    c->gop_size = 10;
    c->max_b_frames = 1;
    c->pix_fmt = AV_PIX_FMT_YUV420P;

    avcodec_open2(c, codec, NULL);

    f = fopen(filename, "wb");

    frame = av_frame_alloc();
    frame->format = AV_PIX_FMT_RGB24;
    frame->width = c->width;
    frame->height = c->height;

    int ret = av_frame_get_buffer(frame, 0);

    tmp_frame = av_frame_alloc();
    tmp_frame->format = AV_PIX_FMT_YUV420P;
    tmp_frame->width = c->width;
    tmp_frame->height = c->height;

    ret = av_frame_get_buffer(tmp_frame, 0);

    pkt = av_packet_alloc();

    sws_context = sws_getContext(c->width, c->height, AV_PIX_FMT_RGB24,
c->width, c->height, AV_PIX_FMT_YUV420P, 0, 0, 0, 0);

ENCODE_FRAME METHOD

void Encoder::encode_frame(AVCodecContext *enc_ctx, AVFrame *frame,
AVPacket *pkt, FILE *outfile) {
    int ret;
    ret = avcodec_send_frame(enc_ctx, frame);
    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "error during encoding\n");
            exit(1);
        }
        fwrite(pkt->data, 1, pkt->size, outfile);
        av_packet_unref(pkt);
    }
}

ENCODE METHOD
This method is called every time a new pixel buffer is available

void Encoder::encode(const uint8_t *pixels) {
    av_frame_make_writable(frame);
    av_frame_make_writable(tmp_frame);

    av_image_fill_arrays(frame->data, frame->linesize, pixels,
AV_PIX_FMT_RGB24, c->width, c->height, 32);
    av_image_alloc(tmp_frame->data, tmp_frame->linesize, c->width,
c->height, AV_PIX_FMT_YUV420P, 32);

    sws_scale(sws_context, frame->data, frame->linesize, 0, c->height,
tmp_frame->data, tmp_frame->linesize);
    tmp_frame->pts = ++frame_pts;
    encode_frame(c, tmp_frame, pkt, f);
    // Do I need to free something here ??
    // av_freep(&tmp_frame->data[0]);
}


More information about the libav-api mailing list