赞
踩
├─ bin ├─ doc ├─ include ├─ libavcodec ├─ libavdevice ├─ libavfilter ├─ libavformat ├─ libavutil ├─ libpostproc ├─ libswresample └─ libswscale ├─ lib └─pkgconfig ├─ src └─ main.cpp ├─ build_x64 └─ CMakeLists.txt
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"); }
cmake_minimum_required (VERSION 3.5) project (FFmpegSDK) MESSAGE(STATUS "PROJECT_SOURCE_DIR" ${PROJECT_SOURCE_DIR}) SET(SRC_LISTS ${PROJECT_SOURCE_DIR}/src/main.cpp) # 配置工程需要的头文件目录 include_directories(${PROJECT_SOURCE_DIR}/include) IF(WIN32) set(CMAKE_C_FLAGS_RELEASE "/MD /MP /Od /Zi /EHsc") ENDIF() set(PRO_AVCODEC_LIB ${PROJECT_SOURCE_DIR}/lib/avcodec.lib) set(PRO_AVFORMAT_LIB ${PROJECT_SOURCE_DIR}/lib/avformat.lib) set(PRO_AVUTIL_LIB ${PROJECT_SOURCE_DIR}/lib/avutil.lib) ADD_EXECUTABLE(FFmpegSDK ${SRC_LISTS}) TARGET_LINK_LIBRARIES(FFmpegSDK ${PRO_AVCODEC_LIB} ${PRO_AVFORMAT_LIB} ${PRO_AVUTIL_LIB})
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。