How to modify the bit_rate of AVFormatContext?

140 Views Asked by At

Hello,I would like to know how to modify the bit_rate of AVFormatContext.

Here is the minimal reproducible example.This is a simple process for pushing rtmp video streams.Now I want to control the bitrate of the video it pushes.

I tried modifying the bitrate like this, but it didn't work.

AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
int64_t bit_rate = 400*1000;
....
ofmt_ctx->bit_rate = bit_rate;

Can be compiled by g++ -Wall -o -g -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/local/include -L/usr/local/lib simplt_push_streaming.cpp -o test.out -lavformat -lavcodec -lavutil -lgobject-2.0 -lglib-2.0 -lpthread

And my ffmpeg version: ffmpeg version 4.4.2-0ubuntu0.22.04.1

#include <stdio.h>
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
};

int main(int argc, char* argv[])
{
    AVOutputFormat *ofmt = NULL;
    //Input AVFormatContext and Output AVFormatContext
    AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
    AVPacket pkt;
    const char *in_filename, *out_filename;
    int ret, i;
    int videoindex=-1;
    int frame_index=0;
    int64_t start_time=0;
    int64_t bit_rate = 400*1000;
    in_filename  = "/home/zion/video/mecha.flv";// Input file URL
    out_filename = "rtmp://localhost:1935/live/test";//Output URL [RTMP]
    av_register_all();
    avformat_network_init();
    avformat_open_input(&ifmt_ctx, in_filename, 0, 0);
    avformat_find_stream_info(ifmt_ctx, 0);
    for(i=0; i<ifmt_ctx->nb_streams; i++) 
        if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
            videoindex=i;
            break;
        }
    //Output
    avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename); //RTMP
    ofmt = ofmt_ctx->oformat;
    for (i = 0; i < ifmt_ctx->nb_streams; i++) {
        //Create output AVStream according to input AVStream
        AVStream *in_stream = ifmt_ctx->streams[i];
        AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
        //Copy the settings of AVCodecContext
        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
        out_stream->codec->codec_tag = 0;
        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    }
    //Open output URL
    if (!(ofmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
    }
    //Write file header
    avformat_write_header(ofmt_ctx, NULL);
    start_time=av_gettime();
    while (1) {
        AVStream *in_stream, *out_stream;
        //Get an AVPacket
        ret = av_read_frame(ifmt_ctx, &pkt);
        if (ret < 0)
            break;
        //Important:Delay
        if(pkt.stream_index==videoindex){
            AVRational time_base=ifmt_ctx->streams[videoindex]->time_base;
            AVRational time_base_q={1,AV_TIME_BASE};
            int64_t pts_time = av_rescale_q(pkt.dts, time_base, time_base_q);
            int64_t now_time = av_gettime() - start_time;
            if (pts_time > now_time)
                av_usleep(pts_time - now_time);
        }
        in_stream  = ifmt_ctx->streams[pkt.stream_index];
        out_stream = ofmt_ctx->streams[pkt.stream_index];
        if(pkt.stream_index==videoindex){
            printf("Send %8d video frames to output URL\n",frame_index);
            frame_index++;
        }
/*I tried modifying the bitrate here and I'm not sure if this is the correct usage.*/
        ofmt_ctx->bit_rate = bit_rate;
        av_interleaved_write_frame(ofmt_ctx, &pkt);
        av_free_packet(&pkt);
    }
    //Write file trailer
    av_write_trailer(ofmt_ctx);
end:
    avformat_close_input(&ifmt_ctx);
    /* close output */
    if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
        avio_close(ofmt_ctx->pb);
    avformat_free_context(ofmt_ctx);
    return 0;
}
0

There are 0 best solutions below