Commit bc52e542d1e046d2f5c24ba363331191f31f08b5

Authored by Hu Chunming
1 parent f667f79a

添加关键帧解码功能

.vscode/settings.json
... ... @@ -9,6 +9,7 @@
9 9 "typeinfo": "cpp",
10 10 "iostream": "cpp",
11 11 "thread": "cpp",
12   - "nvdec.h": "c"
  12 + "nvdec.h": "c",
  13 + "chrono": "cpp"
13 14 }
14 15 }
15 16 \ No newline at end of file
... ...
src/FFNvDecoder.cpp
... ... @@ -5,6 +5,8 @@
5 5 #include <thread>
6 6 #include <fstream>
7 7  
  8 +#include <chrono>
  9 +
8 10 #include "FFCuContextManager.h"
9 11  
10 12 using namespace std;
... ... @@ -45,11 +47,12 @@ FFNvDecoder::FFNvDecoder()
45 47 m_post_decode_thread = 0;
46 48  
47 49 m_bFinished = false;
  50 + m_dec_keyframe = false;
48 51 }
49 52  
50 53 FFNvDecoder::~FFNvDecoder()
51 54 {
52   -
  55 + m_dec_keyframe = false;
53 56 }
54 57  
55 58 bool FFNvDecoder::init(FFDecConfig& cfg)
... ... @@ -157,6 +160,18 @@ void FFNvDecoder::start(){
157 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 175 void FFNvDecoder::decode_thread()
161 176 {
162 177 AVPacket* pkt ;
... ... @@ -172,6 +187,8 @@ void FFNvDecoder::decode_thread()
172 187 }
173 188 ,this);
174 189  
  190 + // long start_time = get_cur_time();
  191 +
175 192 while (m_bRunning)
176 193 {
177 194 if (!m_bReal)
... ... @@ -202,6 +219,11 @@ void FFNvDecoder::decode_thread()
202 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 227 if (m_bReal)
206 228 {
207 229 if (m_bPause)
... ... @@ -235,6 +257,10 @@ void FFNvDecoder::decode_thread()
235 257  
236 258 m_bRunning = false;
237 259  
  260 + // long end_time = get_cur_time();
  261 +
  262 + // cout << "解码用时:" << end_time - start_time << endl;
  263 +
238 264 if (m_post_decode_thread != 0)
239 265 {
240 266 pthread_join(m_post_decode_thread,0);
... ... @@ -258,6 +284,7 @@ void FFNvDecoder::decode_finished()
258 284 }
259 285  
260 286 m_bFinished = true;
  287 + m_dec_keyframe = false;
261 288 }
262 289  
263 290 void FFNvDecoder::post_decode_thread()
... ... @@ -285,6 +312,7 @@ void FFNvDecoder::close()
285 312 if(m_decode_thread != 0){
286 313 pthread_join(m_decode_thread,0);
287 314 }
  315 + m_dec_keyframe = false;
288 316 }
289 317  
290 318 void FFNvDecoder::setName(string nm){
... ... @@ -330,4 +358,9 @@ void FFNvDecoder::pause()
330 358 void FFNvDecoder::resume()
331 359 {
332 360 m_bPause = false;
  361 +}
  362 +
  363 +void FFNvDecoder::setDecKeyframe(bool bKeyframe)
  364 +{
  365 + m_dec_keyframe = bKeyframe;
333 366 }
334 367 \ No newline at end of file
... ...
src/FFNvDecoder.h
... ... @@ -47,6 +47,8 @@ public:
47 47 void pause();
48 48 void resume();
49 49  
  50 + void setDecKeyframe(bool bKeyframe);
  51 +
50 52 bool isRunning();
51 53 bool isFinished();
52 54 bool getResolution( int &width, int &height );
... ... @@ -88,4 +90,6 @@ private:
88 90 FrameQueue mFrameQueue;
89 91  
90 92 bool m_bReal; // 是否实时流
  93 +
  94 + bool m_dec_keyframe;
91 95 };
92 96 \ No newline at end of file
... ...
src/FFNvDecoderManager.cpp
... ... @@ -215,7 +215,7 @@ bool FFNvDecoderManager::isSurport(FFDecConfig&amp; cfg)
215 215 }
216 216  
217 217 bool FFNvDecoderManager::isRunning(const string name){
218   - if (name.empty())
  218 + if (name.empty())
219 219 {
220 220 cout << "name 为空!"<< endl;
221 221 return false;
... ... @@ -229,4 +229,23 @@ bool FFNvDecoderManager::isRunning(const string name){
229 229  
230 230 cout << "没有找到name为" << name << "的解码器!" << endl;
231 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 252 \ No newline at end of file
... ...
src/FFNvDecoderManager.h
... ... @@ -156,6 +156,16 @@ public:
156 156 **************************************************/
157 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 169 private:
160 170 FFNvDecoderManager(){}
161 171  
... ...
src/main.cpp
... ... @@ -92,7 +92,7 @@ bool count_flag = false;
92 92 int count = 0;
93 93 int count_std = 100;
94 94  
95   -long long get_cur_time(){
  95 +static long long get_cur_time(){
96 96 // 获取操作系统当前时间点(精确到微秒)
97 97 chrono::time_point<chrono::system_clock, chrono::microseconds> tpMicro
98 98 = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now());
... ... @@ -104,10 +104,12 @@ long long get_cur_time(){
104 104 return currentTime;
105 105 }
106 106  
107   -int sum = 0;
  107 +static int sum = 0;
108 108 unsigned char *pHwData = nullptr;
109 109  
110 110 void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
  111 + // std::this_thread::sleep_for(std::chrono::milliseconds(30000));
  112 +
111 113 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
112 114 if (decoder!= nullptr)
113 115 {
... ... @@ -122,44 +124,47 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
122 124 }
123 125 count++;
124 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 163 // string test_uri = "rtmp://192.168.10.56:1935/objecteye/1";
161 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 169 void createDecode(int index){
165 170 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
... ... @@ -226,24 +231,25 @@ int main(){
226 231  
227 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 240 MgrDecConfig config;
236 241 config.name = "dec";
237 242 config.cfg.uri = test_uri;
238 243 config.cfg.post_decoded_cbk = postDecoded0;
239 244 config.cfg.force_tcp = true;
240   - config.cfg.gpuid = "1";
  245 + config.cfg.gpuid = "2";
241 246 FFNvDecoder* dec2 = pDecManager->createDecoder(config);
242 247 if (!dec2)
243 248 {
244 249 return 1;
245 250 }
246 251 pDecManager->setUserPtr(config.name, dec2);
  252 + pDecManager->setDecKeyframe(config.name, true);
247 253 pDecManager->startDecodeByName(config.name);
248 254  
249 255 pthread_t m_decode_thread;
... ... @@ -300,9 +306,9 @@ int main(){
300 306 // // pDecManager->resumeDecoder("dec1");
301 307 // pDecManager->resumeDecoder("dec2");
302 308  
303   - cout << "总共帧数:" << sum << endl;
304   -
305 309 while (getchar() != 'q');
306 310  
  311 + cout << "总共帧数:" << sum << endl;
  312 +
307 313 pDecManager->closeAllDecoder();
308 314 }
309 315 \ No newline at end of file
... ...