[Libav-user] GIF API access

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[Libav-user] GIF API access

Gustavo González-4
Hi,

I wonder if using Libav as dependency allows me to call the functions defined in the file libavformat/gif.c

Functions like these:

static int gif_image_write_header(AVIOContext *pb, int width, int height,
                                  int loop_count, uint32_t *palette)

static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)

static int gif_write_trailer(AVFormatContext *s)

As the avconv binary allows me to create animated GIF examples from sequences of PNG files, I guess it is accessing the GIF API, but I was unable to trace all the route to find the top level functions I could use to create animated GIFs from my own code.

Any sugestion? Any handy example to watch? I am still studying avconv.c but it's a little complex to follow.

Thanks.

--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Malik Jahanzeb
I guess gif.c functionality is exposed as a 'muxer' with the following standard interface that all muxers have in ffmpeg:

static const AVClass gif_muxer_class = {
    .class_name = "GIF muxer",
    .item_name  = av_default_item_name,
    .version    = LIBAVUTIL_VERSION_INT,
    .option     = options,
};

AVOutputFormat ff_gif_muxer = {
    .name           = "gif",
    .long_name      = NULL_IF_CONFIG_SMALL("GIF Animation"),
    .mime_type      = "image/gif",
    .extensions     = "gif",
    .priv_data_size = sizeof(GIFContext),
    .audio_codec    = AV_CODEC_ID_NONE,
    .video_codec    = AV_CODEC_ID_GIF,
    .write_header   = gif_write_header,
    .write_packet   = gif_write_packet,
    .write_trailer  = gif_write_trailer,
    .priv_class     = &gif_muxer_class,
    .flags          = AVFMT_VARIABLE_FPS,
};

You need to find out how to use a muxer in your program. Challenge is that ffmpeg samples are few, very high level and work at a file level. I wished there was a sample program to just demonstrate how to use a muxer or demuxer etc.

I needed a different muxer for my program but I couldn't find an example to follow. I ended up surgically adding code snippets into my program.

Thanks,
Malik

On Tue, Feb 14, 2017 at 1:08 PM, Gustav González <[hidden email]> wrote:
Hi,

I wonder if using Libav as dependency allows me to call the functions defined in the file libavformat/gif.c

Functions like these:

static int gif_image_write_header(AVIOContext *pb, int width, int height,
                                  int loop_count, uint32_t *palette)

static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)

static int gif_write_trailer(AVFormatContext *s)

As the avconv binary allows me to create animated GIF examples from sequences of PNG files, I guess it is accessing the GIF API, but I was unable to trace all the route to find the top level functions I could use to create animated GIFs from my own code.

Any sugestion? Any handy example to watch? I am still studying avconv.c but it's a little complex to follow.

Thanks.

--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user



_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Carl Eugen Hoyos-2
2017-02-14 21:09 GMT+01:00 Malik Jahanzeb <[hidden email]>:

> I needed a different muxer for my program but I couldn't find an example to
> follow.

Did you look into doc/examples?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Gustavo González-4

Hi!

I'm getting closer to create an animated GIF using a (Qt) QImage array as input.

This is the latest GIF file I could create -> http://maefloresta.com/tmp/test.gif

Using this method as part of the process, I insert every frame into the GIF file:

writeVideoFrame(AVFormatContext *oc, AVStream *video_st, const QImage &image) 
{
QImage img = image.convertToFormat(Format_RGB888); AVPacket pkt; av_init_packet(&pkt); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = video_st->index; pkt.data = (uint8_t *) img.bits(); pkt.size = sizeof(AVFrame); av_write_frame(oc, &pkt); frameCount++;
}

As you can see it, the GIF file is not animated. Just the first frame is displayed, but the picture encoding is accurate. I was sneaking around inside the container using an hex editor and the 15 frames I created for that example are there. I am missing some kind of flag or instruction to activate the animated format.

Any suggestion?

PS: I tried to use the function avcodec_encode_video2() to add the frames into the file, but it was unsuccessful. Creating my own packets (AVPacket) was the best approach for now.


