瀏覽代碼

change driver_h264_rtpsclient. upload is ok.

yuchuli 3 年之前
父節點
當前提交
4111be5fe8

+ 73 - 0
src/driver/driver_h264_rtspclient/.gitignore

@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+

+ 53 - 0
src/driver/driver_h264_rtspclient/driver_h264_rtspclient.pro

@@ -0,0 +1,53 @@
+QT -= gui
+
+QT += network
+CONFIG += c++11 console
+CONFIG -= app_bundle
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which as been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+!include(../../../include/common.pri ) {
+    error( "Couldn't find the common.pri file!" )
+}
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += main.cpp
+
+
+#DEFINES += USE_QSV
+
+LIBS +=  -lavcodec -lavformat -lavutil
+#if(contains(DEFINES,USE_QSV)){
+#INCLUDEPATH += /usr/local/include
+#INCLUDEPATH += /opt/intel/mediasdk/include
+#LIBS += /opt/intel/mediasdk/lib/libmfx.so.1
+#LIBS += -L/opt/intel/mediasdk/lib -lmfx
+#LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavcodec.so.59
+#LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavutil.so.57
+#LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavdevice.so.59
+#LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavformat.so.59
+
+
+#} else {
+
+#INCLUDEPATH += /usr/include/x86_64-linux-gnu
+#LIBS +=  -lavcodec -lavformat -lavutil
+#}
+
+INCLUDEPATH += /usr/include/x86_64-linux-gnu
+
+
+INCLUDEPATH += $$PWD/Include
+
+
+#INCLUDEPATH += $$PWD/libEasyRTSPClient/Include
+
+LIBS += -L$$PWD -leasypusher -leasyrtspclient

+ 446 - 0
src/driver/driver_h264_rtspclient/main.cpp

