Commit 3c7e3e11e19bf471a835a17f40ae895783bbf6ab

Authored by Hu Chunming
1 parent 0a826b3d

1.修改日志

2.添加DECODE_FINISHED_CALLBACK
3.添加isPausing接口
4.添加getCachedQueueLength接口
5.添加snapshot和releaseFFImgInfo接口
6.测试代码添加log回调的自定义设置
src/FFNvDecoder.cpp
1 1 #include "FFNvDecoder.h"
2   -#include<iostream>
3 2  
4 3 #include <chrono>
5 4 #include <thread>
... ... @@ -24,7 +23,7 @@ static AVPixelFormat get_hw_format(AVCodecContext *avctx, const AVPixelFormat *p
24 23 return *p;
25 24 }
26 25  
27   - //cout << "Failed to get HW surface format";
  26 + av_log(NULL, AV_LOG_ERROR, "Failed to get HW surface format. \n");
28 27 return AV_PIX_FMT_NONE;
29 28 }
30 29  
... ... @@ -86,13 +85,13 @@ bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
86 85 fmt_ctx = avformat_alloc_context();
87 86 const char* input_file = uri;
88 87 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
89   - cout << "Cannot open input file: " << input_file;
  88 + av_log(NULL, AV_LOG_ERROR, "Cannot open input file: %s \n", input_file);
90 89 return false;
91 90 }
92 91  
93 92 // 查找流信息
94 93 if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
95   - cout << "Cannot find input stream information";
  94 + av_log(NULL, AV_LOG_ERROR, "Cannot find input stream information ! \n");
96 95 return false;
97 96 }
98 97  
... ... @@ -100,7 +99,7 @@ bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
100 99 AVCodec *decoder = nullptr;
101 100 stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
102 101 if (stream_index < 0) {
103   - cout << "Cannot find a video stream in the input file";
  102 + av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file ! \n");
104 103 return false;
105 104 }
106 105  
... ... @@ -130,9 +129,9 @@ bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
130 129 // 打开解码器流
131 130 AVDictionary *op = nullptr;
132 131 av_dict_set( &op, "gpu", gpuid, 0 );
133   - // av_dict_set( &op, "surfaces", "3", 0 );
  132 + av_dict_set( &op, "surfaces", "10", 0 );
134 133 if (avcodec_open2(avctx, vcodec, &op) < 0) {
135   - cout << "Failed to open codec for stream" << stream_index;
  134 + av_log(NULL, AV_LOG_ERROR, "Failed to open codec for stream ! \n");
136 135 return false;
137 136 }
138 137  
... ... @@ -208,14 +207,9 @@ void FFNvDecoder::decode_thread()
208 207 }
209 208  
210 209 int result = av_read_frame(fmt_ctx, pkt);
211   - if (result == AVERROR_EOF)
  210 + if (result == AVERROR_EOF || result < 0)
