Commit 58f76d3f6d5a55c3cb6e45f9e9afa22d36ca3e9b
1 parent
77e1339c
改用FFRecoder2
Showing
5 changed files
with
112 additions
and
45 deletions
src/decoder/dvpp/DvppDecoder.cpp
@@ -197,7 +197,7 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ | @@ -197,7 +197,7 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ | ||
197 | m_vdec_out_size = frame_width * frame_height * 3 / 2; | 197 | m_vdec_out_size = frame_width * frame_height * 3 / 2; |
198 | 198 | ||
199 | #ifdef USE_VILLAGE | 199 | #ifdef USE_VILLAGE |
200 | - bool bRet = m_recoderManager.init(stream, avctx); | 200 | + bool bRet = m_recoderManager.init2(frame_width, frame_height, m_fps, avctx->bit_rate); |
201 | if (!bRet){ | 201 | if (!bRet){ |
202 | LOG_ERROR("[{}]- m_recoderManager 初始化失败!", m_dec_name); | 202 | LOG_ERROR("[{}]- m_recoderManager 初始化失败!", m_dec_name); |
203 | } | 203 | } |
src/decoder/dvpp/FFRecoder2.cpp
@@ -72,7 +72,8 @@ bool FFRecoder2::init(int w, int h, int fps, int bit_rate, const char* outfile_n | @@ -72,7 +72,8 @@ bool FFRecoder2::init(int w, int h, int fps, int bit_rate, const char* outfile_n | ||
72 | av_opt_set(codec_ctx_->priv_data, "tune", "zerolatency", 0); | 72 | av_opt_set(codec_ctx_->priv_data, "tune", "zerolatency", 0); |
73 | 73 | ||
74 | // 打开解码器 | 74 | // 打开解码器 |
75 | - if (avcodec_open2(codec_ctx_, encoder, nullptr) < 0) { | 75 | + int ret = avcodec_open2(codec_ctx_, encoder, nullptr); |
76 | + if (ret < 0) { | ||
76 | fprintf(stderr, "Open encoder failed!\n"); | 77 | fprintf(stderr, "Open encoder failed!\n"); |
77 | return false; | 78 | return false; |
78 | } | 79 | } |
@@ -206,7 +207,14 @@ bool FFRecoder2::write_frame(const AVFrame* frame) | @@ -206,7 +207,14 @@ bool FFRecoder2::write_frame(const AVFrame* frame) | ||
206 | return true; | 207 | return true; |
207 | } | 208 | } |
208 | 209 | ||
210 | +static double a2d(AVRational a) { | ||
211 | + return a.den / a.num; | ||
212 | +} | ||
213 | + | ||
209 | bool FFRecoder2::write_pkt(AVPacket* pkt) { | 214 | bool FFRecoder2::write_pkt(AVPacket* pkt) { |
215 | + frame_nb++; | ||
216 | + pkt->duration = int(a2d(codec_ctx_->time_base)); | ||
217 | + pkt->pts = frame_nb; | ||
210 | // 将pts缩放到输出流的time_base上 | 218 | // 将pts缩放到输出流的time_base上 |
211 | av_packet_rescale_ts(pkt, codec_ctx_->time_base, out_stream_->time_base); | 219 | av_packet_rescale_ts(pkt, codec_ctx_->time_base, out_stream_->time_base); |
212 | pkt->stream_index = out_stream_->index; | 220 | pkt->stream_index = out_stream_->index; |
src/decoder/dvpp/FFRecoder2.h
@@ -35,4 +35,6 @@ private: | @@ -35,4 +35,6 @@ private: | ||
35 | AVFormatContext* fmt_ctx_; | 35 | AVFormatContext* fmt_ctx_; |
36 | AVStream* out_stream_; | 36 | AVStream* out_stream_; |
37 | AVFrame* yuv_frame_; | 37 | AVFrame* yuv_frame_; |
38 | + | ||
39 | + int frame_nb{0}; | ||
38 | }; | 40 | }; |
39 | \ No newline at end of file | 41 | \ No newline at end of file |
src/decoder/dvpp/FFRecoderTaskManager.cpp
@@ -31,9 +31,16 @@ static bool is_key_frame(AVPacket *pkt) { | @@ -31,9 +31,16 @@ static bool is_key_frame(AVPacket *pkt) { | ||
31 | 31 | ||
32 | FFRecoderTaskManager::FFRecoderTaskManager(){ | 32 | FFRecoderTaskManager::FFRecoderTaskManager(){ |
33 | m_recoder_thread = nullptr; | 33 | m_recoder_thread = nullptr; |
34 | + m_cache_thread = nullptr; | ||
35 | + | ||
36 | + m_bExit = false; | ||
37 | + m_bExitRecoderThread = false; | ||
34 | } | 38 | } |
35 | 39 | ||
36 | FFRecoderTaskManager::~FFRecoderTaskManager(){ | 40 | FFRecoderTaskManager::~FFRecoderTaskManager(){ |
41 | + | ||
42 | + close(); | ||
43 | + | ||
37 | LOG_DEBUG("~FFRecoderTaskManager()"); | 44 | LOG_DEBUG("~FFRecoderTaskManager()"); |
38 | } | 45 | } |
39 | 46 | ||
@@ -71,11 +78,11 @@ bool FFRecoderTaskManager::init2(int w, int h, int fps, int bit_rate) { | @@ -71,11 +78,11 @@ bool FFRecoderTaskManager::init2(int w, int h, int fps, int bit_rate) { | ||
71 | m_fps = 25; | 78 | m_fps = 25; |
72 | } | 79 | } |
73 | 80 | ||
74 | - m_recoder_thread = new std::thread( | 81 | + m_cache_thread = new std::thread( |
75 | [](void* arg) { | 82 | [](void* arg) { |
76 | FFRecoderTaskManager* _this=(FFRecoderTaskManager*)arg; | 83 | FFRecoderTaskManager* _this=(FFRecoderTaskManager*)arg; |
77 | if(_this != nullptr) { | 84 | if(_this != nullptr) { |
78 | - _this->recode_thread2(); | 85 | + _this->pkt_cache_thread(); |
79 | }else{ | 86 | }else{ |
80 | LOG_ERROR("recode 线程启动失败 !"); | 87 | LOG_ERROR("recode 线程启动失败 !"); |
81 | } | 88 | } |
@@ -89,16 +96,15 @@ static AVPacket* packet_clone(AVPacket* pkt) { | @@ -89,16 +96,15 @@ static AVPacket* packet_clone(AVPacket* pkt) { | ||
89 | AVPacket *new_pkt = av_packet_alloc(); | 96 | AVPacket *new_pkt = av_packet_alloc(); |
90 | av_init_packet( new_pkt ); | 97 | av_init_packet( new_pkt ); |
91 | av_new_packet(new_pkt, pkt->size); | 98 | av_new_packet(new_pkt, pkt->size); |
92 | - // new_pkt->data = (uint8_t *)av_malloc(pkt->size) ; | ||
93 | memcpy(new_pkt->data, pkt->data, pkt->size); | 99 | memcpy(new_pkt->data, pkt->data, pkt->size); |
94 | new_pkt->size = pkt->size; | 100 | new_pkt->size = pkt->size; |
95 | - new_pkt->pts = pkt->pts; | ||
96 | - new_pkt->dts = pkt->dts; | ||
97 | - new_pkt->stream_index = pkt->stream_index; | ||
98 | - new_pkt->duration = pkt->duration; | ||
99 | - new_pkt->pos = pkt->pos; | ||
100 | - new_pkt->flags = pkt->flags; | ||
101 | - av_copy_packet_side_data(new_pkt, pkt); | 101 | + // new_pkt->pts = pkt->pts; |
102 | + // new_pkt->dts = pkt->dts; | ||
103 | + // new_pkt->stream_index = pkt->stream_index; | ||
104 | + // new_pkt->duration = pkt->duration; | ||
105 | + // new_pkt->pos = pkt->pos; | ||
106 | + // new_pkt->flags = pkt->flags; | ||
107 | + // av_copy_packet_side_data(new_pkt, pkt); | ||
102 | return new_pkt; | 108 | return new_pkt; |
103 | } | 109 | } |
104 | 110 | ||
@@ -124,19 +130,9 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ | @@ -124,19 +130,9 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ | ||
124 | } else { | 130 | } else { |
125 | newDataPkt->isKeyFrame = false; | 131 | newDataPkt->isKeyFrame = false; |
126 | } | 132 | } |
127 | - | ||
128 | - m_pkt_list.emplace_back(newDataPkt); | ||
129 | - | ||
130 | - std::lock_guard<std::mutex> l_info(m_recoderinfo_list_mtx); | ||
131 | - if(m_recoderinfo_list.size() <= 0){ | ||
132 | - // 没有任务的时候,维持500的长度 | ||
133 | - while(m_pkt_list.size() > 1000) { | ||
134 | - DataPacket* dataPkt = m_pkt_list.front(); | ||
135 | - delete dataPkt; | ||
136 | - dataPkt = nullptr; | ||
137 | - m_pkt_list.pop_front(); | ||
138 | - } | ||
139 | - } | 133 | + |
134 | + std::lock_guard<std::mutex> l_info(m_pkt_list_short_mtx); | ||
135 | + m_pkt_list_short.push_back(newDataPkt); | ||
140 | } | 136 | } |
141 | 137 | ||
142 | void FFRecoderTaskManager::save_intask_recoderinfo(RecoderInfo info) { | 138 | void FFRecoderTaskManager::save_intask_recoderinfo(RecoderInfo info) { |
@@ -284,11 +280,76 @@ void FFRecoderTaskManager::recode_thread() { | @@ -284,11 +280,76 @@ void FFRecoderTaskManager::recode_thread() { | ||
284 | LOG_INFO("recode_thread end."); | 280 | LOG_INFO("recode_thread end."); |
285 | } | 281 | } |
286 | 282 | ||
283 | +void FFRecoderTaskManager::pkt_cache_thread() { | ||
284 | + LOG_INFO("pkt_cache_thread start..."); | ||
285 | + | ||
286 | + m_recoder_thread = new std::thread( | ||
287 | + [](void* arg) { | ||
288 | + FFRecoderTaskManager* _this=(FFRecoderTaskManager*)arg; | ||
289 | + if(_this != nullptr) { | ||
290 | + _this->recode_thread2(); | ||
291 | + }else{ | ||
292 | + LOG_ERROR("recode 线程启动失败 !"); | ||
293 | + } | ||
294 | + return (void*)0; | ||
295 | + }, this); | ||
296 | + | ||
297 | + // 开始缓存 | ||
298 | + while(true) { | ||
299 | + if(m_bExit) { | ||
300 | + break; | ||
301 | + } | ||
302 | + | ||
303 | + std::this_thread::sleep_for(std::chrono::milliseconds(500)); | ||
304 | + | ||
305 | + m_pkt_list_short_mtx.lock(); | ||
306 | + m_pkt_list_mtx.lock(); | ||
307 | + for (size_t i = 0; i < m_pkt_list_short.size(); i++) { | ||
308 | + auto item = m_pkt_list_short.front(); | ||
309 | + m_pkt_list.push_back(item); | ||
310 | + m_pkt_list_short.pop_front(); | ||
311 | + } | ||
312 | + m_pkt_list_mtx.unlock(); | ||
313 | + m_pkt_list_short_mtx.unlock(); | ||
314 | + | ||
315 | + | ||
316 | + std::lock_guard<std::mutex> l_info(m_recoderinfo_list_mtx); | ||
317 | + if(m_recoderinfo_list.size() <= 0){ | ||
318 | + // 没有任务的时候,维持500的长度 | ||
319 | + m_pkt_list_mtx.lock(); | ||
320 | + while(m_pkt_list.size() > 1000) { | ||
321 | + DataPacket* dataPkt = m_pkt_list.front(); | ||
322 | + delete dataPkt; | ||
323 | + dataPkt = nullptr; | ||
324 | + m_pkt_list.pop_front(); | ||
325 | + } | ||
326 | + m_pkt_list_mtx.unlock(); | ||
327 | + } | ||
328 | + } | ||
329 | + | ||
330 | + m_bExitRecoderThread = true; | ||
331 | + | ||
332 | + if (m_recoder_thread) { | ||
333 | + m_recoder_thread->join(); | ||
334 | + delete m_recoder_thread; | ||
335 | + m_recoder_thread = nullptr; | ||
336 | + } | ||
337 | + | ||
338 | + // 清空数据 | ||
339 | + while(!m_pkt_list.empty()) { | ||
340 | + DataPacket* dataPkt = m_pkt_list.front(); | ||
341 | + delete dataPkt; | ||
342 | + dataPkt = nullptr; | ||
343 | + m_pkt_list.pop_front(); | ||
344 | + } | ||
345 | + | ||
346 | + LOG_INFO("pkt_cache_thread end."); | ||
347 | +} | ||
287 | 348 | ||
288 | void FFRecoderTaskManager::recode_thread2() { | 349 | void FFRecoderTaskManager::recode_thread2() { |
289 | LOG_INFO("recode_thread2 start..."); | 350 | LOG_INFO("recode_thread2 start..."); |
290 | while(true) { | 351 | while(true) { |
291 | - if(m_bExit) { | 352 | + if(m_bExitRecoderThread) { |
292 | break; | 353 | break; |
293 | } | 354 | } |
294 | 355 | ||
@@ -313,16 +374,7 @@ void FFRecoderTaskManager::recode_thread2() { | @@ -313,16 +374,7 @@ void FFRecoderTaskManager::recode_thread2() { | ||
313 | 374 | ||
314 | LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); | 375 | LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); |
315 | 376 | ||
316 | - m_pkt_list_mtx.lock(); | ||
317 | - auto it = m_pkt_list.begin(); | ||
318 | - while (it != it_data) { | ||
319 | - DataPacket* dataPkt = m_pkt_list.front(); | ||
320 | - delete dataPkt; | ||
321 | - dataPkt = nullptr; | ||
322 | - m_pkt_list.pop_front(); | ||
323 | - it = m_pkt_list.begin(); | ||
324 | - } | ||
325 | - m_pkt_list_mtx.unlock(); | 377 | + std::lock_guard<std::mutex> l_long(m_pkt_list_mtx); |
326 | 378 | ||
327 | string file_name = recoderinfo.recoderPath; | 379 | string file_name = recoderinfo.recoderPath; |
328 | 380 | ||
@@ -377,24 +429,24 @@ void FFRecoderTaskManager::recode_thread2() { | @@ -377,24 +429,24 @@ void FFRecoderTaskManager::recode_thread2() { | ||
377 | m_recoderinfo_list_mtx.unlock(); | 429 | m_recoderinfo_list_mtx.unlock(); |
378 | } | 430 | } |
379 | 431 | ||
380 | - LOG_INFO("recode_thread end."); | 432 | + LOG_INFO("recode_thread2 end."); |
381 | } | 433 | } |
382 | 434 | ||
383 | void FFRecoderTaskManager::close() { | 435 | void FFRecoderTaskManager::close() { |
384 | m_bExit = true; | 436 | m_bExit = true; |
385 | 437 | ||
386 | - if (m_recoder_thread) { | ||
387 | - m_recoder_thread->join(); | ||
388 | - delete m_recoder_thread; | ||
389 | - m_recoder_thread = nullptr; | 438 | + if (m_cache_thread) { |
439 | + m_cache_thread->join(); | ||
440 | + delete m_cache_thread; | ||
441 | + m_cache_thread = nullptr; | ||
390 | } | 442 | } |
391 | 443 | ||
392 | // 清空数据 | 444 | // 清空数据 |
393 | - while(!m_pkt_list.empty()) { | ||
394 | - DataPacket* dataPkt = m_pkt_list.front(); | 445 | + while(!m_pkt_list_short.empty()) { |
446 | + DataPacket* dataPkt = m_pkt_list_short.front(); | ||
395 | delete dataPkt; | 447 | delete dataPkt; |
396 | dataPkt = nullptr; | 448 | dataPkt = nullptr; |
397 | - m_pkt_list.pop_front(); | 449 | + m_pkt_list_short.pop_front(); |
398 | } | 450 | } |
399 | } | 451 | } |
400 | 452 |
src/decoder/dvpp/FFRecoderTaskManager.h
@@ -39,6 +39,7 @@ public: | @@ -39,6 +39,7 @@ public: | ||
39 | public: | 39 | public: |
40 | void recode_thread(); | 40 | void recode_thread(); |
41 | void recode_thread2(); | 41 | void recode_thread2(); |
42 | + void pkt_cache_thread(); | ||
42 | 43 | ||
43 | private: | 44 | private: |
44 | void save_intask_recoderinfo(RecoderInfo info); | 45 | void save_intask_recoderinfo(RecoderInfo info); |
@@ -47,19 +48,23 @@ private: | @@ -47,19 +48,23 @@ private: | ||
47 | private: | 48 | private: |
48 | std::queue<int> m_key_frame_interval; | 49 | std::queue<int> m_key_frame_interval; |
49 | std::list<unsigned long long> m_keyframe_nb_list; | 50 | std::list<unsigned long long> m_keyframe_nb_list; |
50 | - std::list<DataPacket*> m_pkt_list; | 51 | + std::list<DataPacket*> m_pkt_list_short; // 临时缓存 |
52 | + mutex m_pkt_list_short_mtx; | ||
53 | + std::list<DataPacket*> m_pkt_list; //主要缓存 | ||
51 | mutex m_pkt_list_mtx; | 54 | mutex m_pkt_list_mtx; |
52 | 55 | ||
53 | std::list<RecoderInfo> m_recoderinfo_list; | 56 | std::list<RecoderInfo> m_recoderinfo_list; |
54 | mutex m_recoderinfo_list_mtx; | 57 | mutex m_recoderinfo_list_mtx; |
55 | 58 | ||
56 | bool m_bExit{false}; | 59 | bool m_bExit{false}; |
60 | + bool m_bExitRecoderThread{false}; | ||
57 | 61 | ||
58 | AVRational m_time_base; | 62 | AVRational m_time_base; |
59 | AVCodecContext* m_avctx; | 63 | AVCodecContext* m_avctx; |
60 | AVStream* m_inStream; | 64 | AVStream* m_inStream; |
61 | 65 | ||
62 | thread* m_recoder_thread{nullptr}; | 66 | thread* m_recoder_thread{nullptr}; |
67 | + thread* m_cache_thread{nullptr}; | ||
63 | 68 | ||
64 | mq_callback_t mq_publish_func; | 69 | mq_callback_t mq_publish_func; |
65 | 70 |