基于opencv采集推流
1.opencv采集rtsp解码 //可以基于usb 摄像机(调用系统驱动)和rtsp(调用ffmpeg 接口 转yuv加解码) 摄像机
2.ffmpeg缩放转换像素格式
3.ffmpeg编码H264
4.ffmpeg推流rtmp
sws_getCachedContext (像素格式转换 会清理之前的数据)
1.struct SwsContext *context, 2.int srcW,int srcH,enum AVPixelFormat srcFormat, 3.int dstW,int dstH 4.enum AVPixelFormat dstFormat, //AV_PIX_FMT_YUV420P 5.int flags. //SWS_BICUBIC 6.srcFilter,dstFilter,param
SWS_SCALE
1.c 上下文 2.srcSlice (原数据) srcStride(每一行数据长度) 3.srcSliceY srcSliceH(高度) 4.dst dstStride (输出每一行大小) 5.Returns 输出slice的高度
avcodec_find_encoder
1.AVCodecID -AV_CODEC_ID_H264 2.avcodec_find_encoder_by_name 3.AVCodec
avcodec_alloc_context3
1.AVCodecContext* 2.avcodec_alloc_context3 3.(const AVCodec *codec);
int avcodec_open2 ( AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
avcodec_send_frame
1.AVCodecContext *avctx; 2.const AVframe *frame; 3.avcodec_receive_packet
example.cpp
#include#include #include #include // 1. 更换包含头文件 #include #include #include extern "C" { #include #include #include #include } using namespace cv; using namespace std; int main(int argc,char *argv) { VideoCapture cam; string inUrl = "rtsp://test:test@192.168.1.4"; //nginx-rtmp 直播服务器rtmp推流URL char *outUrl = "rtmp://0.0.0.0/live"; //注册所有的编解码器 avcodec_register_all(); //注册所有的封装器 av_register_all(); //注册所有网络协议 avformat_network_init(); Mat frame; namedWindow("video"); //像素格式转换的上下文 SwsContext *vsc = NULL; //输出的数据结构 AVframe *yuv = NULL; //编码器的上下文 AVCodecContext *vc = NULL; //rtmp flv 封装器 AVFormatContext *ic = NULL; try { //cam.open(inUrl); //1.使用opencv打开rtsp相机 cam.open(0); if(!cam.isOpened()) { throw logic_error("cam open failed"); } cout< format = AV_PIX_FMT_YUV420P; yuv->width = inWidth; yuv->height = inHeight; yuv->pts = 0; //分配yuv空间 int ret = av_frame_get_buffer(yuv,32); if(ret != 0) { char buf[1024] = {0}; av_strerror(ret, buf,sizeof(buf) - 1); throw logic_error(buf); } //4初始化编码上下文 //a 找到编码器 AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264); if(!codec) { throw logic_error("Can't find h264 encoder!"); } //b 创建编码器上下文 vc = avcodec_alloc_context3(codec); if(!vc) { throw logic_error("avcodec_alloc_context3 failed!"); } //c 配置编码器参数 vc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //全局的参数 vc->codec_id = codec->id; vc->thread_count = 8; vc->bit_rate = 50*1024*8; //压缩后每秒视频的bit位大小 50kb vc->width = inWidth; vc->height = inHeight; vc->time_base = {1,fps}; //时间基数 vc->framerate = {fps,1}; //画面组的大小,多少帧一个关键帧 vc->gop_size = 50; vc->max_b_frames = 0; vc->pix_fmt = AV_PIX_FMT_YUV420P; //d 打开编码器 ret = avcodec_open2(vc,0,0); if(ret!=0) { char buf[1024] = {0}; av_strerror(ret,buf,sizeof(buf) - 1); throw logic_error(buf); } cout<<"avcodec_open2 success!"< codecpar->codec_tag = 0; //从编码器复制参数 avcodec_parameters_from_context(vs->codecpar,vc); av_dump_format(ic,0,outUrl,1); //打开rtmp的网络输出IO ret = avio_open(&ic->pb,outUrl,AVIO_FLAG_WRITE); if(ret != 0) { char buf[1024] = {0}; av_strerror(ret,buf,sizeof(buf) - 1); throw logic_error(buf); } //写入封装头 ret = avformat_write_header(ic,NULL); if(ret != 0) { char buf[1024] = {0}; av_strerror(ret,buf,sizeof(buf) - 1); throw logic_error(buf); } AVPacket pkt; memset(&pkt,0,sizeof(pkt)); int vpts = 0; for(;;) { //读取rtsp视频帧,解码视频帧 if(!cam.grab()) { continue; } //yuv转为rgb //输入的数据结构 if(!cam.retrieve(frame)) { continue; } imshow("video",frame); waitKey(1); //rgb to yuv //输入的数据格式 uint8_t *indata[AV_NUM_DATA_POINTERS] = {0}; //bgrbgrbgr //plane inData[0]bbbb gggg rrrr indata[0] = frame.data; int insize[AV_NUM_DATA_POINTERS] = {0}; //一行(宽)数据的字节数 insize[0] = frame.cols * frame.elemSize(); int h = sws_scale(vsc,indata,insize,0,frame.rows, //输入数据 yuv->data,yuv->linesize); if(h<=0) { continue; } // cout<<" "< pts = vpts; vpts++; //h264编码 ret = avcodec_send_frame(vc,yuv); if(ret!=0) continue; //每次都会调用av_frame_unref(frame) avcodec_receive_packet(vc,&pkt); if(ret != 0 || pkt.size > 0) { cout<<"*"< time_base,vs->time_base); pkt.dts = av_rescale_q(pkt.dts,vs->time_base,vs->time_base); ret = av_interleaved_write_frame(ic,&pkt); if(ret == 0) { cout<<"#"< CMakeLists.txt
cmake_minimum_required(VERSION 3.1) project(opencv_example_project) find_package(OpenCV REQUIRED) message(STATUS "OpenCV library status:") message(STATUS " config: ${OpenCV_DIR}") message(STATUS " version: ${OpenCV_VERSION}") message(STATUS " libraries: ${OpenCV_LIBS}") message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") find_library(AVCODEC_LIBRARY avcodec) find_library(AVFORMAT_LIBRARY avformat) find_library(AVUTIL_LIBRARY avutil) find_library(AVDEVICE_LIBRARY avdevice) add_executable(opencv_example example.cpp) target_link_libraries(opencv_example PRIVATE ${OpenCV_LIBS} pthread swresample m swscale avformat avcodec avutil avfilter avdevice postproc z lzma rt)xz@xiaqiu:~/study/csdn/rtmp/video$ ps -ef | grep nginx root 11058 1829 0 10:57 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 11059 11058 0 10:57 ? 00:00:01 nginx: worker process xz 25982 2623 1 18:55 pts/0 00:00:00 grep --color=auto nginx xz@xiaqiu:~/study/csdn/rtmp/video$ xz@xiaqiu:~/study/csdn/opencv/opencv_rtsp_to_rtmp/build$ ./opencv_example [ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (935) open OpenCV | GStreamer warning: Cannot query video position: status=0, value=-1, duration=-1 rtsp://test:test@192.168.1.4cam open success [libx264 @ 0x559a17b20480] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 0x559a17b20480] profile High, level 3.0 [libx264 @ 0x559a17b20480] 264 - core 155 r2917 0a84d98 - H.264/MPEG-4 AVC codec - Copyleft 2003-2018 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=8 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=2 keyint=50 keyint_min=5 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=abr mbtree=1 bitrate=409 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 avcodec_open2 success! Output #0, flv, to 'rtmp://0.0.0.0/live': Stream #0:0: Video: h264, yuv420p, 640x480, q=2-31, 409 kb/s *754#*31#*27#*36#*26#*62#*30#*599#*338#*977#*1388#*1968#*2586#*3770#*1869#*5468#*6066#*7062#*5309#*3508#*5436#*4551#*4048#*5790#*4911#*2078#*1699#*1514#*6736#*2203#*854#*744#*507#*4641#*2346#*1031#*782#*717#*722#*4806#*885#*650#*657#*2627#*938#*383#*406#*369#*435#*1853#*579#*398#*425#*3135#*1935#*962#*1475#*4911#*1811#*5288#*2198#*1839#*1769#*1733#*5254#*1783#*1711#*1478#*1394#*5439#*1690#*1466#*1285#*1031#*5187#*1539#*1303#*1102#*1040#*5200#*1334#*1223#*1088#*1198#*4879#*1256#*1116#*1027#*988#*4967#*1205#*1273#*1046#*990#*969#*4808#*1254#*1120#*985#*989#*4885#*1293#*1109#*954#*929#*4937#*1259#*983#*874#*913#*4725#*1266#*1210#*1005#*982#*4669#*1362#*1657#*1111#*3958#*2372#*904#*879#*905#*3998#*2361#*990#*1009#*924#*984#*4396#*1125#*960#*1116#*943#*4299#*1064#*986#*977#*897#*892#*4338#*1233#*1050#*921#*930#*4397#*1291#*1040#*1043#*1041#*4374#*1304#*1114#*939#*943#*4241#*1163#*1037#*949#*893#*4376#*1252#*1109#*971#*864#*989#*4255#*1157#*1034#*966#*930#*1032#*4184#*1229#*1018#*993#*873#*4358#*1188#*1138#*1305#*3667#*2262#*951#*803#*875#*3187#*2212#*978#*880#*3250#*1790#*1970#*765#*660#*2818#*1888#*1839#*651#*624#*2735#*1850#*1951#*650#*602#*2672#*1923#*2208#*938#*771#*2953#*1963#*2020#*787#*647#*603#*2770#*2065#*793#*690#*725#*2764#*2091#*788#*798#*719#*726#*3026#*995#*853#*689#*692#*2969#*922#*786#*772#*674#*3163#*1004#*841#*705#*688#*3253#*1060#*925#*950#*870#*816#*3473#*1258#*940#*955#*820#*3680#*1700#*1496#*1481#*1460#*1462#*1395#*4610#*1408#*1890#*1159#*1108#*980#*958#*3843#*1214#*1038#*879#*832#*830#*963#*3802#*1099#*1011#*998#*856#*986#*862#*3805#*1299#*1154#*1049#*1017#*4329#*1831#*1492#*1506#*1444#*1246#*1179#*4803#*1610#*1285#*1386#*1256#*4852#*1470#*1389#*1344#*1304#*4899#*1546#*1311#*1251#*1242#*5175#*1511#*1310#*1249#*1146#*5174#*1475#*1349#*1247#*1205#*5151#*1566#*1278#*1370#QObject::~QObject: Timers cannot be stopped from another thread打开新终端
xz@xiaqiu:~/study/csdn/opencv/opencv_rtsp_to_rtmp/build$ ffplay rtmp://0.0.0.0/live欢迎分享,转载请注明来源:内存溢出
评论列表(0条)