瀏覽代碼

change h264_dec, qsv code ok,but use new ffmpeg.

yuchuli 3 年之前
父節點
當前提交
7b0effb201

+ 0 - 0
src/driver/driver_h264_dev/.gitignore → src/driver/driver_h264_dec/.gitignore


+ 27 - 8
src/driver/driver_h264_dev/driver_h264_dev.pro → src/driver/driver_h264_dec/driver_h264_dec.pro

@@ -7,6 +7,7 @@ CONFIG -= app_bundle
 # In order to do so, uncomment the following line.
 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
+
 !include(../../../include/common.pri ) {
     error( "Couldn't find the common.pri file!" )
 }
@@ -25,16 +26,34 @@ CONFIG -= app_bundle
 
 
 SOURCES += \
-        main.cpp \
-        ../../include/msgtype/rawpic.pb.cc
-
-LIBS += -lavcodec -lavformat -lavutil
-
-HEADERS += \
-        ../../include/msgtype/rawpic.pb.h
-
+        ../../include/msgtype/rawpic.pb.cc \
+        main.cpp
 
 # Default rules for deployment.
 qnx: target.path = /tmp/$${TARGET}/bin
 else: unix:!android: target.path = /opt/$${TARGET}/bin
 !isEmpty(target.path): INSTALLS += target
+
+DEFINES += USE_QSV
+
+
+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
+}
+
+HEADERS += \
+    ../../include/msgtype/rawpic.pb.h
+

+ 317 - 0
src/driver/driver_h264_dec/main.cpp