2017-02-14 18:58 GMT-05:00 Carl Eugen Hoyos <[hidden email]>:
2017-02-14 21:09 GMT+01:00 Malik Jahanzeb <[hidden email]>:

> I needed a different muxer for my program but I couldn't find an example to
> follow.

Did you look into doc/examples?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user



--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Carl Eugen Hoyos-2
2017-02-27 4:13 GMT+01:00 Gustav González <[hidden email]>:
> I'm getting closer to create an animated GIF using a (Qt) QImage
> array as input.

Since your sample code does not use the gif encoder, I don't see
how it can lead to an animated gif as output file.

Please do not top-post here, Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Gustavo González-4
2017-02-27 4:30 GMT-05:00 Carl Eugen Hoyos <[hidden email]>:
2017-02-27 4:13 GMT+01:00 Gustav González <[hidden email]>:
> I'm getting closer to create an animated GIF using a (Qt) QImage
> array as input.

Since your sample code does not use the gif encoder, I don't see
how it can lead to an animated gif as output file.

So, the right way to ensure a functional animated GIF is using the avcodec_encode_video2() function to insert the frames?

--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Gustavo González-4
2017-02-27 11:02 GMT-05:00 Gustav González <[hidden email]>:
2017-02-27 4:30 GMT-05:00 Carl Eugen Hoyos <[hidden email]>:
2017-02-27 4:13 GMT+01:00 Gustav González <[hidden email]>:
> I'm getting closer to create an animated GIF using a (Qt) QImage
> array as input.

Since your sample code does not use the gif encoder, I don't see
how it can lead to an animated gif as output file.

So, the right way to ensure a functional animated GIF is using the avcodec_encode_video2() function to insert the frames?

--
============================
  Gustav Gonzalez
  [hidden email]
============================

Finally, I could create an animated GIF for the first time. Nevertheless, I need to adjust the FPS parameter in some point because the animation looks too slow. I am doing it from the AVCodecContext variable, like this:

    int fps = 24;
    AVCodecContext *c;
    c->time_base.den = fps;
    c->time_base.num = 1;

But anyway, it doesn't matter the value I set for the fps variable, the result is always the same (slow). On the other hand, this is the code I use to process every QImage object:

        int got_packet = 0;
        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.data = NULL; // packet data will be allocated by the encoder
        pkt.size = 0;

        QImage img = image.convertToFormat(Format_RGB888);
        avpicture_fill((AVPicture *)frame, img.bits(), AV_PIX_FMT_RGB24, w, h);

        int ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
        if (ret < 0) {
            tError() << "Error encoding video frame!";
            return false;
        }

        if (got_packet) {
            pkt.stream_index = video_st->index;
            ret = av_interleaved_write_frame(oc, &pkt);
        } else {
            ret = 0;
        }

Any suggestion about how to fix the FPS issue? Thanks!

--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Carl Eugen Hoyos-2
2017-03-05 2:52 GMT+01:00 Gustav González <[hidden email]>:

> QImage img = image.convertToFormat(Format_RGB888);

Not necessarily related: Why are you not using libswscale or
the scale filter?

> avpicture_fill((AVPicture *)frame, img.bits(), AV_PIX_FMT_RGB24, w, h);

FFmpeg's git encoder does not support RGB24, so whatever you are
doing is unfortunately not supported here.

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Gustavo González-4
2017-03-05 8:43 GMT-05:00 Carl Eugen Hoyos <[hidden email]>:
2017-03-05 2:52 GMT+01:00 Gustav González <[hidden email]>:

> QImage img = image.convertToFormat(Format_RGB888);

Not necessarily related: Why are you not using libswscale or
the scale filter?

In fact, I tried it using different parameters for a week. That was my first approach to the problem, but always I got an error message from the encoder, telling me that the AVFrame format was wrong.  
Looking for a solution, I found this alternative that only requires two lines to get an accurate AVFrame. All I can say about it, is that it's working.
 

> avpicture_fill((AVPicture *)frame, img.bits(), AV_PIX_FMT_RGB24, w, h);

