From: Mark Thompson <sw@jkqxz.net> To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH] amfenc: Use a blocking call instead of sleeping and polling Date: Wed, 18 Oct 2023 21:36:23 +0100 Message-ID: <d788c258-f65b-4f87-8ae4-e9a753af6416@jkqxz.net> (raw) In-Reply-To: <CADnG-DSc0Or_3+5Jv9LPwSAH6tLtFBOzpXih2LD=0amiE1i_MA@mail.gmail.com> --- On 17/10/2023 18:11, Evgeny Pavlov wrote: > The reason for using av_usleep() here is that AMF API doesn’t provide an > API for explicit wait. There are two modes to get output from encoder: > > 1. Polling with some sleep to avoid CPU thrashing – currently used in FFmpeg > > 2. Set timeout parameter on AMF encoder and QueryOutput call will block > till output is available or the timeout happens. > > #2 is the preferable way but it is designed more to be used with a separate > polling thread. With a single-thread approach in FFmpeg, the use of timeout > can block input submission making things slower. This is even more > pronounced when B-frames are enabled and several inputs are needed to produce > the first output. This approach seems like it should work here? Run non-blocking until the queue is full, then switch to blocking when you need to wait for some output. I tried the patch enclosing (H.264 only, different proprties needed for other codecs), but it doesn't seem to work - the test assert always hits immediately and timing shows that QueryOutput didn't block even though the timeout should be set? I'm probably doing something incorrect, maybe you would know how to fix it. > The condition of this sleep is in special events (primarily when amf input > queue is full), not the core loop part. During the experiments the cpu > increasing is about 2-4% or so, not a burst. What cases are you experimenting with? The most problematic case I can think of is multiple encodes running simultaneously sharing the same instance so that each one has to wait for others to complete and therefore all queues fill up. The busy wait will end up being the only place where it can block (since everything else runs asynchronously), so you will peg one CPU at close to 100% per encode running. Thanks, - Mark libavcodec/amfenc.c | 22 +++++++++++++++++++--- libavcodec/amfenc.h | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 061859f85c..db7ddbb083 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -713,13 +713,22 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) } } - + block_and_wait = 0; do { - block_and_wait = 0; // poll data if (!avpkt->data && !avpkt->buf) { + int64_t timeout = block_and_wait ? 100 : 0; + if (timeout != ctx->output_query_timeout) { + av_log(avctx, AV_LOG_INFO, "Set output query timeout to %"PRId64"\n", timeout); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, timeout); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Failed to set output query timeout\n"); + ctx->output_query_timeout = timeout; + } + res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data); if (data) { + av_log(avctx, AV_LOG_INFO, "QueryOutput returned with data\n"); + // copy data to packet AMFBuffer *buffer; AMFGuid guid = IID_AMFBuffer(); @@ -740,7 +749,13 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) data->pVtbl->Release(data); AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); + } else { + av_log(avctx, AV_LOG_INFO, "QueryOutput returned with nothing (%d)\n", res_query); + // For testing, shouldn't hit this unless machine is otherwise very loaded. + av_assert0(!block_and_wait); } + + block_and_wait = 0; } res_resubmit = AMF_OK; if (ctx->delayed_surface != NULL) { // try to resubmit frame @@ -769,8 +784,9 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) if (query_output_data_flag == 0) { if (res_resubmit == AMF_INPUT_FULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max)) { + av_log(avctx, AV_LOG_INFO, "Need to wait for output\n"); block_and_wait = 1; - av_usleep(1000); + //av_usleep(1000); } } } while (block_and_wait); diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 2dbd378ef8..64c77115b6 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -72,6 +72,7 @@ typedef struct AmfContext { int delayed_drain; AMFSurface *delayed_surface; AVFrame *delayed_frame; + int64_t output_query_timeout; // shift dts back by max_b_frames in timing AVFifo *timestamp_list; -- 2.39.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-10-18 20:36 UTC|newest] Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-10-16 9:13 [FFmpeg-devel] [PATCH] avcodec/amfenc: Fix for windows imprecise sleep Evgeny Pavlov 2023-10-16 21:24 ` Mark Thompson 2023-10-17 1:25 ` Zhao Zhili 2023-10-17 17:11 ` Evgeny Pavlov 2023-10-17 19:45 ` Kacper Michajlow 2023-10-18 10:32 ` Evgeny Pavlov 2023-10-18 20:36 ` Mark Thompson [this message] 2023-10-19 16:13 ` [FFmpeg-devel] [PATCH] amfenc: Use a blocking call instead of sleeping and polling Evgeny Pavlov 2023-10-22 14:30 ` Mark Thompson 2023-11-13 14:37 ` [FFmpeg-devel] [PATCH v2] avcodec/amfenc: increase precision of Sleep() on Windows Evgeny Pavlov 2023-11-20 16:01 ` Evgeny Pavlov 2023-11-27 13:42 ` Mark Thompson 2023-11-27 14:04 ` Henrik Gramner via ffmpeg-devel 2024-02-19 15:26 ` Evgeny Pavlov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=d788c258-f65b-4f87-8ae4-e9a753af6416@jkqxz.net \ --to=sw@jkqxz.net \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git