@@ -0,0 +1,317 @@
+#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>
+#include <thread>
+
+#include "modulecomm.h"
+
+#include <opencv2/opencv.hpp>
+#include <opencv2/core.hpp>
+
+#include <opencv2/imgproc.hpp>
+
+//#include "opencv2/imgcodecs/legacy/constants_c.h"
+#include <opencv2/imgproc/types_c.h>
+
+#include "rawpic.pb.h"
+
+
+
+bool gbNewData ;
+#include <QWaitCondition>
+#include <QMutex>
+
+QWaitCondition gwc;
+QMutex gWaitMutex;
+int gndatasize;
+
+char * gstrbuffer;
+QMutex gMutexLock;
+
+bool gbNewOut ;
+QWaitCondition gwcout;
+char * gstrout;
+QMutex gWaitMutexout;
+QMutex gMutexout;
+int gnoutsize ;
+
+bool gbStartRecv = false;
+
+extern void StartDecode();
+
+#include <iostream>
+
+void ListenFrame(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    static bool bStart = false;
+    if(nSize < 6)return;
+
+    if(gbStartRecv == false)return;
+
+    if(bStart == false)
+    {
+        if(strdata[4] == 0x27)
+        {
+            std::cout<<" SPS Size "<<nSize<<std::endl;
+            bStart = true;
+        }
+    }
+    if(bStart == false)
+    {
+        return;
+    }
+    std::cout<<" start. "<<std::endl;
+    gMutexLock.lock();
+    memcpy(gstrbuffer,strdata,nSize);
+    gndatasize = nSize;
+    gbNewData = true;
+    gMutexLock.unlock();
+    gwc.wakeAll();
+
+
+
+    char strout[1000];
+    memcpy(strout,strdata,100);
+    char strprint[1000];
+    sprintf(strprint,"%02x %02x %02x %02x %02x %02x %02x %02x",strout[0],strout[1],
+            strout[2],strout[3],strout[4],strout[5],strout[6],strout[7]);
+    std::cout<<strprint<<std::endl;
+
+}
+
+void read_h264_frame(char * strbuf, int & ndatasize)
+{
+    while(gbNewData == false)
+    {
+        gWaitMutex.lock();
+        gwc.wait(&gWaitMutex,10);
+        gWaitMutex.unlock();
+    }
+    std::cout<<"frame data. "<<std::endl;
+    gMutexLock.lock();
+    memcpy(strbuf,gstrbuffer,gndatasize);
+    ndatasize = gndatasize;
+    gbNewData = false;
+    gMutexLock.unlock();
+}
+
+#define INBUF_SIZE 4096
+
+void * gpa;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
+                   const char *filename)
+{
+    char buf[1024];
+    int ret;
+
+    ret = avcodec_send_packet(dec_ctx, pkt);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending a packet for decoding\n");
+        exit(1);
+    }
+
+
+    while (ret >= 0) {
+        ret = avcodec_receive_frame(dec_ctx, frame);
+        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+            return;
+        else if (ret < 0) {
+            fprintf(stderr, "Error during decoding\n");
+            exit(1);
+        }
+
+        printf("saving frame %3d\n", dec_ctx->frame_number);
+        fflush(stdout);
+
+        /* the picture is allocated by the decoder. no need to
+           free it */
+        snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
+
+        int cy = 720;
+        int cx = 1280;
+        cv::Mat yuvImg;
+        cv::Mat rgbImg(cy, cx,CV_8UC3);
+        yuvImg.create(cy*3/2, cx, CV_8UC1);
+        memcpy(yuvImg.data, frame->data[0], cy*cx);
+        memcpy(yuvImg.data + cy*cx,frame->data[1],cy*cx/4);
+        memcpy(yuvImg.data + cy*cx + cy*cx/4,frame->data[2],cy*cx/4);
+        cv::cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420);
+
+        iv::vision::rawpic pic;
+
+        qint64 time = QDateTime::currentMSecsSinceEpoch();
+        QTime xg;
+        xg.start();
+        pic.set_time(time);
+        pic.set_index(0);//gindex++;
+
+
+        pic.set_elemsize(rgbImg.elemSize());
+        pic.set_width(rgbImg.cols);
+        pic.set_height(rgbImg.rows);
+        pic.set_mattype(rgbImg.type());
+
+
+            pic.set_picdata(rgbImg.data,rgbImg.rows*rgbImg.cols*rgbImg.elemSize());
+//                pic.set_picdata(matcompress.data,matcompress.rows*matcompress.cols*matcompress.elemSize());
+            pic.set_type(1);
+
+
+//            qDebug("buff size is %d",buff.size());
+
+
+        int nSize = pic.ByteSize();
+
+          char * strser = new char[nSize];
+        bool bser = pic.SerializeToArray(strser,nSize);
+        qDebug("time is %ld pac time is %d size is %d",QDateTime::currentMSecsSinceEpoch(),xg.elapsed(),nSize);
+
+//        iv::modulecomm::ModuleSendMsg(gpa,str.data(),str.length());
+        if(bser)iv::modulecomm::ModuleSendMsg(gpa,strser,nSize);
+        else
+        {
+            std::cout<<"frame "<< "serialize error. "<<std::endl;
+        }
+           delete strser;
+
+//        pgm_save(frame->data[0], frame->linesize[0],
+//                 frame->width, frame->height, buf);
+    }
+}
+
+
+int ThreadDec()
+{
+    const char *filename, *outfilename;
+    const AVCodec *codec;
+    AVCodecParserContext *parser;
+    AVCodecContext *c= NULL;
+    FILE *f;
+    AVFrame *frame;
+    uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
+    uint8_t *data;
+    size_t   data_size;
+    int ret;
+    AVPacket *pkt;
+
+//    if (argc <= 2) {
+//        fprintf(stderr, "Usage: %s <input file> <output file>\n"
+//                "And check your input file is encoded by mpeg1video please.\n", argv[0]);
+//        exit(0);
+//    }
+    filename    = "/home/yuchuli/testr.mp4";
+    outfilename = "/home/yuchuli/testr.yuv";
+
+    pkt = av_packet_alloc();
+    if (!pkt)
+        exit(1);
+
+    /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
+    memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+    /* find the MPEG-1 video decoder */
+    codec = avcodec_find_decoder(AV_CODEC_ID_H264);
+    if (!codec) {
+        fprintf(stderr, "Codec not found\n");
+        exit(1);
+    }
+
+    parser = av_parser_init(codec->id);
+    if (!parser) {
+        fprintf(stderr, "parser not found\n");
+        exit(1);
+    }
+
+    c = avcodec_alloc_context3(codec);
+    if (!c) {
+        fprintf(stderr, "Could not allocate video codec context\n");
+        exit(1);
+    }
+
+    /* For some codecs, such as msmpeg4 and mpeg4, width and height
+       MUST be initialized there because this information is not
+       available in the bitstream. */
+
+    /* open it */
+    if (avcodec_open2(c, codec, NULL) < 0) {
+        fprintf(stderr, "Could not open codec\n");
+        exit(1);
+    }
+
+    f = fopen(filename, "rb");
+    if (!f) {
+        fprintf(stderr, "Could not open %s\n", filename);
+        exit(1);
+    }
+
+    frame = av_frame_alloc();
+    if (!frame) {
+        fprintf(stderr, "Could not allocate video frame\n");
+        exit(1);
+    }
+
+    char * strbuff = new char[10000000];
+    int ndatasize = 0;
+    gbStartRecv = true;
+    while (1) {
+
+        read_h264_frame(strbuff,ndatasize);
+        pkt->data = (uint8_t *)strbuff;
+        pkt->size = ndatasize;
+        if (pkt->size)
+        {
+            std::cout<<"decode ."<<std::endl;
+            decode(c, frame, pkt, outfilename);
+        }
+
+    }
+
+    /* flush the decoder */
+//    decode(c, frame, NULL, outfilename);
+
+    fclose(f);
+
+    av_parser_close(parser);
+    avcodec_free_context(&c);
+    av_frame_free(&frame);
+    av_packet_free(&pkt);
+
+    return 0;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication a(argc, argv);
+
+    gpa = iv::modulecomm::RegisterSend("h264pic",20000000,1);
+    gstrbuffer = new char[1000000];
+    gstrout = new char[30000000];
+    iv::modulecomm::RegisterRecv("h264frame",ListenFrame);
+
+    std::thread * decthread = new std::thread(ThreadDec);
+
+    return a.exec();
+}

