Commit 48330793ad1c28eccd227fa1fa19b1f72b2fed6e
1 parent
e96e6489
修正解码线程自然结束时解码器内存没有释放的问题
Showing
5 changed files
with
111 additions
and
58 deletions
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 |