Commit bc52e542d1e046d2f5c24ba363331191f31f08b5

Authored by Hu Chunming
1 parent f667f79a

添加关键帧解码功能

.vscode/settings.json
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 "typeinfo": "cpp", 9 "typeinfo": "cpp",
10 "iostream": "cpp", 10 "iostream": "cpp",
11 "thread": "cpp", 11 "thread": "cpp",
12 - "nvdec.h": "c" 12 + "nvdec.h": "c",
  13 + "chrono": "cpp"
13 } 14 }
14 } 15 }
15 \ No newline at end of file 16 \ No newline at end of file
src/FFNvDecoder.cpp
@@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
5 #include <thread> 5 #include <thread>
6 #include <fstream> 6 #include <fstream>
7 7
  8 +#include <chrono>
  9 +
8 #include "FFCuContextManager.h" 10 #include "FFCuContextManager.h"
9 11
10 using namespace std; 12 using namespace std;
@@ -45,11 +47,12 @@ FFNvDecoder::FFNvDecoder() @@ -45,11 +47,12 @@ FFNvDecoder::FFNvDecoder()
45 m_post_decode_thread = 0; 47 m_post_decode_thread = 0;
46 48
47 m_bFinished = false; 49 m_bFinished = false;
  50 + m_dec_keyframe = false;
48 } 51 }
49 52
50 FFNvDecoder::~FFNvDecoder() 53 FFNvDecoder::~FFNvDecoder()
51 { 54 {
52 - 55 + m_dec_keyframe = false;
53 } 56 }
54 57
55 bool FFNvDecoder::init(FFDecConfig& cfg) 58 bool FFNvDecoder::init(FFDecConfig& cfg)
@@ -157,6 +160,18 @@ void FFNvDecoder::start(){ @@ -157,6 +160,18 @@ void FFNvDecoder::start(){
157 ,this); 160 ,this);
158 } 161 }
159 162
  163 +static long long get_cur_time(){
  164 + // 获取操作系统当前时间点(精确到微秒)
  165 + chrono::time_point<chrono::system_clock, chrono::microseconds> tpMicro
  166 + = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now());
  167 + // (微秒精度的)时间点 => (微秒精度的)时间戳
  168 + time_t totalMicroSeconds = tpMicro.time_since_epoch().count();
  169 +
  170 + long long currentTime = ((long long)totalMicroSeconds)/1000;
  171 +
  172 + return currentTime;
  173 +}
  174 +
160 void FFNvDecoder::decode_thread() 175 void FFNvDecoder::decode_thread()
161 { 176 {
162 AVPacket* pkt ; 177 AVPacket* pkt ;
@@ -172,6 +187,8 @@ void FFNvDecoder::decode_thread() @@ -172,6 +187,8 @@ void FFNvDecoder::decode_thread()
172 } 187 }
173 ,this); 188 ,this);
174 189
  190 + // long start_time = get_cur_time();
  191 +
175 while (m_bRunning) 192 while (m_bRunning)
176 { 193 {
177 if (!m_bReal) 194 if (!m_bReal)
@@ -202,6 +219,11 @@ void FFNvDecoder::decode_thread() @@ -202,6 +219,11 @@ void FFNvDecoder::decode_thread()
202 break; 219 break;
203 } 220 }
204 221
  222 + if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) {
  223 + av_packet_unref(pkt);
  224 + continue;
  225 + }
  226 +
