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 | 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
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 | ... | ... |