Commit 48330793ad1c28eccd227fa1fa19b1f72b2fed6e

Authored by Hu Chunming
1 parent e96e6489

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

src/FFNvDecoder.cpp
... ... @@ -41,6 +41,8 @@ FFNvDecoder::FFNvDecoder()
41 41  
42 42 m_decode_thread = 0;
43 43 m_post_decode_thread = 0;
  44 +
  45 + m_bFinished = false;
44 46 }
45 47  
46 48 FFNvDecoder::~FFNvDecoder()
... ... @@ -73,12 +75,12 @@ bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
73 75 av_dict_set( &options, "bufsize", "655360", 0 );
74 76 av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 );
75 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 80 fmt_ctx = avformat_alloc_context();
79 81 const char* input_file = uri;
80 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 84 return false;
83 85 }
84 86  
... ... @@ -135,6 +137,13 @@ void FFNvDecoder::start(){
135 137 return (void*)0;
136 138 }
137 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 148 pthread_create(&m_post_decode_thread,0,
140 149 [](void* arg)
... ... @@ -144,13 +153,6 @@ void FFNvDecoder::start(){
144 153 return (void*)0;
145 154 }
146 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 157 while (m_bRunning)
156 158 {
... ... @@ -214,9 +216,36 @@ void FFNvDecoder::decode_thread()
214 216 }
215 217  
216 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 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 249 void FFNvDecoder::post_decode_thread()
221 250 {
222 251 while (m_bRunning)
... ... @@ -242,24 +271,6 @@ void FFNvDecoder::close()
242 271 if(m_decode_thread != 0){
243 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 276 void FFNvDecoder::setName(string nm){
... ... @@ -280,6 +291,11 @@ bool FFNvDecoder::isRunning()
280 291 return m_bRunning;
281 292 }
282 293  
  294 +bool FFNvDecoder::isFinished()
  295 +{
  296 + return m_bFinished;
  297 +}
  298 +
283 299 bool FFNvDecoder::getResolution( int &width, int &height )
284 300 {
285 301 if (avctx != nullptr)
... ...
src/FFNvDecoder.h
... ... @@ -48,6 +48,7 @@ public:
48 48 void resume();
49 49  
50 50 bool isRunning();
  51 + bool isFinished();
51 52 bool getResolution( int &width, int &height );
52 53  
53 54 void setName(string nm);
... ... @@ -60,6 +61,7 @@ private:
60 61 void decode_thread();
61 62 void post_decode_thread();
62 63 bool init(const char* uri, const char* gpuid, bool force_tcp);
  64 + void decode_finished();
63 65  
64 66 public:
65 67 POST_DECODE_CALLBACK post_decoded_cbk;
... ... @@ -77,6 +79,7 @@ private:
77 79 pthread_t m_post_decode_thread;
78 80  
79 81 bool m_bRunning;
  82 + bool m_bFinished;
80 83 string name;
81 84  
82 85 bool m_bPause;
... ...
src/FFNvDecoderManager.cpp
... ... @@ -3,7 +3,11 @@
3 3  
4 4 using namespace std;
5 5  
  6 +
6 7 FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){
  8 +
  9 + closeAllFinishedDecoder();
  10 +
7 11 int num = decoderMap.count(config.name);
8 12 if (num > 0)
9 13 {
... ... @@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder()
126 130 {
127 131 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
128 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 149 int FFNvDecoderManager::count()
133 150 {
  151 + closeAllFinishedDecoder();
  152 +
134 153 return decoderMap.size();
135 154 }
136 155  
... ...
src/FFNvDecoderManager.h
... ... @@ -37,6 +37,9 @@ public:
37 37  
38 38 bool closeDecoderByName(string name);
39 39 void closeAllDecoder();
  40 + void closeAllFinishedDecoder();
  41 +
  42 + bool removeDecoderByName(string name);
40 43  
41 44 bool pauseDecoder(string name);
42 45 bool resumeDecoder(string name);
... ...
src/main.cpp
... ... @@ -14,11 +14,11 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){
14 14 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
15 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 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 23 if (gpuFrame->format == AV_PIX_FMT_CUDA)
24 24 {
... ... @@ -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 46 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
48 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 50 config.cfg.post_decoded_cbk = postDecoded;
52 51 config.cfg.force_tcp = true;
53 52 config.cfg.gpuid = "1";
54 53 FFNvDecoder* decoder = pDecManager->createDecoder(config);
55 54 if (!decoder)
56 55 {
57   - return 1;
  56 + return ;
58 57 }
59 58 pDecManager->setUserPtr(config.name, decoder);
60 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 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 76 config.cfg.gpuid = "2";
65 77 FFNvDecoder* dec2 = pDecManager->createDecoder(config);
66 78 if (!dec2)
... ... @@ -71,27 +83,27 @@ int main(){
71 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 108 // while (getchar() != 'q');
97 109  
... ...