fftools/ffmpeg_filter: move filtering to a separate thread

As previously for decoding, this is merely "scaffolding" for moving to a
fully threaded architecture and does not yet make filtering truly
parallel - the main thread will currently wait for the filtering thread
to finish its work before continuing. That will change in future commits
after encoders are also moved to threads and a thread-aware scheduler is
added.
This commit is contained in:
Anton Khirnov 2023-06-08 20:36:33 +02:00
parent 4b8a171beb
commit d35c05cb9e
3 changed files with 732 additions and 143 deletions

View File

@ -80,6 +80,14 @@ enum HWAccelID {
HWACCEL_GENERIC, HWACCEL_GENERIC,
}; };
enum FrameOpaque {
FRAME_OPAQUE_REAP_FILTERS = 1,
FRAME_OPAQUE_CHOOSE_INPUT,
FRAME_OPAQUE_SUB_HEARTBEAT,
FRAME_OPAQUE_EOF,
FRAME_OPAQUE_SEND_COMMAND,
};
typedef struct HWDevice { typedef struct HWDevice {
const char *name; const char *name;
enum AVHWDeviceType type; enum AVHWDeviceType type;
@ -730,7 +738,6 @@ const FrameData *frame_data_c(AVFrame *frame);
int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference);
int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb);
int ifilter_sub2video(InputFilter *ifilter, const AVFrame *frame);
void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb); void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb);
/** /**

View File

@ -147,11 +147,12 @@ fail:
static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame)
{ {
int i, ret; int i, ret = 0;
av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */
for (i = 0; i < ist->nb_filters; i++) { for (i = 0; i < ist->nb_filters; i++) {
ret = ifilter_send_frame(ist->filters[i], decoded_frame, i < ist->nb_filters - 1); ret = ifilter_send_frame(ist->filters[i], decoded_frame,
i < ist->nb_filters - 1 ||
ist->dec->type == AVMEDIA_TYPE_SUBTITLE);
if (ret == AVERROR_EOF) if (ret == AVERROR_EOF)
ret = 0; /* ignore */ ret = 0; /* ignore */
if (ret < 0) { if (ret < 0) {
@ -380,15 +381,6 @@ static int video_frame_process(InputStream *ist, AVFrame *frame)
return 0; return 0;
} }
static void sub2video_flush(InputStream *ist)
{
for (int i = 0; i < ist->nb_filters; i++) {
int ret = ifilter_sub2video(ist->filters[i], NULL);
if (ret != AVERROR_EOF && ret < 0)
av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n");
}
}
static int process_subtitle(InputStream *ist, AVFrame *frame) static int process_subtitle(InputStream *ist, AVFrame *frame)
{ {
Decoder *d = ist->decoder; Decoder *d = ist->decoder;
@ -426,14 +418,9 @@ static int process_subtitle(InputStream *ist, AVFrame *frame)
if (!subtitle) if (!subtitle)
return 0; return 0;
for (int i = 0; i < ist->nb_filters; i++) { ret = send_frame_to_filters(ist, frame);
ret = ifilter_sub2video(ist->filters[i], frame); if (ret < 0)
if (ret < 0) { return ret;
av_log(ist, AV_LOG_ERROR, "Error sending a subtitle for filtering: %s\n",
av_err2str(ret));
return ret;
}
}
subtitle = (AVSubtitle*)frame->buf[0]->data; subtitle = (AVSubtitle*)frame->buf[0]->data;
if (!subtitle->num_rects) if (!subtitle->num_rects)
@ -824,14 +811,10 @@ finish:
return ret; return ret;
// signal EOF to our downstreams // signal EOF to our downstreams
if (ist->dec->type == AVMEDIA_TYPE_SUBTITLE) ret = send_filter_eof(ist);
sub2video_flush(ist); if (ret < 0) {
else { av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");
ret = send_filter_eof(ist); return ret;
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");
return ret;
}
} }
return AVERROR_EOF; return AVERROR_EOF;

File diff suppressed because it is too large Load Diff