212 211 {
213   - cout << "Failed to read frame!" << endl;
214   - break;
215   - }
216   - if (result < 0)
217   - {
218   - cout << "Failed to read frame!" << endl;
  212 + av_log(NULL, AV_LOG_ERROR, "Failed to read frame! \n");
219 213 break;
220 214 }
221 215  
... ... @@ -234,19 +228,16 @@ void FFNvDecoder::decode_thread()
234 228 }
235 229 }
236 230  
237   - if (stream_index == pkt->stream_index)
238   - {
  231 + if (stream_index == pkt->stream_index){
239 232 result = avcodec_send_packet(avctx, pkt);
240   - if (result < 0)
241   - {
242   - cout << "Failed to send pkt:" << result << endl;
  233 + if (result < 0){
  234 + av_log(NULL, AV_LOG_ERROR, "Failed to send pkt: %d \n",result);
243 235 continue;
244 236 }
245 237  
246 238 result = avcodec_receive_frame(avctx, gpuFrame);
247   - if (result == AVERROR(EAGAIN) || result == AVERROR_EOF || result < 0)
248   - {
249   - cout << "Failed to receive frame"<< endl;
  239 + if ((result == AVERROR(EAGAIN) || result == AVERROR_EOF) || result < 0){
  240 + av_log(NULL, AV_LOG_ERROR, "Failed to receive frame: %d \n",result);
250 241 continue;
251 242 }
252 243  
... ... @@ -255,6 +246,14 @@ void FFNvDecoder::decode_thread()
255 246 av_packet_unref(pkt);
256 247 }
257 248  
  249 + // 队列中没有数据了再结束
  250 + while (mFrameQueue.length() > 0){
  251 + if(!m_bRunning){
  252 + break;
  253 + }
  254 + std::this_thread::sleep_for(std::chrono::milliseconds(10));
  255 + }
  256 +
258 257 m_bRunning = false;
259 258  
260 259 // long end_time = get_cur_time();
... ... @@ -266,9 +265,11 @@ void FFNvDecoder::decode_thread()
266 265 pthread_join(m_post_decode_thread,0);
267 266 }
268 267  
  268 + decode_finished_cbk(m_userPtr);
  269 +
269 270 decode_finished();
270 271  
271   - cout << "decode thread exited." << endl;
  272 + av_log(NULL, AV_LOG_INFO, "decode thread exited. \n");
272 273 }
273 274  
274 275 void FFNvDecoder::decode_finished()
... ... @@ -289,7 +290,7 @@ void FFNvDecoder::decode_finished()
289 290  
290 291 void FFNvDecoder::post_decode_thread()
291 292 {
292   - while (m_bRunning)
  293 + while (m_bRunning || mFrameQueue.length() > 0)
293 294 {
294 295 AVFrame * gpuFrame = mFrameQueue.getHead();
295 296 if (gpuFrame == nullptr)
... ... @@ -302,8 +303,8 @@ void FFNvDecoder::post_decode_thread()
302 303  
303 304 mFrameQueue.addHead();
304 305 }
305   -
306   - cout << "post decode thread exited." << endl;
  306 +
  307 + av_log(NULL, AV_LOG_INFO, "post decode thread exited. \n");
307 308 }
308 309  
309 310 void FFNvDecoder::close()
... ... @@ -338,6 +339,10 @@ bool FFNvDecoder::isFinished()
338 339 return m_bFinished;
339 340 }
340 341  
  342 +bool FFNvDecoder::isPausing(){
  343 + return m_bPause;
  344 +}
  345 +
