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,7 +150,7 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ | ||
150 | pix_fmt = (AVPixelFormat)codecpar->format; | 150 | pix_fmt = (AVPixelFormat)codecpar->format; |
151 | m_fps = av_q2d(stream ->avg_frame_rate); | 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 | LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps); | 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,9 +379,6 @@ void DvppDecoder::read_thread() { | ||
379 | 379 | ||
380 | if (video_index == pkt->stream_index){ | 380 | if (video_index == pkt->stream_index){ |
381 | 381 | ||
382 | - frame_nb++; | ||
383 | - m_recoderManager.cache_pkt(pkt, frame_nb); | ||
384 | - | ||
385 | ret = av_bsf_send_packet(h264bsfc, pkt); | 382 | ret = av_bsf_send_packet(h264bsfc, pkt); |
386 | if(ret < 0) { | 383 | if(ret < 0) { |
387 | LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); | 384 | LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); |
@@ -401,6 +398,9 @@ void DvppDecoder::read_thread() { | @@ -401,6 +398,9 @@ void DvppDecoder::read_thread() { | ||
401 | break; | 398 | break; |
402 | } | 399 | } |
403 | 400 | ||
401 | + frame_nb++; | ||
402 | + m_recoderManager.cache_pkt(pkt, frame_nb); | ||
403 | + | ||
404 | m_pktQueue_mutex.lock(); | 404 | m_pktQueue_mutex.lock(); |
405 | DataPacket* data_pkt = new DataPacket(); | 405 | DataPacket* data_pkt = new DataPacket(); |
406 | data_pkt->pkt = pkt; | 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,11 +121,12 @@ bool FFRecoder::init(int w, int h, AVRational time_base, AVCodecContext* avctx, | ||
121 | return true; | 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 | codec_ctx_ = (AVCodecContext*)av_malloc(sizeof(AVCodecContext)); | 126 | codec_ctx_ = (AVCodecContext*)av_malloc(sizeof(AVCodecContext)); |
127 | avcodec_copy_context(codec_ctx_, avctx); | 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 | // [2] 创建输出上下文 | 131 | // [2] 创建输出上下文 |
131 | avformat_alloc_output_context2(&fmt_ctx_, nullptr, nullptr, outfile_name); | 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,7 +136,8 @@ bool FFRecoder::init(AVRational time_base, AVCodecContext* avctx, const char* ou | ||
135 | out_stream_->id = 0; | 136 | out_stream_->id = 0; |
136 | out_stream_->codecpar->codec_tag = 0; | 137 | out_stream_->codecpar->codec_tag = 0; |
137 | avcodec_parameters_from_context(out_stream_->codecpar, codec_ctx_); | 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 | av_dump_format(fmt_ctx_, out_stream_->id, outfile_name, 1); | 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,14 +246,32 @@ void FFRecoder::update_pts(AVPacket* pkt) { | ||
244 | bool FFRecoder::write_pkt(AVPacket *pkt) { | 246 | bool FFRecoder::write_pkt(AVPacket *pkt) { |
245 | char errbuf[64]{ 0 }; | 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 | pkt->stream_index = out_stream_->index; | 272 | pkt->stream_index = out_stream_->index; |
254 | - update_pts(pkt); | 273 | + |
274 | + | ||
255 | // 将数据写入到输出流 | 275 | // 将数据写入到输出流 |
256 | int ret = av_interleaved_write_frame(fmt_ctx_, pkt); | 276 | int ret = av_interleaved_write_frame(fmt_ctx_, pkt); |
257 | if (ret < 0) { | 277 | if (ret < 0) { |
src/decoder/dvpp/FFRecoder.h
@@ -24,7 +24,7 @@ public: | @@ -24,7 +24,7 @@ public: | ||
24 | bool flush(); | 24 | bool flush(); |
25 | 25 | ||
26 | // AVPacket 方式 | 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 | bool write_pkt(AVPacket *pkt); | 28 | bool write_pkt(AVPacket *pkt); |
29 | 29 | ||
30 | private: | 30 | private: |
@@ -50,5 +50,9 @@ private: | @@ -50,5 +50,9 @@ private: | ||
50 | int64_t last_src_pts; | 50 | int64_t last_src_pts; |
51 | int64_t last_pts; | 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 | \ No newline at end of file | 59 | \ No newline at end of file |
src/decoder/dvpp/FFRecoderTaskManager.cpp
@@ -37,9 +37,10 @@ FFRecoderTaskManager::~FFRecoderTaskManager(){ | @@ -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 | m_avctx = avctx; | 42 | m_avctx = avctx; |
43 | + m_inStream = stream; | ||
43 | 44 | ||
44 | m_recoder_thread = new std::thread( | 45 | m_recoder_thread = new std::thread( |
45 | [](void* arg) { | 46 | [](void* arg) { |
@@ -55,6 +56,24 @@ bool FFRecoderTaskManager::init(AVRational time_base, AVCodecContext* avctx){ | @@ -55,6 +56,24 @@ bool FFRecoderTaskManager::init(AVRational time_base, AVCodecContext* avctx){ | ||
55 | return true; | 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 | void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ | 77 | void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ |
59 | if(m_bExit) { | 78 | if(m_bExit) { |
60 | // 任务退出了就不再缓存数据了 | 79 | // 任务退出了就不再缓存数据了 |
@@ -91,6 +110,42 @@ void FFRecoderTaskManager::cache_pkt(AVPacket* pkt, long long frame_nb){ | @@ -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 | void FFRecoderTaskManager::save_intask_frame_nb(unsigned long long frame_nb) { | 149 | void FFRecoderTaskManager::save_intask_frame_nb(unsigned long long frame_nb) { |
95 | if(m_intask_frame_nb_list.size() <= 0) { | 150 | if(m_intask_frame_nb_list.size() <= 0) { |
96 | m_intask_frame_nb_list.push_back(frame_nb); | 151 | m_intask_frame_nb_list.push_back(frame_nb); |
@@ -158,6 +213,43 @@ list<DataPacket*>::iterator FFRecoderTaskManager::getStartIterator(unsigned long | @@ -158,6 +213,43 @@ list<DataPacket*>::iterator FFRecoderTaskManager::getStartIterator(unsigned long | ||
158 | return m_pkt_list.begin(); | 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 | void FFRecoderTaskManager::create_recode_task(AVRational time_base, AVCodecContext* avctx, RecoderInfo& recoderInfo){ | 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,7 +303,7 @@ void FFRecoderTaskManager::recode_thread(RecodeParam recodeParam){ | ||
211 | std::string id = recoderInfo.task_id + "_" + recoderInfo.object_id + "_" + std::to_string(recoderInfo.frame_nb); | 303 | std::string id = recoderInfo.task_id + "_" + recoderInfo.object_id + "_" + std::to_string(recoderInfo.frame_nb); |
212 | string file_name = recoderInfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; | 304 | string file_name = recoderInfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; |
213 | FFRecoder ffrecoder; | 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 | if (!bInit) { | 307 | if (!bInit) { |
216 | LOG_ERROR("ffrecoder init error : {} {} {}", recoderInfo.task_id, recoderInfo.object_id, recoderInfo.frame_nb); | 308 | LOG_ERROR("ffrecoder init error : {} {} {}", recoderInfo.task_id, recoderInfo.object_id, recoderInfo.frame_nb); |
217 | m_id_recoderTask.erase(id); | 309 | m_id_recoderTask.erase(id); |
@@ -260,6 +352,161 @@ void FFRecoderTaskManager::recode_thread2() { | @@ -260,6 +352,161 @@ void FFRecoderTaskManager::recode_thread2() { | ||
260 | continue; | 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 | LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); | 510 | LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); |
264 | 511 | ||
265 | m_pkt_list_mtx.lock(); | 512 | m_pkt_list_mtx.lock(); |
@@ -276,7 +523,7 @@ void FFRecoderTaskManager::recode_thread2() { | @@ -276,7 +523,7 @@ void FFRecoderTaskManager::recode_thread2() { | ||
276 | std::string id = recoderinfo.task_id + "_" + recoderinfo.object_id + "_" + std::to_string(recoderinfo.frame_nb); | 523 | std::string id = recoderinfo.task_id + "_" + recoderinfo.object_id + "_" + std::to_string(recoderinfo.frame_nb); |
277 | string file_name = recoderinfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; | 524 | string file_name = recoderinfo.recoderDir + "/recoder_" + id + "_" + std::to_string(get_cur_time()) + ".mp4"; |
278 | FFRecoder ffrecoder; | 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 | if (!bInit) { | 527 | if (!bInit) { |
281 | LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); | 528 | LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); |
282 | ffrecoder.uninit(); | 529 | ffrecoder.uninit(); |
src/decoder/dvpp/FFRecoderTaskManager.h
@@ -28,18 +28,26 @@ public: | @@ -28,18 +28,26 @@ public: | ||
28 | void cache_pkt(AVPacket* pkt, long long frame_nb); | 28 | void cache_pkt(AVPacket* pkt, long long frame_nb); |
29 | void create_recode_task(AVRational time_base, AVCodecContext* avctx, RecoderInfo& recoderInfo); | 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 | void create_recode_task2(RecoderInfo& recoderInfo); | 32 | void create_recode_task2(RecoderInfo& recoderInfo); |
33 | 33 | ||
34 | void close(); | 34 | void close(); |
35 | 35 | ||
36 | void set_mq_callback(mq_callback_t cb); | 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 | public: | 41 | public: |
39 | void recode_thread(RecodeParam param); | 42 | void recode_thread(RecodeParam param); |
40 | list<DataPacket*>::iterator getStartIterator(unsigned long long frame_nb); | 43 | list<DataPacket*>::iterator getStartIterator(unsigned long long frame_nb); |
44 | + list<DataPacket*>::iterator getEndIterator(unsigned long long frame_nb); | ||
41 | 45 | ||
42 | void recode_thread2(); | 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 | private: | 52 | private: |
45 | void save_intask_frame_nb(unsigned long long frame_nb); | 53 | void save_intask_frame_nb(unsigned long long frame_nb); |
@@ -64,8 +72,12 @@ private: | @@ -64,8 +72,12 @@ private: | ||
64 | 72 | ||
65 | AVRational m_time_base; | 73 | AVRational m_time_base; |
66 | AVCodecContext* m_avctx; | 74 | AVCodecContext* m_avctx; |
75 | + AVStream* m_inStream; | ||
67 | 76 | ||
68 | thread* m_recoder_thread{nullptr}; | 77 | thread* m_recoder_thread{nullptr}; |
69 | 78 | ||
70 | mq_callback_t mq_publish_func; | 79 | mq_callback_t mq_publish_func; |
80 | + | ||
81 | + std::list<DataFrame*> m_frame_list; | ||
82 | + mutex m_frame_list_mtx; | ||
71 | }; | 83 | }; |
72 | \ No newline at end of file | 84 | \ No newline at end of file |
src/decoder/dvpp/depend_headers.h
@@ -49,4 +49,17 @@ struct DataPacket { | @@ -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 | #endif | 65 | #endif |
53 | \ No newline at end of file | 66 | \ No newline at end of file |
src/decoder/test_recoder.cpp
@@ -29,6 +29,8 @@ void algorthim_process_thread(); | @@ -29,6 +29,8 @@ void algorthim_process_thread(); | ||
29 | void recode_thread(); | 29 | void recode_thread(); |
30 | void algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem); | 30 | void algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem); |
31 | 31 | ||
32 | +void test_recode_thread(); | ||
33 | + | ||
32 | void post_decod_cbk(const void * userPtr, DeviceMemory* devFrame){ | 34 | void post_decod_cbk(const void * userPtr, DeviceMemory* devFrame){ |
33 | do{ | 35 | do{ |
34 | if(m_bfinish){ | 36 | if(m_bfinish){ |
@@ -62,7 +64,7 @@ int main(){ | @@ -62,7 +64,7 @@ int main(){ | ||
62 | 64 | ||
63 | MgrDecConfig config; | 65 | MgrDecConfig config; |
64 | config.name = task_id; | 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 | config.cfg.post_decoded_cbk = post_decod_cbk; | 68 | config.cfg.post_decoded_cbk = post_decod_cbk; |
67 | config.cfg.decode_finished_cbk = decode_finished_cbk; | 69 | config.cfg.decode_finished_cbk = decode_finished_cbk; |
68 | config.cfg.force_tcp = true; // rtsp用tcp | 70 | config.cfg.force_tcp = true; // rtsp用tcp |
@@ -95,8 +97,14 @@ int main(){ | @@ -95,8 +97,14 @@ int main(){ | ||
95 | } | 97 | } |
96 | , nullptr); | 98 | , nullptr); |
97 | 99 | ||
100 | + // m_recodeThread = new thread([](void* arg) { | ||
101 | + // recode_thread(); | ||
102 | + // return (void*)0; | ||
103 | + // } | ||
104 | + // , nullptr); | ||
105 | + | ||
98 | m_recodeThread = new thread([](void* arg) { | 106 | m_recodeThread = new thread([](void* arg) { |
99 | - recode_thread(); | 107 | + test_recode_thread(); |
100 | return (void*)0; | 108 | return (void*)0; |
101 | } | 109 | } |
102 | , nullptr); | 110 | , nullptr); |
@@ -183,6 +191,43 @@ void algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem) { | @@ -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 | void recode_thread() { | 231 | void recode_thread() { |
187 | while(true) { | 232 | while(true) { |
188 | 233 |