[Libav-user] Fill AVFrame from a Cairo surface

Colossus colossus73 at gmail.com
Mon Aug 16 12:37:00 EEST 2021


Hello Nicolas,

thanks for replying. The documentation is not very clear. I already looked
at
encode_video.c and it wasn't useful as it creates a dummy image, I have to
read
data from a cairo surface instead. There should be more documentation on
*HOW*
to put the single puzzle pieces *TOGETHER, *not just describing the *SINGLE*
pieces
to my humble opinion.

Also I'm not sure what you mean with: "Calling av_frame_make_writable() on
a frame you just allocated makes
 no sense." as in encode_video.c at line 140 I see the call to
av_frame_allloc() and then at line
160, so after line 140 I read the call to av_frame_make_writable()...

I know where the flaw is as I used return codes not visible in the code
above. I
clearly stated it in my message:

"But *avcodec_send_frame*() called from img_export_encode_av_frame() always
return:"

Did you reply from the beach...?

Anyway thanks for the tip on the stride. I will made new researches based
on this information.

Kind regards
Giuseppe


On Mon, 16 Aug 2021 at 10:20, Nicolas George <george at nsup.org> wrote:

> Colossus (12021-08-16):
> > I have this piece of code:
> > static gboolean img_export_frame_to_avframe(img_window_struct *img,
> > cairo_surface_t *surface)
> > {
> > gint width, height, stride, row, col, offset;
> > uint8_t  *pix;
> >
> > /* Image info and pixel data */
> > width  = cairo_image_surface_get_width( surface );
> > height = cairo_image_surface_get_height( surface );
> > stride = cairo_image_surface_get_stride( surface );
> > pix    = cairo_image_surface_get_data( surface );
> >
> > g_print("Stride: %d\n",stride);
> >
> > /* Avlibrary stuff */
> > img->video_frame = av_frame_alloc();
> > av_frame_make_writable(img->video_frame);
> > img->video_frame->format = AV_PIX_FMT_RGBA;
> > img->video_frame->width  = width;
> > img->video_frame->height = height;
> > img->video_frame->linesize[0] = stride;
> >
> > av_frame_get_buffer(img->video_frame, 1);
> > img->video_packet = av_packet_alloc();
> >
> > for( row = 0; row < img->video_frame->height; row++ )
> > {
> > for( col = 0; col < img->video_frame->width; col++ )
> > {
> > offset = 3 * col + row * img->video_frame->linesize[0];
> > img->video_frame->data[0][offset + 0] = pix[0];
> > img->video_frame->data[0][offset + 1] = pix[1];
> > img->video_frame->data[0][offset + 2] = pix[2];
> > }
> > }
> > img_export_encode_av_frame(img->video_frame, img->video_format_context,
> > img->codec_context, img->video_packet);
> > return TRUE;
> > }
> >
> > But avcodec_send_frame() called from img_export_encode_av_frame() always
> > return:
> >
> > libx264 @ 0x5582519787c0] Input picture width (640) is greater than
> stride
> > (0)
> >
> > The stride is 5120 not 0! Where am I wrong? Also I grepped with the
> > recursive option the whole ffmpeg4 source and I couldn't find the error
> > message above of course without the 640 and 0...
>
> You are calling frame-related functions haphazardly and seem to have
> misunderstood how stride works. And you do not check your return values.
> And you seem to be misusing the encoding API too.
>
> Stride is not a property of the image, it is a property of the allocated
> memory. That means stride is chosen by whoever allocates the image. If
> you ask FFmpeg to allocate the image for you, then FFmpeg gets to decide
> the stride.
>
> You would set the stride yourself if you were trying to use an already
> allocated memory buffer. For example if you want to use memory mapped
> from a video device. Or if you want to use the frame data from
> cairo_surface_t directly (which I am not sure is possible, and very
> tricky anyway).
>
> As for the frame-related functions:
>
> - Calling av_frame_make_writable() on a frame you just allocated makes
>   no sense.
>
> - Calling av_frame_make_writable() before av_frame_get_buffer(). The
>   point of av_frame_make_writable() is to reuse buffers that are already
>   allocated if possible.
>
> As for the encoding API, your single call to
> img_export_encode_av_frame() shows you probably assume one input frame
> will give you one output packet. This is not true.
>
> Start with checking the return value of all your function calls, and you
> will see where the flaw is.
>
> Look at doc/examples/encode_video.c to see how it does it and work from
> there.
>
> Regards,
>
> --
>   Nicolas George
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/libav-user
>
> To unsubscribe, visit link above, or email
> libav-user-request at ffmpeg.org with subject "unsubscribe".
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20210816/37303a90/attachment.htm>


More information about the Libav-user mailing list