From patchwork Fri Apr 28 10:19:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Muhammad Faiz X-Patchwork-Id: 3507 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.3.129 with SMTP id 123csp172755vsd; Fri, 28 Apr 2017 03:25:28 -0700 (PDT) X-Received: by 10.223.168.120 with SMTP id l111mr6474277wrc.137.1493375128556; Fri, 28 Apr 2017 03:25:28 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g7si7101227wra.242.2017.04.28.03.25.27; Fri, 28 Apr 2017 03:25:28 -0700 (PDT) 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=@gmail.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=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 81B16689800; Fri, 28 Apr 2017 13:25:22 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E7A5A68094E for ; Fri, 28 Apr 2017 13:25:15 +0300 (EEST) Received: by mail-pg0-f65.google.com with SMTP id t7so4742857pgt.1 for ; Fri, 28 Apr 2017 03:25:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=yX/uAa/bznwOXo3w5cC5nuRWwd52mZBIUMXVLhksUp4=; b=dduEs0YGhSz4SatpJaDFfaZMg4NqhAUaWBWPHuIPm3o9Jt3xB4vFmQUF9UHekJJdch kqHOZNMDb36CDkNulV+b3kep7km5lQ0gFNKzVYYWA2DyGZqquHBjgGesX4Sbk5RofhgG wvag+OfVWYi6W/b2vgt8fHpaSWjDnRtfyKSchjdKmDK5lJlxsuDHjHQnl/CBPu5uNtDu +thhfxtrGeTBo+mswvR528HfCM44dhMbuKAbLbQWyYVS5PJejzYUGWgn5ZAawuWbFmI/ fsfkBQuJFu3PyK5BYtRRfOukhfF/dO4/IGCjpgQ2XghrvzC771oSSCOIAfH1a2+wjrqN UgIg== 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=yX/uAa/bznwOXo3w5cC5nuRWwd52mZBIUMXVLhksUp4=; b=ql1cjw1aakr7yyqVIjqIXenlnNzfhp3H1GGVDdt9oWhgsjCuHeVs2RmP3hpvc1smGJ 4t/PFHoah2btCUZoKlevtam3F6grJAhv4PHMQ4Vv2faFuk8QzM7SusTXgwt+qbbZGqVn pyAyvd0fWFrNpKKKQQcrIAIRcgMeYDOVVo1l/mmz4Z3CiBADHYO73XmSTmv53mWBo3ze nMQK8ApJfinBBV7dSba1HNnIQEf4PobaNIcCDPeRbtL1KmezZ3vu6XrC+v4QLBsb1p5N oTcb9uUyOtSJ0yVLavkUr9JT+jwXiH576cq5LNUeAyu2XNEYVUyHNZ6U67h4MjGyLVNq Cv3g== X-Gm-Message-State: AN3rC/4w/pmdzqS0y+yoqAnZpPBm4hf6sDBavKY6jSxiRb1GqFK7hDDi w2EA0OIzfI25zA== X-Received: by 10.98.13.19 with SMTP id v19mr11124957pfi.89.1493374770490; Fri, 28 Apr 2017 03:19:30 -0700 (PDT) Received: from localhost.localdomain ([114.121.239.120]) by smtp.gmail.com with ESMTPSA id u128sm9399828pfb.55.2017.04.28.03.19.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 28 Apr 2017 03:19:29 -0700 (PDT) From: Muhammad Faiz To: ffmpeg-devel@ffmpeg.org Date: Fri, 28 Apr 2017 17:19:13 +0700 Message-Id: <20170428101913.12093-1-mfcc64@gmail.com> X-Mailer: git-send-email 2.9.3 Subject: [FFmpeg-devel] [PATCH v2] avcodec/pthread_frame, decode: allow errors to happen on draining 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: Muhammad Faiz MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" So, all frames and errors are correctly reported in order. Also limit the numbers of error during draining to prevent infinite loop. This fix fate failure with THREADS>=4: make fate-h264-attachment-631 THREADS=4 This also reverts a755b725ec1d657609c8bd726ce37e7cf193d03f. Suggested-by: wm4, Ronald S. Bultje, Marton Balint Signed-off-by: Muhammad Faiz --- libavcodec/decode.c | 21 +++++++++++++++++++-- libavcodec/internal.h | 3 +++ libavcodec/pthread_frame.c | 15 +++++++-------- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 6ff3c40..edfae55 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -568,8 +568,24 @@ FF_ENABLE_DEPRECATION_WARNINGS avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); #endif - if (avctx->internal->draining && !got_frame) - avci->draining_done = 1; + /* do not stop draining when got_frame != 0 or ret < 0 */ + if (avctx->internal->draining && !got_frame) { + if (ret < 0) { + /* prevent infinite loop if a decoder wrongly always return error on draining */ + /* reasonable nb_errors_max = maximum b frames + thread count */ + int nb_errors_max = 20 + (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME ? + avctx->thread_count : 1); + + if (avci->nb_draining_errors++ >= nb_errors_max) { + av_log(avctx, AV_LOG_ERROR, "Too many errors when draining, this is a bug. " + "Stop draining and force EOF.\n"); + avci->draining_done = 1; + ret = AVERROR_BUG; + } + } else { + avci->draining_done = 1; + } + } avci->compat_decode_consumed += ret; @@ -1659,6 +1675,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx) { avctx->internal->draining = 0; avctx->internal->draining_done = 0; + avctx->internal->nb_draining_errors = 0; av_frame_unref(avctx->internal->buffer_frame); av_frame_unref(avctx->internal->compat_decode_frame); av_packet_unref(avctx->internal->buffer_pkt); diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 84d3362..caa46dc 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -200,6 +200,9 @@ typedef struct AVCodecInternal { int showed_multi_packet_warning; int skip_samples_multiplier; + + /* to prevent infinite loop on errors when draining */ + int nb_draining_errors; } AVCodecInternal; struct AVCodecDefault { diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 13d6828..363b139 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -509,8 +509,8 @@ int ff_thread_decode_frame(AVCodecContext *avctx, /* * Return the next available frame from the oldest thread. * If we're at the end of the stream, then we have to skip threads that - * didn't output a frame, because we don't want to accidentally signal - * EOF (avpkt->size == 0 && *got_picture_ptr == 0). + * didn't output a frame/error, because we don't want to accidentally signal + * EOF (avpkt->size == 0 && *got_picture_ptr == 0 && err >= 0). */ do { @@ -526,20 +526,19 @@ int ff_thread_decode_frame(AVCodecContext *avctx, av_frame_move_ref(picture, p->frame); *got_picture_ptr = p->got_frame; picture->pkt_dts = p->avpkt.dts; - - if (p->result < 0) - err = p->result; + err = p->result; /* * A later call with avkpt->size == 0 may loop over all threads, - * including this one, searching for a frame to return before being + * including this one, searching for a frame/error to return before being * stopped by the "finished != fctx->next_finished" condition. - * Make sure we don't mistakenly return the same frame again. + * Make sure we don't mistakenly return the same frame/error again. */ p->got_frame = 0; + p->result = 0; if (finished >= avctx->thread_count) finished = 0; - } while (!avpkt->size && !*got_picture_ptr && finished != fctx->next_finished); + } while (!avpkt->size && !*got_picture_ptr && err >= 0 && finished != fctx->next_finished); update_context_from_thread(avctx, p->avctx, 1);