205 if (m_bReal) 227 if (m_bReal)
206 { 228 {
207 if (m_bPause) 229 if (m_bPause)
@@ -235,6 +257,10 @@ void FFNvDecoder::decode_thread() @@ -235,6 +257,10 @@ void FFNvDecoder::decode_thread()
235 257
236 m_bRunning = false; 258 m_bRunning = false;
237 259
  260 + // long end_time = get_cur_time();
  261 +
  262 + // cout << "解码用时:" << end_time - start_time << endl;
  263 +
238 if (m_post_decode_thread != 0) 264 if (m_post_decode_thread != 0)
239 { 265 {
240 pthread_join(m_post_decode_thread,0); 266 pthread_join(m_post_decode_thread,0);
@@ -258,6 +284,7 @@ void FFNvDecoder::decode_finished() @@ -258,6 +284,7 @@ void FFNvDecoder::decode_finished()
258 } 284 }
259 285
260 m_bFinished = true; 286 m_bFinished = true;
  287 + m_dec_keyframe = false;
261 } 288 }
262 289
263 void FFNvDecoder::post_decode_thread() 290 void FFNvDecoder::post_decode_thread()
@@ -285,6 +312,7 @@ void FFNvDecoder::close() @@ -285,6 +312,7 @@ void FFNvDecoder::close()
285 if(m_decode_thread != 0){ 312 if(m_decode_thread != 0){
286 pthread_join(m_decode_thread,0); 313 pthread_join(m_decode_thread,0);
287 } 314 }
  315 + m_dec_keyframe = false;
