From patchwork Fri Oct 5 17:39:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: bananaman255@gmail.com X-Patchwork-Id: 10579 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:ab0:73d2:0:0:0:0:0 with SMTP id m18csp694078uaq; Fri, 5 Oct 2018 10:40:12 -0700 (PDT) X-Google-Smtp-Source: ACcGV60qsR4pY97lB1CPE6Kb0ueLbSeWEm9CBi5T0v0F/8Sfz5TEYFJiTAaOlTV8orhncB8rfpsL X-Received: by 2002:a1c:c708:: with SMTP id x8-v6mr8509024wmf.116.1538761212243; Fri, 05 Oct 2018 10:40:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538761212; cv=none; d=google.com; s=arc-20160816; b=R+2D55pkGN5AF//aMIrPdaHS0s6M7tHI7DQy7LIEwODNvPwbrjnn/bkrOcb4AdSg7e X2cpHiVurpcUx7GVvt2SQFoj3ccEeDua6DGufHRlhZjoew8qplhWRCsGIlCP5rTb5vgm eZZVv2PQfm1dFLLepgtp1cWqGCzM+KRmNJULtoqo2w3AK/qo0IJ64+ipEgZ0wsvfaLwS Ziee51AsVNo+/LZNvQ2r4as/o1gn1G8w7kHhmqeaz2jYol1K1aElPwbKmI1jROFA/vmK hwKy02HwpJB0IJsi/9JCWQRDPCxecfKWCipBSQVgoXdPjGzU7qOx3ie7EQWR8OyPxLcT jAiQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to; bh=6lq6LClYqYsAf4Yj/NfB3jULv8dm0S3YnsC68CYZUdE=; b=y72c/PugZx7JQzP8Vm/IGrN0v8vPXCCEOw4FbckSpeWOPdCqtrL31pKhTrJHGSsTPt oQzLNoHjYCiy2ye03Du/nMyJcDmE9sQBHcZNykTcekVyU+mEvUsan//LDVl2BfyvM+5a H2VnbQjO2Wps6E2JmLvuB57/GYI0HIcXE5mPb8LOgrXMOp5F32RzJHB+C+JJikQB59no SkDLYa9JseIrReImFNmAwbxwxTnkYNuktoSZ8Rt2oDsSCWSilCnkin86Dn/M4jSvJm0A 3rMA8JIMQN0dcYM3/Pu1m0OBWZAz6JVZ7366m/T3YVsMHVwCuMjCTrsO9jknb7MWQM1d UZhQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=d0h6Hjls; 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=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g205-v6si1912431wma.183.2018.10.05.10.40.11; Fri, 05 Oct 2018 10:40:12 -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 header.s=20161025 header.b=d0h6Hjls; 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=QUARANTINE 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 EFB7468A4A7; Fri, 5 Oct 2018 20:39:48 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 84099689FC2 for ; Fri, 5 Oct 2018 20:39:42 +0300 (EEST) Received: by mail-wm1-f68.google.com with SMTP id z204-v6so2658274wmc.5 for ; Fri, 05 Oct 2018 10:40:03 -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=wyLmlruaXbR1htAbUSWgqQoFF+nrszN9jckJ77xvtXs=; b=d0h6HjlscXqBkcH7I7lTf9WB9VpOMOdtMDHDteTbuID1KKYihjZHJNMtZB+tUK+YPj Z5CUtEGTY47JyW8Z0UpnAsqZFhwKRpucrsbVUO3UX0Z95IAxhe/WoiMlorkNuyU1cBgI 4/nyxRST/QuvV75qrRzQvXj//lIPVsoPW6JEtKe7cvRG/ongt248kUcJyvBQTGONFaAn Fk6D8AAqXLlE4chOPkQBipCOY6rvyT66N7iWqX4BQ4bEPVvgaqymJ21IKrNzCC159idD MPL3Kdt0lMYCbibgRBZnmeBZHolhS1Y4eGepmghyOYR0NW6geYvFWJ6XV+rAhrnIWkg0 y/2Q== 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=wyLmlruaXbR1htAbUSWgqQoFF+nrszN9jckJ77xvtXs=; b=F7xD4mZBzPUuvkxH9SMZX+wM1R0Mq0b7DxvSGJ+ZmOAeuyk5oTig4kV4B7QmRwo3Lq M6kkWpmGIQZ2QofXeCPwKzs4xidEOGtBOgz8/QNl+vYqno1PuYfqW5p1ljvpMShGZneU vOBzVjOYh5hlQbYDrbbd3weAqU+BoIDpR4jCE8xpJjxi3ICuzjV6UTH0wDXVvUwNL7KX Ng8BxPVwLA6dcouEfl0gQy9Y/kpnqJcEWptZrNufxi/TybOw0kZEhJEfHJoXq+fLZliJ qd0l/FkIAkjpCr1hXEnNmJnuHx6Hhn4lYogZL+6WP4NXFvGZ1MXa2mAbAi+zVg7vvkE4 vNpg== X-Gm-Message-State: ABuFfoghcNDKuTQsyIP5CVAjp4keCImbhkJk42xaf7m05GAgUe/K/pKe Hrgyhny56rJ+qvZLfrIoPldqYbZQ X-Received: by 2002:a1c:d4b:: with SMTP id 72-v6mr9143802wmn.102.1538761202372; Fri, 05 Oct 2018 10:40:02 -0700 (PDT) Received: from localhost.localdomain (117.98.132.37.dynamic.jazztel.es. [37.132.98.117]) by smtp.googlemail.com with ESMTPSA id 140-v6sm4423678wmx.34.2018.10.05.10.40.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 05 Oct 2018 10:40:01 -0700 (PDT) From: bananaman255@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Fri, 5 Oct 2018 19:39:26 +0200 Message-Id: <20181005173926.1568-1-bananaman255@gmail.com> X-Mailer: git-send-email 2.11.0.windows.3 Subject: [FFmpeg-devel] [PATCH] avcodec/wmadec: fix WMA gapless playback 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: bnnm MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: bnnm Fixes trac issue #7473. Removes encoder delay (skip samples) and writes remaining frame samples after EOF to get correct sample count. Output is now accurate vs players that use Microsoft's codecs (Windows Media Format Runtime). Tested vs encode>decode WMAv2 with MS's codecs and most sample rate/bit rate/channel/mode combinations in ASF/XWMA. WMAv1 appears to use the same delay, from FFmpeg samples. Signed-off-by: bnnm --- libavcodec/wma.h | 2 ++ libavcodec/wmadec.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/libavcodec/wma.h b/libavcodec/wma.h index 325f03c44b..c80068de80 100644 --- a/libavcodec/wma.h +++ b/libavcodec/wma.h @@ -133,6 +133,8 @@ typedef struct WMACodecContext { float lsp_pow_m_table2[(1 << LSP_POW_BITS)]; AVFloatDSPContext *fdsp; + int eof_done; /* decode flag to output remaining samples after EOF */ + #ifdef TRACE int frame_count; #endif /* TRACE */ diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index 78b51e5871..d59432d3f1 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -124,6 +124,11 @@ static av_cold int wma_decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + /* Skip WMA encoder delay (>=32000: 4096, >=22050: 2048, >=8000: 1024). + * The amount doesn't seem specified in the flags or container (ASF/XWMA), + * but can be verified compared to Microsoft codecs' output. */ + avctx->internal->skip_samples = s->frame_len * 2; + return 0; } @@ -819,7 +824,29 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, ff_tlog(avctx, "***decode_superframe:\n"); if (buf_size == 0) { + /* must output one final frame with remaining samples */ + + if (s->eof_done) + return 0; + + /* get output buffer */ + frame->nb_samples = s->frame_len; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (float **) frame->extended_data; + + /* clean output buffer and copy last IMCDT samples */ + for (i = 0; i < s->avctx->channels; i++) { + memset(frame->extended_data[i], 0, + s->frame_len * sizeof(*s->frame_out[i])); + + memcpy(frame->extended_data[i], &s->frame_out[i][0], + s->frame_len * sizeof(*s->frame_out[i]) >> 1); + } + s->last_superframe_len = 0; + s->eof_done = 1; + *got_frame_ptr = 1; return 0; } if (buf_size < avctx->block_align) { @@ -965,6 +992,9 @@ static av_cold void flush(AVCodecContext *avctx) s->last_bitoffset = s->last_superframe_len = 0; + + s->eof_done = 0; + avctx->internal->skip_samples = s->frame_len * 2; } #if CONFIG_WMAV1_DECODER @@ -978,7 +1008,7 @@ AVCodec ff_wmav1_decoder = { .close = ff_wma_end, .decode = wma_decode_superframe, .flush = flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; @@ -994,7 +1024,7 @@ AVCodec ff_wmav2_decoder = { .close = ff_wma_end, .decode = wma_decode_superframe, .flush = flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, };