-1

I try to encode single pictures to a .avi video. The goal is to have every picture displayed for a set amount of seconds to create a slide show. I tried my script with 10 pictures and a delay of 1/5 of a second but the output file was not even half a second long (but displayed every picture). For setting the framerate I use the time_base option of the AVCodeContext:

ctx->time_base = (AVRational) {1, 5};

When I use the command ffmpeg -framerate 1/3 -i img%03d.png -codec png output.avi everything works fine and I get the file I want. I use the png codec because it was the only one i tried that is playable with Windows Media Player.

Am I missing anything here? Is there another option that has impact on the framerate?

This is my code so far:

Note: I use a couple of self made data structures and methodes from other classes. They are the ones written in Caps Lock. They basicly do what the name suggests but are necessary for my project. The Input Array contains the pictures that i want to encode.

include <libavutil/opt.h>
include <libavutil/imgutils.h>
include <libavutil/error.h>

void PixmapsToAVI (ARRAY* arr, String outfile, double secs)
{
     if (arr!=nil && outfile!="" && secs!=0) {
         AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_PNG);
         if (codec) {
             int width  = -1;
             int height = -1;
             int ret = 0;

             AVCodecContext* ctx = NULL;
             ctx = avcodec_alloc_context3(codec);
             AVFrame* frame = av_frame_alloc();
             AVPacket* pkt  = av_packet_alloc();

             FILE* file = fopen(outfile, "wb");

             ARRAYELEMENT* e;
             int count = 0;
             forall (e, *arr) {
                 BITMAP bitmap (e->value, false);
                 if (width < 0) {
                     width  = bitmap.Width();
                     height = bitmap.Height();

                     ctx->width = width;
                     ctx->height = height;
                     ctx->time_base = (AVRational){1, 5};
                     ctx->framerate = (AVRational){5, 1};
                     ctx->pix_fmt = AV_PIX_FMT_RGB24;
                     ret = avcodec_open2(ctx, codec, NULL);

                     frame->width  = width;
                     frame->height = height;
                     frame->format = ctx->pix_fmt;
                     av_opt_set(ctx->priv_data, "preset", "slow", 1);

                 }
                 ret  = av_frame_get_buffer(frame, 1);
                 frame->linesize[0] = width*3;

                 bitmap.Convert32();
                 byte* pixels = bitmap.PixelsRGB();      

//The two methodes above convert the Pixmap into the RGB structure we need
//They are not needed to get an output file but are needed to get one that makes sense

                     fflush(stdout);
                     int writeable = av_frame_make_writable(frame);
                     if (writeable>=0) {
                         for(int i=0; i<(height*width*3); i++){
                             frame->data[0][i] = pixels[i];
                         }
                     }
                     ret = avcodec_send_frame(ctx, frame);
                     for(int i=0; i<secs; i++){
                         fflush(stdout);
                         avcodec_send_frame(ctx, frame);
                     }
                     while (ret >= 0) {
                       ret = avcodec_receive_packet(ctx, pkt);
                     }
                     count++;
                 avcodec_receive_packet(ctx, pkt);
                 fwrite(pkt->data, 1, pkt->size, file);
                 fflush(stdout);
                 av_packet_unref(pkt);
             }
             fclose(file);
             avcodec_free_context(&ctx);
             av_frame_free(&frame);
             av_packet_free(&pkt);

         }
     }
} 






1 Answers1

0

png codec because it was the only one i tried that is playable with Windows Media Player.

try to install k-lite codec pack for media player, it can help to display other format https://codecguide.com/download_k-lite_codec_pack_basic.htm

I tried my script with 10 pictures and a delay of 1/5 of a second but the output file was not even half a second long (but displayed every picture).

ctx->time_base = (AVRational) {1, 5};

/* frames per second */
c->time_base = (AVRational){1, 25};
c->framerate = (AVRational){25, 1};

please take a look at below reference may help you https://libav.org/documentation/doxygen/master/encode_video_8c-example.html#a25

  • Tank you for your answer. I already spend hours looking at the libav documentation and examples but they weren't helpful for me. Maybe I'm missing something there but as I see it I copied the way they set the framerate in the example and it didn't work. I tried your idea using the additional codec pack but it didn't work either. I tried the WMV2 codec but im not sure that it is the right one for the pack. Do you have any suggestions which codec to use? – Tobias v. Brevern Jun 02 '20 at 13:52
  • I am sorry that I cant provide more help to you in C. Would you mind to use C# which can provide same function to you? https://stackoverflow.com/questions/9744026/image-sequence-to-video-stream and https://stackoverflow.com/questions/39625554/single-image-to-video-in-c-sharp these 2 pages have helped me to finish the same stuff before, hope it helps. – Oving Cheng Jun 03 '20 at 02:15