Commit 48330793ad1c28eccd227fa1fa19b1f72b2fed6e

Authored by Hu Chunming
1 parent e96e6489

修正解码线程自然结束时解码器内存没有释放的问题

src/FFNvDecoder.cpp
@@ -41,6 +41,8 @@ FFNvDecoder::FFNvDecoder() @@ -41,6 +41,8 @@ FFNvDecoder::FFNvDecoder()
41 41
42 m_decode_thread = 0; 42 m_decode_thread = 0;
43 m_post_decode_thread = 0; 43 m_post_decode_thread = 0;
  44 +
  45 + m_bFinished = false;
44 } 46 }
45 47
46 FFNvDecoder::~FFNvDecoder() 48 FFNvDecoder::~FFNvDecoder()
@@ -73,12 +75,12 @@ bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp) @@ -73,12 +75,12 @@ bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
73 av_dict_set( &options, "bufsize", "655360", 0 ); 75 av_dict_set( &options, "bufsize", "655360", 0 );
74 av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 ); 76 av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 );
75 // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s 77 // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
76 - av_dict_set( &options, "stimeout", "3000000", 0 ); 78 + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
77 79
78 fmt_ctx = avformat_alloc_context(); 80 fmt_ctx = avformat_alloc_context();
79 const char* input_file = uri; 81 const char* input_file = uri;
80 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { 82 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
81 - cout << "Cannot open input file" << input_file; 83 + cout << "Cannot open input file: " << input_file;
82 return false; 84 return false;
83 } 85 }
84 86
@@ -135,6 +137,13 @@ void FFNvDecoder::start(){ @@ -135,6 +137,13 @@ void FFNvDecoder::start(){
135 return (void*)0; 137 return (void*)0;
136 } 138 }
137 ,this); 139 ,this);
  140 +}
  141 +
  142 +void FFNvDecoder::decode_thread()
  143 +{
  144 + AVPacket* pkt ;
  145 + pkt = av_packet_alloc();
  146 + av_init_packet( pkt );
138 147
139 pthread_create(&m_post_decode_thread,0, 148 pthread_create(&m_post_decode_thread,0,
140 [](void* arg) 149 [](void* arg)
@@ -144,13 +153,6 @@ void FFNvDecoder::start(){ @@ -144,13 +153,6 @@ void FFNvDecoder::start(){
144 return (void*)0; 153 return (void*)0;
145 } 154 }
146 ,this); 155 ,this);
147 -}  
148 -  
149 -void FFNvDecoder::decode_thread()  
150 -{  
151 - AVPacket* pkt ;  
152 - pkt = av_packet_alloc();  
153 - av_init_packet( pkt );  
154 156
155 while (m_bRunning) 157 while (m_bRunning)
156 { 158 {
@@ -214,9 +216,36 @@ void FFNvDecoder::decode_thread() @@ -214,9 +216,36 @@ void FFNvDecoder::decode_thread()
214 } 216 }
215 217
216 m_bRunning = false; 218 m_bRunning = false;
  219 +
  220 + if (m_post_decode_thread != 0)
  221 + {
  222 + pthread_join(m_post_decode_thread,0);
  223 + }
  224 +
  225 + decode_finished();
  226 +
217 cout << "decode thread exited." << endl; 227 cout << "decode thread exited." << endl;
218 } 228 }
219 229
  230 +void FFNvDecoder::decode_finished()
  231 +{
  232 + if (avctx)
  233 + {
  234 + if (avctx->hw_device_ctx)
  235 + {
  236 + av_buffer_unref(&avctx->hw_device_ctx);
  237 + }
  238 + avcodec_free_context(&avctx);
  239 + }
  240 +
  241 + if (fmt_ctx)
  242 + {
  243 + avformat_close_input(&fmt_ctx);
  244 + }
  245 +
  246 + m_bFinished = true;
  247 +}
  248 +
