video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2021-07-30 8f44600c2e5d6141aebf49536a6ddbafc6c18d75
csrc/thirdparty/gb28181/include/PsToEs.hpp
@@ -4,7 +4,9 @@
#include <deque>
#include <pthread.h>
#include <unistd.h>
#include "librtsp.h"
#include <sys/time.h>
using namespace std;
@@ -14,7 +16,7 @@
public:
    MyQueue():mtx(PTHREAD_MUTEX_INITIALIZER), cond(PTHREAD_COND_INITIALIZER){
        t.tv_sec = 0;
        t.tv_nsec = 20000000;
        t.tv_nsec = 0;
    }
    ~MyQueue() {
@@ -39,9 +41,16 @@
    T pop() {
        pthread_mutex_lock(&mtx);
        while (q.empty()) {
            pthread_cond_wait(&cond, &mtx);
        if (q.empty()) {
            gettimeofday(&now, NULL);
            t.tv_sec = now.tv_sec + 3;
            t.tv_nsec = now.tv_usec * 1000;
//            pthread_cond_wait(&cond, &mtx);
            pthread_cond_timedwait(&cond, &mtx, &t);
        }
        if (q.empty()) {
            pthread_mutex_unlock(&mtx);
            return 0;
        }
        T value = q.front();
        q.pop_front();
@@ -67,11 +76,22 @@
      while (!q.empty()) q.pop_front();
      pthread_mutex_unlock(&mtx);
    }
   void clearAll(std::function<void(T)> fn){
      pthread_mutex_lock(&mtx);
      while (!q.empty()){
         T value = q.front();
         fn(value);
         q.pop_front();
      }
      pthread_mutex_unlock(&mtx);
   }
private:
    deque<T> q;
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    timespec t;
    struct timeval now;
};
typedef struct _buffInfo {
@@ -87,11 +107,25 @@
   ~GB28181API(){
      printf("GB28181API end!\n");
      m_rtpQueue.clearAll();
      // m_rtpQueue.clearAll();
      m_rtpQueue.clearAll([](frameBuffInfo *info){
         if (info){
            delete[] info->buff;
            delete info;
         }
      });
      deleteCamera();
   }
   bool pushInfo(unsigned char *data, int datalen) {
      while(m_rtpQueue.count_queue() > 120){
            auto p = m_rtpQueue.popNotWait();
            if (p){
                delete[] p->buff;
                delete p;
            }
        }
      frameBuffInfo *info = new frameBuffInfo();
      info->buff = new unsigned char[datalen];
@@ -115,7 +149,11 @@
         //从缓存中获取buffinfo
         frameBuffInfo *buffinfo = _this->m_rtpQueue.pop();
//         printf(" m_rtpQueue.pop after \n");
            if(buffinfo != nullptr){
         diff = len - buffinfo->buffLen;
            }else{
                return 0;
            }
         //帧长大于bufsize
         if (diff < 0) {
@@ -127,6 +165,13 @@
            info->buff = new unsigned char[buffinfo->buffLen - len]{};
            memcpy(info->buff, buffinfo->buff + len, buffinfo->buffLen - len);
            while(_this->m_rtpQueue.count_queue() > 120){
                    auto p = _this->m_rtpQueue.popNotWait();
                    if (p){
                        delete[] p->buff;
                        delete p;
                    }
                }
//            printf("/帧长大于info->buffLen:%d\n", info->buffLen);
            _this->m_rtpQueue.push_front_one(info);
//            printf("/帧长大于info->buffLen\n");
@@ -149,21 +194,79 @@
       return bufsize;
   }
    static int capturePic(void *opaque, char *buf, int *bufsize, const int tt) {
        GB28181API *_this = (GB28181API *) opaque;
        int len = 0;
        *bufsize = 0;
        int ttt = 0;
        do {
           if (ttt > tt) return 0;
           ttt++;
            //从缓存中获取buffinfo
            if (_this->m_rtpQueue.count_queue() == 0) {
//                printf(" count_queue == 0 \n");
                usleep(200000);
                continue;
            }
            frameBuffInfo *buffinfo = _this->m_rtpQueue.pop();
            if (buffinfo == nullptr) {
                printf(" buffinfo == nullptr \n");
                return 0;
            }
////////////////////////////////////////////////////////
            FILE* fpJpg = NULL;
             char fileJpgName[32] = "./tmpCaptureJpg.jpg";
            char fileIFrameName[32] = "./tmpCaptureX264IFrame";
            char cmd[512] = {0};
            for(int i = 0; i < 10 * 25; i++){
               if (!buffinfo){
                  buffinfo = _this->m_rtpQueue.pop();
               }
               if (!buffinfo) continue;
               auto fpIframe = fopen(fileIFrameName, "wb+");
               fwrite(buffinfo->buff, buffinfo->buffLen, 1, fpIframe);
               fflush(fpIframe);
               fclose(fpIframe);
               memset(cmd, 0, 512);
               sprintf(cmd, "ffmpeg -i %s -y -f image2 -ss 00:00:00 -vframes 1 %s >/dev/null", fileIFrameName,
                       fileJpgName);
               int rr = system(cmd);
                delete[] buffinfo->buff;
               delete buffinfo;
               buffinfo = nullptr;
               fpJpg = fopen(fileJpgName, "rb");
               if (fpJpg) {
                   break;
               }
            }
///////////////////////////////////////////////////////////
            fseek(fpJpg, 0, SEEK_END);
            len = ftell(fpJpg);
            fseek(fpJpg, 0, SEEK_SET);
            *bufsize = fread(buf, sizeof(char), len, fpJpg);
            fclose(fpJpg);
            memset(cmd, 0, 128);
            sprintf(cmd, "rm %s %s >/dev/null", fileIFrameName, fileJpgName);
            system(cmd);
        } while (*bufsize == 0);
        return *bufsize;
    }
   static void streamCallBack(int datatype, int frametype, unsigned char *data, unsigned int datalen, long userdata)
   {
      GB28181API *_this = (GB28181API *)userdata;
      //printf("userdata:%ld,datatype:%d, frametype:%d,  datalen:%d\n", userdata, datatype, frametype, datalen);
      /*static FILE* fp_write = NULL;
      if (!fp_write)
      {
          fp_write = fopen("stream_callback.mp4", "wb+");
      }
      fwrite(data, sizeof(char), datalen, fp_write);   */
      static bool startFlag = false;
      if(frametype == GB_VIDEO_FRAME_I){
@@ -174,20 +277,27 @@
      }
   }
   void addCamera(string &rtsp){
//      long userdata = 1001;//
      printf("RTSPSTREAM_Open\n");
      handle = RTSPSTREAM_Open(rtsp.c_str(), streamCallBack, (long)this);
//      return handle;
   long addCamera(string &rtsp){
        int count = 0;
        while (handle == -1 && count <= 3) {
            count ++;
            handle = RTSPSTREAM_Open(rtsp.c_str(), streamCallBack, (long) this);
            printf("RTSPSTREAM_Open, handle:%ld \n", handle);
        }
      return handle;
   }
   void deleteCamera(){
      printf("RTSPSTREAM_Close\n");
      RTSPSTREAM_Close(handle);
      if(handle != -1){
         RTSPSTREAM_Close(handle);
      }
      handle = -1;
   }   
private:
   MyQueue<frameBuffInfo *> m_rtpQueue;
   long handle;
   long handle = -1;
};