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;
}