c
复制代码
extern "C"{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/time.h"
};
#include <iostream>
void printErr(int errNum);
static double r2d(AVRational r){
return (r.num == 0 || r.den == 0) ? 0.0 : (double)r.num / (double)r.den;
}
int main(){
//初始化网络库以及网络加密协议相关的库
avformat_network_init();
//打开文件, 解封文件头
AVFormatContext *inContext = NULL;
char *inFile = "001.mp4";
int ret = avformat_open_input(&inContext, inFile, 0, 0);
if(ret != 0){
printErr(ret);
return -1;
}
std::cout<<"avformat_open_input success"<<std::endl;
//获取音视频流信息
ret = avformat_find_stream_info(inContext, 0);
if(ret != 0){
printErr(ret);
return -1;
}
std::cout<<"avformat_find_stream_info success"<<std::endl;
//打印信息
av_dump_format(inContext, 0, inFile, 0);
//输出流
AVFormatContext *outContext;
char *outFile = "rtmp://192.168.206.131:10088/live";
ret = avformat_alloc_output_context2(&outContext, 0, "flv", outFile);
if(outContext == 0){
printErr(ret);
return -1;
}
std::cout<<"avformat_alloc_output_context2 success"<<std::endl;
//配置输出流
//遍历输入的AVStream
for(int i = 0; i < inContext->nb_streams; i++){
AVStream *outStream = avformat_new_stream(outContext, NULL);
if(outStream == NULL){
printErr(-1);
return -1;
}
//复制配置信息
ret = avcodec_parameters_copy(outStream->codecpar, inContext->streams[i]->codecpar);
if(ret < 0){
printErr(ret);
return -1;
}
outStream->codecpar->codec_tag = 0;
}
//输出
av_dump_format(outContext, 0, outFile, 1);
//rtmp推流
//打开io
ret = avio_open(&outContext->pb, outFile, AVIO_FLAG_WRITE);
if(ret != 0){
printErr(ret);
return -1;
}
std::cout<<"avio_open success"<<std::endl;
//写入头信息
ret = avformat_write_header(outContext, NULL);
if(ret < 0){
printErr(ret);
return -1;
}
std::cout<<"avformat_write_header success"<<std::endl;
//推流帧数据
AVPacket avpkt;
long long startTime = av_gettime();
while(1){
//读帧数据
ret = av_read_frame(inContext, &avpkt);
if(ret != 0){
break;
}
std::cout << avpkt.pts << std::endl;
//计算转换pts dts
AVRational inTime = inContext->streams[avpkt.stream_index]->time_base;
AVRational outTime = outContext->streams[avpkt.stream_index]->time_base;
avpkt.pts = av_rescale_q_rnd(avpkt.pts, inTime, outTime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
avpkt.dts = av_rescale_q_rnd(avpkt.dts, inTime, outTime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
avpkt.duration = av_rescale_q_rnd(avpkt.duration, inTime, outTime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
avpkt.pos = -1;
//处理视频帧,控制推流速度
if(inContext->streams[avpkt.stream_index]->codecpar->codec_type = AVMEDIA_TYPE_VIDEO){
//时间基数
AVRational tb = inContext->streams[avpkt.stream_index]->time_base;
long long nowTime = av_gettime() - startTime;
long long dtsTime = avpkt.dts * (1000 * 1000 * r2d(tb));
if(dtsTime > nowTime){
av_usleep(dtsTime - nowTime);
}
}
//发送数据
ret = av_interleaved_write_frame(outContext, &avpkt);
if(ret < 0){
printErr(ret);
return -1;
}
//释放
av_packet_unref(&avpkt);
}
system("pause");
return 0;
}
void printErr(int errNum){
char errBuf[1024] = {0};
av_strerror(errNum, errBuf, sizeof(errBuf));
system("pause");
}