FFmpeg's git encoder does not support RGB24, so whatever you are
doing is unfortunately not supported here.

Someone told me the same. So I started to use the format AV_FIX_FMT_RGB8. The funny thing was that while I was running my program, I got a (red) warning message from the libav API, asking me to use RGB24. I already checked the gif.c code, and effectively there is NOT support for RGB24. I can't explain it.

Counting on I have been researching about this topic for around a month, testing all the logic suggestions and the crazy ones, I decided to change the format to RGB24, following the libav warning advice. Crazy or not, the warning message disappeared and the code works, I mean, I got an animated GIF from a sequence of QImage objects.

About the pending issue, I thought it was related to the FPS variable of the files but I was wrong, the problem is the size of them, they are giants! (MBs for every second) So large, that the browser only can play them slowly. I ran other tests using mplayer and the speed of the animations is right.

So, my next challenge is to low the size of the frames to finish my implementation. Any hint?

--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Carl Eugen Hoyos-2
2017-03-06 1:44 GMT+01:00 Gustav González <[hidden email]>:

> So, my next challenge is to low the size of the frames to finish my
> implementation. Any hint?

Yes, please see my last two emails in this thread.

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Gustavo González-4
2017-03-05 20:46 GMT-05:00 Carl Eugen Hoyos <[hidden email]>:
2017-03-06 1:44 GMT+01:00 Gustav González <[hidden email]>:

> So, my next challenge is to low the size of the frames to finish my
> implementation. Any hint?

Yes, please see my last two emails in this thread.

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user


Getting back to the libswscale approach, I was trying to transform the QImage sequence into AVFrame variables:

        QImage image(path_to_image);
        AVPicture picture;
        avpicture_alloc(&picture, PIX_FMT_RGB32, w, h);
        memcpy(picture.data[0], image.bits(), w*h*4);

        QVector<int> strides(image.height(), image.bytesPerLine());
        struct SwsContext *sws_context = sws_getContext(w, h, PIX_FMT_RGB32, w, h, AV_PIX_FMT_RGB8, SWS_BICUBIC, NULL, NULL, NULL);
        sws_scale(sws_context, picture.data, picture.linesize, 0, h, frame->data, frame->linesize);

Is this code something similar or related to your suggestion? Thanks.

--
============================
  Gustav Gonzalez
  [hidden email]
============================

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: GIF API access

Carl Eugen Hoyos-2
2017-03-06 5:56 GMT+01:00 Gustav González <[hidden email]>:
> 2017-03-05 20:46 GMT-05:00 Carl Eugen Hoyos <[hidden email]>:
>>
>> 2017-03-06 1:44 GMT+01:00 Gustav González <[hidden email]>:
>>
>> > So, my next challenge is to low the size of the frames to finish my
>> > implementation. Any hint?
>>
>> Yes, please see my last two emails in this thread.

To repeat and evaluate:
Current FFmpeg does not support RGB24 in gif.
I don't know if you are using other software or an
old version of FFmpeg, in both cases, you cannot
get support here.
This is the first issue you have to solve: Either update
to current FFmpeg or get support somewhere else.
And yes, you have guessed correctly that PAL8
ensures a smaller file size.

> Getting back to the libswscale approach, I was trying to transform the
> QImage sequence into AVFrame variables:
>
>         QImage image(path_to_image);
>         AVPicture picture;
>         avpicture_alloc(&picture, PIX_FMT_RGB32, w, h);

>         memcpy(picture.data[0], image.bits(), w*h*4);

Unrelated: I suggest you try to avoid the memcpy().

>
>         QVector<int> strides(image.height(), image.bytesPerLine());

>         struct SwsContext *sws_context = sws_getContext(w, h, PIX_FMT_RGB32,
> w, h, AV_PIX_FMT_RGB8, SWS_BICUBIC, NULL, NULL, NULL);

It is not so easy to get palettised data. It is a two-step process
involving the paletteget and paletteuse filter, see for example:
http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html
Please try with ffmpeg (the application) first to find out if
this is really worth the effort (and if you need to program
something instead of calling the application).

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Loading...