288 } 316 }
289 317
290 void FFNvDecoder::setName(string nm){ 318 void FFNvDecoder::setName(string nm){
@@ -330,4 +358,9 @@ void FFNvDecoder::pause() @@ -330,4 +358,9 @@ void FFNvDecoder::pause()
330 void FFNvDecoder::resume() 358 void FFNvDecoder::resume()
331 { 359 {
332 m_bPause = false; 360 m_bPause = false;
  361 +}
  362 +
  363 +void FFNvDecoder::setDecKeyframe(bool bKeyframe)
  364 +{
  365 + m_dec_keyframe = bKeyframe;
333 } 366 }
334 \ No newline at end of file 367 \ No newline at end of file
src/FFNvDecoder.h
@@ -47,6 +47,8 @@ public: @@ -47,6 +47,8 @@ public:
47 void pause(); 47 void pause();
48 void resume(); 48 void resume();
49 49
  50 + void setDecKeyframe(bool bKeyframe);
  51 +
50 bool isRunning(); 52 bool isRunning();
51 bool isFinished(); 53 bool isFinished();
52 bool getResolution( int &width, int &height ); 54 bool getResolution( int &width, int &height );
@@ -88,4 +90,6 @@ private: @@ -88,4 +90,6 @@ private:
88 FrameQueue mFrameQueue; 90 FrameQueue mFrameQueue;
89 91
90 bool m_bReal; // 是否实时流 92 bool m_bReal; // 是否实时流
  93 +
  94 + bool m_dec_keyframe;
91 }; 95 };
92 \ No newline at end of file 96 \ No newline at end of file
src/FFNvDecoderManager.cpp
@@ -215,7 +215,7 @@ bool FFNvDecoderManager::isSurport(FFDecConfig&amp; cfg) @@ -215,7 +215,7 @@ bool FFNvDecoderManager::isSurport(FFDecConfig&amp; cfg)
215 } 215 }
216 216
217 bool FFNvDecoderManager::isRunning(const string name){ 217 bool FFNvDecoderManager::isRunning(const string name){
218 - if (name.empty()) 218 + if (name.empty())
219 { 219 {
220 cout << "name 为空!"<< endl; 220 cout << "name 为空!"<< endl;
221 return false; 221 return false;
@@ -229,4 +229,23 @@ bool FFNvDecoderManager::isRunning(const string name){ @@ -229,4 +229,23 @@ bool FFNvDecoderManager::isRunning(const string name){
229 229
230 cout << "没有找到name为" << name << "的解码器!" << endl; 230 cout << "没有找到name为" << name << "的解码器!" << endl;
231 return false; 231 return false;
  232 +}
  233 +
  234 +bool FFNvDecoderManager::setDecKeyframe(const string name, bool bKeyframe)
  235 +{
  236 + if (name.empty())
  237 + {
  238 + cout << "name 为空!"<< endl;
  239 + return false;
  240 + }
  241 +
  242 + auto dec = decoderMap.find(name);
  243 + if (dec != decoderMap.end())
  244 + {
  245 + dec->second->setDecKeyframe(bKeyframe);
  246 + return true;
  247 + }
  248 +
  249 + cout << "没有找到name为" << name << "的解码器!" << endl;
  250 + return false;
232 } 251 }
233 \ No newline at end of file 252 \ No newline at end of file
src/FFNvDecoderManager.h
@@ -156,6 +156,16 @@ public: @@ -156,6 +156,16 @@ public:
156 **************************************************/ 156 **************************************************/
157 int count(); 157 int count();
158 158
  159 + /**************************************************
  160 + * 接口:setDecKeyframe
  161 + * 功能:设置是否只解码关键帧。默认全解
  162 + * 参数:const string name 解码器名称
  163 + * bool bKeyframe 是否只解码关键帧。true,只解码关键帧;false,普通的全解码
  164 + * 返回:void
  165 + * 备注:
  166 + **************************************************/
  167 + bool setDecKeyframe(const string name, bool bKeyframe);
  168 +
159 private: 169 private:
160 FFNvDecoderManager(){} 170 FFNvDecoderManager(){}
161 171
src/main.cpp
@@ -92,7 +92,7 @@ bool count_flag = false; @@ -92,7 +92,7 @@ bool count_flag = false;
92 int count = 0; 92 int count = 0;
93 int count_std = 100; 93 int count_std = 100;
94 94
95 -long long get_cur_time(){ 95 +static long long get_cur_time(){
96 // 获取操作系统当前时间点(精确到微秒) 96 // 获取操作系统当前时间点(精确到微秒)
97 chrono::time_point<chrono::system_clock, chrono::microseconds> tpMicro 97 chrono::time_point<chrono::system_clock, chrono::microseconds> tpMicro
98 = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now()); 98 = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now());
@@ -104,10 +104,12 @@ long long get_cur_time(){ @@ -104,10 +104,12 @@ long long get_cur_time(){
104 return currentTime; 104 return currentTime;
105 } 105 }
106 106
107 -int sum = 0; 107 +static int sum = 0;
108 unsigned char *pHwData = nullptr; 108 unsigned char *pHwData = nullptr;
109 109
110 void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ 110 void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
  111 + // std::this_thread::sleep_for(std::chrono::milliseconds(30000));
  112 +
111 FFNvDecoder* decoder = (FFNvDecoder*)userPtr; 113 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
112 if (decoder!= nullptr) 114 if (decoder!= nullptr)
113 { 115 {
@@ -122,44 +124,47 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ @@ -122,44 +124,47 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
122 } 124 }
123 count++; 125 count++;
124 sum ++ ; 126 sum ++ ;
125 - if (count >= count_std)  
126 - {  
127 - end_time = get_cur_time();  
128 - long time_using = end_time - start_time;  
129 - double time_per_frame = double(time_using)/count_std ;  
130 - cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl;  
131 - cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;  
132 - cout << gpuFrame->pts << endl;  
133 -  
134 - count_flag = false;  
135 - }  
136 -  
137 - if (gpuFrame->format == AV_PIX_FMT_CUDA)  
138 - {  
139 - cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));  
140 - cout << "gpu id : " << decoder->m_cfg.gpuid.c_str() << endl;  
141 - cudaError_t cudaStatus;  
142 - if(pHwData == nullptr){  
143 - cuda_common::setColorSpace2( ITU709, 0 );  
144 - cudaStatus = cudaMalloc((void **)&pHwData, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));  
145 - }  
146 - cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwData, gpuFrame->width, gpuFrame->height);  
147 - cudaDeviceSynchronize();  
148 - if (cudaStatus != cudaSuccess) {  
149 - cout << "CUDAToBGR failed !!!" << endl;  
150 - return;  
151 - }  
152 -  
153 - string path = "/home/cmhu/data/test/" + to_string(sum) + ".jpg";  
154 - saveJpeg(path.c_str(), pHwData, gpuFrame->width, gpuFrame->height, nullptr); // 验证 CUDAToRGB  
155 - } 127 + // if (count >= count_std)
  128 + // {
  129 + // // end_time = get_cur_time();
  130 + // // long time_using = end_time - start_time;
  131 + // // double time_per_frame = double(time_using)/count_std ;
  132 + // // cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl;
  133 + // cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
  134 + // cout << gpuFrame->pts << endl;
  135 +
  136 + // count_flag = false;
  137 + // }
  138 + // cout << "帧数:" << sum << endl;
  139 +
  140 + // if (gpuFrame->format == AV_PIX_FMT_CUDA)
  141 + // {
  142 + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
  143 + // // cout << "gpu id : " << decoder->m_cfg.gpuid.c_str() << endl;
  144 + // cudaError_t cudaStatus;
  145 + // if(pHwData == nullptr){
  146 + // cuda_common::setColorSpace2( ITU709, 0 );
  147 + // cudaStatus = cudaMalloc((void **)&pHwData, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
  148 + // }
  149 + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwData, gpuFrame->width, gpuFrame->height);
  150 + // cudaDeviceSynchronize();
  151 + // if (cudaStatus != cudaSuccess) {
  152 + // cout << "CUDAToBGR failed !!!" << endl;
  153 + // return;
  154 + // }
  155 +
  156 + // string path = "/home/cmhu/data/test/" + to_string(sum) + ".jpg";
  157 + // saveJpeg(path.c_str(), pHwData, gpuFrame->width, gpuFrame->height, nullptr); // 验证 CUDAToRGB
  158 + // }
