From: Evgeny Pavlov <lucenticus@gmail.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: Re: [FFmpeg-devel] [PATCH] amfenc: Use a blocking call instead of sleeping and polling Date: Thu, 19 Oct 2023 18:13:53 +0200 Message-ID: <CADnG-DSgZENn9=qxUnZCOXi7Ac+e4ShmBqH+dyuTZHsNApHCJQ@mail.gmail.com> (raw) In-Reply-To: <d788c258-f65b-4f87-8ae4-e9a753af6416@jkqxz.net> On Wed, Oct 18, 2023 at 10:36 PM Mark Thompson <sw@jkqxz.net> wrote: > --- > 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". > Dynamic switching between non-blocking & blocking approaches isn’t supported in AMF at this time. We might request to implement this feature for AMF team, but it might took some time to implement this. I would suggest using av_usleep(500) until this feature is implemented. > What cases are you experimenting with? This issue is very easy to reproduce when: 1) low resolution transcoding 2) hardware accelerated decoding The command line sample: ffmpeg -hwaccel d3d11va -hwaccel_output_format d3d11 -i input_480x360_h264.mp4 -c:v hevc_amf output_480x360_hevc.mp4 _______________________________________________ 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-19 16:37 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 ` [FFmpeg-devel] [PATCH] amfenc: Use a blocking call instead of sleeping and polling Mark Thompson 2023-10-19 16:13 ` Evgeny Pavlov [this message] 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='CADnG-DSgZENn9=qxUnZCOXi7Ac+e4ShmBqH+dyuTZHsNApHCJQ@mail.gmail.com' \ --to=lucenticus@gmail.com \ --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