+ 0 - 8
src/driver/driver_h264_dev/main.cpp

@@ -1,8 +0,0 @@
-#include <QCoreApplication>
-
-int main(int argc, char *argv[])
-{
-    QCoreApplication a(argc, argv);
-
-    return a.exec();
-}

+ 25 - 1
src/driver/driver_h264_enc/driver_h264_enc.pro

@@ -34,7 +34,31 @@ DEFINES += QT_DEPRECATED_WARNINGS
 SOURCES += main.cpp \
     ../../include/msgtype/rawpic.pb.cc
 
-LIBS += -lavcodec -lavformat -lavutil
+
+DEFINES += USE_QSV
+
+
+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
+}
+
+
+
+
+
 
 HEADERS += \
     ../../include/msgtype/rawpic.pb.h

+ 104 - 15
src/driver/driver_h264_enc/main.cpp

@@ -6,6 +6,18 @@ extern "C"
 #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>
@@ -42,12 +54,28 @@ QMutex gWaitMutexout;
 QMutex gMutexout;
 int gnoutsize = 0;
 
-static char * gstrwidth ="1920";
-static char * gstrheight = "1080";
+static char * gstrwidth ="1280";
+static char * gstrheight = "720";
 int gnwidth,gnheight;
 
 void * gpaout;
 
+#include <QFile>
+QFile gFile;
+
+
+int W = 1280;
+int H = 720;
+void yuvI420ToNV12(char *I420,int w,int h,char *NV12)
+{
+    memcpy(NV12,I420,w*h);//y分量
+    for(int i = 0,j = 0;i<w*h/4;i++,j+=2)
+    {
+         memcpy(NV12+w*h+j,I420+w*h+i,1);//u分量
+         memcpy(NV12+w*h+j+1,I420+w*h+i+w*h/4,1);//v分量
+    }
+}
+
 static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
                    FILE *outfile)
 {
@@ -75,27 +103,61 @@ static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
         std::cout<<"time: "<<std::chrono::system_clock::now().time_since_epoch().count()/1000000<<std::endl;
         printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
         iv::modulecomm::ModuleSendMsg(gpaout,(char *)pkt->data,pkt->size);
+        gFile.write((char *)pkt->data,pkt->size);
+        gFile.flush();
 //        fwrite(pkt->data, 1, pkt->size, outfile);
         av_packet_unref(pkt);
     }
 
+
 }
 
 
 
 void ThreadEnc()
 {
-    AVCodec *codec;
+    const AVCodec *codec;
     AVCodecContext *c= NULL;
     AVFrame * frame;
     AVPacket * pkt;
 
     char * strbuf = new char[30000000];
+    char * strbufnv12 = new char[30000000];
+    int ret;
+
+#ifndef USE_QSV
+    av_register_all();
+
+   codec = avcodec_find_encoder(AV_CODEC_ID_H264);// avcodec_find_encoder_by_name("h264");
+#endif
 
+#ifdef USE_QSV
+   AVBufferRef *device_ref = NULL;
+
+//       av_hwdevice_ctx_init();
+    ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_QSV,"auto", NULL, 0);
+    codec = avcodec_find_encoder_by_name("h264_qsv");
+#endif
+
+
+
+
+//      AVCodecContext *decoder_ctx = NULL;
+//        AVBufferRef *device_ref = NULL;
+
+ //       av_hwdevice_ctx_init();
+//    ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_QSV,"auto", NULL, 0);
+//    codec = avcodec_find_encoder_by_name("libx264");
+//    /* 检查下是否打开成功,失败则直接跳出去 */
+//    if (ret < 0) {
+//        fprintf(stderr, "Cannot open the hardware device\n");
+//        return ;
+//    }
+
+
+//    codec = avcodec_find_encoder_by_name("h264");
 
-    avcodec_register_all();
 