220 void FFNvDecoder::post_decode_thread() 249 void FFNvDecoder::post_decode_thread()
221 { 250 {
222 while (m_bRunning) 251 while (m_bRunning)
@@ -242,24 +271,6 @@ void FFNvDecoder::close() @@ -242,24 +271,6 @@ void FFNvDecoder::close()
242 if(m_decode_thread != 0){ 271 if(m_decode_thread != 0){
243 pthread_join(m_decode_thread,0); 272 pthread_join(m_decode_thread,0);
244 } 273 }
245 - if (m_post_decode_thread != 0)  
246 - {  
247 - pthread_join(m_post_decode_thread,0);  
248 - }  
249 -  
250 - if (avctx)  
251 - {  
252 - if (avctx->hw_device_ctx)  
253 - {  
254 - av_buffer_unref(&avctx->hw_device_ctx);  
255 - }  
256 - avcodec_free_context(&avctx);  
257 - }  
258 -  
259 - if (fmt_ctx)  
260 - {  
261 - avformat_close_input(&fmt_ctx);  
262 - }  
263 } 274 }
264 275
265 void FFNvDecoder::setName(string nm){ 276 void FFNvDecoder::setName(string nm){
@@ -280,6 +291,11 @@ bool FFNvDecoder::isRunning() @@ -280,6 +291,11 @@ bool FFNvDecoder::isRunning()
280 return m_bRunning; 291 return m_bRunning;
281 } 292 }
282 293
  294 +bool FFNvDecoder::isFinished()
  295 +{
  296 + return m_bFinished;
  297 +}
  298 +
