From patchwork Fri Feb 2 02:37:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: rshaffer@tunein.com X-Patchwork-Id: 7477 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.156.27 with SMTP id q27csp318600jak; Thu, 1 Feb 2018 18:43:19 -0800 (PST) X-Google-Smtp-Source: AH8x224RO3yv2hWrvG0kXXitbZR89ucUjwzZ/tiPsawz0RXH9axFnlpV1L7/tipXbR1xkE9RaTda X-Received: by 10.28.46.88 with SMTP id u85mr27146553wmu.12.1517539399664; Thu, 01 Feb 2018 18:43:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517539399; cv=none; d=google.com; s=arc-20160816; b=XDKrwE4oPh/HoYleCctTkHo8Ax4IkiK1leHDiSDbmkOXLvqLLjXwzSdw8ICaS64YPd 5peSCTKtnC2fwE9KMi0cb4HlpSYAl215v5QD3f5/kMnbp5lcF5qVG0QGoAXIvcVUV2vc QwQjMH5zwPkSosqOuiJdFJmegW+PQjmhu9fUk2sywEqYUbJfaXZSqTBkMpEsAIJSw7EI YOkucXDNEFjeHzg8vrd07gzWVKVD664DB7SbEw9LHgm7lwX/RDVkiFdU+KFyecJjHU3O TnLTVSpXfFitAfbiMjL/UCUtThdcwoQOyqAvDWTQ0+Mn+FX+RcTYoHyk+ULh7Tm0Q6gt aCtg== 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:arc-authentication-results; bh=QLmDxJvdyY/bothaXWlyW54V9FdGQM93TmusCc7wnF8=; b=hnsHYCSCfPv4WHDFtmNTSV0CBk+kxvUeyhTX74J0Vqr6KbnPYfB9MxnlvG1bsxAjVQ LXJmm6zf7ivVzu16zqVjokppgzSYeehjg7qwbIJ/lmTyOhaFtXsjoXXa0n44T10Sg2bC VpI9I3uDNUBWmul72+94p0+YbGXAi7HQQsmj/HHrXo6ent4Dd4wI2SG2feClIMkM0tez 6jOCqp+3zJCAE+9xsqYG6/8X1lP6QH6IkRCJ4buzRBwrKqIYRhzs02EZbIQaoSGhtSoG chYP1IKVSDl4/JpySIbNqoteLmdjuzgLEY+CpR7Az20WF9ZcvcCWPTjDw9fqhEbds/Lw No0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@tunein-com.20150623.gappssmtp.com header.s=20150623 header.b=UILORxkM; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o63si423791wmd.241.2018.02.01.18.43.19; Thu, 01 Feb 2018 18:43:19 -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=@tunein-com.20150623.gappssmtp.com header.s=20150623 header.b=UILORxkM; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 405BE689256; Fri, 2 Feb 2018 04:43:07 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3E46768834F for ; Fri, 2 Feb 2018 04:43:00 +0200 (EET) Received: by mail-pf0-f194.google.com with SMTP id a88so16509716pfe.12 for ; Thu, 01 Feb 2018 18:43:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tunein-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=05UyromKRbbS/VXSs8aS6D8uUCZZ24zUHO053n3dkZ0=; b=UILORxkMNrtt2UY/vmvabi8p4y/KFSDp5h8lJjPO4qBnxhRLEvKUOMWIq45xBjtXbg xOuzgNSbindcMPWdXRFzJSHj57r8zSRB0uVlTQeEMZXAVCObmS5ZBdF0gcjGMuKewl+1 5hT6cObNSKVjbsRbEJY2veE8EpxBddep7xEtiVS+xizPM+e4boo8ryZCbURc1PoCMUDf yx3803atGhBFOciZJfAnyToLIhHb1LjaTz9Ls/WcMg7fpBh7OzKHRFKFFYtKd+dVsdla CgDaSAnmGRBLnAZ2IXwLg0ZDDUqpNhC8uDEGbqLlghVlkroofjO7IGEyJ7CcIpVh2z3e 4A7A== 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=05UyromKRbbS/VXSs8aS6D8uUCZZ24zUHO053n3dkZ0=; b=aaQNIAWQQgrE161NU8vnTA/FKs4q3H97DKEKfRwbKIU+g5UWwryLN6nINdu1s2+f5Y 8jw8IhF1h56LMb0vssg3GGdio8AJr2326Ea4QqIsj854BLSrWJDq4H3XLnDYoy3WTWzS xkkQjWdO6wb2tK0pOKcYLFKWAR5Oa7bsXAZUGt7sgxH6IEiqvSHZ/VimMvCM8jsNlV2q 31Nv4My2yydgTuA6mqy30/JnHQZNIqSRQr1X7ImU7HGxmfQd7w735KYJ/aSk8QFcWzhN MCBKts4kQVR22WPwq8lh8myZJghkE2cByjyMrYZEnP3WoRWEvSH29hgs93DxXuDc+QWP +nJg== X-Gm-Message-State: AKwxytda/F7egL1SFiYc+cAv3EipKmAjvAchZFldE3Rl9upRcElyRGgp 8jIJBtjRxBeo1voaQXhA/fULKO2SDQk= X-Received: by 10.98.59.5 with SMTP id i5mr3096927pfa.146.1517539069540; Thu, 01 Feb 2018 18:37:49 -0800 (PST) Received: from 000984.tunein.corp ([199.87.87.163]) by smtp.gmail.com with ESMTPSA id b63sm1080758pfl.78.2018.02.01.18.37.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Feb 2018 18:37:48 -0800 (PST) From: rshaffer@tunein.com To: ffmpeg-devel@ffmpeg.org Date: Thu, 1 Feb 2018 18:37:45 -0800 Message-Id: <20180202023745.68519-1-rshaffer@tunein.com> X-Mailer: git-send-email 2.14.3 (Apple Git-98) Subject: [FFmpeg-devel] [PATCH] libavformat/aac: Parse ID3 tags between ADTS frames. 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: Richard Shaffer MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Richard Shaffer While rare, ID3 tags may be inserted between ADTS frames. This change enables parsing them and setting the appropriate metadata updated event flag. --- I have encountered a streaming provider that I must support which does this. There are indications that it isn't totally off the wall, and that it does happen in the wild: * https://www.w3.org/TR/mse-byte-stream-format-mpeg-audio/ (See specifically sections 3 and 4.) * https://github.com/video-dev/hls.js/issues/508 That being said, the providers that do this are in the minority. It seems most streaming providers will do one of the following: 1. If using .aac segments inside of HLS, use the #EXTINF for text metadata and use an ID3 tag at the head of the segment for things like timing metadata. 2. If streaming raw AAC over HTTP, use Icy metadata. Aside from comments on the code, I'd be interested in any opinion about whether this is something that should or should not be supported in libavformat. Thanks, -Richard libavformat/aacdec.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 36d558ff54..5ec706bdc7 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -22,8 +22,10 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "id3v1.h" +#include "id3v2.h" #include "apetag.h" #define ADTS_HEADER_SIZE 7 @@ -116,13 +118,52 @@ static int adts_aac_read_header(AVFormatContext *s) return 0; } +static int handle_id3(AVFormatContext *s, AVPacket *pkt) +{ + AVDictionary *metadata = NULL; + AVIOContext ioctx; + ID3v2ExtraMeta *id3v2_extra_meta = NULL; + int ret; + + ret = av_append_packet(s->pb, pkt, ff_id3v2_tag_len(pkt->data) - pkt->size); + if (ret < 0) { + av_packet_unref(pkt); + return ret; + } + + ffio_init_context(&ioctx, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL); + ff_id3v2_read_dict(&ioctx, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); + if ((ret = ff_id3v2_parse_priv_dict(&metadata, &id3v2_extra_meta)) < 0) + goto error; + + if (metadata) { + if ((ret = av_dict_copy(&s->metadata, metadata, 0)) < 0) + goto error; + s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; + } + +error: + av_packet_unref(pkt); + ff_id3v2_free_extra_meta(&id3v2_extra_meta); + av_dict_free(&metadata); + + return ret; +} + static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, fsize; - ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); + ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE)); + + if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { + if ((ret = handle_id3(s, pkt)) >= 0) + ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); + } + if (ret < 0) return ret; + if (ret < ADTS_HEADER_SIZE) { av_packet_unref(pkt); return AVERROR(EIO); @@ -139,7 +180,7 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_INVALIDDATA; } - ret = av_append_packet(s->pb, pkt, fsize - ADTS_HEADER_SIZE); + ret = av_append_packet(s->pb, pkt, fsize - pkt->size); if (ret < 0) av_packet_unref(pkt);