mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 20:42:49 +08:00 
			
		
		
		
	fftools/ffmpeg: move filtering functions to ffmpeg_filter
This commit is contained in:
		
							
								
								
									
										216
									
								
								fftools/ffmpeg.c
									
									
									
									
									
								
							
							
						
						
									
										216
									
								
								fftools/ffmpeg.c
									
									
									
									
									
								
							| @@ -651,66 +651,6 @@ void close_output_stream(OutputStream *ost) | |||||||
|         sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); |         sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Get and encode new output from any of the filtergraphs, without causing |  | ||||||
|  * activity. |  | ||||||
|  * |  | ||||||
|  * @return  0 for success, <0 for severe errors |  | ||||||
|  */ |  | ||||||
| static int reap_filters(int flush) |  | ||||||
| { |  | ||||||
|     AVFrame *filtered_frame = NULL; |  | ||||||
|  |  | ||||||
|     /* Reap all buffers present in the buffer sinks */ |  | ||||||
|     for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { |  | ||||||
|         AVFilterContext *filter; |  | ||||||
|         int ret = 0; |  | ||||||
|  |  | ||||||
|         if (!ost->filter || !ost->filter->graph->graph) |  | ||||||
|             continue; |  | ||||||
|         filter = ost->filter->filter; |  | ||||||
|  |  | ||||||
|         filtered_frame = ost->filtered_frame; |  | ||||||
|  |  | ||||||
|         while (1) { |  | ||||||
|             ret = av_buffersink_get_frame_flags(filter, filtered_frame, |  | ||||||
|                                                AV_BUFFERSINK_FLAG_NO_REQUEST); |  | ||||||
|             if (ret < 0) { |  | ||||||
|                 if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { |  | ||||||
|                     av_log(NULL, AV_LOG_WARNING, |  | ||||||
|                            "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); |  | ||||||
|                 } else if (flush && ret == AVERROR_EOF) { |  | ||||||
|                     if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) |  | ||||||
|                         enc_frame(ost, NULL); |  | ||||||
|                 } |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|             if (ost->finished) { |  | ||||||
|                 av_frame_unref(filtered_frame); |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (filtered_frame->pts != AV_NOPTS_VALUE) { |  | ||||||
|                 AVRational tb = av_buffersink_get_time_base(filter); |  | ||||||
|                 ost->filter->last_pts = av_rescale_q(filtered_frame->pts, tb, |  | ||||||
|                                                      AV_TIME_BASE_Q); |  | ||||||
|                 filtered_frame->time_base = tb; |  | ||||||
|  |  | ||||||
|                 if (debug_ts) |  | ||||||
|                     av_log(NULL, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", |  | ||||||
|                            av_ts2str(filtered_frame->pts), |  | ||||||
|                            av_ts2timestr(filtered_frame->pts, &tb), |  | ||||||
|                            tb.num, tb.den); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             enc_frame(ost, filtered_frame); |  | ||||||
|             av_frame_unref(filtered_frame); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) | static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) | ||||||
| { | { | ||||||
|     AVBPrint buf, buf_script; |     AVBPrint buf, buf_script; | ||||||
| @@ -914,112 +854,6 @@ int ifilter_has_all_input_formats(FilterGraph *fg) | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) |  | ||||||
| { |  | ||||||
|     FilterGraph *fg = ifilter->graph; |  | ||||||
|     AVFrameSideData *sd; |  | ||||||
|     int need_reinit, ret; |  | ||||||
|     int buffersrc_flags = AV_BUFFERSRC_FLAG_PUSH; |  | ||||||
|  |  | ||||||
|     if (keep_reference) |  | ||||||
|         buffersrc_flags |= AV_BUFFERSRC_FLAG_KEEP_REF; |  | ||||||
|  |  | ||||||
|     /* determine if the parameters for this input changed */ |  | ||||||
|     need_reinit = ifilter->format != frame->format; |  | ||||||
|  |  | ||||||
|     switch (ifilter->ist->par->codec_type) { |  | ||||||
|     case AVMEDIA_TYPE_AUDIO: |  | ||||||
|         need_reinit |= ifilter->sample_rate    != frame->sample_rate || |  | ||||||
|                        av_channel_layout_compare(&ifilter->ch_layout, &frame->ch_layout); |  | ||||||
|         break; |  | ||||||
|     case AVMEDIA_TYPE_VIDEO: |  | ||||||
|         need_reinit |= ifilter->width  != frame->width || |  | ||||||
|                        ifilter->height != frame->height; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!ifilter->ist->reinit_filters && fg->graph) |  | ||||||
|         need_reinit = 0; |  | ||||||
|  |  | ||||||
|     if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || |  | ||||||
|         (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) |  | ||||||
|         need_reinit = 1; |  | ||||||
|  |  | ||||||
|     if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { |  | ||||||
|         if (!ifilter->displaymatrix || memcmp(sd->data, ifilter->displaymatrix, sizeof(int32_t) * 9)) |  | ||||||
|             need_reinit = 1; |  | ||||||
|     } else if (ifilter->displaymatrix) |  | ||||||
|         need_reinit = 1; |  | ||||||
|  |  | ||||||
|     if (need_reinit) { |  | ||||||
|         ret = ifilter_parameters_from_frame(ifilter, frame); |  | ||||||
|         if (ret < 0) |  | ||||||
|             return ret; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* (re)init the graph if possible, otherwise buffer the frame and return */ |  | ||||||
|     if (need_reinit || !fg->graph) { |  | ||||||
|         if (!ifilter_has_all_input_formats(fg)) { |  | ||||||
|             AVFrame *tmp = av_frame_clone(frame); |  | ||||||
|             if (!tmp) |  | ||||||
|                 return AVERROR(ENOMEM); |  | ||||||
|  |  | ||||||
|             ret = av_fifo_write(ifilter->frame_queue, &tmp, 1); |  | ||||||
|             if (ret < 0) |  | ||||||
|                 av_frame_free(&tmp); |  | ||||||
|  |  | ||||||
|             return ret; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         ret = reap_filters(1); |  | ||||||
|         if (ret < 0 && ret != AVERROR_EOF) { |  | ||||||
|             av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); |  | ||||||
|             return ret; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         ret = configure_filtergraph(fg); |  | ||||||
|         if (ret < 0) { |  | ||||||
|             av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); |  | ||||||
|             return ret; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, buffersrc_flags); |  | ||||||
|     if (ret < 0) { |  | ||||||
|         if (ret != AVERROR_EOF) |  | ||||||
|             av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); |  | ||||||
|         return ret; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) |  | ||||||
| { |  | ||||||
|     int ret; |  | ||||||
|  |  | ||||||
|     ifilter->eof = 1; |  | ||||||
|  |  | ||||||
|     if (ifilter->filter) { |  | ||||||
|         ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); |  | ||||||
|         if (ret < 0) |  | ||||||
|             return ret; |  | ||||||
|     } else { |  | ||||||
|         // the filtergraph was never configured |  | ||||||
|         if (ifilter->format < 0) { |  | ||||||
|             ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); |  | ||||||
|             if (ret < 0) |  | ||||||
|                 return ret; |  | ||||||
|         } |  | ||||||
|         if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { |  | ||||||
|             av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); |  | ||||||
|             return AVERROR_INVALIDDATA; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. | // This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. | ||||||
| // There is the following difference: if you got a frame, you must call | // There is the following difference: if you got a frame, you must call | ||||||
| // it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 | // it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 | ||||||
| @@ -2262,54 +2096,6 @@ discard_packet: | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Perform a step of transcoding for the specified filter graph. |  | ||||||
|  * |  | ||||||
|  * @param[in]  graph     filter graph to consider |  | ||||||
|  * @param[out] best_ist  input stream where a frame would allow to continue |  | ||||||
|  * @return  0 for success, <0 for error |  | ||||||
|  */ |  | ||||||
| static int transcode_from_filter(FilterGraph *graph, InputStream **best_ist) |  | ||||||
| { |  | ||||||
|     int i, ret; |  | ||||||
|     int nb_requests, nb_requests_max = 0; |  | ||||||
|     InputFilter *ifilter; |  | ||||||
|     InputStream *ist; |  | ||||||
|  |  | ||||||
|     *best_ist = NULL; |  | ||||||
|     ret = avfilter_graph_request_oldest(graph->graph); |  | ||||||
|     if (ret >= 0) |  | ||||||
|         return reap_filters(0); |  | ||||||
|  |  | ||||||
|     if (ret == AVERROR_EOF) { |  | ||||||
|         ret = reap_filters(1); |  | ||||||
|         for (i = 0; i < graph->nb_outputs; i++) |  | ||||||
|             close_output_stream(graph->outputs[i]->ost); |  | ||||||
|         return ret; |  | ||||||
|     } |  | ||||||
|     if (ret != AVERROR(EAGAIN)) |  | ||||||
|         return ret; |  | ||||||
|  |  | ||||||
|     for (i = 0; i < graph->nb_inputs; i++) { |  | ||||||
|         ifilter = graph->inputs[i]; |  | ||||||
|         ist = ifilter->ist; |  | ||||||
|         if (input_files[ist->file_index]->eagain || |  | ||||||
|             input_files[ist->file_index]->eof_reached) |  | ||||||
|             continue; |  | ||||||
|         nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); |  | ||||||
|         if (nb_requests > nb_requests_max) { |  | ||||||
|             nb_requests_max = nb_requests; |  | ||||||
|             *best_ist = ist; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!*best_ist) |  | ||||||
|         for (i = 0; i < graph->nb_outputs; i++) |  | ||||||
|             graph->outputs[i]->ost->unavailable = 1; |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Run a single step of transcoding. |  * Run a single step of transcoding. | ||||||
|  * |  * | ||||||
| @@ -2343,7 +2129,7 @@ static int transcode_step(void) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (ost->filter && ost->filter->graph->graph) { |     if (ost->filter && ost->filter->graph->graph) { | ||||||
|         if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0) |         if ((ret = fg_transcode_step(ost->filter->graph, &ist)) < 0) | ||||||
|             return ret; |             return ret; | ||||||
|         if (!ist) |         if (!ist) | ||||||
|             return 0; |             return 0; | ||||||
|   | |||||||
| @@ -799,6 +799,9 @@ int init_complex_filtergraph(FilterGraph *fg); | |||||||
|  |  | ||||||
| void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); | void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); | ||||||
|  |  | ||||||
|  | int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); | ||||||
|  | int ifilter_send_eof(InputFilter *ifilter, int64_t pts); | ||||||
|  |  | ||||||
| int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); | int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); | ||||||
| int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); | int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); | ||||||
| int ifilter_has_all_input_formats(FilterGraph *fg); | int ifilter_has_all_input_formats(FilterGraph *fg); | ||||||
| @@ -811,6 +814,23 @@ int ifilter_has_all_input_formats(FilterGraph *fg); | |||||||
|  */ |  */ | ||||||
| FilterGraph *fg_create(char *graph_desc); | FilterGraph *fg_create(char *graph_desc); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Perform a step of transcoding for the specified filter graph. | ||||||
|  |  * | ||||||
|  |  * @param[in]  graph     filter graph to consider | ||||||
|  |  * @param[out] best_ist  input stream where a frame would allow to continue | ||||||
|  |  * @return  0 for success, <0 for error | ||||||
|  |  */ | ||||||
|  | int fg_transcode_step(FilterGraph *graph, InputStream **best_ist); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get and encode new output from any of the filtergraphs, without causing | ||||||
|  |  * activity. | ||||||
|  |  * | ||||||
|  |  * @return  0 for success, <0 for severe errors | ||||||
|  |  */ | ||||||
|  | int reap_filters(int flush); | ||||||
|  |  | ||||||
| int ffmpeg_parse_options(int argc, char **argv); | int ffmpeg_parse_options(int argc, char **argv); | ||||||
|  |  | ||||||
| void enc_stats_write(OutputStream *ost, EncStats *es, | void enc_stats_write(OutputStream *ost, EncStats *es, | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ | |||||||
| #include "libavutil/pixfmt.h" | #include "libavutil/pixfmt.h" | ||||||
| #include "libavutil/imgutils.h" | #include "libavutil/imgutils.h" | ||||||
| #include "libavutil/samplefmt.h" | #include "libavutil/samplefmt.h" | ||||||
|  | #include "libavutil/timestamp.h" | ||||||
|  |  | ||||||
| // FIXME: YUV420P etc. are actually supported with full color range, | // FIXME: YUV420P etc. are actually supported with full color range, | ||||||
| // yet the latter information isn't available here. | // yet the latter information isn't available here. | ||||||
| @@ -1300,3 +1301,204 @@ int filtergraph_is_simple(FilterGraph *fg) | |||||||
| { | { | ||||||
|     return !fg->graph_desc; |     return !fg->graph_desc; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int reap_filters(int flush) | ||||||
|  | { | ||||||
|  |     AVFrame *filtered_frame = NULL; | ||||||
|  |  | ||||||
|  |     /* Reap all buffers present in the buffer sinks */ | ||||||
|  |     for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { | ||||||
|  |         AVFilterContext *filter; | ||||||
|  |         int ret = 0; | ||||||
|  |  | ||||||
|  |         if (!ost->filter || !ost->filter->graph->graph) | ||||||
|  |             continue; | ||||||
|  |         filter = ost->filter->filter; | ||||||
|  |  | ||||||
|  |         filtered_frame = ost->filtered_frame; | ||||||
|  |  | ||||||
|  |         while (1) { | ||||||
|  |             ret = av_buffersink_get_frame_flags(filter, filtered_frame, | ||||||
|  |                                                AV_BUFFERSINK_FLAG_NO_REQUEST); | ||||||
|  |             if (ret < 0) { | ||||||
|  |                 if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { | ||||||
|  |                     av_log(NULL, AV_LOG_WARNING, | ||||||
|  |                            "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); | ||||||
|  |                 } else if (flush && ret == AVERROR_EOF) { | ||||||
|  |                     if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) | ||||||
|  |                         enc_frame(ost, NULL); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             if (ost->finished) { | ||||||
|  |                 av_frame_unref(filtered_frame); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (filtered_frame->pts != AV_NOPTS_VALUE) { | ||||||
|  |                 AVRational tb = av_buffersink_get_time_base(filter); | ||||||
|  |                 ost->filter->last_pts = av_rescale_q(filtered_frame->pts, tb, | ||||||
|  |                                                      AV_TIME_BASE_Q); | ||||||
|  |                 filtered_frame->time_base = tb; | ||||||
|  |  | ||||||
|  |                 if (debug_ts) | ||||||
|  |                     av_log(NULL, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", | ||||||
|  |                            av_ts2str(filtered_frame->pts), | ||||||
|  |                            av_ts2timestr(filtered_frame->pts, &tb), | ||||||
|  |                            tb.num, tb.den); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             enc_frame(ost, filtered_frame); | ||||||
|  |             av_frame_unref(filtered_frame); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ifilter_send_eof(InputFilter *ifilter, int64_t pts) | ||||||
|  | { | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|  |     ifilter->eof = 1; | ||||||
|  |  | ||||||
|  |     if (ifilter->filter) { | ||||||
|  |         ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |     } else { | ||||||
|  |         // the filtergraph was never configured | ||||||
|  |         if (ifilter->format < 0) { | ||||||
|  |             ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); | ||||||
|  |             if (ret < 0) | ||||||
|  |                 return ret; | ||||||
|  |         } | ||||||
|  |         if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { | ||||||
|  |             av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); | ||||||
|  |             return AVERROR_INVALIDDATA; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) | ||||||
|  | { | ||||||
|  |     FilterGraph *fg = ifilter->graph; | ||||||
|  |     AVFrameSideData *sd; | ||||||
|  |     int need_reinit, ret; | ||||||
|  |     int buffersrc_flags = AV_BUFFERSRC_FLAG_PUSH; | ||||||
|  |  | ||||||
|  |     if (keep_reference) | ||||||
|  |         buffersrc_flags |= AV_BUFFERSRC_FLAG_KEEP_REF; | ||||||
|  |  | ||||||
|  |     /* determine if the parameters for this input changed */ | ||||||
|  |     need_reinit = ifilter->format != frame->format; | ||||||
|  |  | ||||||
|  |     switch (ifilter->ist->par->codec_type) { | ||||||
|  |     case AVMEDIA_TYPE_AUDIO: | ||||||
|  |         need_reinit |= ifilter->sample_rate    != frame->sample_rate || | ||||||
|  |                        av_channel_layout_compare(&ifilter->ch_layout, &frame->ch_layout); | ||||||
|  |         break; | ||||||
|  |     case AVMEDIA_TYPE_VIDEO: | ||||||
|  |         need_reinit |= ifilter->width  != frame->width || | ||||||
|  |                        ifilter->height != frame->height; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!ifilter->ist->reinit_filters && fg->graph) | ||||||
|  |         need_reinit = 0; | ||||||
|  |  | ||||||
|  |     if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || | ||||||
|  |         (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) | ||||||
|  |         need_reinit = 1; | ||||||
|  |  | ||||||
|  |     if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { | ||||||
|  |         if (!ifilter->displaymatrix || memcmp(sd->data, ifilter->displaymatrix, sizeof(int32_t) * 9)) | ||||||
|  |             need_reinit = 1; | ||||||
|  |     } else if (ifilter->displaymatrix) | ||||||
|  |         need_reinit = 1; | ||||||
|  |  | ||||||
|  |     if (need_reinit) { | ||||||
|  |         ret = ifilter_parameters_from_frame(ifilter, frame); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* (re)init the graph if possible, otherwise buffer the frame and return */ | ||||||
|  |     if (need_reinit || !fg->graph) { | ||||||
|  |         if (!ifilter_has_all_input_formats(fg)) { | ||||||
|  |             AVFrame *tmp = av_frame_clone(frame); | ||||||
|  |             if (!tmp) | ||||||
|  |                 return AVERROR(ENOMEM); | ||||||
|  |  | ||||||
|  |             ret = av_fifo_write(ifilter->frame_queue, &tmp, 1); | ||||||
|  |             if (ret < 0) | ||||||
|  |                 av_frame_free(&tmp); | ||||||
|  |  | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ret = reap_filters(1); | ||||||
|  |         if (ret < 0 && ret != AVERROR_EOF) { | ||||||
|  |             av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ret = configure_filtergraph(fg); | ||||||
|  |         if (ret < 0) { | ||||||
|  |             av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, buffersrc_flags); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         if (ret != AVERROR_EOF) | ||||||
|  |             av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) | ||||||
|  | { | ||||||
|  |     int i, ret; | ||||||
|  |     int nb_requests, nb_requests_max = 0; | ||||||
|  |     InputFilter *ifilter; | ||||||
|  |     InputStream *ist; | ||||||
|  |  | ||||||
|  |     *best_ist = NULL; | ||||||
|  |     ret = avfilter_graph_request_oldest(graph->graph); | ||||||
|  |     if (ret >= 0) | ||||||
|  |         return reap_filters(0); | ||||||
|  |  | ||||||
|  |     if (ret == AVERROR_EOF) { | ||||||
|  |         ret = reap_filters(1); | ||||||
|  |         for (i = 0; i < graph->nb_outputs; i++) | ||||||
|  |             close_output_stream(graph->outputs[i]->ost); | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  |     if (ret != AVERROR(EAGAIN)) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     for (i = 0; i < graph->nb_inputs; i++) { | ||||||
|  |         ifilter = graph->inputs[i]; | ||||||
|  |         ist = ifilter->ist; | ||||||
|  |         if (input_files[ist->file_index]->eagain || | ||||||
|  |             input_files[ist->file_index]->eof_reached) | ||||||
|  |             continue; | ||||||
|  |         nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); | ||||||
|  |         if (nb_requests > nb_requests_max) { | ||||||
|  |             nb_requests_max = nb_requests; | ||||||
|  |             *best_ist = ist; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!*best_ist) | ||||||
|  |         for (i = 0; i < graph->nb_outputs; i++) | ||||||
|  |             graph->outputs[i]->ost->unavailable = 1; | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Anton Khirnov
					Anton Khirnov