On Sun, 23 Feb 2014 10:59:22 -0500, Reinhard Tartler <[email protected]> wrote:
> On Sun, Feb 23, 2014 at 10:29 AM, Anton Khirnov <[email protected]> wrote:
> >
> > On Sun, 23 Feb 2014 09:34:46 -0500, Reinhard Tartler <[email protected]>
> > wrote:
> >> The patch quoted below requires quite non-trivial changes to
> >> applications. Consider amide's http://amide.sourceforge.net/
> >> mpeg_encode_frame() function:
> >>
> >>
> >> gboolean mpeg_encode_frame(gpointer data, GdkPixbuf * pixbuf) {
> >> encode_t * encode = data;
> >> gint out_size;
> >>
> >> convert_rgb_pixbuf_to_yuv(encode->yuv, pixbuf);
> >>
> >> /* encode the image */
> >> out_size = avcodec_encode_video(encode->context,
> >> encode->output_buffer, encode->output_buffer_size, encode->picture);
> >> fwrite(encode->output_buffer, 1, out_size, encode->output_file);
> >>
> >> return TRUE;
> >> };
> >>
> >> This application so far has successfully used libavcodec without the
> >> use of AVPackets. Can someone help with explaining to amide developers
> >> why exactly their code improves by using of avcodec_encode_video2
> >> instead? I'm not even sure if I got this patch right:
> >>
> >>
> >> --- amide-1.0.4.orig/src/mpeg_encode.c
> >> +++ amide-1.0.4/src/mpeg_encode.c
> >> @@ -268,7 +269,7 @@ gpointer mpeg_encode_setup(gchar * outpu
> >> return NULL;
> >> }
> >>
> >> - encode->picture= avcodec_alloc_frame();
> >> + encode->picture= av_frame_alloc();
> >> if (!encode->picture) {
> >> g_warning("couldn't allocate memory for encode->picture");
> >> encode_free(encode);
> >> @@ -360,14 +361,37 @@ gpointer mpeg_encode_setup(gchar * outpu
> >> gboolean mpeg_encode_frame(gpointer data, GdkPixbuf * pixbuf) {
> >> encode_t * encode = data;
> >> gint out_size;
> >> + AVPacket pkt;
> >> + int ret, got_packet = 0;
> >>
> >> convert_rgb_pixbuf_to_yuv(encode->yuv, pixbuf);
> >>
> >> - /* encode the image */
> >> - out_size = avcodec_encode_video(encode->context,
> >> encode->output_buffer, encode->output_buffer_size, encode->picture);
> >> - fwrite(encode->output_buffer, 1, out_size, encode->output_file);
> >> + av_init_packet(&pkt);
> >> + pkt.data = encode->output_buffer;
> >> + pkt.size = encode->output_buffer_size;
> >
> > No need for this, just initialize the whole packet to 0, then the encoder
> > will
> > allocate the memory for you. You can the delete output_buffer(_size) and the
> > code allocating and freeing it.
> >
> >>
> >> - return TRUE;
> >> + /* encode the image */
> >> + ret = avcodec_encode_video2(encode->context, &pkt, encode->picture,
> >> &got_packet);
> >> + if (!ret && got_packet && encode->context->coded_frame) {
> >> + encode->context->coded_frame->pts = pkt.pts;
> >> + encode->context->coded_frame->key_frame = !!(pkt.flags &
> >> AV_PKT_FLAG_KEY);
> >> + }
> >
> > The if() block is not needed.
> >
> >> +
> >> + /* free any side data since we cannot return it */
> >> + if (pkt.side_data_elems > 0) {
> >> + int i;
> >> + for (i = 0; i < pkt.side_data_elems; i++)
> >> + av_free(pkt.side_data[i].data);
> >> + av_freep(&pkt.side_data);
> >> + pkt.side_data_elems = 0;
> >> + }
> >> +
> >> + if (!ret) {
> >> + fwrite(encode->output_buffer, 1, pkt.size, encode->output_file);
> >> + return TRUE;
> >> + } else {
> >> + return FALSE;
> >> + }
> >
> > This can be replaced by
> > if (ret >= 0 && got_packet) {
> > fwrite(pkt.data, 1, pkt.size, encode->output_file);
> > av_free_packet(&pkt);
> > }
> > return (ret >= 0) ? TRUE : FALSE;
> >
> > With those changes, the new code is about the same length as the old,
> > possibly
> > even shorter.
>
> Please double check if I got your suggestions right:
>
>
> gboolean mpeg_encode_frame(gpointer data, GdkPixbuf * pixbuf) {
> encode_t * encode = data;
> gint out_size;
This variable is unused now
> AVPacket pkt = { 0 };
> int ret, got_packet = 0;
>
> convert_rgb_pixbuf_to_yuv(encode->yuv, pixbuf);
>
> /* encode the image */
> ret = avcodec_encode_video2(encode->context, &pkt, encode->picture,
> &got_packet);
>
> if (ret >= 0 && got_packet) {
> fwrite(pkt.data, 1, pkt.size, encode->output_file);
> av_free_packet(&pkt);
> }
> return (ret >= 0) ? TRUE : FALSE;
> };
>
> I'm not sure about the initialization part, did you really mean that
> it is not necessary to call av_init_packet()?
Otherwise the code looks correct to me.
And yes, it's not necessary to call av_init_packet(), avcodec_encode_video2()
will do that for you. The only fields that matter are the values of packet
data/size
--
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel