ffmpeg 推流 flv

//打开格式进行解封装


1.avformat_open_input(
AVFormatContext **ps, //打开文件的上下文
const char *url,//文件的路径
AVInputFormat *fmt,
AVDictionary **options
)

AVFormatContext


封装格式的上下文
AVIOContext *pb; IO上下文
AVStream x**streams; //视频音频字幕流
int nb_streams; 

AVStream



AVRational time_base;
AVCodecParameters *codecpar; (( 音视频参数 ))
AVCodecContext *codec;

AVPacket


int64_t pts; //pts * (num / den)
int64_t dts; 
uint8_t *data;int size;
int stream_index;
int flags;

CMakeLists.txt


cmake_minimum_required(VERSION 3.4.1)
project(ffmpeg_pro VERSION 0.1.0 LANGUAGES CXX C)
##配置 预编译库 如ffmpeg库 路径
 
# find_library(AVCODEC_LIBRARY avcodec)
# find_library(AVFORMAT_LIBRARY avformat)
# find_library(AVUTIL_LIBRARY avutil)
# find_library(AVDEVICE_LIBRARY avdevice)
##加入预编译库的头文件 如ffmpeg库 的头文件
#include_directories(include)

add_executable(ffmpeg_pro main.cpp)
message(STATUS ${AVCODEC_LIBRARY})

target_link_libraries(
	ffmpeg_pro  
	pthread 
	swresample 
	m 
	swscale 
	avformat	
	avcodec 
	avutil 
	avfilter 
	avdevice 
	postproc 
	z 
	lzma  
	rt)

main.cpp


extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/time.h>
}
#include <iostream>
using namespace std;

int XError(int errNum)
{
	char buf[1024] = {0};
	av_strerror(errNum,buf,sizeof(buf));
	cout<<buf<<endl;
	return -1;
}


static double r2d(AVRational r)
{
	return r.num == 0 || r.den == 0?0. : (double)r.num/(double)r.den;
}

int main()
{
	cout<<"file to rtmp test"<<endl;
	char *inUrl = "test.flv";
	char *outUrl = "rtmp:/0.0.0.0/live";


	//初始化所有的封装和解封装 flv mp4 mov mp3
	av_register_all();

	//初始化网络库
	avformat_network_init();
	输入处理部分
	//1.打开文件,解封装
	//输入解封装的上下文
	AVFormatContext *ictx = NULL;
	
	//打开文件解封文件头
	int re = avformat_open_input(&ictx, inUrl,0,0);
	if(re != 0)
	{
 		return XError(re);
	}
	cout<<"open file "<<inUrl<<"Success "<<endl;

	//获取音视频流信息,h264 flv	
	re = avformat_find_stream_info(ictx,0);
	if(re != 0)
	{
 		return XError(re);
	}
	av_dump_format(ictx,0,inUrl,0);

	
	//输出流
	//创建输出流上下文
	AVFormatContext *octx = NULL;
	//对于文件可以知道输出文件格式可以不用传"flv"
	//流媒体需要指定输出格式
	avformat_alloc_output_context2(&octx,0,"flv",outUrl);
	if(!octx)
	{
		return XError(re);
	}
	cout<<"octx create Success"<<endl;

	//配置输出流
	//遍历输入的AVStream
	for(int i = 0; i < ictx->nb_streams; i++)
	{
		//创建输出流
		AVStream *out = avformat_new_stream(octx,ictx->streams[i]->codec->codec);
		if(!out)
		{
			return XError(0);
		}
		//复制配置信息 用于mp4 ffmpeg 不支持但是也会封装,流媒体服务器支持
		//avcodec_copy_context(out->codec,ictx->streams[i]->codec);
		//Output #0, flv, to 'rtmp:/0.0.0.0/live':
		//Stream #0:0: Unknown: none
		//Stream #0:1: Unknown: none

		re = avcodec_parameters_copy(out->codecpar,ictx->streams[i]->codecpar);
		out->codec->codec_tag = 0;
	}
	av_dump_format(octx,0,outUrl,1);
	

	//rtmp推流

	//打开io
	re = avio_open(&octx->pb,outUrl,AVIO_FLAG_WRITE);
	if(!octx->pb)
	{
		return XError(re);
	}

	//写入头信息
	re = avformat_write_header(octx,0);
	if(re < 0)
	{
		return XError(re);
	}
	cout<<"avformat_write_header "<<re<<endl;

	//推流每一帧数据
	AVPacket pkt;
	long long startTime = av_gettime();
	for(;;)
	{
		//ictx 输入流的格式上下文
		//需要释放空间
		re = av_read_frame(ictx,&pkt);
		if(re != 0)
		{
			break;
		}
		cout<<pkt.pts<<" "<<flush;
		//计算转换pts dts
		AVRational itime = ictx->streams[pkt.stream_index]->time_base;
		AVRational otime = octx->streams[pkt.stream_index]->time_base;
		//pkt.pts itime 原time_base
		//otime	输出的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)
		{
			AVRational tb = ictx->streams[pkt.stream_index]->time_base;
			//time_base 指一秒钟有tb.num / tb.den单位
			//已经过去的时间
			long long now = av_gettime() - startTime;
			long long dts = 0;
			//读取时间比发送时间快
			dts = pkt.dts * (1000 * 1000 *  r2d(tb));
			if(dts > now)
				av_usleep(dts - now);
		}

		re = av_interleaved_write_frame(octx,&pkt);

		if(re < 0)
		{
			return XError(re);
		}
		//av_packet_unref(&pkt);
	}
	return 0;
}



运行


xz@xiaqiu:~/study/csdn/rtmp/file_to_rtmp/build$ ./ffmpeg_pro 
file to rtmp test
open file test.flvSuccess 
Input #0, flv, from 'test.flv':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
  Duration: 00:00:26.10, start: 0.000000, bitrate: 4600 kb/s
    Stream #0:0: Audio: mp3, 48000 Hz, stereo, fltp, 128 kb/s
    Stream #0:1: Video: flv1, yuv420p, 1366x768, 200 kb/s, 30 fps, 30 tbr, 1k tbn
octx create Success
Output #0, flv, to 'rtmp:/0.0.0.0/live':
    Stream #0:0: Audio: mp3, 48000 Hz, stereo, fltp, 128 kb/s
    Stream #0:1: Video: flv1, yuv420p, 1366x768, q=2-31, 200 kb/s
avformat_write_header 0
0 23 24 48 56 72 90 96 120 123 144 156 168 190 192 216 223 240 256 264 288 290 312 323 336 356 360 384 390 408 423 432 456 456 480 490 504 523 528 552 556 576 590 600 623 624 648 656 672 690 696 720 723 744 756 768 790 792 816 823 840 856 864 888 890 912 923 936 956 960 984 990 1008 1023 1032 1056 1056 1080 1090 1104 1123 1128 1152 1156 1176 1190 1200 1223 1224 1248 1256 1272 1290 1296 1320 1323 1344 1356 1368 1390 1392 1416 1423 1440 1456 1464 1488 1490 1512 1523 1536 1556 1560 1584 1590 1608 1623 1632 1656 1656 1680 1690 1704 1723 1728 1752 1756 1776 1790 1800 1823 1824 1848 1856 1872 1890 1896 1920 1923 1944 1956 1968 1990 1992 2016 2023 2040 2056 2064 2088 2090 2112 2123 2136 2156 2160 2184 2190 2208 2223 2232 2256 2256 2280 2290 2304 2323 2328 2352 2356 2376 2390 2400 2423 2424 2448 2456 2472 2490 2496 2520 2523 2544 2556 2568 2590 2592 2616 2623 2640 2656 2664 2688 2690 2712 2723 2736 2756 2760 2784 2790 2808 2823 2832 2856 2856 2880 2890 2904 2923 2928 2952 2956 2976 2990 3000 3023 3024 3048 3056 3072 3090 3096 3120 3123 3144 3156 3168 3190 3192 3216 3223 3240 3256 3264 3288 3290 3312 3323 3336 3356 3360 3384 3390 3408 3423 3432 3456 3456 3480 3490 3504 3523 3528 3552 3556 3576 3590 3600 3623 3624 3648 3656 3672 3690 3696 3720 3723 3744 3756 3768 3790 3792 3816 3823 3840 3856 3864 3888 3890 3912 3923 3936 3956 3960 3984 3990 4008 4023 4032 4056 4056 4080 4090 4104 4123 4128 4152 4156 4176 4190 4200 4223 4224 4248 4256 4272 4290 4296 4320 4323 4344 4356 4368 4390 4392 4416 4423 4440 4456 4464 4488 4490 4512 4523 4536 4556 4560 4584 4590 4608 4623 4632 4656 4656 4680 4690 4704 4723 4728 4752 4756 4776 4790 4800 4823 4824 4848 4856 4872 4890 4896 4920 4923 4944 4956 4968 4990 4992 5016 5023 5040 5056 5064 5088 5090 5112 5123 5136 5156 5160 5184 5190 5208 5223 5232 5256 5256 5280 5290 5304 5323 5328 5352 5356 5376 5390 5400 5423 5424 5448 5456 5472 5490 5496 5520 5523 5544 5556 5568 5590 5592 5616 5623 5640 5656 5664 5688 5690 5712 5723 5736 5756 5760 5784 5790 5808 5823 5832 5856 ^C
xz@xiaqiu:~/study/csdn/rtmp/file_to_rtmp/build$ 

VLC 输入rtmp://0.0.0.0/live 播放

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值