FFmpeg5.0.1 代码读取MP4视频推送RTMP流
Posted Leonban
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFmpeg5.0.1 代码读取MP4视频推送RTMP流相关的知识,希望对你有一定的参考价值。
当下代码在FfmpegTest类创建实例时调用
可根据实际情况在main()函数中调用videoPlay(pszFile, pszRTMPURL)。
源代码分享
#include "ffmpegtest.h"
#include <iostream>
#include <QDebug>
using namespace std;
extern "C"
#include <libavcodec/avcodec.h>
#include "libavformat/avformat.h"
#include "libavutil/time.h"
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
void XError(int errNum)
char buf[1024] = 0 ;
av_strerror(errNum, buf, sizeof(buf));
cout << buf << endl;
getchar();
static double r2d(AVRational r)
return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;
FfmpegTest::FfmpegTest(QWidget *parent)
: QMainWindow(parent)
ui.setupUi(this);
//主函数调用部分
const char* pszFile = "D:/work/Ffmpeg/ffmpeg_code/guduyueqiu.mp4";
const char* pszRTMPURL = "rtmp://192.168.3.10/live/livestream";
videoPlay(pszFile, pszRTMPURL);
void FfmpegTest::videoPlay(const char* pszFile, const char* pszRTMPURL)
int nVideoIndex = -1;
avformat_network_init();
AVFormatContext* pInputAVFormatContext = NULL;
int nRet = avformat_open_input(&pInputAVFormatContext, pszFile, 0, NULL);
if (nRet < 0)
XError(nRet);
nRet = avformat_find_stream_info(pInputAVFormatContext, 0);
if (nRet != 0)
XError(nRet);
av_dump_format(pInputAVFormatContext, 0, pszFile, 0);
AVFormatContext* pOutputAVFormatContext = NULL;
nRet = avformat_alloc_output_context2(&pOutputAVFormatContext, NULL, "flv", pszRTMPURL);
if (nRet < 0)
XError(nRet);
for (int i = 0; i < pInputAVFormatContext->nb_streams; i++)
AVStream* pInputAVStream = pInputAVFormatContext->streams[i];
AVStream* pOutputAVStream = avformat_new_stream(pOutputAVFormatContext, 0);
nRet = avcodec_parameters_copy(pOutputAVStream->codecpar, pInputAVStream->codecpar);
if (nRet < 0)
XError(nRet);
pOutputAVStream->codecpar->codec_tag = 0;
for (int i = 0; i < pInputAVFormatContext->nb_streams; i++)
if (pInputAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
nVideoIndex = i;
break;
av_dump_format(pOutputAVFormatContext, 0, pszRTMPURL, 1);
nRet = avio_open(&pOutputAVFormatContext->pb, pszRTMPURL, AVIO_FLAG_WRITE);
if (nRet < 0)
XError(nRet);
nRet = avformat_write_header(pOutputAVFormatContext, 0);
if (nRet < 0)
XError(nRet);
AVPacket pkt;
std::int64_t llStartTime = av_gettime();
std::int64_t llFrameIndex = 0;
while (true)
AVStream* pInputStream = NULL;
AVStream* pOutputStream = NULL;
nRet = av_read_frame(pInputAVFormatContext, &pkt);
if (nRet < 0)
break;
if (pkt.pts == AV_NOPTS_VALUE)
AVRational timeBase = pInputAVFormatContext->streams[nVideoIndex]->time_base;
std::int64_t llCalcDuration = (double)AV_TIME_BASE / av_q2d(pInputAVFormatContext->streams[nVideoIndex]->r_frame_rate);
pkt.pts = (double)(llFrameIndex * llCalcDuration) / (double(av_q2d(timeBase)*AV_TIME_BASE));
pkt.dts = pkt.pts;
pkt.duration = (double)llCalcDuration / (double)(av_q2d(timeBase)*AV_TIME_BASE);
if (pkt.stream_index == nVideoIndex)
AVRational timeBase = pInputAVFormatContext->streams[nVideoIndex]->time_base;
AVRational timeBaseQ = 1, AV_TIME_BASE ;
std::int64_t pts_time = av_rescale_q(pkt.dts, timeBase, timeBaseQ);
std::int64_t now_time = av_gettime() - llStartTime;
AVRational avr = pInputAVFormatContext->streams[nVideoIndex]->time_base;
if (pts_time > now_time)
av_usleep((unsigned int)(pts_time - now_time));
pInputStream = pInputAVFormatContext->streams[pkt.stream_index];
pOutputStream = pOutputAVFormatContext->streams[pkt.stream_index];
pkt.pts = av_rescale_q_rnd(pkt.pts, pInputStream->time_base, pOutputStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, pInputStream->time_base, pOutputStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.duration = (int)av_rescale_q(pkt.duration, pInputStream->time_base, pOutputStream->time_base);
pkt.pos = -1;
if (pkt.stream_index == nVideoIndex)
llFrameIndex++;
nRet = av_interleaved_write_frame(pOutputAVFormatContext, &pkt);
if (nRet < 0)
std::cout << "发送数据包出错" << std::endl;
break;
av_packet_unref(&pkt);
av_write_trailer(pOutputAVFormatContext);
if (!(pOutputAVFormatContext->oformat->flags & AVFMT_NOFILE))
avio_close(pOutputAVFormatContext->pb);
avformat_free_context(pOutputAVFormatContext);
avformat_close_input(&pInputAVFormatContext);
效果展示
以上是关于FFmpeg5.0.1 代码读取MP4视频推送RTMP流的主要内容,如果未能解决你的问题,请参考以下文章