341 346 bool FFNvDecoder::getResolution( int &width, int &height )
342 347 {
343 348 if (avctx != nullptr)
... ... @@ -363,4 +368,135 @@ void FFNvDecoder::resume()
363 368 void FFNvDecoder::setDecKeyframe(bool bKeyframe)
364 369 {
365 370 m_dec_keyframe = bKeyframe;
  371 +}
  372 +
  373 +int FFNvDecoder::getCachedQueueLength(){
  374 + return mFrameQueue.length();
  375 +}
  376 +
  377 +FFImgInfo* FFNvDecoder::snapshot(const string& uri){
  378 +
  379 + AVFormatContext* ifmt_ctx = NULL;
  380 + AVCodecContext* codec_ctx = nullptr;
  381 + AVCodec* codec = nullptr;
  382 + AVPacket* pkt = nullptr;
  383 + AVFrame *frame = nullptr;
  384 + AVFrame *pFrameRGB = nullptr;
  385 + int video_index = -1;
  386 + AVStream* st = nullptr;
  387 + SwsContext *img_convert_ctx = nullptr;
  388 + uint8_t *buffer = NULL;
  389 + int numBytes = 0;
  390 +
  391 + FFImgInfo* imgInfo = nullptr;
  392 +
  393 + //av_register_all();
  394 + avformat_network_init();
  395 +
  396 + ///打开输入的流
  397 + int ret = avformat_open_input(&ifmt_ctx, uri.c_str(), NULL, NULL);
  398 + if (ret != 0){
  399 + av_log(NULL, AV_LOG_ERROR, "Couldn't open input stream ! \n");
  400 + goto end_flag ;
  401 + }
  402 +
  403 + //查找流信息
  404 + if (avformat_find_stream_info(ifmt_ctx, NULL) < 0){
  405 + av_log(NULL, AV_LOG_ERROR, "Couldn't find stream information ! \n");
  406 + goto end_flag ;
  407 + }
  408 +
  409 + //找到视频流索引
  410 + video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
  411 +
  412 + st = ifmt_ctx->streams[video_index];
  413 +
  414 + //找到解码器
  415 + codec = avcodec_find_decoder(st->codecpar->codec_id);
  416 + if (!codec){
  417 + av_log(NULL, AV_LOG_ERROR, "Codec not found ! \n");
  418 + goto end_flag ;
  419 + }
  420 +
  421 + //申请AVCodecContext
  422 + codec_ctx = avcodec_alloc_context3(codec);
  423 + if (!codec_ctx){
  424 + goto end_flag ;
  425 + }
  426 +
  427 + avcodec_parameters_to_context(codec_ctx, ifmt_ctx->streams[video_index]->codecpar);
  428 +
  429 + //打开解码器
  430 + if ((ret = avcodec_open2(codec_ctx, codec, NULL) < 0)){
  431 + goto end_flag ;
  432 + }
  433 +
  434 + // 计算解码后原始数据所需缓冲区大小,并分配内存空间 Determine required buffer size and allocate buffer
  435 + numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
  436 + buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
  437 +
  438 + pFrameRGB = av_frame_alloc();
  439 + av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_BGR24, codec_ctx->width, codec_ctx->height, 1);
  440 +
  441 + img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height,codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_BGR24,
  442 + SWS_BICUBIC, NULL, NULL, NULL);
  443 +
  444 + pkt = av_packet_alloc();
  445 + frame = av_frame_alloc();
  446 + while (av_read_frame(ifmt_ctx, pkt) >= 0){
  447 + if (pkt->stream_index == video_index){
  448 + int ret = avcodec_send_packet(codec_ctx, pkt);
  449 + if (ret >= 0){
  450 + ret = avcodec_receive_frame(codec_ctx, frame);
  451 + if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){
  452 + av_log(NULL, AV_LOG_ERROR, "Failed to receive frame: %d \n", ret);
  453 + continue;
  454 + }
  455 +
  456 + sws_scale(img_convert_ctx, (const unsigned char* const*)frame->data, frame->linesize, 0, codec_ctx->height, pFrameRGB->data, pFrameRGB->linesize);
  457 +
  458 + imgInfo = new FFImgInfo();
  459 + imgInfo->pData = buffer;
  460 + imgInfo->height = codec_ctx->height;
  461 + imgInfo->width = codec_ctx->width;
  462 +
  463 + break;
  464 + }
  465 + }
  466 + }
  467 +
  468 +end_flag:
  469 + if (codec_ctx != nullptr){
  470 + avcodec_close(codec_ctx);
  471 + avcodec_free_context(&codec_ctx);
  472 + }
  473 +
  474 + if (ifmt_ctx != nullptr){
  475 + avformat_close_input(&ifmt_ctx);
  476 + }
  477 +
  478 + if (frame != nullptr){
  479 + av_frame_free(&frame);
  480 + }
  481 +
  482 + if (pFrameRGB != nullptr){
  483 + av_frame_free(&pFrameRGB);
  484 + }
  485 +
  486 + if (pkt != nullptr){
  487 + av_packet_free(&pkt);
  488 + }
  489 +
  490 + return imgInfo;
  491 +}
  492 +
  493 +void FFNvDecoder::releaseFFImgInfo(FFImgInfo* info){
  494 + if(nullptr != info){
  495 + if(info->pData != nullptr){
  496 + av_free(info->pData);
  497 + info->pData = nullptr;
  498 + }
  499 + delete info;
  500 + info = nullptr;
  501 + }
366 502 }
367 503 \ No newline at end of file
... ...
src/FFNvDecoder.h
... ... @@ -12,6 +12,7 @@ extern &quot;C&quot;
12 12 #include <libavutil/avutil.h>
13 13 #include <libavutil/pixdesc.h>
14 14 #include <libswscale/swscale.h>
  15 + #include <libavutil/imgutils.h>
