Commit bf661eb0b3b0cda5a2b5a5a420de46cf311e17e7
1 parent
d9fc3e82
录像文件保存优化
Showing
7 changed files
with
363 additions
and
22 deletions
src/decoder/dvpp/DvppDecoder.cpp
... | ... | @@ -150,7 +150,7 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ |
150 | 150 | pix_fmt = (AVPixelFormat)codecpar->format; |
151 | 151 | m_fps = av_q2d(stream ->avg_frame_rate); |
152 | 152 | |
153 | - m_recoderManager.init(stream->time_base, avctx); | |
153 | + m_recoderManager.init(stream, avctx); | |
154 | 154 | |
155 | 155 | LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps); |
156 | 156 | |
... | ... | @@ -379,9 +379,6 @@ void DvppDecoder::read_thread() { |
379 | 379 | |
380 | 380 | if (video_index == pkt->stream_index){ |
381 | 381 | |
382 | - frame_nb++; | |
383 | - m_recoderManager.cache_pkt(pkt, frame_nb); | |
384 | - | |
385 | 382 | ret = av_bsf_send_packet(h264bsfc, pkt); |
386 | 383 | if(ret < 0) { |
387 | 384 | LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); |
... | ... | @@ -401,6 +398,9 @@ void DvppDecoder::read_thread() { |
401 | 398 | break; |
402 | 399 | } |
403 | 400 | |
401 | + frame_nb++; | |
402 | + m_recoderManager.cache_pkt(pkt, frame_nb); | |
403 | + | |
404 | 404 | m_pktQueue_mutex.lock(); |
405 | 405 | DataPacket* data_pkt = new DataPacket(); |
406 | 406 | data_pkt->pkt = pkt; | ... | ... |
src/decoder/dvpp/FFRecoder.cpp
... | ... | @@ -121,11 +121,12 @@ bool FFRecoder::init(int w, int h, AVRational time_base, AVCodecContext* avctx, |
121 | 121 | return true; |
122 | 122 | } |
123 | 123 | |
124 | -bool FFRecoder::init(AVRational time_base, AVCodecContext* avctx, const char* outfile_name) { | |
124 | +bool FFRecoder::init(AVStream* stream, AVCodecContext* avctx, const char* outfile_name) { | |
125 | 125 | |
126 | 126 | codec_ctx_ = (AVCodecContext*)av_malloc(sizeof(AVCodecContext)); |
127 | 127 | avcodec_copy_context(codec_ctx_, avctx); |
128 | - codec_ctx_->time_base = time_base; | |
128 | + codec_ctx_->time_base = stream->time_base; | |
129 | + m_inStream = stream; | |
129 | 130 | |
130 | 131 | // [2] 创建输出上下文 |
131 | 132 | avformat_alloc_output_context2(&fmt_ctx_, nullptr, nullptr, outfile_name); |
... | ... | @@ -135,7 +136,8 @@ bool FFRecoder::init(AVRational time_base, AVCodecContext* avctx, const char* ou |
135 | 136 | out_stream_->id = 0; |
136 | 137 | out_stream_->codecpar->codec_tag = 0; |
137 | 138 | avcodec_parameters_from_context(out_stream_->codecpar, codec_ctx_); |
138 | - out_stream_->time_base = { 1,30 }; | |
139 | + // out_stream_->time_base = { 1,30 }; | |
140 | + out_stream_->time_base = stream->time_base; | |
139 | 141 | |
140 | 142 | av_dump_format(fmt_ctx_, out_stream_->id, outfile_name, 1); |
141 | 143 | |
... | ... | @@ -244,14 +246,32 @@ void FFRecoder::update_pts(AVPacket* pkt) { |
244 | 246 | bool FFRecoder::write_pkt(AVPacket *pkt) { |
245 | 247 | char errbuf[64]{ 0 }; |
246 | 248 | |
247 | - // frame_number++; | |
248 | - // pkt->pts = av_rescale_q(frame_number, codec_ctx_->time_base, out_stream_->time_base); | |
249 | - // pkt->dts = pkt->pts; | |
250 | - // pkt->duration = av_rescale_q(1, codec_ctx_->time_base, out_stream_->time_base); | |
249 | + // av_packet_rescale_ts(pkt, codec_ctx_->time_base, out_stream_->time_base); | |
250 | + // update_pts(pkt); | |
251 | + // pkt->stream_index = out_stream_->index; | |
252 | + | |
253 | + // if(pkt->pts==AV_NOPTS_VALUE) | |
254 | + { | |
255 | + // printf("frame_index:%d\n", frame_index); | |
256 | + //Write PTS | |
257 | + AVRational time_base1 = codec_ctx_->time_base; | |
258 | + //Duration between 2 frames (us) | |
259 | + int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(m_inStream->r_frame_rate); | |
260 | + //Parameters | |
261 | + pkt->pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE); | |
262 | + pkt->dts = pkt->pts; | |
263 | + pkt->duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE); | |
264 | + frame_index++; | |
265 | + } | |
266 | + // Convert PTS/DTS | |
267 | + pkt->pts = av_rescale_q_rnd(pkt->pts, codec_ctx_->time_base, out_stream_->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); | |
268 | + pkt->dts = av_rescale_q_rnd(pkt->dts, codec_ctx_->time_base, out_stream_->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); | |
269 | + pkt->duration = av_rescale_q(pkt->duration, codec_ctx_->time_base, out_stream_->time_base); | |
270 | + pkt->pos = -1; | |
251 | 271 | |
252 | - av_packet_rescale_ts(pkt, codec_ctx_->time_base, out_stream_->time_base); | |
253 | 272 | pkt->stream_index = out_stream_->index; |
254 | - update_pts(pkt); | |
273 | + | |
274 | + | |
255 | 275 | // 将数据写入到输出流 |
256 | 276 | int ret = av_interleaved_write_frame(fmt_ctx_, pkt); |
257 | 277 | if (ret < 0) { | ... | ... |
src/decoder/dvpp/FFRecoder.h
... | ... | @@ -24,7 +24,7 @@ public: |
24 | 24 | bool flush(); |
25 | 25 | |
26 | 26 | // AVPacket 方式 |
27 | - bool init(AVRational time_base, AVCodecContext* avctx, const char* outfile_name); | |
27 | + bool init(AVStream* stream, AVCodecContext* avctx, const char* outfile_name); | |
28 | 28 | bool write_pkt(AVPacket *pkt); |
29 | 29 | |
30 | 30 | private: |
... | ... | @@ -50,5 +50,9 @@ private: |
50 | 50 | int64_t last_src_pts; |
51 | 51 | int64_t last_pts; |
52 | 52 | |
53 | - int64_t frame_number{0}; | |
53 | + int64_t first_pts; | |
54 | + int64_t first_dts; | |
55 | + | |
56 | + int64_t frame_index{0}; | |
57 | + AVStream* m_inStream; | |
54 | 58 | }; |
55 | 59 | \ No newline at end of file | ... | ... |
src/decoder/dvpp/FFRecoderTaskManager.cpp
... | ... | @@ -37,9 +37,10 @@ FFRecoderTaskManager::~FFRecoderTaskManager(){ |
37 | 37 | |
38 | 38 | } |
39 | 39 | |
40 | -bool FFRecoderTaskManager::init(AVRational time_base, AVCodecContext* avctx){ | |
41 | - m_time_base = time_base; | |
40 | +bool FFRecoderTaskManager::init(AVStream* stream, AVCodecContext* avctx){ | |
41 | + m_time_base = stream->time_base; | |
42 | 42 | m_avctx = avctx; |
43 | + m_inStream = stream; | |
43 | 44 | |
44 | 45 | m_recoder_thread = new std::thread( |
45 | 46 | [](void* arg) { |
... | ... | @@ -55,6 +56,24 @@ bool FFRecoderTaskManager::init(AVRational time_base, AVCodecContext* avctx){ |
55 | 56 | return true; |
56 | 57 | } |
57 | 58 | |
59 | +bool FFRecoderTaskManager::init3(AVRational time_base, AVCodecContext* avctx){ | |
60 | + m_time_base = time_base; | |
61 | + m_avctx = avctx; | |
62 | + | |
63 | + m_recoder_thread = new std::thread( | |
64 | + [](void* arg) { | |
65 | + FFRecoderTaskManager* _this=(FFRecoderTaskManager*)arg; | |
66 | + if(_this != nullptr) { | |
67 | + _this->recode_thread3(); | |
68 | + }else{ | |
69 | + LOG_ERROR("recode 线程启动失败 !"); | |
70 | + } | |
71 | + return (void*)0; | |
72 | + }, this); | |
73 | + | |
74 | + return true; | |
75 | +} | |
76 | + | |
58 | 77 | void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ |
59 | 78 | if(m_bExit) { |
60 | 79 | // 任务退出了就不再缓存数据了 |
... | ... | @@ -91,6 +110,42 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ |
91 | 110 | } |
92 | 111 | } |
93 | 112 | |
113 | +void FFRecoderTaskManager::cache_frame(AVFrame* frame, long long frame_nb){ | |
114 | + if(m_bExit) { | |
115 | + // 任务退出了就不再缓存数据了 | |
116 | + return; | |
117 | + } | |
118 | + | |
119 | + std::lock_guard<std::mutex> l_pkt(m_frame_list_mtx); | |
120 | + | |
121 | + // 考虑到一个AVPacket中的数据并不很大,为减少与解码模块的耦合度,方便管理,这里做一个clone | |
122 | + AVFrame *new_pkt = av_frame_clone(frame); | |
123 | + | |
124 | + DataFrame* newFrame = new DataFrame(); | |
125 | + newFrame->frame = new_pkt; | |
126 | + newFrame->frame_nb = frame_nb; | |
127 | + m_frame_list.emplace_back(newFrame); | |
128 | + | |
129 | + // if(is_key_frame(pkt)){ | |
130 | + // // 越来越大的值 | |
131 | + // newFrame->isKeyFrame = true; | |
132 | + // LOG_INFO("key frame_nb: {}", frame_nb); | |
133 | + // } else { | |
134 | + // newFrame->isKeyFrame = false; | |
135 | + // } | |
136 | + | |
137 | + std::lock_guard<std::mutex> l_info(m_recoderinfo_list_mtx); | |
138 | + if(m_recoderinfo_list.size() <= 0){ | |
139 | + // 没有任务的时候,维持500的长度 | |
140 | + while(m_frame_list.size() > 1000) { | |
141 | + DataFrame* dataPkt = m_frame_list.front(); | |
142 | + delete dataPkt; | |
143 | + dataPkt = nullptr; | |
144 | + m_frame_list.pop_front(); | |
145 | + } | |
146 | + } | |
147 | +} | |
148 | + | |
94 | 149 | void FFRecoderTaskManager::save_intask_frame_nb(unsigned long long frame_nb) { |
95 | 150 | if(m_intask_frame_nb_list.size() <= 0) { |
96 | 151 | m_intask_frame_nb_list.push_back(frame_nb); |
... | ... | @@ -158,6 +213,43 @@ list<DataPacket*>::iterator FFRecoderTaskManager::getStartIterator(unsigned long |
158 | 213 | return m_pkt_list.begin(); |
159 | 214 | } |
160 | 215 | |
216 | +list<DataPacket*>::iterator FFRecoderTaskManager::getEndIterator(unsigned long long frame_nb){ | |
217 | + std::lock_guard<std::mutex> l(m_pkt_list_mtx); | |
218 | + | |
219 | + auto it_first = m_pkt_list.end(); | |
220 | + | |
221 | + auto it_second = m_pkt_list.begin(); | |
222 | + for(;it_second != m_pkt_list.end(); it_second++) { | |
223 | + DataPacket* dataPkt = *it_second; | |
224 | + if (dataPkt->isKeyFrame && dataPkt->frame_nb >= frame_nb){ | |
225 | + return it_second; | |
226 | + } | |
227 | + } | |
228 | + | |
229 | + return m_pkt_list.end(); | |
230 | +} | |
231 | + | |
232 | +list<DataFrame*>::iterator FFRecoderTaskManager::getStartIterator3(unsigned long long frame_nb) { | |
233 | + std::lock_guard<std::mutex> l(m_frame_list_mtx); | |
234 | + | |
235 | + auto it_first = m_frame_list.begin(); | |
236 | + | |
237 | + long long start_frame_nb = (long long)(frame_nb - 375); | |
238 | + if(start_frame_nb <= 0) { | |
239 | + return it_first; | |
240 | + } | |
241 | + | |
242 | + auto it_second = m_frame_list.begin(); | |
243 | + for(;it_second != m_frame_list.end(); it_second++) { | |
244 | + DataFrame* dataPkt = *it_second; | |
245 | + if (dataPkt->frame_nb >= start_frame_nb){ | |
246 | + return it_second; | |
247 | + } | |
248 | + } | |
249 | + | |
250 | + return m_frame_list.begin(); | |
251 | +} | |
252 | + | |
161 | 253 | // 多线程版 |
162 | 254 | void FFRecoderTaskManager::create_recode_task(AVRational time_base, AVCodecContext* avctx, RecoderInfo& recoderInfo){ |
163 | 255 | |
... | ... | @@ -211,7 +303,7 @@ void FFRecoderTaskManager::recode_thread(RecodeParam recodeParam){ |
211 | 303 | std::string id = recoderInfo.task_id + "_" + recoderInfo.object_id + "_" + std::to_string(recoderInfo.frame_nb); |
212 | 304 | string file_name = recoderInfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; |
213 | 305 | FFRecoder ffrecoder; |
214 | - bool bInit = ffrecoder.init(recodeParam.time_base, recodeParam.avctx, file_name.c_str()); | |
306 | + bool bInit = ffrecoder.init(m_inStream, recodeParam.avctx, file_name.c_str()); | |
215 | 307 | if (!bInit) { |
216 | 308 | LOG_ERROR("ffrecoder init error : {} {} {}", recoderInfo.task_id, recoderInfo.object_id, recoderInfo.frame_nb); |
217 | 309 | m_id_recoderTask.erase(id); |
... | ... | @@ -260,6 +352,161 @@ void FFRecoderTaskManager::recode_thread2() { |
260 | 352 | continue; |
261 | 353 | } |
262 | 354 | |
355 | + auto it_end = getEndIterator(recoderinfo.frame_nb); | |
356 | + | |
357 | + LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); | |
358 | + | |
359 | + m_pkt_list_mtx.lock(); | |
360 | + auto it = m_pkt_list.begin(); | |
361 | + while (it != it_data) { | |
362 | + DataPacket* dataPkt = m_pkt_list.front(); | |
363 | + delete dataPkt; | |
364 | + dataPkt = nullptr; | |
365 | + m_pkt_list.pop_front(); | |
366 | + it = m_pkt_list.begin(); | |
367 | + } | |
368 | + m_pkt_list_mtx.unlock(); | |
369 | + | |
370 | + std::string id = recoderinfo.task_id + "_" + recoderinfo.object_id + "_" + std::to_string(recoderinfo.frame_nb); | |
371 | + string file_name = recoderinfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; | |
372 | + FFRecoder ffrecoder; | |
373 | + bool bInit = ffrecoder.init(m_inStream, m_avctx, file_name.c_str()); | |
374 | + if (!bInit) { | |
375 | + LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); | |
376 | + ffrecoder.uninit(); | |
377 | + continue; | |
378 | + } | |
379 | + LOG_INFO("record start, pkt_list size: {} id: {}", m_pkt_list.size(), id); | |
380 | + | |
381 | + int count = 0; | |
382 | + auto it_save = it_data; | |
383 | + unsigned long long start_frame_nb = (*it_data)->frame_nb; | |
384 | + unsigned long long end_frame_nb = (*it_data)->frame_nb; | |
385 | + for (; it_save != m_pkt_list.end() && count < 500; ++it_save) { | |
386 | + DataPacket* dataPkt = *it_save; | |
387 | + if(dataPkt->frame_nb > recoderinfo.frame_nb) { | |
388 | + break; | |
389 | + } | |
390 | + AVPacket* pkt = dataPkt->pkt; | |
391 | + ffrecoder.write_pkt(pkt); | |
392 | + count++; | |
393 | + end_frame_nb = (*it_save)->frame_nb; | |
394 | + } | |
395 | + | |
396 | + // ffrecoder.flush(); | |
397 | + ffrecoder.uninit(); | |
398 | + | |
399 | + // 发送mq消息 | |
400 | + if(mq_publish_func) { | |
401 | + mq_publish_func(recoderinfo.mq_info.c_str()); | |
402 | + } | |
403 | + | |
404 | + LOG_INFO("record end, total save: {} start_frame_nb: {} end_frame_nb: {} file_path: {}", count, start_frame_nb, end_frame_nb, file_name); | |
405 | + } | |
406 | + | |
407 | + LOG_INFO("recode_thread2 end."); | |
408 | +} | |
409 | + | |
410 | +void FFRecoderTaskManager::recode_thread3() { | |
411 | + LOG_INFO("recode_thread2 start..."); | |
412 | + while(true) { | |
413 | + if(m_bExit) { | |
414 | + break; | |
415 | + } | |
416 | + | |
417 | + m_recoderinfo_list_mtx.lock(); | |
418 | + if(m_recoderinfo_list.size() <= 0){ | |
419 | + m_recoderinfo_list_mtx.unlock(); | |
420 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
421 | + continue; | |
422 | + } | |
423 | + | |
424 | + auto it_param = m_recoderinfo_list.begin(); | |
425 | + RecoderInfo recoderinfo = *it_param; | |
426 | + m_recoderinfo_list.pop_front(); | |
427 | + m_recoderinfo_list_mtx.unlock(); | |
428 | + | |
429 | + auto it_data = getStartIterator3(recoderinfo.frame_nb); | |
430 | + if(it_data == m_frame_list.end()) { | |
431 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
432 | + continue; | |
433 | + } | |
434 | + | |
435 | + LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); | |
436 | + | |
437 | + m_frame_list_mtx.lock(); | |
438 | + auto it = m_frame_list.begin(); | |
439 | + while (it != it_data) { | |
440 | + DataFrame* dataPkt = m_frame_list.front(); | |
441 | + delete dataPkt; | |
442 | + dataPkt = nullptr; | |
443 | + m_frame_list.pop_front(); | |
444 | + it = m_frame_list.begin(); | |
445 | + } | |
446 | + m_frame_list_mtx.unlock(); | |
447 | + | |
448 | + std::string id = recoderinfo.task_id + "_" + recoderinfo.object_id + "_" + std::to_string(recoderinfo.frame_nb); | |
449 | + string file_name = recoderinfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; | |
450 | + FFRecoder ffrecoder; | |
451 | + bool bInit = ffrecoder.init(m_avctx->width, m_avctx->height, m_time_base, m_avctx, file_name.c_str()); | |
452 | + if (!bInit) { | |
453 | + LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); | |
454 | + ffrecoder.uninit(); | |
455 | + continue; | |
456 | + } | |
457 | + LOG_INFO("record start, pkt_list size: {} id: {}", m_frame_list.size(), id); | |
458 | + | |
459 | + int count = 0; | |
460 | + auto it_save = it_data; | |
461 | + unsigned long long start_frame_nb = (*it_data)->frame_nb; | |
462 | + unsigned long long end_frame_nb = (*it_data)->frame_nb; | |
463 | + for (; it_save != m_frame_list.end() && count < 500; ++it_save) { | |
464 | + DataFrame* dataPkt = *it_save; | |
465 | + AVFrame* pkt = dataPkt->frame; | |
466 | + ffrecoder.write_frame(pkt); | |
467 | + count++; | |
468 | + end_frame_nb = (*it_save)->frame_nb; | |
469 | + } | |
470 | + | |
471 | + // ffrecoder.flush(); | |
472 | + ffrecoder.uninit(); | |
473 | + | |
474 | + // 发送mq消息 | |
475 | + if(mq_publish_func) { | |
476 | + mq_publish_func(recoderinfo.mq_info.c_str()); | |
477 | + } | |
478 | + | |
479 | + LOG_INFO("record end, total save: {} start_frame_nb: {} end_frame_nb: {} file_path: {}", count, start_frame_nb, end_frame_nb, file_name); | |
480 | + } | |
481 | + | |
482 | + LOG_INFO("recode_thread2 end."); | |
483 | +} | |
484 | + | |
485 | +void FFRecoderTaskManager::recode_thread4() { | |
486 | + LOG_INFO("recode_thread2 start..."); | |
487 | + while(true) { | |
488 | + if(m_bExit) { | |
489 | + break; | |
490 | + } | |
491 | + | |
492 | + m_recoderinfo_list_mtx.lock(); | |
493 | + if(m_recoderinfo_list.size() <= 0){ | |
494 | + m_recoderinfo_list_mtx.unlock(); | |
495 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
496 | + continue; | |
497 | + } | |
498 | + | |
499 | + auto it_param = m_recoderinfo_list.begin(); | |
500 | + RecoderInfo recoderinfo = *it_param; | |
501 | + m_recoderinfo_list.pop_front(); | |
502 | + m_recoderinfo_list_mtx.unlock(); | |
503 | + | |
504 | + auto it_data = getStartIterator(recoderinfo.frame_nb); | |
505 | + if(it_data == m_pkt_list.end()) { | |
506 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
507 | + continue; | |
508 | + } | |
509 | + | |
263 | 510 | LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); |
264 | 511 | |
265 | 512 | m_pkt_list_mtx.lock(); |
... | ... | @@ -276,7 +523,7 @@ void FFRecoderTaskManager::recode_thread2() { |
276 | 523 | std::string id = recoderinfo.task_id + "_" + recoderinfo.object_id + "_" + std::to_string(recoderinfo.frame_nb); |
277 | 524 | string file_name = recoderinfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; |
278 | 525 | FFRecoder ffrecoder; |
279 | - bool bInit = ffrecoder.init(m_time_base, m_avctx, file_name.c_str()); | |
526 | + bool bInit = ffrecoder.init(m_inStream, m_avctx, file_name.c_str()); | |
280 | 527 | if (!bInit) { |
281 | 528 | LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); |
282 | 529 | ffrecoder.uninit(); | ... | ... |
src/decoder/dvpp/FFRecoderTaskManager.h
... | ... | @@ -28,18 +28,26 @@ public: |
28 | 28 | void cache_pkt(AVPacket* pkt, long long frame_nb); |
29 | 29 | void create_recode_task(AVRational time_base, AVCodecContext* avctx, RecoderInfo& recoderInfo); |
30 | 30 | |
31 | - bool init(AVRational time_base, AVCodecContext* avctx); | |
31 | + bool init(AVStream* stream, AVCodecContext* avctx); | |
32 | 32 | void create_recode_task2(RecoderInfo& recoderInfo); |
33 | 33 | |
34 | 34 | void close(); |
35 | 35 | |
36 | 36 | void set_mq_callback(mq_callback_t cb); |
37 | 37 | |
38 | + bool init3(AVRational time_base, AVCodecContext* avctx); | |
39 | + void cache_frame(AVFrame* frame, long long frame_nb); | |
40 | + | |
38 | 41 | public: |
39 | 42 | void recode_thread(RecodeParam param); |
40 | 43 | list<DataPacket*>::iterator getStartIterator(unsigned long long frame_nb); |
44 | + list<DataPacket*>::iterator getEndIterator(unsigned long long frame_nb); | |
41 | 45 | |
42 | 46 | void recode_thread2(); |
47 | + void recode_thread4(); | |
48 | + | |
49 | + list<DataFrame*>::iterator getStartIterator3(unsigned long long frame_nb); | |
50 | + void recode_thread3(); | |
43 | 51 | |
44 | 52 | private: |
45 | 53 | void save_intask_frame_nb(unsigned long long frame_nb); |
... | ... | @@ -64,8 +72,12 @@ private: |
64 | 72 | |
65 | 73 | AVRational m_time_base; |
66 | 74 | AVCodecContext* m_avctx; |
75 | + AVStream* m_inStream; | |
67 | 76 | |
68 | 77 | thread* m_recoder_thread{nullptr}; |
69 | 78 | |
70 | 79 | mq_callback_t mq_publish_func; |
80 | + | |
81 | + std::list<DataFrame*> m_frame_list; | |
82 | + mutex m_frame_list_mtx; | |
71 | 83 | }; |
72 | 84 | \ No newline at end of file | ... | ... |
src/decoder/dvpp/depend_headers.h
... | ... | @@ -49,4 +49,17 @@ struct DataPacket { |
49 | 49 | } |
50 | 50 | }; |
51 | 51 | |
52 | +struct DataFrame { | |
53 | + AVFrame* frame {nullptr}; | |
54 | + unsigned long long frame_nb{0}; | |
55 | + bool isKeyFrame{false}; | |
56 | + | |
57 | + ~DataFrame(){ | |
58 | + if(frame != nullptr) { | |
59 | + av_frame_free(&frame); | |
60 | + frame = nullptr; | |
61 | + } | |
62 | + } | |
63 | +}; | |
64 | + | |
52 | 65 | #endif |
53 | 66 | \ No newline at end of file | ... | ... |
src/decoder/test_recoder.cpp
... | ... | @@ -29,6 +29,8 @@ void algorthim_process_thread(); |
29 | 29 | void recode_thread(); |
30 | 30 | void algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem); |
31 | 31 | |
32 | +void test_recode_thread(); | |
33 | + | |
32 | 34 | void post_decod_cbk(const void * userPtr, DeviceMemory* devFrame){ |
33 | 35 | do{ |
34 | 36 | if(m_bfinish){ |
... | ... | @@ -62,7 +64,7 @@ int main(){ |
62 | 64 | |
63 | 65 | MgrDecConfig config; |
64 | 66 | config.name = task_id; |
65 | - config.cfg.uri = "rtsp://admin:ad123456@192.168.60.165:554/cam/realmonitor?channel=1&subtype=0"; | |
67 | + config.cfg.uri = "rtsp://122.97.218.170:8604/openUrl/LBBYTra?params=eyJwcm90b2NhbCI6InJ0c3AiLCJjbGllbnRUeXBlIjoib3Blbl9hcGkiLCJleHByaWVUaW1lIjotMSwicHJvdG9jb2wiOiJydHNwIiwiZXhwaXJlVGltZSI6MzAwLCJlbmFibGVNR0MiOnRydWUsImV4cGFuZCI6InN0YW5kYXJkPXJ0c3Amc3RyZWFtZm9ybT1ydHAiLCJhIjoiOTgzYjRjMmUxMThlNGU1OTlkYThmMTI3NTkyMGViODV8MXwwfDEiLCJ0IjoxfQ=="; | |
66 | 68 | config.cfg.post_decoded_cbk = post_decod_cbk; |
67 | 69 | config.cfg.decode_finished_cbk = decode_finished_cbk; |
68 | 70 | config.cfg.force_tcp = true; // rtsp用tcp |
... | ... | @@ -95,8 +97,14 @@ int main(){ |
95 | 97 | } |
96 | 98 | , nullptr); |
97 | 99 | |
100 | + // m_recodeThread = new thread([](void* arg) { | |
101 | + // recode_thread(); | |
102 | + // return (void*)0; | |
103 | + // } | |
104 | + // , nullptr); | |
105 | + | |
98 | 106 | m_recodeThread = new thread([](void* arg) { |
99 | - recode_thread(); | |
107 | + test_recode_thread(); | |
100 | 108 | return (void*)0; |
101 | 109 | } |
102 | 110 | , nullptr); |
... | ... | @@ -183,6 +191,43 @@ void algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem) { |
183 | 191 | } |
184 | 192 | } |
185 | 193 | |
194 | +void test_recode_thread() { | |
195 | + unsigned long long frame_index = 0; | |
196 | + while(true) { | |
197 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
198 | + | |
199 | + DeviceMemory* mem = nullptr; | |
200 | + m_DataListMtx.lock(); | |
201 | + while (!m_RgbDataList.empty()){ | |
202 | + DeviceMemory* gpuMem = m_RgbDataList.front(); | |
203 | + if(gpuMem->getMem() == nullptr){ | |
204 | + // 错误数据,直接删除 | |
205 | + delete gpuMem; | |
206 | + gpuMem = nullptr; | |
207 | + printf("mem is null \n"); | |
208 | + } else { | |
209 | + frame_index ++ ; | |
210 | + if (frame_index % 50 == 0) { | |
211 | + RecoderInfo recoderInfo; | |
212 | + recoderInfo.task_id = gpuMem->getId(); | |
213 | + recoderInfo.object_id = std::to_string(obj_id); | |
214 | + recoderInfo.recoderDir = "./res/recode"; | |
215 | + recoderInfo.frame_nb = gpuMem->getFrameNb(); | |
216 | + | |
217 | + DecoderManager* pDecManager = DecoderManager::getInstance(); | |
218 | + pDecManager->doRecode(recoderInfo); | |
219 | + | |
220 | + obj_id++; | |
221 | + } | |
222 | + delete gpuMem; | |
223 | + gpuMem = nullptr; | |
224 | + } | |
225 | + m_RgbDataList.pop_front(); | |
226 | + } | |
227 | + m_DataListMtx.unlock(); | |
228 | + } | |
229 | +} | |
230 | + | |
186 | 231 | void recode_thread() { |
187 | 232 | while(true) { |
188 | 233 | ... | ... |