main.cpp 10.4 KB
#include "FFNvDecoderManager.h"
#include <iostream>

#include "cuda_kernels.h"

#include "NvJpegEncoder.h"

#include <pthread.h>
#include <thread>

#include <chrono>

unsigned char *pHwRgb[2] = {nullptr, nullptr};

int sum1 = 0;
int sum2 = 0;

cudaStream_t stream[2];

/**
 * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况
 * */
void postDecoded(const void * userPtr, AVFrame * gpuFrame){
    FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
    if (decoder!= nullptr)
    {
        // cout << "decode name: " << decoder->getName() << endl;

            // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);
            // cout << "pixfmt: " << gpu_pixfmt << endl;
            // cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
            // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;

            int sum = sum1;
            if (decoder->getName() == "dec1")
            {
                sum1 ++ ;
                sum = sum1;

                if (gpuFrame->format == AV_PIX_FMT_CUDA)
                {   
                    cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
                    cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
                    cudaError_t cudaStatus;
                    if(pHwRgb[0] == nullptr){
                        // cudaStreamCreate(&stream[0]);
                        cuda_common::setColorSpace2( ITU709, 0 );
                        cudaStatus = cudaMalloc((void **)&pHwRgb[0], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
                    }
                    cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[0], gpuFrame->width, gpuFrame->height);
                    cudaDeviceSynchronize();
                    if (cudaStatus != cudaSuccess) {
                        cout << "CUDAToBGR failed !!!" << endl;
                        return;
                    }

                    string path = "/home/cmhu/data/" + decoder->getName() + "/" + to_string(sum) + ".jpg";
                    saveJpeg(path.c_str(), pHwRgb[0], gpuFrame->width, gpuFrame->height, stream[0]);  // 验证 CUDAToRGB 
                }
            } else if (decoder->getName() == "dec2") 
            {
                sum2 ++ ;
                sum = sum2;

                if (gpuFrame->format == AV_PIX_FMT_CUDA)
                {   
                    cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
                    cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
                    cudaError_t cudaStatus;
                    if(pHwRgb[1] == nullptr){
                        // cudaStreamCreate(&stream[1]);
                        cuda_common::setColorSpace2( ITU709, 0 );
                        cudaStatus = cudaMalloc((void **)&pHwRgb[1], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
                    }
                    cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[1], gpuFrame->width, gpuFrame->height);
                    cudaDeviceSynchronize();
                    if (cudaStatus != cudaSuccess) {
                        cout << "CUDAToBGR failed !!!" << endl;
                        return;
                    }

                    string path = "/home/cmhu/data/" + decoder->getName() + "/" + to_string(sum) + ".jpg";
                    saveJpeg(path.c_str(), pHwRgb[1], gpuFrame->width, gpuFrame->height, stream[1]);  // 验证 CUDAToRGB 
                }
            }
    }
}

long start_time = 0;
long end_time = 0;
bool count_flag = false;
int count = 0;
int count_std = 100;

long long get_cur_time(){
    // 获取操作系统当前时间点(精确到微秒)
    chrono::time_point<chrono::system_clock, chrono::microseconds> tpMicro
        = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now());
    // (微秒精度的)时间点 => (微秒精度的)时间戳
    time_t totalMicroSeconds = tpMicro.time_since_epoch().count();

	long long currentTime = ((long long)totalMicroSeconds)/1000;

    return currentTime;
}

int sum = 0;
unsigned char *pHwData = nullptr;

void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
    FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
    if (decoder!= nullptr)
    {
        // cout << "decode name: " << decoder->getName() << endl;
        if (decoder->getName() == "dec")
        {
            if (! count_flag)
            {
                count_flag = true;
                count = 0;
                end_time = start_time = get_cur_time();
            }
            count++;
            sum ++ ;
            if (count >= count_std)
            {
                end_time = get_cur_time();
                long time_using = end_time - start_time;
                double time_per_frame = double(time_using)/count_std ;
                cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl;
                cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
                cout << gpuFrame->pts << endl;

                count_flag = false;
            }

            if (gpuFrame->format == AV_PIX_FMT_CUDA)
            {   
                cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
                cout << "gpu id : " << decoder->m_cfg.gpuid.c_str() << endl;
                cudaError_t cudaStatus;
                if(pHwData == nullptr){
                    cuda_common::setColorSpace2( ITU709, 0 );
                    cudaStatus = cudaMalloc((void **)&pHwData, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
                }
                cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwData, gpuFrame->width, gpuFrame->height);
                cudaDeviceSynchronize();
                if (cudaStatus != cudaSuccess) {
                    cout << "CUDAToBGR failed !!!" << endl;
                    return;
                }

                string path = "/home/cmhu/data/test/" + to_string(sum) + ".jpg";
                saveJpeg(path.c_str(), pHwData, gpuFrame->width, gpuFrame->height, nullptr);  // 验证 CUDAToRGB 
            }
        }
    }
}

