From bc52e542d1e046d2f5c24ba363331191f31f08b5 Mon Sep 17 00:00:00 2001 From: cmhu <2657262686@qq.com> Date: Wed, 19 Oct 2022 10:27:29 +0800 Subject: [PATCH] 添加关键帧解码功能 --- .vscode/settings.json | 3 ++- src/FFNvDecoder.cpp | 35 ++++++++++++++++++++++++++++++++++- src/FFNvDecoder.h | 4 ++++ src/FFNvDecoderManager.cpp | 21 ++++++++++++++++++++- src/FFNvDecoderManager.h | 10 ++++++++++ src/main.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------ 6 files changed, 118 insertions(+), 45 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c2847e1..7cfc35b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "typeinfo": "cpp", "iostream": "cpp", "thread": "cpp", - "nvdec.h": "c" + "nvdec.h": "c", + "chrono": "cpp" } } \ No newline at end of file diff --git a/src/FFNvDecoder.cpp b/src/FFNvDecoder.cpp index ffd6be9..d491a17 100644 --- a/src/FFNvDecoder.cpp +++ b/src/FFNvDecoder.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include "FFCuContextManager.h" using namespace std; @@ -45,11 +47,12 @@ FFNvDecoder::FFNvDecoder() m_post_decode_thread = 0; m_bFinished = false; + m_dec_keyframe = false; } FFNvDecoder::~FFNvDecoder() { - + m_dec_keyframe = false; } bool FFNvDecoder::init(FFDecConfig& cfg) @@ -157,6 +160,18 @@ void FFNvDecoder::start(){ ,this); } +static long long get_cur_time(){ + // 获取操作系统当前时间点(精确到微秒) + chrono::time_point tpMicro + = chrono::time_point_cast(chrono::system_clock::now()); + // (微秒精度的)时间点 => (微秒精度的)时间戳 + time_t totalMicroSeconds = tpMicro.time_since_epoch().count(); + + long long currentTime = ((long long)totalMicroSeconds)/1000; + + return currentTime; +} + void FFNvDecoder::decode_thread() { AVPacket* pkt ; @@ -172,6 +187,8 @@ void FFNvDecoder::decode_thread() } ,this); + // long start_time = get_cur_time(); + while (m_bRunning) { if (!m_bReal) @@ -202,6 +219,11 @@ void FFNvDecoder::decode_thread() break; } + if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) { + av_packet_unref(pkt); + continue; + } + if (m_bReal) { if (m_bPause) @@ -235,6 +257,10 @@ void FFNvDecoder::decode_thread() m_bRunning = false; + // long end_time = get_cur_time(); + + // cout << "解码用时:" << end_time - start_time << endl; + if (m_post_decode_thread != 0) { pthread_join(m_post_decode_thread,0); @@ -258,6 +284,7 @@ void FFNvDecoder::decode_finished() } m_bFinished = true; + m_dec_keyframe = false; } void FFNvDecoder::post_decode_thread() @@ -285,6 +312,7 @@ void FFNvDecoder::close() if(m_decode_thread != 0){ pthread_join(m_decode_thread,0); } + m_dec_keyframe = false; } void FFNvDecoder::setName(string nm){ @@ -330,4 +358,9 @@ void FFNvDecoder::pause() void FFNvDecoder::resume() { m_bPause = false; +} + +void FFNvDecoder::setDecKeyframe(bool bKeyframe) +{ + m_dec_keyframe = bKeyframe; } \ No newline at end of file diff --git a/src/FFNvDecoder.h b/src/FFNvDecoder.h index 7fcce6c..35e016e 100644 --- a/src/FFNvDecoder.h +++ b/src/FFNvDecoder.h @@ -47,6 +47,8 @@ public: void pause(); void resume(); + void setDecKeyframe(bool bKeyframe); + bool isRunning(); bool isFinished(); bool getResolution( int &width, int &height ); @@ -88,4 +90,6 @@ private: FrameQueue mFrameQueue; bool m_bReal; // 是否实时流 + + bool m_dec_keyframe; }; \ No newline at end of file diff --git a/src/FFNvDecoderManager.cpp b/src/FFNvDecoderManager.cpp index 4044778..2624c39 100644 --- a/src/FFNvDecoderManager.cpp +++ b/src/FFNvDecoderManager.cpp @@ -215,7 +215,7 @@ bool FFNvDecoderManager::isSurport(FFDecConfig& cfg) } bool FFNvDecoderManager::isRunning(const string name){ - if (name.empty()) + if (name.empty()) { cout << "name 为空!"<< endl; return false; @@ -229,4 +229,23 @@ bool FFNvDecoderManager::isRunning(const string name){ cout << "没有找到name为" << name << "的解码器!" << endl; return false; +} + +bool FFNvDecoderManager::setDecKeyframe(const string name, bool bKeyframe) +{ + if (name.empty()) + { + cout << "name 为空!"<< endl; + return false; + } + + auto dec = decoderMap.find(name); + if (dec != decoderMap.end()) + { + dec->second->setDecKeyframe(bKeyframe); + return true; + } + + cout << "没有找到name为" << name << "的解码器!" << endl; + return false; } \ No newline at end of file diff --git a/src/FFNvDecoderManager.h b/src/FFNvDecoderManager.h index f05e5c8..0f6f075 100644 --- a/src/FFNvDecoderManager.h +++ b/src/FFNvDecoderManager.h @@ -156,6 +156,16 @@ public: **************************************************/ int count(); + /************************************************** + * 接口:setDecKeyframe + * 功能:设置是否只解码关键帧。默认全解 + * 参数:const string name 解码器名称 + * bool bKeyframe 是否只解码关键帧。true,只解码关键帧;false,普通的全解码 + * 返回:void + * 备注: + **************************************************/ + bool setDecKeyframe(const string name, bool bKeyframe); + private: FFNvDecoderManager(){} diff --git a/src/main.cpp b/src/main.cpp index e0fbba6..3f4b14f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -92,7 +92,7 @@ bool count_flag = false; int count = 0; int count_std = 100; -long long get_cur_time(){ +static long long get_cur_time(){ // 获取操作系统当前时间点(精确到微秒) chrono::time_point tpMicro = chrono::time_point_cast(chrono::system_clock::now()); @@ -104,10 +104,12 @@ long long get_cur_time(){ return currentTime; } -int sum = 0; +static int sum = 0; unsigned char *pHwData = nullptr; void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ + // std::this_thread::sleep_for(std::chrono::milliseconds(30000)); + FFNvDecoder* decoder = (FFNvDecoder*)userPtr; if (decoder!= nullptr) { @@ -122,44 +124,47 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ } 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 - } + // 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; + // } + // cout << "帧数:" << sum << endl; + + // 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"; +// string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; +// string test_uri = "rtsp://176.10.0.2:8554/stream"; +string test_uri = "/home/cmhu/data2/Street.uvf"; void createDecode(int index){ FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); @@ -226,24 +231,25 @@ int main(){ FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); - int count = 99; - for (size_t i = 0; i < count ; i++) - { - createDecode(i); - } + // 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"; + config.cfg.gpuid = "2"; FFNvDecoder* dec2 = pDecManager->createDecoder(config); if (!dec2) { return 1; } pDecManager->setUserPtr(config.name, dec2); + pDecManager->setDecKeyframe(config.name, true); pDecManager->startDecodeByName(config.name); pthread_t m_decode_thread; @@ -300,9 +306,9 @@ int main(){ // // pDecManager->resumeDecoder("dec1"); // pDecManager->resumeDecoder("dec2"); - cout << "总共帧数:" << sum << endl; - while (getchar() != 'q'); + cout << "总共帧数:" << sum << endl; + pDecManager->closeAllDecoder(); } \ No newline at end of file -- libgit2 0.21.4