FFmpeg4.0笔记:rtsp2rtmp
Github
https://github.com/gongluck/FFmpeg4.0-study.git
#include <iostream>
using namespace std;
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/time.h"
}
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")
char av_error[AV_ERROR_MAX_STRING_SIZE] = { 0 };
#define av_err2str(errnum) \
av_make_error_string(av_error, AV_ERROR_MAX_STRING_SIZE, errnum)
#define INFILE "in.flv"
#define RTMP "rtmp://192.168.140.128/live/test"
#define RTSP "rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"
int file2rtmp()
{
int ret = 0;
//封装上下文
AVFormatContext* ictx = nullptr;
AVFormatContext* octx = nullptr;
const char* iurl = INFILE;
const char* ourl = RTMP;
int64_t starttime;
ret = avformat_network_init();
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//打开文件,解封文件头
ret = avformat_open_input(&ictx, iurl, nullptr, nullptr);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
cerr << "open file " << iurl << " success." << endl;
//获取音视频流信息,h264 flv
ret = avformat_find_stream_info(ictx, nullptr);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//打印媒体信息
av_dump_format(ictx, 0, iurl, 0);
//////////////////////////////
//输出流
ret = avformat_alloc_output_context2(&octx, av_guess_format(nullptr, INFILE, nullptr), nullptr, ourl);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
cout << "octx create success." << endl;
//配置输出流
for (int i = 0; i < ictx->nb_streams; ++i)
{
//创建流
AVStream* ostream = avformat_new_stream(octx, avcodec_find_encoder(ictx->streams[i]->codecpar->codec_id));
if (ostream == nullptr)
goto END;
//复制配置信息
ret = avcodec_parameters_copy(ostream->codecpar, ictx->streams[i]->codecpar);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
ostream->codecpar->codec_tag = 0;//标记不需要重新编解码
}
av_dump_format(octx, 0, ourl, 1);
//////////////////////////////
//推流
ret = avio_open2(&octx->pb, ourl, AVIO_FLAG_WRITE, nullptr, nullptr);
if (ret < 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//写入头信息
ret = avformat_write_header(octx, nullptr);
if (ret < 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//推流每一帧数据
AVPacket pkt;
starttime = av_gettime();
while (av_read_frame(ictx, &pkt) == 0)
{
//计算转换pts dts
AVRational itime = ictx->streams[pkt.stream_index]->time_base;
AVRational otime = octx->streams[pkt.stream_index]->time_base;
pkt.pts = av_rescale_q_rnd(pkt.pts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q_rnd(pkt.duration, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.pos = -1;
if (ictx->streams[pkt.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
int64_t nowtime = av_gettime() - starttime;
int64_t dts = pkt.dts * av_q2d(octx->streams[pkt.stream_index]->time_base) * 1000 * 1000;
if(dts > nowtime)
/*av_usleep(dts- nowtime)*/;
}
ret = av_interleaved_write_frame(octx, &pkt);
av_packet_unref(&pkt);
if (ret < 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
}
ret = av_write_trailer(octx);//写文件尾
if (ret < 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
END:
if (ictx != nullptr)
avformat_close_input(&ictx);
if (octx != nullptr)
{
avio_close(octx->pb);
avformat_free_context(octx);
}
ret = avformat_network_deinit();
if (ret != 0)
cout << av_err2str(ret) << endl;
return 0;
}
int rtsp2rtmp()
{
int ret = 0;
//封装上下文
AVFormatContext* ictx = nullptr;
AVFormatContext* octx = nullptr;
const char* iurl = RTSP;
const char* ourl = RTMP;
int64_t starttime;
ret = avformat_network_init();
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//打开文件,解封文件头
ret = avformat_open_input(&ictx, iurl, nullptr, nullptr);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
cerr << "open file " << iurl << " success." << endl;
//获取音视频流信息,h264 flv
ret = avformat_find_stream_info(ictx, nullptr);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//打印媒体信息
av_dump_format(ictx, 0, iurl, 0);
//////////////////////////////
//输出流
ret = avformat_alloc_output_context2(&octx, av_guess_format(nullptr, INFILE, nullptr), nullptr, ourl);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
cerr << "octx create success." << endl;
//配置输出流
for (int i = 0; i < ictx->nb_streams; ++i)
{
//创建流
AVStream* ostream = avformat_new_stream(octx, avcodec_find_encoder(ictx->streams[i]->codecpar->codec_id));
if (ostream == nullptr)
return -1;
//复制配置信息
ret = avcodec_parameters_copy(ostream->codecpar, ictx->streams[i]->codecpar);
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
ostream->codecpar->codec_tag = 0;//标记不需要重新编解码
}
av_dump_format(octx, 0, ourl, 1);
//////////////////////////////
//推流
if (ret != 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
ret = avio_open(&octx->pb, ourl, AVIO_FLAG_WRITE);
if (ret < 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//写入头信息
ret = avformat_write_header(octx, nullptr);
if (ret < 0)
{
cout << av_err2str(ret) << endl;
goto END;
}
//推流每一帧数据
AVPacket pkt;
starttime = av_gettime();
while (av_read_frame(ictx, &pkt) == 0)
{
//计算转换pts dts
AVRational itime = ictx->streams[pkt.stream_index]->time_base;
AVRational otime = octx->streams[pkt.stream_index]->time_base;
pkt.pts = av_rescale_q_rnd(pkt.pts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q_rnd(pkt.duration, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.pos = -1;
ret = av_interleaved_write_frame(octx, &pkt);
av_packet_unref(&pkt);
if (ret < 0)
cout << av_err2str(ret) << endl;//不用退出
}
END:
if (ictx != nullptr)
avformat_close_input(&ictx);
if (octx != nullptr)
{
avio_close(octx->pb);
avformat_free_context(octx);
}
ret = avformat_network_deinit();
if (ret != 0)
cout << av_err2str(ret) << endl;
return 0;
}
int main()
{
//file2rtmp();
rtsp2rtmp();
system("pause");
return 0;
}
FFmpeg4.0笔记:rtsp2rtmp的更多相关文章
- FFmpeg4.0笔记:file2rtmp
Github: https://github.com/gongluck/FFmpeg4.0-study.git #include <iostream> using namespace st ...
- FFmpeg4.0笔记:封装ffmpeg的解封装功能类CDemux
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDemux.h /*********************** ...
- FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CSws.h /************************* ...
- FFmpeg4.0笔记:封装ffmpeg的音频重采样功能类CSwr
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CSwr.h /************************* ...
- FFmpeg4.0笔记:封装ffmpeg的解码功能类CDecode
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDecode.h /********************** ...
- FFmpeg4.0笔记:本地媒体文件解码、帧格式转换、重采样、编码、封装、转封装、avio、硬解码等例子
Github https://github.com/gongluck/FFmpeg4.0-study/blob/master/official%20example/my_example.cpp #in ...
- FFmpeg4.0笔记:采集系统声音
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff // 采集系统声音 void test_systemsound() ...
- FFmpeg4.0笔记:采集桌面
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff // 采集桌面 void test_desktop() { boo ...
- FFmpeg4.0笔记:VS2019编译FFmpeg4.0源码
0.下载TDM.msys和yasm 1.安装TDM-GCC-64 2.安装msys到TDM-GCC的安装目录中 3.将call "C:\Program Files (x86)\Microso ...
随机推荐
- UI设计初学者必看,这款设计神器教你快速入门
网络时代,网页和手机App已经深入到人们生活的方方面面.这也使得App界面设计越来越受青年求职者们的青睐,并纷纷投入这个行业.但是,作为UI设计初学者,究竟如何才能快速的入门?当今市场上,是否有那么一 ...
- jmeter使用HTTP代理服务器
浏览器>web服务器 浏览器>HTTP代理服务器>web服务器 jmeter>HTTP代理服务器>web服务器 浏览器>jmeter HTTP服务器>web服 ...
- android 使用UDP发送数据 DatagramSocket 创建对象为null
DatagramSocket socket=null; try { socket = new DatagramSocket(); //这里创建对象为空 } catch (SocketExceptio ...
- Tomcat优化详细1
在Tomcat和应用程序进行了压力测试后,如果您对应用程序的性能结果不太满意,就可以采取一些性能调整措施了,当然了前提是应用程序没有问题,我们这里只讲Tomcat的调整.由于Tomcat的运行依赖于J ...
- 旅行家的预算(NOIP1999&水题测试2017082301)
题目链接:旅行家的预算 这题还可以,不算太水. 这题贪心即可. 我们采取如下动作: 如果在装满油的情况下能到达的范围内,没有加油站,则无解. 如果在装满油的情况下能到达的范围内,油价最低的加油站的油价 ...
- hdu-6058 Kanade's sum
题意:略 思路:要我们求每个区间第K大数之和,其实可以转换为求多少个区间的第K大数是X,然后我们在求和就好了. 那么我们可以从小到大枚举所有可能成为第K大的数.为什么从小到大呢? 因为从小到大我们就略 ...
- python早期看书笔记
- ORA-38301:can not perform DDL/DML over objects in Recycle Bin
一个智障操作,drop一个用户,下面的东西比较多,删得比较慢,然后shell突然关了. 就导致了,删不掉,又不能创建新的用户.出版本要得比较急,就先创建新的用户测试去了. 今天要弄个东西,又想起这个事 ...
- 2019.01.14 bzoj5343: [Ctsc2018]混合果汁(整体二分+权值线段树)
传送门 整体二分好题. 题意简述:nnn种果汁,每种有三个属性:美味度,单位体积价格,购买体积上限. 现在有mmm个询问,每次问能否混合出总体积大于某个值,总价格小于某个值的果汁,如果能,求所有方案中 ...
- 2019.01.13 loj#6515. 贪玩蓝月(线段树分治+01背包)
传送门 题意简述:有一个初始为空的双端队列,每次可以在队首和队尾插入或弹出一个二元组(wi,vi)(w_i,v_i)(wi,vi),支持询问从当前队列中选取若干个元素是的他们的和对 MODMODM ...