Christoph
Christoph

Reputation: 1058

How to force an input frame rate on libav for mjpeg

I am using libav to parsing a MJPEG Stream to get the packet data for resending it over an websocket, now I am facing the issue that ffmpeg use only 25 FPS. I know the Stream has 60FPS for 100%

These are the values after open and read the stream Informations:

avg_frame_rate = 0, r_frame_rate = 25/1, time_base = 1/25

I tried to set all of them to a setting for 60FPS, but this looks has no effect. I have set time_base to 1/60 and also frame rates to 60 but none of them are making any difference.

Because its an MJPEG Stream libav needs to guess the framerate, but I don't know why setting time_base or framerate does not have any effect.

Maybe someone could help me how I could force 60 FPS for parsing an MJEPG Stream, this would be great.

Thank u

This is just an Illustration of my code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

int main(int argc, char *argv[]) {
    AVFormatContext *fmt_ctx = NULL;
    AVCodecContext *codec_ctx = NULL;
    AVCodec *codec = NULL;
    AVPacket pkt;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <mjpeg-stream-url>\n", argv[0]);
        exit(1);
    }

    av_register_all();

    if (avformat_open_input(&fmt_ctx, argv[1], NULL, NULL) < 0) {
        fprintf(stderr, "Could not open stream '%s'\n", argv[1]);
        exit(1);
    }

    if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
        fprintf(stderr, "Could not find stream information\n");
        exit(1);
    }

    int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);

    if (video_stream_index < 0) {
        fprintf(stderr, "Could not find video stream\n");
        exit(1);
    }

    AVStream *video_stream = fmt_ctx->streams[video_stream_index];
    stream->time_base = (AVRational) { 1, 60};
    stream->avg_frame_rate = (AVRational) { 60, 1 };
    stream->r_frame_rate = (AVRational) { 60, 1 };

    av_init_packet(&pkt);

    while (av_read_frame(fmt_ctx, &pkt) >= 0) {
        if (pkt.stream_index == video_stream_index) {
            // Sending it to an websocket ....
        }
        av_packet_unref(&pkt);
    }

    avformat_close_input(&fmt_ctx);
    avformat_free_context(fmt_ctx);

    return 0;
}

Upvotes: 0

Views: 538

Answers (1)

Mehmet YILMAZ
Mehmet YILMAZ

Reputation: 111

The AVDictionary sets additional/specific parameters to endpoints and if you call it while opening the endpoint, it uses these specific parameters to open the endpoint.

It could take multiple key - value pairs and applies all of them to the endpoint.

I suppose creating an AVDictionay and passing a "framerate", "60" or may be "framerate" "60000/1000" parameter could solve your problem. Or if your source supports format_code then you could also use the format code something like "format_code", "Hp60" in the AVDictionary.

AVDictionary *options{nullptr};

// You should find the right parameter name 
// like "frame_rate", "format_code", "sample_rate" etc. 
// You can also set multiple options there! 
// you may put all the possibilities once!

if(av_dict_set(&options, "framerate", "60", 0) < 0) {
        fprintf(stderr, "Could not set the option!\n");
        exit(1);
}

if (avformat_open_input(&fmt_ctx, argv[1], NULL, &options) < 0) {
        fprintf(stderr, "Could not open stream '%s'\n", argv[1]);
        exit(1);
}

Upvotes: 0

Related Questions