Skip to content

Commit 5584909

Browse files
HuHengjonahmvp
authored andcommitted
Modify flush method of filter graph
use av_buffersrc_close for better compliance with common standards and resolve the frame loss issue when use fps filter. fix
1 parent 3b92c69 commit 5584909

File tree

3 files changed

+66
-8
lines changed

3 files changed

+66
-8
lines changed

bmf/c_modules/include/ffmpeg_filter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class CFFFilter : public Module {
3838
std::vector<bool> in_eof_;
3939
std::vector<bool> out_eof_;
4040
std::vector<bool> out_eof_send_;
41+
std::vector<bool> push_eof_;
42+
43+
4144
std::map<int, FilterConfig> config_;
4245
int64_t stream_start_time_;
4346
int64_t stream_first_dts_;
@@ -79,6 +82,7 @@ class CFFFilter : public Module {
7982

8083
bmf_sdk::Packet convert_avframe_to_packet(AVFrame *frame, int index);
8184
bool check_finished();
85+
bool check_input_finished();
8286
int get_cache_frame(int index, AVFrame *&frame, int &choose_index);
8387
};
8488

bmf/c_modules/src/ffmpeg_filter.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ int CFFFilter::process_filter_graph(Task &task) {
433433
ret = filter_graph_->push_frame(frame, choose_index);
434434
if (frame) {
435435
av_frame_free(&frame);
436+
} else if(choose_index >=0 && choose_index < num_input_streams_){
437+
push_eof_[choose_index] = true;
436438
}
437439
if (ret < 0) {
438440
BMFLOG_NODE(BMF_INFO, node_id_) << "init push frame, ret: " << ret;
@@ -449,6 +451,7 @@ int CFFFilter::process_filter_graph(Task &task) {
449451
int ret =
450452
filter_graph_->reap_filters(output_frames, push_frame_flag);
451453
push_frame_flag = 0;
454+
int get_num = output_frames.size();
452455
for (auto output_frame : output_frames) {
453456
for (int index = 0; index < output_frame.second.size();
454457
index++) {
@@ -465,6 +468,14 @@ int CFFFilter::process_filter_graph(Task &task) {
465468
task.fill_output_packet(output_frame.first, packet);
466469
}
467470
}
471+
472+
if (check_input_finished() && get_num == 0) {
473+
for (int i = 0; i < num_output_streams_; i++) {
474+
out_eof_[i] = true;
475+
}
476+
return 0;
477+
}
478+
468479
if (check_finished()) {
469480
return 0;
470481
}
@@ -474,7 +485,7 @@ int CFFFilter::process_filter_graph(Task &task) {
474485
if (ret != AVERROR(EAGAIN) && ret < 0) {
475486
return ret;
476487
}
477-
int index = filter_graph_->get_the_most_failed_nb_request();
488+
int index = filter_graph_->get_the_most_failed_nb_request(push_eof_);
478489
if (index >= 0) {
479490
AVFrame *frame;
480491
int choose_index;
@@ -491,13 +502,18 @@ int CFFFilter::process_filter_graph(Task &task) {
491502
push_frame_flag = 1;
492503
if (frame) {
493504
av_frame_free(&frame);
505+
506+
} else if(choose_index >=0 && choose_index < num_input_streams_){
507+
push_eof_[choose_index] = true;
494508
}
509+
495510
if (ret < 0) {
496511
BMFLOG_NODE(BMF_INFO, node_id_) << "push frame, choose_index: " << choose_index << " ret: " << ret;
497512
return ret;
498513
}
499514
} else if (in_eof_[index]) {
500515
filter_graph_->push_frame(NULL, index);
516+
push_eof_[index] = true;
501517
push_frame_flag = 1;
502518
} else {
503519
break;
@@ -535,6 +551,15 @@ bool CFFFilter::check_finished() {
535551
return true;
536552
}
537553

554+
bool CFFFilter::check_input_finished() {
555+
for (int i = 0; i < num_input_streams_; i++) {
556+
if (!in_eof_[i] || !push_eof_[i]) {
557+
return false;
558+
}
559+
}
560+
return true;
561+
}
562+
538563
int CFFFilter::process(Task &task) {
539564
std::lock_guard<std::mutex> lk(cache_mutex_);
540565

@@ -558,6 +583,11 @@ int CFFFilter::process(Task &task) {
558583
in_eof_.push_back(false);
559584
}
560585
}
586+
if (push_eof_.size() == 0) {
587+
for (int i = 0; i < num_input_streams_; i++) {
588+
push_eof_.push_back(false);
589+
}
590+
}
561591
}
562592
if (!num_output_streams_) {
563593
num_output_streams_ = task.get_outputs().size();
@@ -642,6 +672,7 @@ int CFFFilter::process(Task &task) {
642672
int CFFFilter::reset() {
643673
for (int i = 0; i < num_input_streams_; i++) {
644674
in_eof_[i] = false;
675+
push_eof_[i] = false;
645676
}
646677
for (int i = 0; i < num_output_streams_; i++) {
647678
out_eof_[i] = false;

bmf/sdk/cpp_sdk/include/bmf/sdk/filter_graph.h

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class FilterGraph {
6262
std::map<int, FilterConfig> in_configs_;
6363
std::map<int, FilterConfig> out_configs_;
6464
bool b_init_;
65+
std::map<int, int64_t> next_pts_map;
6566

6667
public:
6768
AVFilterGraph *filter_graph_;
@@ -439,8 +440,18 @@ class FilterGraph {
439440
return -1;
440441
}
441442

442-
ret = av_buffersrc_add_frame_flags(buffer_src_ctx_[in_idx], frame,
443+
if (frame == NULL && next_pts_map.find(in_idx) != next_pts_map.end()) {
444+
ret = av_buffersrc_close(buffer_src_ctx_[in_idx], next_pts_map[in_idx], AV_BUFFERSRC_FLAG_PUSH);
445+
446+
} else {
447+
ret = av_buffersrc_add_frame_flags(buffer_src_ctx_[in_idx], frame,
443448
AV_BUFFERSRC_FLAG_PUSH);
449+
if (frame) {
450+
int64_t duration = frame->pkt_duration > 0 ? frame->pkt_duration : 1;
451+
next_pts_map[in_idx] = frame->pts + duration;
452+
}
453+
}
454+
444455
if (ret < 0) {
445456
av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
446457
return ret;
@@ -536,10 +547,13 @@ class FilterGraph {
536547
return 0;
537548
};
538549

539-
int get_the_most_failed_nb_request() {
540-
int index = -1;
541-
int most_failed_request = 0;
550+
int get_the_most_failed_nb_request(std::vector<bool>& push_eofs) {
551+
int index = 0;
552+
int most_failed_request = -1;
542553
for (int i = 0; i < buffer_src_ctx_.size(); i++) {
554+
if (push_eofs[i]) {
555+
continue;
556+
}
543557
int failed_request =
544558
av_buffersrc_get_nb_failed_requests(buffer_src_ctx_[i]);
545559
if (failed_request > most_failed_request) {
@@ -603,9 +617,18 @@ class FilterGraph {
603617
int push_frame(AVFrame *frame, int index) {
604618
int ret = 0;
605619
if ((ret = check_input_property(frame, index)) >= 0) {
606-
ret = av_buffersrc_add_frame_flags(buffer_src_ctx_[index], frame,
607-
AV_BUFFERSRC_FLAG_PUSH |
608-
AV_BUFFERSRC_FLAG_KEEP_REF);
620+
if (frame == NULL && next_pts_map.find(index) != next_pts_map.end()) {
621+
ret = av_buffersrc_close(buffer_src_ctx_[index], next_pts_map[index], AV_BUFFERSRC_FLAG_PUSH | AV_BUFFERSRC_FLAG_KEEP_REF);
622+
623+
} else {
624+
ret = av_buffersrc_add_frame_flags(buffer_src_ctx_[index], frame,
625+
AV_BUFFERSRC_FLAG_PUSH |
626+
AV_BUFFERSRC_FLAG_KEEP_REF);
627+
if (frame) {
628+
int64_t duration = frame->pkt_duration > 0 ? frame->pkt_duration : 1;
629+
next_pts_map[index] = frame->pts + duration;
630+
}
631+
}
609632
if (ret < 0) {
610633
if (ret != AVERROR_EOF) {
611634
BMFLOG(BMF_ERROR) << "add frame error: " << ret;

0 commit comments

Comments
 (0)