-     codec = avcodec_find_encoder(AV_CODEC_ID_H264);// avcodec_find_encoder_by_name("h264");
 
      if(codec == NULL)
      {
@@ -115,11 +177,12 @@ void ThreadEnc()
          if (!pkt)
              exit(1);
 
+
          /* put sample parameters */
          c->bit_rate = 4000000;
          /* resolution must be a multiple of two */
-         c->width = 1920;
-         c->height = 1080;
+         c->width = 1280;
+         c->height = 720;
          /* frames per second */
 
          c->time_base = (AVRational){1, 30};
@@ -133,16 +196,31 @@ void ThreadEnc()
           */
          c->gop_size = 10;
          c->max_b_frames = 1;
-         c->pix_fmt = AV_PIX_FMT_YUV420P;
+
+
+  //       c->pix_fmt =  AV_PIX_FMT_YUV420P;//
+         c->pix_fmt =  AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;
+
+
 
          if (codec->id == AV_CODEC_ID_H264)
          {
-              av_opt_set(c->priv_data, "preset", "fast", 0);
-              av_opt_set(c->priv_data, "tune", "zerolatency", 0);
+             av_opt_set(c->priv_data, "profile", "baseline", 0);
+
+#ifndef USE_QSV
+              av_opt_set(c->priv_data, "preset", "ultrafast", 0);
+#endif
+//             av_opt_set(c->priv_data, "preset", "fast", 0);
+            av_opt_set(c->priv_data, "tune", "zerolatency", 0);
+//             av_opt_set_int(c->priv_data, "tune", 0, 0);
+//             av_opt_set_double(c->priv_data,"look_ahead",0.03,0);
+//             av_opt_set(c->priv_data,"qp","qp_constant",0);
+//             av_opt_set_int(c->priv_data,"rc_method",9,0);
+//             av_opt_set(c->priv_data,"look_ahead_downsampling","off",0);
          }
 
           /* open it */
-          int ret = avcodec_open2(c, codec, NULL);
+          ret = avcodec_open2(c, codec, NULL);
           if (ret < 0) {
               std::cout<<"Could not open codec: "<<std::endl;
  //             fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
@@ -185,9 +263,14 @@ void ThreadEnc()
             if (ret < 0)
                 exit(1);
 
-            memcpy(frame->data[0],strbuf,gnwidth*gnheight);
-            memcpy(frame->data[1],strbuf + gnwidth*gnheight,gnwidth*gnheight/4);
-            memcpy(frame->data[2],strbuf+gnwidth*gnheight+gnwidth*gnheight/4,gnwidth*gnheight/4);
+            yuvI420ToNV12(strbuf,1280,720,strbufnv12);
+            memcpy(frame->data[0],strbufnv12,gnwidth*gnheight);
+            memcpy(frame->data[1],strbufnv12 + gnwidth*gnheight,gnwidth*gnheight*1/2);
+//            memcpy(frame->data[2],strbuf+gnwidth*gnheight+gnwidth*gnheight/4,gnwidth*gnheight/4);
+
+ //           memcpy(frame->data[0],strbuf,gnwidth*gnheight);
+ //           memcpy(frame->data[1],strbuf + gnwidth*gnheight,gnwidth*gnheight/4);
+ //           memcpy(frame->data[2],strbuf+gnwidth*gnheight+gnwidth*gnheight/4,gnwidth*gnheight/4);
 
             frame->pts = i;i++;
 
@@ -225,13 +308,16 @@ void Listenpic(const char * strdata,const unsigned int nSize,const unsigned int
 
  //       qDebug("jpg");
         std::vector<unsigned char> buff(pic.picdata().data(),pic.picdata().data()+pic.picdata().size());
+        QTime xTime;
+        xTime.start();
         mat = cv::imdecode(buff,1);
+//        std::cout<<" jpg decode time: "<<xTime.elapsed()<<std::endl;
     }
 
     cv::Mat dstYuvImage;
     QTime xTime;
     xTime.start();
-    cv::cvtColor(mat, dstYuvImage, CV_BGR2YUV_I420);
+    cv::cvtColor(mat, dstYuvImage,  CV_BGR2YUV_I420);
 //    std::cout<<" cvt time: "<<xTime.elapsed()<<std::endl;
     gMutexLock.lock();
     memcpy(gstrbuffer,(char *)dstYuvImage.data,gnwidth*gnheight*3/2);
@@ -249,6 +335,9 @@ int main(int argc, char *argv[])
 {
     QCoreApplication a(argc, argv);
 
+    gFile.setFileName("/home/yuchuli/test1.mp4");
+    gFile.open(QIODevice::ReadWrite);
+
     gstrbuffer = new char[30000000];
     gstrout = new char[10000000];
     gnwidth = atoi(gstrwidth);