Commit bf661eb0b3b0cda5a2b5a5a420de46cf311e17e7

Authored by Hu Chunming
1 parent d9fc3e82

录像文件保存优化

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&lt;DataPacket*&gt;::iterator FFRecoderTaskManager::getStartIterator(unsigned long @@ -158,6 +213,43 @@ list&lt;DataPacket*&gt;::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&lt;DeviceMemory*&gt; vec_gpuMem) { @@ -183,6 +191,43 @@ void algorthim_face_detect(vector&lt;DeviceMemory*&gt; 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