283 bool FFNvDecoder::getResolution( int &width, int &height ) 299 bool FFNvDecoder::getResolution( int &width, int &height )
284 { 300 {
285 if (avctx != nullptr) 301 if (avctx != nullptr)
src/FFNvDecoder.h
@@ -48,6 +48,7 @@ public: @@ -48,6 +48,7 @@ public:
48 void resume(); 48 void resume();
49 49
50 bool isRunning(); 50 bool isRunning();
  51 + bool isFinished();
51 bool getResolution( int &width, int &height ); 52 bool getResolution( int &width, int &height );
52 53
53 void setName(string nm); 54 void setName(string nm);
@@ -60,6 +61,7 @@ private: @@ -60,6 +61,7 @@ private:
60 void decode_thread(); 61 void decode_thread();
61 void post_decode_thread(); 62 void post_decode_thread();
62 bool init(const char* uri, const char* gpuid, bool force_tcp); 63 bool init(const char* uri, const char* gpuid, bool force_tcp);
  64 + void decode_finished();
63 65
64 public: 66 public:
65 POST_DECODE_CALLBACK post_decoded_cbk; 67 POST_DECODE_CALLBACK post_decoded_cbk;
@@ -77,6 +79,7 @@ private: @@ -77,6 +79,7 @@ private:
77 pthread_t m_post_decode_thread; 79 pthread_t m_post_decode_thread;
78 80
79 bool m_bRunning; 81 bool m_bRunning;
  82 + bool m_bFinished;
80 string name; 83 string name;
81 84
82 bool m_bPause; 85 bool m_bPause;
src/FFNvDecoderManager.cpp
@@ -3,7 +3,11 @@ @@ -3,7 +3,11 @@
3 3
4 using namespace std; 4 using namespace std;
5 5
  6 +
6 FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){ 7 FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){
  8 +
  9 + closeAllFinishedDecoder();
  10 +
7 int num = decoderMap.count(config.name); 11 int num = decoderMap.count(config.name);
8 if (num > 0) 12 if (num > 0)
9 { 13 {
@@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder() @@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder()
126 { 130 {
127 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){ 131 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
128 iter->second->close(); 132 iter->second->close();
  133 + delete iter->second;
  134 + }
  135 + decoderMap.clear();
  136 +}
  137 +
  138 +void FFNvDecoderManager::closeAllFinishedDecoder()
  139 +{
  140 + for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
  141 + if (iter->second->isFinished())
  142 + {
  143 + delete iter->second;
  144 + decoderMap.erase(iter);
  145 + }
129 } 146 }
130 } 147 }
131 148
132 int FFNvDecoderManager::count() 149 int FFNvDecoderManager::count()
133 { 150 {
  151 + closeAllFinishedDecoder();
  152 +
134 return decoderMap.size(); 153 return decoderMap.size();
135 } 154 }
136 155
src/FFNvDecoderManager.h
@@ -37,6 +37,9 @@ public: @@ -37,6 +37,9 @@ public:
37 37
38 bool closeDecoderByName(string name); 38 bool closeDecoderByName(string name);
39 void closeAllDecoder(); 39 void closeAllDecoder();
  40 + void closeAllFinishedDecoder();
  41 +
  42 + bool removeDecoderByName(string name);
40 43
41 bool pauseDecoder(string name); 44 bool pauseDecoder(string name);
42 bool resumeDecoder(string name); 45 bool resumeDecoder(string name);
src/main.cpp
@@ -14,11 +14,11 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){ @@ -14,11 +14,11 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){
14 FFNvDecoder* decoder = (FFNvDecoder*)userPtr; 14 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
15 if (decoder!= nullptr) 15 if (decoder!= nullptr)
16 { 16 {
17 - cout << decoder->getName() << endl;  
18 - const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);  
19 - cout << "pixfmt: " << gpu_pixfmt << endl; 17 + cout << "decode name: " << decoder->getName() << endl;
  18 + // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);
  19 + // cout << "pixfmt: " << gpu_pixfmt << endl;
20 cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl; 20 cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
21 - cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl; 21 + // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;
22 22
23 if (gpuFrame->format == AV_PIX_FMT_CUDA) 23 if (gpuFrame->format == AV_PIX_FMT_CUDA)
24 { 24 {
@@ -42,25 +42,37 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){ @@ -42,25 +42,37 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){
42 } 42 }
43 } 43 }
44 44
45 -int main(){  
46 - 45 +void createDecode(int index){
47 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); 46 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
48 MgrDecConfig config; 47 MgrDecConfig config;
49 - config.name = "dec1";  
50 - config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1"; 48 + config.name = "dec" + to_string(index);
  49 + config.cfg.uri = "rtsp://176.10.0.4:8554/stream";
51 config.cfg.post_decoded_cbk = postDecoded; 50 config.cfg.post_decoded_cbk = postDecoded;
52 config.cfg.force_tcp = true; 51 config.cfg.force_tcp = true;
53 config.cfg.gpuid = "1"; 52 config.cfg.gpuid = "1";
54 FFNvDecoder* decoder = pDecManager->createDecoder(config); 53 FFNvDecoder* decoder = pDecManager->createDecoder(config);
55 if (!decoder) 54 if (!decoder)
56 { 55 {
57 - return 1; 56 + return ;
58 } 57 }
59 pDecManager->setUserPtr(config.name, decoder); 58 pDecManager->setUserPtr(config.name, decoder);
60 pDecManager->startDecodeByName(config.name); 59 pDecManager->startDecodeByName(config.name);
  60 +}
  61 +
  62 +int main(){
  63 +
  64 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
61 65
  66 + // for (size_t i = 0; i < 20; i++)
  67 + // {
  68 + // createDecode(i);
  69 + // }
  70 +
  71 + MgrDecConfig config;
62 config.name = "dec2"; 72 config.name = "dec2";
63 - config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1"; 73 + config.cfg.uri = "/home/cmhu/data/test.mp4";
  74 + config.cfg.post_decoded_cbk = postDecoded;
  75 + config.cfg.force_tcp = true;
64 config.cfg.gpuid = "2"; 76 config.cfg.gpuid = "2";
65 FFNvDecoder* dec2 = pDecManager->createDecoder(config); 77 FFNvDecoder* dec2 = pDecManager->createDecoder(config);
66 if (!dec2) 78 if (!dec2)
@@ -71,27 +83,27 @@ int main(){ @@ -71,27 +83,27 @@ int main(){
71 pDecManager->startDecodeByName(config.name); 83 pDecManager->startDecodeByName(config.name);
72 84
73 85
74 - config.name = "dec0";  
75 - config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";  
76 - config.cfg.gpuid = "0";  
77 - FFNvDecoder* dec0 = pDecManager->createDecoder(config);  
78 - if (!dec0)  
79 - {  
80 - return 1;  
81 - }  
82 - pDecManager->setUserPtr(config.name, dec0);  
83 - pDecManager->startDecodeByName(config.name);  
84 -  
85 - config.name = "dec01";  
86 - config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";  
87 - config.cfg.gpuid = "0";  
88 - FFNvDecoder* dec01 = pDecManager->createDecoder(config);  
89 - if (!dec01)  
90 - {  
91 - return 1;  
92 - }  
93 - pDecManager->setUserPtr(config.name, dec01);  
94 - pDecManager->startDecodeByName(config.name); 86 + // config.name = "dec0";
  87 + // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  88 + // config.cfg.gpuid = "0";
  89 + // FFNvDecoder* dec0 = pDecManager->createDecoder(config);
  90 + // if (!dec0)
  91 + // {
  92 + // return 1;
  93 + // }
  94 + // pDecManager->setUserPtr(config.name, dec0);
  95 + // pDecManager->startDecodeByName(config.name);
  96 +
  97 + // config.name = "dec01";
  98 + // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  99 + // config.cfg.gpuid = "0";
  100 + // FFNvDecoder* dec01 = pDecManager->createDecoder(config);
  101 + // if (!dec01)
  102 + // {
  103 + // return 1;
  104 + // }
  105 + // pDecManager->setUserPtr(config.name, dec01);
  106 + // pDecManager->startDecodeByName(config.name);
95 107
96 // while (getchar() != 'q'); 108 // while (getchar() != 'q');
97 109