156 } 159 }
157 } 160 }
158 } 161 }
159 162
160 // string test_uri = "rtmp://192.168.10.56:1935/objecteye/1"; 163 // string test_uri = "rtmp://192.168.10.56:1935/objecteye/1";
161 // string test_uri = "/home/cmhu/data/output_800x480.mp4"; 164 // string test_uri = "/home/cmhu/data/output_800x480.mp4";
162 -string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; 165 +// string test_uri = "/home/cmhu/data/output_1920x1080.mp4";
  166 +// string test_uri = "rtsp://176.10.0.2:8554/stream";
  167 +string test_uri = "/home/cmhu/data2/Street.uvf";
163 168
164 void createDecode(int index){ 169 void createDecode(int index){
165 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); 170 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
@@ -226,24 +231,25 @@ int main(){ @@ -226,24 +231,25 @@ int main(){
226 231
227 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); 232 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
228 233
229 - int count = 99;  
230 - for (size_t i = 0; i < count ; i++)  
231 - {  
232 - createDecode(i);  
233 - } 234 + // int count = 99;
  235 + // for (size_t i = 0; i < count ; i++)
  236 + // {
  237 + // createDecode(i);
  238 + // }
234 239
235 MgrDecConfig config; 240 MgrDecConfig config;
236 config.name = "dec"; 241 config.name = "dec";
237 config.cfg.uri = test_uri; 242 config.cfg.uri = test_uri;
238 config.cfg.post_decoded_cbk = postDecoded0; 243 config.cfg.post_decoded_cbk = postDecoded0;
239 config.cfg.force_tcp = true; 244 config.cfg.force_tcp = true;
240 - config.cfg.gpuid = "1"; 245 + config.cfg.gpuid = "2";
241 FFNvDecoder* dec2 = pDecManager->createDecoder(config); 246 FFNvDecoder* dec2 = pDecManager->createDecoder(config);
242 if (!dec2) 247 if (!dec2)
243 { 248 {
244 return 1; 249 return 1;
245 } 250 }
246 pDecManager->setUserPtr(config.name, dec2); 251 pDecManager->setUserPtr(config.name, dec2);
  252 + pDecManager->setDecKeyframe(config.name, true);
247 pDecManager->startDecodeByName(config.name); 253 pDecManager->startDecodeByName(config.name);
248 254
249 pthread_t m_decode_thread; 255 pthread_t m_decode_thread;
@@ -300,9 +306,9 @@ int main(){ @@ -300,9 +306,9 @@ int main(){
300 // // pDecManager->resumeDecoder("dec1"); 306 // // pDecManager->resumeDecoder("dec1");
301 // pDecManager->resumeDecoder("dec2"); 307 // pDecManager->resumeDecoder("dec2");
302 308
303 - cout << "总共帧数:" << sum << endl;  
304 -  
305 while (getchar() != 'q'); 309 while (getchar() != 'q');
306 310
  311 + cout << "总共帧数:" << sum << endl;
  312 +
307 pDecManager->closeAllDecoder(); 313 pDecManager->closeAllDecoder();
308 } 314 }
309 \ No newline at end of file 315 \ No newline at end of file