zoukankan      html  css  js  c++  java
  • FFmpeg4.0笔记:file2rtmp

    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 main()
    {
    	file2rtmp();
    	system("pause");
    	return 0;
    }
    
  • 相关阅读:
    Power BI 根据用户权限动态生成导航跳转目标
    Power BI Tooltips 增强功能
    Power BI refresh error “could not load file or assembly…provided impersonation level is invalid”
    SQL 错误代码 18456
    如何使用SQL Server Integration Services从多个Excel文件读取数据
    通过表格编辑器将现有表引入Power BI数据流
    Power BI 中动态增长的柱状图
    ambari2.7.3离线安装hdp3.1.0时,ambari-hdp-1.repo中baseurl无值
    ambari 安装 cannot download file mysql-connector-java from http://8080/resource/mysql-connector-java.jar
    洛谷P4180 [BJWC2010]严格次小生成树
  • 原文地址:https://www.cnblogs.com/gongluck/p/9027163.html
Copyright © 2011-2022 走看看