// string test_uri = "rtmp://192.168.10.56:1935/objecteye/1";
// string test_uri = "/home/cmhu/data/output_800x480.mp4";
string test_uri = "/home/cmhu/data/output_1920x1080.mp4";

void createDecode(int index){
    FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
    MgrDecConfig config;
    config.name = "dec" + to_string(index);
    config.cfg.uri = test_uri;
    config.cfg.post_decoded_cbk = postDecoded;
    config.cfg.force_tcp = true;

    if (index % 2 == 0)
    {
        config.cfg.gpuid = "2";
    }
    else
    {
        config.cfg.gpuid = "1";
    }
    
    FFNvDecoder* decoder = pDecManager->createDecoder(config);
    if (!decoder)
    {
        return ;
    }
    pDecManager->setUserPtr(config.name, decoder);
    pDecManager->startDecodeByName(config.name);
}

#define checkCudaErrors(S) do {CUresult  status; \
        status = S; \
        if (status != CUDA_SUCCESS ) std::cout << __LINE__ <<" checkCudaErrors - status = " << status << std::endl; \
        } while (false)

int CheckCUDAProperty( int devId )
{
    cuInit(0);

	CUdevice dev = devId;
	size_t memSize = 0;
	char devName[256] = {0};
	int major = 0, minor = 0;
	CUresult rlt = CUDA_SUCCESS;

	rlt = cuDeviceComputeCapability( &major, &minor, dev );
	checkCudaErrors( rlt );

	rlt = cuDeviceGetName( devName, sizeof( devName ), dev );
	checkCudaErrors( rlt );

	printf( "Using GPU Device %d: %s has SM %d.%d compute capability\n",
		    dev, devName, major, minor );

	rlt = cuDeviceTotalMem( &memSize, dev );
	checkCudaErrors( rlt );

	printf( "Total amount of global memory:   %4.4f MB\n",
		   (float)memSize / ( 1024 * 1024 ) );

	return 0;
}

int main(){

    CheckCUDAProperty(1);

    FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();

    int count = 99;
    for (size_t i = 0; i < count ; i++)
    {
        createDecode(i);
    }

    MgrDecConfig config;
    config.name = "dec";
    config.cfg.uri = test_uri;
    config.cfg.post_decoded_cbk = postDecoded0;
    config.cfg.force_tcp = true;
    config.cfg.gpuid = "1";
    FFNvDecoder* dec2 = pDecManager->createDecoder(config);
    if (!dec2)
    {
        return 1;
    }
    pDecManager->setUserPtr(config.name, dec2);
    pDecManager->startDecodeByName(config.name);

    pthread_t m_decode_thread;
    pthread_create(&m_decode_thread,0,
        [](void* arg)
        {
            while (true)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(5000));
                FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
                int count = pDecManager->count();
                cout << "当前运行路数: " << pDecManager->count() << endl;
                if (count <= 0)
                {
                    break;
                }
            }  

            return (void*)0;
        }
    ,nullptr);

    
    // config.name = "dec0";
    // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
    // config.cfg.gpuid = "0";
    // FFNvDecoder* dec0 = pDecManager->createDecoder(config);
    // if (!dec0)
    // {
    //     return 1;
    // }
    // pDecManager->setUserPtr(config.name, dec0);
    // pDecManager->startDecodeByName(config.name);

    // config.name = "dec01";
    // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
    // config.cfg.gpuid = "0";
    // FFNvDecoder* dec01 = pDecManager->createDecoder(config);
    // if (!dec01)
    // {
    //     return 1;
    // }
    // pDecManager->setUserPtr(config.name, dec01);
    // pDecManager->startDecodeByName(config.name);

    // while (getchar() != 'q');  

    // // pDecManager->closeDecoderByName("dec1");
    // // pDecManager->pauseDecoder("dec1");
    // pDecManager->pauseDecoder("dec2");

    // while (getchar() != 'q');

    // // pDecManager->resumeDecoder("dec1");
    // pDecManager->resumeDecoder("dec2");

    cout << "总共帧数:" << sum << endl;

    while (getchar() != 'q');

    pDecManager->closeAllDecoder();
}