From patchwork Fri Jul 13 10:35:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karsten Otto X-Patchwork-Id: 9711 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:104:0:0:0:0:0 with SMTP id c4-v6csp596031jad; Fri, 13 Jul 2018 03:35:17 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdERrorFENYcj/sGEOWBujT7vDdWP1QGTKu88LZTs1D3U+QrfgBAavAG8bTAwETcOgrsolu X-Received: by 2002:a1c:1203:: with SMTP id 3-v6mr3850294wms.46.1531478116961; Fri, 13 Jul 2018 03:35:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531478116; cv=none; d=google.com; s=arc-20160816; b=J8Y8wxuokyf8aK2njMb92hGRIYIFBK5tHFz9dKeflzgQlnI/AA+6C+kcCBcQmn0FJf BVAJ6M0/WJDlSeuPlSe1V5kjPOBQJSK2Zsmnfz+tYOYzGVBQ/psxAWyHShABulXoEHGi XypojSc4+FVnfLlfSUy5dSeqGc1bMNHuk+VlIRpZtPq0bx536bzdoRXrnOyRKntK7LEq UpbQ0AvB/jSrkLKC/LJYYoYY47L1oFtuXZyhql3CqSNX0arg5t0P043ZXMIdWDJHiLui 7cPp6h6jU9MVVhToOltQxDEPZsecXIoVTXT1yF8tyMSEE/pM1kIvMIJ+tEPh9C3m1EdX qUWg== 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:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=amjL+vGjrXNJzV47jxFp3dH1Ws1jWwiqqKtSiRqeMjM=; b=uK4wnkjbv1smQJG5GCpx0drr/iriuBU+KuQEBgpVAFRBPuOG0J5Nfv7nyyYM9mfdFl iPjs/lsRGPeHpI3AUd8jYCz/blkGVNDYNqCyJqzcmORd7bG1ibwzFubWXCidCt7TTJYf yPJ1T3WFvLpI8OahRnxZNwiiNo5R04RH3+mENqYpuhfCqcF/hEfHBTSsCkXpGbLp2RgZ lDjArz/F/DbXwaMArsOCjrqTX17WKLgTL4Xu7K0UgUh9oux9HtuwMN7svdvSonjKV+B9 6ynb2ZFrsw5siKSzsfI/q5NuBFl8lmwC+U2nFG8qau4ypTuxfVssTDjf5q9HVe9/PX4r 3+RQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@posteo.de header.s=2017 header.b=mrsf9zky; 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=posteo.de Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q3-v6si4594273wmf.230.2018.07.13.03.35.16; Fri, 13 Jul 2018 03:35:16 -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=@posteo.de header.s=2017 header.b=mrsf9zky; 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=posteo.de Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 122A368A449; Fri, 13 Jul 2018 13:35:07 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E150B689C8D for ; Fri, 13 Jul 2018 13:35:00 +0300 (EEST) Received: from submission (posteo.de [89.146.220.130]) by mout01.posteo.de (Postfix) with ESMTPS id 9A680210ED for ; Fri, 13 Jul 2018 12:35:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.de; s=2017; t=1531478108; bh=MWilvAYmWC2+KiTUV0Z3QN50a2GLg6r7P6JUDJU31Ws=; h=From:To:Subject:Date:From; b=mrsf9zkyQ75s28DUoqoTpPGNL6/QAvAgrVCkCUDK/FmgFHfEiTgt9dzxHwB2ofIWB T0ZNouYsxhLEggjc4S/NGE0EsGwuS1c1pbFsVa1KDcQMVpE+Vmdxnu4Nm38N/Ouz/h MGfBxvnQ7IT+9hdxezQUUahxqxloXV6QRnYxVpPxEU/qhoIZGAOnbRAAYkZBjm6dmX yn+PMmcPlvKZZFIPF2NnscVqgY7cexz7y5CQ+2Q7IM2ucx+ahMIw/1kE/bVU2ni+6a swbXk0zeCD2UIsakeUFj6cDLaRnflB6mSNlt+RR6jziBWkyY9ySdx/ekMQ/PU9jr4g 1gvZpYXm5bUcA== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 41Rq235r6Gz9rxK for ; Fri, 13 Jul 2018 12:35:07 +0200 (CEST) From: Karsten Otto To: ffmpeg-devel@ffmpeg.org Date: Fri, 13 Jul 2018 12:35:07 +0200 Message-Id: <20180713103507.24022-1-ottoka@posteo.de> X-Mailer: git-send-email 2.14.3 (Apple Git-98) In-Reply-To: <20180712234848.GC4859@michaelspb> References: <20180712234848.GC4859@michaelspb> Subject: [FFmpeg-devel] [PATCH v6 3/3] aadec: improve seeking in mp3 content 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" MP3 frames may not be aligned to aa chunk boundaries. When seeking, calculate the expected frame offset in the target chunk. Adjust the timestamp and truncate the next packet accordingly. This solution works for the majority of tested audio material. For some rare encodings with mp3 padding or embedded id3 tags, it will mispredict the correct offset, and at worst skip an extra frame. --- This revision includes some comments documenting how/why it works. libavformat/aadec.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 17ad20686b..f7e92dbb4b 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -37,6 +37,7 @@ #define TEA_BLOCK_SIZE 8 #define CHAPTER_HEADER_SIZE 8 #define TIMEPREC 1000 +#define MP3_FRAME_SIZE 104 typedef struct AADemuxContext { AVClass *class; @@ -50,6 +51,7 @@ typedef struct AADemuxContext { int64_t current_chapter_size; int64_t content_start; int64_t content_end; + int seek_offset; } AADemuxContext; static int get_second_size(char *codec_name) @@ -177,6 +179,7 @@ static int aa_read_header(AVFormatContext *s) st->codecpar->sample_rate = 22050; st->need_parsing = AVSTREAM_PARSE_FULL_RAW; avpriv_set_pts_info(st, 64, 8, 32000 * TIMEPREC); + // encoded audio frame is MP3_FRAME_SIZE bytes (+1 with padding, unlikely) } else if (!strcmp(codec_name, "acelp85")) { st->codecpar->codec_id = AV_CODEC_ID_SIPR; st->codecpar->block_align = 19; @@ -228,6 +231,7 @@ static int aa_read_header(AVFormatContext *s) ff_update_cur_dts(s, st, 0); avio_seek(pb, start, SEEK_SET); c->current_chapter_size = 0; + c->seek_offset = 0; return 0; } @@ -266,6 +270,10 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) // is this the last block in this chapter? if (c->current_chapter_size / c->current_codec_second_size == 0) { c->current_codec_second_size = c->current_chapter_size % c->current_codec_second_size; + // normally, seek_offset max MP3_FRAME_SIZE-1 <= current_codec_second_size; + // in short last block, estimate may be off for file with padding + if (c->seek_offset > c->current_codec_second_size) + c->seek_offset = 0; } // decrypt c->current_codec_second_size bytes @@ -293,12 +301,14 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) if (c->current_chapter_size <= 0) c->current_chapter_size = 0; - ret = av_new_packet(pkt, written); + // at this point, seek_offset <= written == current_codec_second_size + ret = av_new_packet(pkt, written - c->seek_offset); if (ret < 0) return ret; - memcpy(pkt->data, buf, written); + memcpy(pkt->data, buf + c->seek_offset, written - c->seek_offset); pkt->pos = pos; + c->seek_offset = 0; return 0; } @@ -342,7 +352,12 @@ static int aa_read_seek(AVFormatContext *s, c->current_chapter_size = chapter_size - chapter_pos; c->chapter_idx = 1 + chapter_idx; - ff_update_cur_dts(s, s->streams[0], ch->start + chapter_pos * TIMEPREC); + // estimate extra offset of first unaligned frame in block (assume no padding) + if (s->streams[0]->codecpar->codec_id == AV_CODEC_ID_MP3) { + c->seek_offset = (MP3_FRAME_SIZE - chapter_pos % MP3_FRAME_SIZE) % MP3_FRAME_SIZE; + } + + ff_update_cur_dts(s, s->streams[0], ch->start + (chapter_pos + c->seek_offset) * TIMEPREC); return 1; }