Commit bc52e542d1e046d2f5c24ba363331191f31f08b5
1 parent
f667f79a
添加关键帧解码功能
Showing
6 changed files
with
118 additions
and
45 deletions
.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& cfg) | @@ -215,7 +215,7 @@ bool FFNvDecoderManager::isSurport(FFDecConfig& 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 |