@@ -0,0 +1,446 @@
+#include <QCoreApplication>
+
+
+
+extern "C"
+{
+#include <libavcodec/avcodec.h>
+#include <libavutil/opt.h>
+#include <libavutil/imgutils.h>
+#include <libavutil/common.h>
+#include "libavutil/error.h"
+#include "libavutil/hwcontext.h"
+#include "libavformat/avformat.h"
+#include "libavformat/avio.h"
+
+#ifdef USE_QSV
+//#include "libavutil/hwcontext_qsv.h"
+
+//#include "libavutil/hwcontext_vaapi.h"
+#endif
+
+
+}
+
+#include <iostream>
+
+
+
+//AVCodec *pCodec=NULL; //解码器指针
+//AVCodecContext* pCodecCtx=NULL; //ffmpeg 解码类的类成员
+
+//AVFormatContext* pFormatCtx=NULL; //保存视频流的信息
+
+//AVFormatContext * fmtctx = avformat_alloc_context();
+
+//    fmtctx->oformat= av_guess_format("rtsp",NULL,NULL);
+//    snprintf(fmtctx->filename,sizeof(fmtctx->filename),"rtsp://127.0.0.1:9554/te.sdp");
+////    pFormatCtx=avformat_alloc_context();
+//AVDictionary* options=NULL;
+////    av_dict_set(&options,"buffer_size","1024000",0);
+////    av_dict_set(&options,"max_delay","500000",0);
+//av_dict_set(&options,"rtsp_transport","tcp",0);
+////    av_dict_set(&options,"stimeout","2000000",0);//如果没有设置stimeout,那么流地址错误,av_read_frame会阻塞(时间单位是微妙)
+
+//int nrtn =  avformat_init_output(fmtctx,&options);
+
+
+int openOutputFile()
+{
+    av_register_all();  //注册库中所有的文件格式和编码器
+    avformat_network_init();
+
+    avcodec_register_all();
+
+
+    const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);
+    AVCodecContext *c= NULL;
+
+    c = avcodec_alloc_context3(codec);
+
+    if(c == NULL)std::cout<<"c NULL ."<<std::endl;
+//    pkt = av_packet_alloc();
+//        if (!pkt)
+//            exit(1);
+        c->bit_rate = 4000000;
+
+        c->width = 1280;
+        c->height = 720;
+
+        c->time_base = (AVRational){1, 30};
+        c->framerate = (AVRational){30, 1};
+
+        c->gop_size = 10;
+        c->max_b_frames = 1;
+        c->pix_fmt =  AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;
+
+
+
+        if (codec->id == AV_CODEC_ID_H264)
+        {
+            av_opt_set(c->priv_data, "profile", "baseline", 0);
+
+
+             av_opt_set(c->priv_data, "preset", "fast", 0);
+           av_opt_set(c->priv_data, "tune", "zerolatency", 0);
+        }
+
+        int retc = avcodec_open2(c, codec, NULL);
+        if (retc < 0) {
+            std::cout<<"Could not open codec: "<<std::endl;
+//             fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
+            exit(1);
+        }
+
+    AVFormatContext * fmtctx = NULL;
+    int nrtn = avformat_alloc_output_context2(&fmtctx,NULL,"rtsp","rtsp://127.0.0.1:9554/test2.sdp");
+
+
+
+    fmtctx->bit_rate = 2000000;
+    fmtctx->fps_probe_size = 30;
+
+    int err = 0;
+
+    AVStream *out_stream = avformat_new_stream(fmtctx, codec);
+
+    out_stream->codecpar->bit_rate = 2000000;
+    out_stream->codecpar->width = 1280;
+    out_stream->codecpar->height = 720;
+
+
+        int ret = 0;
+
+
+
+
+            av_dump_format(fmtctx, 0, fmtctx->filename, 1);
+
+//        int nrx = avformat_init_output(fmtctx,NULL);
+
+        ret = avio_open(&fmtctx->pb,fmtctx->filename,AVIO_FLAG_WRITE);
+//		fmtctx->flags |= AVFMT_FLAG_NONBLOCK;
+//		if (!(fmtctx->flags & AVFMT_NOFILE)) {
+////			AVIOInterruptCB ioCb = { &FfmpegMuxer::ioInterruptCallback, this };
+//			ret = avio_open2(&fmtctx->pb, m_outputFilename.c_str(), AVIO_FLAG_WRITE, &ioCb, nullptr);
+//			if (ret < 0) {
+//				err = ERROR_CODE_FFMPEG_OPEN_AVIO_FAILED;
+//				break;
+//			}
+//		}
+
+        std::cout<<"ret: "<<ret<<std::endl;
+        AVDictionary* options = nullptr;
+            av_dict_set(&options, "rtsp_transport", "tcp", 0);
+            av_dict_set(&options, "stimeout", "8000000", 0);
+        ret = avformat_write_header(fmtctx, &options);
+        if (options != nullptr) {
+            av_dict_free(&options);
+        }
+        if (ret < 0) {
+            err = -1;
+        }
+//	} while (0);
+
+    return err;
+}
+
+
+int test2()
+{
+    AVFormatContext *pFormatCtx;
+    AVCodecContext *pCodecCtx;
+    AVCodec *pCodec;
+    AVFrame *pFrame, *pFrameRGB;
+    AVPacket *packet;
+    uint8_t *out_buffer;
+
+    static struct SwsContext *img_convert_ctx;
+
+    int videoStream, i, numBytes;
+    int ret, got_picture;
+
+    avformat_network_init();   ///初始化FFmpeg网络模块,2017.8.5---lizhen
+    av_register_all();         //初始化FFMPEG  调用了这个才能正常适用编码器和解码器
+
+
+    //Allocate an AVFormatContext.
+    pFormatCtx = avformat_alloc_context();
+
+    ///2017.8.5---lizhen
+    AVDictionary *avdic=NULL;
+    char option_key[]="rtsp_transport";
+    char option_value[]="tcp";
+    av_dict_set(&avdic,option_key,option_value,0);
+//    char option_key2[]="max_delay";
+//    char option_value2[]="100";
+//    av_dict_set(&avdic,option_key2,option_value2,0);
+    ///rtsp地址,可根据实际情况修改
+    char url[]="rtsp://111.33.136.149:9554/test2.sdp";
+
+
+    if (avformat_open_input(&pFormatCtx, url, NULL, &avdic) != 0) {
+        printf("can't open the file. \n");
+        return -1;
+    }
+
+    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
+        printf("Could't find stream infomation.\n");
+        return -2;
+    }
+
+}
+
+
+#include "ffmpeg_outputer.h"
+
+
+#include "modulecomm.h"
+
+
+std::shared_ptr<char> gpstr_data;
+bool gbUpdate = false;
+int gndatasize;
+std::mutex gmutex;
+
+void Listenframe(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    if(nSize<10)return;
+    std::shared_ptr<char> pstr = std::shared_ptr<char>(new char[nSize]);
+    memcpy(pstr.get(),strdata,nSize);
+    gmutex.lock();
+    gpstr_data = pstr;
+    gndatasize = nSize;
+    gbUpdate = true;
+    gmutex.unlock();
+//    qDebug(" %02x %02x %02x %02x %02x %02x",strdata[0],strdata[1],strdata[2],strdata[3],strdata[4],strdata[5]);
+
+
+
+}
+
+std::mutex gmutexlat;
+namespace iv {
+struct datapac
+{
+    int64_t sendtime;
+    int nsize;
+};
+}
+std::vector<iv::datapac> gvectorsend;
+
+void threadrecv()
+{
+    static AVFormatContext *i_fmt_ctx;
+    static AVStream *i_video_stream;
+
+    static AVFormatContext *o_fmt_ctx;
+    static AVStream *o_video_stream;
+
+    static bool bStop = false;
+    static int frame_nums = 0;
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    /* should set to NULL so that avformat_open_input() allocate a new one */
+        i_fmt_ctx = NULL;
+        //这是我用ONVIF协议得到的摄像头RTSP流媒体地址
+        char rtspUrl[] = "rtsp://111.33.136.149:9554/mystream";
+
+
+
+        if (avformat_open_input(&i_fmt_ctx, rtspUrl, NULL, NULL)!=0)
+        {
+            fprintf(stderr, " = could not open input file\n");
+            return ;
+        }
+
+
+        AVDictionary *opts = NULL;
+
+            av_dict_set(&opts, "rtsp_transport", "tcp", 0);
+//            av_dict_set(&opts, "muxdelay", "0.1", 0);
+
+
+        if (avformat_find_stream_info(i_fmt_ctx, &opts)<0)
+        {
+            fprintf(stderr, " = could not find stream info\n");
+            return ;
+        }
+
+
+
+        int last_pts = 0;
+           int last_dts = 0;
+
+           int64_t pts, dts;
+           while(!bStop)
+           {
+               //printf("------------------------------------------------------\n");
+               AVPacket i_pkt;
+               av_init_packet(&i_pkt);
+               i_pkt.size = 0;
+               i_pkt.data = NULL;
+               if (av_read_frame(i_fmt_ctx, &i_pkt) <0 )
+                   break;
+
+               int sizedata = i_pkt.size;
+               int i;;
+               gmutexlat.lock();
+               for(i=gvectorsend.size();i>=0;i--)
+               {
+                   iv::datapac xpac = gvectorsend[i];
+                   if(xpac.nsize == i_pkt.size)
+                   {
+                       std::cout<<"Latency: "<<(std::chrono::system_clock::now().time_since_epoch().count()/1000000  - xpac.sendtime)<<std::endl;
+                   }
+               }
+               gmutexlat.unlock();
+                std::cout<<"    time: "<<std::chrono::system_clock::now().time_since_epoch().count()/1000000<<" read packet size:"<<i_pkt.size<<std::endl;
+           }
+
+
+}
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication a(argc, argv);
+
+    void * pa = iv::modulecomm::RegisterRecv("h264front",Listenframe);
+    AVFormatContext *ifmt_ctx = NULL;
+       AVPacket pkt;
+       const char *in_filename, *out_filename;
+       FfmpegOutputer *pusher = NULL;
+       int ret;
+       int frame_index = 0;
+
+       in_filename = "/home/yuchuli/imx291.h264";
+
+       out_filename = "rtsp://111.33.136.149:9554/testhello2";
+       //out_filename = "rtp://233.233.233.233:6666";
+       //out_filename = "tcp://127.0.0.1:9000";
+       //out_filename = "udp://127.0.0.1:9000";
+
+       av_register_all();         //初始化FFMPEG  调用了这个才能正常适用编码器和解码器
+
+       //Network
+       avformat_network_init();
+
+
+       std::thread * precvthread = new std::thread(threadrecv);
+
+       if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
+           printf("Could not open input file.");
+          return -1;
+       }
+
+
+       if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
+           printf("Failed to retrieve input stream information");
+           return -2 ;
+       }
+
+
+       ifmt_ctx->streams[0]->avg_frame_rate.num = 30;
+       ifmt_ctx->streams[0]->codecpar->sample_aspect_ratio.num = 30;
+       ifmt_ctx->streams[0]->time_base.den = 30;
+
+       ifmt_ctx->bit_rate = 2000000;
+       if (NULL == pusher) {
+           pusher = new FfmpegOutputer();
+           ret = pusher->OpenOutputStream(out_filename, ifmt_ctx);
+           if (ret != 0){
+               return -3;
+           }
+       }
+
+
+       av_dump_format(ifmt_ctx, 0, in_filename, 0);
+
+       int pos = 0;
+       av_read_frame(ifmt_ctx, &pkt);
+       while (true) {
+
+           if(gbUpdate == false)
+           {
+               std::this_thread::sleep_for(std::chrono::milliseconds(1));
+//               av_usleep(1000);
+ //              std::cout<<"sleep. "<<std::endl;
+               continue;
+           }
+ //          continue;
+           gmutex.lock();
+
+           pkt.buf = NULL;
+           pkt.duration = 0;
+           pkt.data = new unsigned char[gndatasize];
+           //           pkt.buf->data = pkt.data;
+           memcpy(pkt.data, gpstr_data.get(),gndatasize);
+           pkt.size = gndatasize;
+  //         std::cout<<" size : "<<gndatasize<<std::endl;
+           //           std::cout<<" buf size: "<<pkt.buf->size<<std::endl;
+           //           pkt.buf->size = gndatasize;
+           pkt.pos =  pos;
+           pkt.pts = AV_NOPTS_VALUE;
+           pkt.dts = AV_NOPTS_VALUE;
+           pos = pos + gndatasize;
+           gbUpdate = false;
+           gmutex.unlock();
+           pkt.flags = 0;
+
+           iv::datapac xpac;
+           xpac.nsize = pkt.size;
+           xpac.sendtime = std::chrono::system_clock::now().time_since_epoch().count()/1000000;
+   //        std::cout<<"send frame "<<std::endl;
+  //         ret = av_read_frame(ifmt_ctx, &pkt);
+           gmutexlat.lock();
+           gvectorsend.push_back(xpac);
+           while(gvectorsend.size()>100)gvectorsend.erase(gvectorsend.begin());
+           gmutexlat.unlock();
+           std::cout<<"    time: "<<std::chrono::system_clock::now().time_since_epoch().count()/1000000<<" pos: "<<pkt.pos<<" size: "<<pkt.size<<" flats: "<<pkt.flags<< std::endl;
+ //          if (ret < 0) break;
+
+           pkt.duration = 3;
+
+//           std::cout<<" pts: "<<pkt.pts<<" dts: "<<pkt.dts<<std::endl;
+           if (pkt.pts == AV_NOPTS_VALUE) {
+               pkt.dts = pkt.pts = (1.0/30)*90*frame_index;
+ //              pkt.dts = pkt.pts = frame_index * 1;
+ //              frame_index++;
+
+           }
+ //          std::cout<<" pts: "<<pkt.pts<<" dts: "<<pkt.dts<<std::endl;
+
+           pusher->InputPacket(&pkt);
+           av_packet_unref(&pkt);
+//           delete pkt.data;
+           frame_index++;
+//           av_usleep(40000);
+       }
+
+       end:
+       avformat_close_input(&ifmt_ctx);
+       avformat_free_context(ifmt_ctx);
+       delete pusher;
+
+
+ //   test2();
+//    openOutputFile();
+//    avcodec_register_all();
+//    avformat_network_init();
+
+//    char* video_dir="rtsp://admin:yltx8888@192.168.37.210:554/h264/ch1/main/av_stream";
+//    char* video_dir="rtmp://58.200.131.2:1935/livetv/cctv6";
+
+
+//    AVFormatContext * fmtctx = avformat_alloc_context();
+//    fmtctx->oformat= av_guess_format("rtsp",NULL,NULL);
+//    snprintf(fmtctx->filename,sizeof(fmtctx->filename),"rtsp://127.0.0.1:9554/te.sdp");
+//    int nrtn = avio_open(&fmtctx->pb,fmtctx->filename,AVIO_FLAG_WRITE);
+//    std::cout<<"hello "<<std::endl;
+////    int nrtn = avformat_open_input(&fmtctx,fmtctx->filename,NULL,NULL);
+//    std::cout<<" nrtn : "<<nrtn<<std::endl;
+    return a.exec();
+}
+
+