15 16 }
16 17  
17 18 using namespace std;
... ... @@ -29,14 +30,22 @@ using namespace std;
29 30 **************************************************/
30 31 typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame);
31 32  
32   -struct FFDecConfig
33   -{
  33 +typedef void(*DECODE_FINISHED_CALLBACK)(const void* userPtr);
  34 +
  35 +struct FFDecConfig{
34 36 string uri; // 视频地址
35 37 POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口
  38 + DECODE_FINISHED_CALLBACK decode_finished_cbk; // 解码线程结束后的回调接口
36 39 string gpuid; // gpu id
37 40 bool force_tcp{true}; // 是否指定使用tcp连接
38 41 };
39 42  
  43 +struct FFImgInfo{
  44 + int width;
  45 + int height;
  46 + unsigned char * pData;
  47 +};
  48 +
40 49 class FFNvDecoder{
41 50 public:
42 51 FFNvDecoder();
... ... @@ -51,6 +60,7 @@ public:
51 60  
52 61 bool isRunning();
53 62 bool isFinished();
  63 + bool isPausing();
54 64 bool getResolution( int &width, int &height );
55 65  
56 66 void setName(string nm);
... ... @@ -58,6 +68,12 @@ public:
58 68  
59 69 bool isSurport(FFDecConfig& cfg);
60 70  
  71 + int getCachedQueueLength();
  72 +
  73 + static FFImgInfo* snapshot(const string& uri);
  74 +
  75 + static void releaseFFImgInfo(FFImgInfo*);
  76 +
61 77 public:
62 78 AVPixelFormat getHwPixFmt();
63 79  
... ... @@ -69,6 +85,7 @@ private:
69 85  
70 86 public:
71 87 POST_DECODE_CALLBACK post_decoded_cbk;
  88 + DECODE_FINISHED_CALLBACK decode_finished_cbk;
72 89 const void * m_userPtr;
73 90 FFDecConfig m_cfg;
74 91  
... ...
src/FFNvDecoderManager.cpp
1 1 #include "FFNvDecoderManager.h"
2   -#include<iostream>
3 2  
4 3 using namespace std;
5 4  
6 5  
7   -FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){
  6 +FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){
8 7  
9 8 closeAllFinishedDecoder();
10 9  
11   - int num = decoderMap.count(config.name);
12   - if (num > 0)
13   - {
14   - cout << "已存在name所标记的解码器" << endl;
  10 + std::lock_guard<std::mutex> l(m_mutex);
  11 +
  12 + auto it = decoderMap.find(config.name);
  13 + if (it != decoderMap.end()){
  14 + av_log(NULL, AV_LOG_ERROR, "已存在name所标记的解码器 \n");
15 15 return nullptr;
16 16 }
17 17  
... ... @@ -26,6 +26,7 @@ FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig&amp; config){
26 26 {
27 27 dec->setName(config.name) ;
28 28 dec->post_decoded_cbk = config.cfg.post_decoded_cbk;
  29 + dec->decode_finished_cbk = config.cfg.decode_finished_cbk;
29 30 decoderMap[config.name] = dec;
30 31 return dec;
31 32 }
... ... @@ -41,10 +42,12 @@ bool FFNvDecoderManager::setUserPtr(const string name, const void * userPtr)
41 42 {
42 43 if (name.empty())
43 44 {
44   - cout << "name 为空!"<< endl;
  45 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
45 46 return false;
46 47 }
47 48  
  49 + std::lock_guard<std::mutex> l(m_mutex);
  50 +
48 51 auto dec = decoderMap.find(name);
49 52 if (dec != decoderMap.end())
50 53 {
... ... @@ -52,7 +55,7 @@ bool FFNvDecoderManager::setUserPtr(const string name, const void * userPtr)
52 55 return true;
53 56 }
54 57  
55   - cout << "没有找到name为" << name << "的解码器!" << endl;
  58 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
56 59 return false;
57 60 }
58 61  
... ... @@ -60,17 +63,19 @@ FFNvDecoder* FFNvDecoderManager::getDecoderByName(const string name)
60 63 {
61 64 if (name.empty())
62 65 {
63   - cout << "name 为空!"<< endl;
  66 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
64 67 return nullptr;
65 68 }
66 69  
  70 + std::lock_guard<std::mutex> l(m_mutex);
  71 +
67 72 auto dec = decoderMap.find(name);
68 73 if (dec != decoderMap.end())
69 74 {
70 75 return dec->second;
71 76 }
72 77  
73   - cout << "没有找到name为" << name << "的解码器!" << endl;
  78 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
74 79 return nullptr;
75 80 }
76 81  
... ... @@ -84,10 +89,12 @@ void FFNvDecoderManager::startDecode(FFNvDecoder* dec){
84 89 bool FFNvDecoderManager::startDecodeByName(const string name){
85 90 if (name.empty())
86 91 {
87   - cout << "name 为空!"<< endl;
  92 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
88 93 return false;
89 94 }
90 95  
  96 + std::lock_guard<std::mutex> l(m_mutex);
  97 +
91 98 auto dec = decoderMap.find(name);
92 99 if (dec != decoderMap.end())
93 100 {
... ... @@ -95,11 +102,14 @@ bool FFNvDecoderManager::startDecodeByName(const string name){
95 102 return true;
96 103 }
97 104  
98   - cout << "没有找到name为" << name << "的解码器!" << endl;
  105 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
99 106 return false;
100 107 }
101 108  
102 109 void FFNvDecoderManager::startAllDecode(){
  110 +
  111 + std::lock_guard<std::mutex> l(m_mutex);
  112 +
103 113 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
104 114 if (!iter->second->isRunning())
105 115 {
... ... @@ -111,11 +121,12 @@ void FFNvDecoderManager::startAllDecode(){
111 121 bool FFNvDecoderManager::closeDecoderByName(const string name){
112 122 if (name.empty())
113 123 {
114   - cout << "name 为空!"<< endl;
  124 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
115 125 return false;
116 126 }
117 127  
118   - m_mutex_erase.lock();
  128 + std::lock_guard<std::mutex> l(m_mutex);
  129 +
119 130 auto dec = decoderMap.find(name);
120 131 if (dec != decoderMap.end())
121 132 {
... ... @@ -124,30 +135,29 @@ bool FFNvDecoderManager::closeDecoderByName(const string name){
124 135 dec->second = nullptr;
125 136 decoderMap.erase(dec);
126 137  
127   - m_mutex_erase.unlock();
128 138 return true;
129 139 }
130 140  
131   - m_mutex_erase.unlock();
132   - cout << "没有找到name为" << name << "的解码器!" << endl;
  141 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
133 142 return false;
134 143 }
135 144  
136 145 void FFNvDecoderManager::closeAllDecoder()
137 146 {
138   - m_mutex_erase.lock();
  147 + std::lock_guard<std::mutex> l(m_mutex);
  148 +
139 149 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
140 150 iter->second->close();
141 151 delete iter->second;
142 152 iter->second = nullptr;
143 153 }
144 154 decoderMap.clear();
145   - m_mutex_erase.unlock();
146 155 }
147 156  
148 157 void FFNvDecoderManager::closeAllFinishedDecoder()
149 158 {
150   - m_mutex_erase.lock();
  159 + std::lock_guard<std::mutex> l(m_mutex);
  160 +
151 161 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); ){
152 162 if (iter->second->isFinished())
153 163 {
... ... @@ -160,13 +170,13 @@ void FFNvDecoderManager::closeAllFinishedDecoder()
160 170 iter++ ;
161 171 }
162 172 }
163   - m_mutex_erase.unlock();
164 173 }
165 174  
166 175 int FFNvDecoderManager::count()
167 176 {
168 177 closeAllFinishedDecoder();
169 178  
  179 + std::lock_guard<std::mutex> l(m_mutex);
170 180 return decoderMap.size();
171 181 }
172 182  
... ... @@ -174,10 +184,12 @@ bool FFNvDecoderManager::pauseDecoder(const string name)
174 184 {
175 185 if (name.empty())
176 186 {
177   - cout << "name 为空!"<< endl;
  187 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
178 188 return false;
179 189 }
180 190  
  191 + std::lock_guard<std::mutex> l(m_mutex);
  192 +
181 193 auto dec = decoderMap.find(name);
182 194 if (dec != decoderMap.end())
183 195 {
... ... @@ -185,7 +197,7 @@ bool FFNvDecoderManager::pauseDecoder(const string name)
185 197 return true;
186 198 }
187 199  
188   - cout << "没有找到name为" << name << "的解码器!" << endl;
  200 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
189 201 return false;
190 202 }
191 203  
... ... @@ -193,10 +205,12 @@ bool FFNvDecoderManager::resumeDecoder(const string name)
193 205 {
194 206 if (name.empty())
195 207 {
196   - cout << "name 为空!"<< endl;
  208 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
197 209 return false;
198 210 }
199 211  
  212 + std::lock_guard<std::mutex> l(m_mutex);
  213 +
200 214 auto dec = decoderMap.find(name);
201 215 if (dec != decoderMap.end())
202 216 {
... ... @@ -204,7 +218,7 @@ bool FFNvDecoderManager::resumeDecoder(const string name)
204 218 return true;
205 219 }
206 220  
207   - cout << "没有找到name为" << name << "的解码器!" << endl;
  221 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
208 222 return false;
209 223 }
210 224  
... ... @@ -217,17 +231,57 @@ bool FFNvDecoderManager::isSurport(FFDecConfig&amp; cfg)
217 231 bool FFNvDecoderManager::isRunning(const string name){
218 232 if (name.empty())
219 233 {
220   - cout << "name 为空!"<< endl;
  234 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
221 235 return false;
222 236 }
223 237  
  238 + std::lock_guard<std::mutex> l(m_mutex);
  239 +
224 240 auto dec = decoderMap.find(name);
225 241 if (dec != decoderMap.end())
226 242 {
227 243 return dec->second->isRunning();
228 244 }
229 245  
230   - cout << "没有找到name为" << name << "的解码器!" << endl;
  246 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
  247 + return false;
  248 +}
  249 +
  250 +bool FFNvDecoderManager::isFinished(const string name){
  251 + if (name.empty())
  252 + {
  253 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
  254 + return false;
  255 + }
  256 +
  257 + std::lock_guard<std::mutex> l(m_mutex);
  258 +
  259 + auto dec = decoderMap.find(name);
  260 + if (dec != decoderMap.end())
  261 + {
  262 + return dec->second->isFinished();
  263 + }
  264 +
  265 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
  266 + return false;
  267 +}
  268 +
  269 +bool FFNvDecoderManager::isPausing(const string name){
  270 + if (name.empty())
  271 + {
  272 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
  273 + return false;
  274 + }
  275 +
  276 + std::lock_guard<std::mutex> l(m_mutex);
  277 +
  278 + auto dec = decoderMap.find(name);
  279 + if (dec != decoderMap.end())
  280 + {
  281 + return dec->second->isPausing();
  282 + }
  283 +
  284 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
231 285 return false;
232 286 }
233 287  
... ... @@ -235,10 +289,12 @@ bool FFNvDecoderManager::setDecKeyframe(const string name, bool bKeyframe)
235 289 {
236 290 if (name.empty())
237 291 {
238   - cout << "name 为空!"<< endl;
  292 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
239 293 return false;
240 294 }
241 295  
  296 + std::lock_guard<std::mutex> l(m_mutex);
  297 +
242 298 auto dec = decoderMap.find(name);
243 299 if (dec != decoderMap.end())
244 300 {
... ... @@ -246,6 +302,65 @@ bool FFNvDecoderManager::setDecKeyframe(const string name, bool bKeyframe)
246 302 return true;
247 303 }
248 304  
249   - cout << "没有找到name为" << name << "的解码器!" << endl;
  305 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
  306 + return false;
  307 +}
  308 +
  309 +bool FFNvDecoderManager::getResolution(const string name, int &width, int &height)
  310 +{
  311 + if (name.empty())
  312 + {
  313 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
  314 + return false;
  315 + }
  316 +
  317 + std::lock_guard<std::mutex> l(m_mutex);
  318 +
  319 + auto dec = decoderMap.find(name);
  320 + if (dec != decoderMap.end())
  321 + {
  322 + dec->second->getResolution(width, height);
  323 + return true;
  324 + }
  325 +
  326 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
250 327 return false;
  328 +}
  329 +
  330 +vector<string> FFNvDecoderManager::getAllDecodeName(){
  331 +
  332 + closeAllFinishedDecoder();
  333 +
  334 + std::lock_guard<std::mutex> l(m_mutex);
  335 +
  336 + vector<string> decode_names;
  337 + for(auto it = decoderMap.begin(); it != decoderMap.end(); ++it){
  338 + decode_names.push_back(it->first);
  339 + }
  340 + return decode_names;
  341 +}
  342 +
  343 +int FFNvDecoderManager::getCachedQueueLength(const string name){
  344 + if (name.empty()){
  345 + av_log(NULL, AV_LOG_ERROR, "name 为空! \n");
  346 + return -1;
  347 + }
  348 +
  349 + std::lock_guard<std::mutex> l(m_mutex);
  350 +
  351 + auto dec = decoderMap.find(name);
  352 + if (dec != decoderMap.end()){
  353 + return dec->second->getCachedQueueLength();
  354 + }
  355 +
  356 + av_log(NULL, AV_LOG_ERROR, "没有找到name为 %s 的解码器! \n", name.c_str());
  357 + return -1;
  358 +}
  359 +
  360 +FFImgInfo* FFNvDecoderManager::snapshot(const string& uri){
  361 + return FFNvDecoder::snapshot(uri);
  362 +}
  363 +
  364 +void FFNvDecoderManager::releaseFFImgInfo(FFImgInfo* info){
  365 + FFNvDecoder::releaseFFImgInfo(info);
251 366 }
252 367 \ No newline at end of file
... ...
src/FFNvDecoderManager.h
... ... @@ -45,7 +45,7 @@ public:
45 45 * 返回:成功返回解码器, 失败返回 nullptr
46 46 * 备注:
47 47 **************************************************/
48   - FFNvDecoder* createDecoder(MgrDecConfig& config);
  48 + FFNvDecoder* createDecoder(MgrDecConfig config);
49 49  
50 50 /**************************************************
51 51 * 接口:setUserPtr
... ... @@ -111,6 +111,15 @@ public:
111 111 **************************************************/
112 112 void closeAllDecoder();
113 113  
  114 + /**************************************************
  115 + * 接口:closeAllDecoderByGpuid
  116 + * 功能:关闭某张显卡撒花姑娘的全部解码器
  117 + * 参数:const string gpuid gpu的id
  118 + * 返回:void
  119 + * 备注:
  120 + **************************************************/
  121 + void closeAllDecoderByGpuid(const string gpuid);
  122 +
114 123 /**************************************************
115 124 * 接口:pauseDecoder
116 125 * 功能:暂停指定名称的解码器
... ... @@ -147,6 +156,24 @@ public:
147 156 **************************************************/
148 157 bool isRunning(const string name);
149 158  
  159 + /**************************************************
  160 + * 接口:isFinished
  161 + * 功能:根据解码器名称判断解码器是否已经结束
  162 + * 参数:const string name 解码器名称
  163 + * 返回:正在运行返回true,否则返回false
  164 + * 备注:
  165 + **************************************************/
  166 + bool isFinished(const string name);
  167 +
  168 + /**************************************************
  169 + * 接口:isPausing
  170 + * 功能:根据解码器名称判断解码器是否暂停
  171 + * 参数:const string name 解码器名称
  172 + * 返回:正在运行返回true,否则返回false
  173 + * 备注:
  174 + **************************************************/
  175 + bool isPausing(const string name);
  176 +
150 177 /**************************************************
151 178 * 接口:count
152 179 * 功能:获取正在运行的解码器数量
... ... @@ -161,11 +188,58 @@ public:
161 188 * 功能:设置是否只解码关键帧。默认全解
162 189 * 参数:const string name 解码器名称
163 190 * bool bKeyframe 是否只解码关键帧。true,只解码关键帧;false,普通的全解码
164   - * 返回:void
  191 + * 返回:bool 成功返回true,失败返回false
165 192 * 备注:
166 193 **************************************************/
167 194 bool setDecKeyframe(const string name, bool bKeyframe);
168 195  
  196 + /**************************************************
  197 + * 接口:getResolution
  198 + * 功能:获取视频分辨率
  199 + * 参数:const string name 解码器名称
  200 + * int &width 从 width 返回视频宽度
  201 + * int &height 从 height 返回视频高度
  202 + * 返回:bool 成功获取返回true,失败返回false
  203 + * 备注:
  204 + **************************************************/
  205 + bool getResolution(const string name, int &width, int &height);
  206 +
  207 + /**************************************************
  208 + * 接口:getAllDecodeName
  209 + * 功能:获取全部解码器名称
  210 + * 参数:void
  211 + * 返回:vector<string> 返回全部解码器名称
  212 + * 备注:
  213 + **************************************************/
  214 + vector<string> getAllDecodeName();
  215 +
  216 + /**************************************************
  217 + * 接口:getCachedQueueLength
  218 + * 功能:获取解码缓冲队列当前长度
  219 + * 参数:const string name 解码器名称
  220 + * 返回:int 解码缓冲队列当前长度
  221 + * 备注:
  222 + **************************************************/
  223 + int getCachedQueueLength(const string name);
  224 +
  225 + /**************************************************
  226 + * 接口:snapshot
  227 + * 功能:获取视频快照
  228 + * 参数:const string& uri 视频地址
  229 + * 返回:FFImgInfo* 快照信息
  230 + * 备注:
  231 + **************************************************/
  232 + FFImgInfo* snapshot(const string& uri);
  233 +
  234 + /**************************************************
  235 + * 接口:releaseFFImgInfo
  236 + * 功能:释放视频快照信息
  237 + * 参数:FFImgInfo* info 视频快照信息
  238 + * 返回:void
  239 + * 备注:
  240 + **************************************************/
  241 + void releaseFFImgInfo(FFImgInfo* info);
  242 +
169 243 private:
170 244 FFNvDecoderManager(){}
171 245  
... ... @@ -174,5 +248,5 @@ private:
174 248 private:
175 249 map<string, FFNvDecoder*> decoderMap;
176 250  
177   - mutex m_mutex_erase;
  251 + mutex m_mutex;
178 252 };
179 253 \ No newline at end of file
... ...
src/main.cpp
... ... @@ -225,8 +225,16 @@ int CheckCUDAProperty( int devId )
225 225 return 0;
226 226 }
227 227  
  228 +void logFF(void *, int level, const char *fmt, va_list ap)
  229 +{
  230 + vfprintf(stdout, fmt, ap);
  231 +}
  232 +
  233 +
228 234 int main(){
229 235  
  236 + // av_log_set_callback(&logFF);
  237 +
230 238 CheckCUDAProperty(0);
231 239  
232 240 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
... ...