//硬件H264 ffmpeg解码
#ifndef _HARD_H264_FFMPEG_DECODE_H
#define _HARD_H264_FFMPEG_DECODE_H

#include <iostream>
#include <chrono>
#include <cmath>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <queue>
#include <mutex>
#include <semaphore.h>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <vector>
#include <memory>

#ifdef __cplusplus
extern "C"
{
#endif
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif

#define DUMP_FRAME(frame) { \
   printf( "%s-%d AVFrame:format=%2d, key_frame=%d, pict_type=%d, width=%4d, height=%4d, data=(%d, %d, %d), linesize=(%4d, %4d, %4d)\n", \
    __func__, __LINE__, \
    frame->format, frame->key_frame, frame->pict_type, \
    frame->width,  frame->height, \
   (frame->data[0] != NULL), \
   (frame->data[1] != NULL), \
   (frame->data[2] != NULL),\
    frame->linesize[0], \
    frame->linesize[1], \
    frame->linesize[2] \
    );}

#define  NVIDIA_H264_DECODER  "h264_cuvid"   
// #define  NVIDIA_H264_DECODER  "h264_v4l2m2m"   

class HardH264FFmpegDecode
{
public:
    HardH264FFmpegDecode();
    ~HardH264FFmpegDecode();

    int HardH264FFmpegDecoderInit(unsigned int uiWidth, unsigned int uiHeight, unsigned int uiFrameRate = 30);
    int HardH264FFmpegDecoderDeInit();
    int HardH264FFmpegDecoder(AVCodecContext *pDecCtx, AVFrame *pFrame, AVPacket *pPkt, void* pOutputData, unsigned int* puiOutputDataSize);
    int HardH264FFmpegDecoderV2(AVCodecContext *pDecCtx, SwsContext *pSwsCtx, AVFrame *pSrcFrame, AVFrame *pDstFrame, AVPacket *pPkt, void* pOutputData, unsigned int* puiOutputDataSize);
    
    const AVCodec *pCodec_ = nullptr;     //解码器
    AVCodecContext *pCodecCtx_ = nullptr;   //上下文
	AVCodecParserContext *pCodecParserCtx_ = nullptr;   //解析器上下文
    AVFrame	*pSrcFrame_ = nullptr;  
    AVFrame	*pDstFrame_ = nullptr; 
    AVPacket *pPacket_ = nullptr;   
    SwsContext *pSwsContext_ = nullptr; 

    uint8_t *pu8OutBuffer_ = nullptr; 

private:
    int HardH264FFmpegDecoderFilterGraph(AVFilterGraph *pGraph, AVFilterContext *pSourceCtx, AVFilterContext *pSinkCtx);
    int HardH264FFmpegDecoderConfigureVideoFilters(AVFilterGraph *pGraph, AVFilterContext* &pDecoderFilterIn, AVFilterContext* &pDecoderFilterOut, const int iWidth, const int iHeight, const int iFormat);
   
    unsigned int uiWidth_, uiHeight_;

    int iFrameFinished_;
    unsigned int uiFrameRate_;
};

#endif

