#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <queue>

#include <opencv2/opencv.hpp>

/*
 * 定义一些输入量
 * FramInputPerSecond   输入源视频获取帧数
 * FramInputInterval    转化成时间间隔
 * TimeoutThreshold     帧过期丢弃阈值
*/
#define FramInputPerSecond  15
#define FramInputInterval   1000/FramInputPerSecond
#define TimeoutThreshold    50

class _fram
{
public:
    _fram(cv::Mat mat, std::chrono::system_clock::time_point tp) : framContent(mat), tp(tp){};
    ~_fram(){};
    cv::Mat framContent;
    std::chrono::system_clock::time_point tp;
};

std::mutex lock;
std::queue<_fram> framBuffer;

int playMedia(){

    double framTpInterval;    // ms time between two fram;
    

    while (true)
    {
        while (framBuffer.empty())
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(40));
            std::cout<<"wait for image"<<std::endl;
        }

        //cv::imshow("buffer",framBuffer.front().framContent);
        //假设需要20ms计算图像

        //模拟读取数据
        cv::Mat cal = framBuffer.front().framContent;
        //计算读取帧与模拟计算
        framTpInterval = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - framBuffer.front().tp).count();
        std::cout<<framTpInterval<<std::endl;
        if (framTpInterval > TimeoutThreshold)
            std::cout<< framTpInterval <<" 延迟!丢弃帧!"<<std::endl;
        else
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        
        framBuffer.pop(); 
        
    }
}

int main(){
    cv::VideoCapture v;
   
    v.open("v4l2src device=/dev/video0 ! image/jpeg,width=1280,height=720 ! jpegdec ! appsink",
            cv::CAP_GSTREAMER);

    if (!v.isOpened())
    {
        std::cout<<"Wrong Open Camera"<<std::endl;
        return -1;
    }


    std::thread T_playMedia(playMedia);
    /*
     *  主线程读取视频输入
     *  并存入到缓冲区中
     */
    while (true)
    {
        cv::Mat framTmp;
        std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();

        v.read(framTmp);

        framBuffer.emplace(framTmp, std::chrono::system_clock::now());
        std::chrono::system_clock::time_point t2 = std::chrono::system_clock::now();

        //std::cout<<std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()<<std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(FramInputInterval)); 
    }
    
     
}

山和山不相遇,人与人要相逢