From patchwork Mon Mar 6 09:38:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wm4 X-Patchwork-Id: 2766 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.50.79 with SMTP id y76csp145vsy; Mon, 6 Mar 2017 01:44:49 -0800 (PST) X-Received: by 10.223.183.6 with SMTP id l6mr13134231wre.60.1488793489243; Mon, 06 Mar 2017 01:44:49 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id t23si9561232wrc.41.2017.03.06.01.44.48; Mon, 06 Mar 2017 01:44:49 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@googlemail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 74915688276; Mon, 6 Mar 2017 11:44:33 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f172.google.com (mail-wr0-f172.google.com [209.85.128.172]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9F25B688261 for ; Mon, 6 Mar 2017 11:44:27 +0200 (EET) Received: by mail-wr0-f172.google.com with SMTP id g10so112175780wrg.2 for ; Mon, 06 Mar 2017 01:44:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=haHM7/wzNymaBnkuTl3WgSOv4KpCUmKXU4dcjin4yC4=; b=c98ZbNKDNJFtwvR/iwOZQM6udul3u9dnfNMU+UFXeOCXIys7LUI6gq7CUDXIL1ZIKH fmIcpHvT7FWY5SyohZf2KdHOt7Yrt6vd5FcCohHGs9Wi8l/5SQTY1jn/OLx1NdC5qwxq gHxj2nfrekP4gTenkxGemfTUUC7UIm2N+IfgYdtaIXjlhyvyn4HRv6Q/St42iBWDPmge 5f0p0aZrshjcDeIRIiGFyn8aZ+AmCITczMDfYf89SzjyAigya+r3njtbFh/+IrJpLlY3 cU4q2Mfc2Tu0hNxLyfGqCVapEL78avslbQkPAZSzrJZfI1fykNTG6uogdrOZ3g0i6EGP L4Lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=haHM7/wzNymaBnkuTl3WgSOv4KpCUmKXU4dcjin4yC4=; b=LaEZtpkUg/YZKTeufiDw/g4VvhiNzS50pT/L0RmiNjcb6ERRZbq7tH+jA2+fCT8Yey koYYeiP68tyl8AO89T44uqthLSY2sAA9D1DkqqayTne40OmvQ14Vhd4PQ2DyudQE0ZIN wnlrbKDz/+A1o/m87aoploOsW4HeKuifm1YCaDnVbHlRwgZk4izGsVtvHxaOYLfQaVFC 8fUZ9d4L2Z2g1qPJOr8dwRyhLJW7nca/cruBeYQIwVM7mdqRGHl03Pb82gV8wdJfi/nl gjkAnCLfkqdGX3/Q0iywQkK+D9o0NgmYQfLY5XOliHdCpwwsiDi7tNi++n4AfvmQ2Q5P ykyQ== X-Gm-Message-State: AMke39mKB1zHrpnw52xV457McBlg6j4qFzeOAJ5vsaDaAlXXFfFPwr3rfKY+8UEZCIi5hg== X-Received: by 10.223.164.85 with SMTP id e21mr13808863wra.58.1488793093692; Mon, 06 Mar 2017 01:38:13 -0800 (PST) Received: from localhost.localdomain (p4FF0036C.dip0.t-ipconnect.de. [79.240.3.108]) by smtp.googlemail.com with ESMTPSA id t194sm14089217wmd.13.2017.03.06.01.38.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Mar 2017 01:38:12 -0800 (PST) From: wm4 To: libav-devel@libav.org Date: Mon, 6 Mar 2017 10:38:12 +0100 Message-Id: <20170306093812.1978-1-nfxjfg@googlemail.com> X-Mailer: git-send-email 2.11.0 Subject: [FFmpeg-devel] [PATCH] avcodec: clarify some decoding/encoding API details X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: wm4 , ffmpeg-devel@ffmpeg.org MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Make it clear that there is no timing-dependent behavior. In particular, there is no state in which both input and output are denied, and where you have to wait for a while yourself to make progress (apparently some hardware decoders like to do this). Avoid wording that makes references to time. It shouldn't be mistaken for some kind of asynchronous API (like POSIX read() can return EAGAIN if there is no new input yet). It's a state machine, so try to use appropriate terms. --- I hope it's actually an improvement, instead of making the wall of text worse. To be fair, I think using EAGAIN was Wrong anyway, but there was a precedent in libavfilter. --- libavcodec/avcodec.h | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 489a618cbb..f9f409d3c5 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -114,6 +114,12 @@ * are filled. This situation is handled transparently if you follow the steps * outlined above. * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive ouput if that + * returns EAGAIN. + * * End of stream situations. These require "flushing" (aka draining) the codec, * as the codec might buffer multiple frames or packets internally for * performance or out of necessity (consider B-frames). @@ -148,7 +154,8 @@ * Unlike with the old video decoding API, multiple frames might result from * a packet. For audio, splitting the input packet into frames by partially * decoding packets becomes transparent to the API user. You never need to - * feed an AVPacket to the API twice. + * feed an AVPacket to the API twice (unless it is rejected with EAGAIN - then + * no data was read from the packet). * Additionally, sending a flush/draining packet is required only once. * - avcodec_encode_video2()/avcodec_encode_audio2(): * Use avcodec_send_frame() to feed input to the encoder, then use @@ -161,7 +168,20 @@ * and will result in arbitrary behavior. * * Some codecs might require using the new API; using the old API will return - * an error when calling it. + * an error when calling it. All codecs support the new API. + * + * A codec is not allowed to return EAGAIN for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in EAGAIN, but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. As long as it never results to both send/receive returning + * both EAGAIN at the same time at any point, and no "flip flopping" between the + * send/receive APIs is possible (e.g. the codec randomly deciding that it + * actually wants to consume a packet now instead of returning a frame, after it + * just has returned EAGAIN on an avcodec_send_packet() call), such behavior + * might still be deemed acceptable. * @} */ @@ -4339,8 +4359,10 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, * a flush packet. * * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): input is not accepted right now - the packet must be - * resent after trying to read output + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all ouput is read, the packet should be resent, and + * the call will not fail with EAGAIN). * AVERROR_EOF: the decoder has been flushed, and no new packets can * be sent to it (also returned if more than 1 flush * packet is sent) @@ -4361,7 +4383,7 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); * * @return * 0: success, a frame was returned - * AVERROR(EAGAIN): output is not available right now - user must try + * AVERROR(EAGAIN): output is not available in this state - user must try * to send new input * AVERROR_EOF: the decoder has been fully flushed, and there will be * no more output frames @@ -4394,8 +4416,10 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); * avctx->frame_size for all frames except the last. * The final frame may be smaller than avctx->frame_size. * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): input is not accepted right now - the frame must be - * resent after trying to read output packets + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_packet() (once + * all ouput is read, the packet should be resent, and + * the call will not fail with EAGAIN). * AVERROR_EOF: the encoder has been flushed, and no new frames can * be sent to it * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a @@ -4413,8 +4437,8 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); * encoder. Note that the function will always call * av_frame_unref(frame) before doing anything else. * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): output is not available right now - user must try - * to send input + * AVERROR(EAGAIN): output is not available in the current state - user + * must try to send input * AVERROR_EOF: the encoder has been fully flushed, and there will be * no more output packets * AVERROR(EINVAL): codec not opened, or it is an encoder