From patchwork Fri Jul 27 14:06:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Tomas_H=C3=A4rdin?= X-Patchwork-Id: 9813 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:104:0:0:0:0:0 with SMTP id c4-v6csp841415jad; Fri, 27 Jul 2018 07:07:08 -0700 (PDT) X-Google-Smtp-Source: AAOMgpch9pOhJjqs+rDXAd95TLjLbu+nL7ZvVRMOS4aO6WF1o14au9M+LQLqM/yDead+a33eLFzH X-Received: by 2002:a1c:e54:: with SMTP id 81-v6mr4635795wmo.84.1532700428571; Fri, 27 Jul 2018 07:07:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1532700428; cv=none; d=google.com; s=arc-20160816; b=St5+JrzoZawu2ldeG8tOeLIVAEQ5N2sbm1T1F2VZ7W0DAlQ/eYiEUG+/nMc8FFo32V EoupBH4DdNiV91rovBiKINjDhmMZB1hPmBg0zOh4iXl5upMi9DFZaqVch1CLsYUXkzOn SvoBqis2uX4/Fu1ILoWEZGc3BepDnhGgBAf/i8eZ4Ztl+eWx5t2ZUnxlR+uaprUUNzCg 3FhRHf/cM01HANG8tn/ZOjbxmobOwVczZByhyrvoH/U2IBHOgyfxZZsICzfg7CEavEXX iB+A7E5rsnk7Aiw/SZ9ofUyC+d709juJS8cbj7oDfib0LktHfwrHGlrFyZx+IkPPBmXm KV0Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:date:to:from:message-id:dkim-signature:dkim-signature :delivered-to:arc-authentication-results; bh=AF4amU/mg8NgkDovlImM294Iah3cZsgZwi0QFaEndaY=; b=OD1bIwJL2XLZjuofAVdqB4nU2EF0c6V+2SI+1abpqcapuM85jml2dbQmlYrMyiA1gb TO77sJne3b91Z8DQ1QJvirsmJraF7SgAn5xZiM458MJs7zeWginWsWmX85DjK2xsZySB ChLFEYu3q7avcPyupMNIf4+fosLXTr9qgSB0e/dG6p4vyTpl4radQVCv/BRMIa/fhCsH hjpwZnZJSIgiWXWBxMHw2mRhCNkA8OBYCHDxcCW3/VXTa0SXrdv3MeqHJaUvkNyFny23 jGskRQwQ0oHhmJkKbIe2yXXziiQfpFg9zNPu1VANMm4KiiVpHClIWDdErdiuuc9yL0MW k4Fg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@acc.umu.se header.s=mail1 header.b=D3sbZOGM; dkim=neutral (body hash did not verify) header.i=@acc.umu.se header.s=mail1 header.b=R2k8RoDv; 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 l28-v6si3399112wrb.290.2018.07.27.07.07.08; Fri, 27 Jul 2018 07:07:08 -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=@acc.umu.se header.s=mail1 header.b=D3sbZOGM; dkim=neutral (body hash did not verify) header.i=@acc.umu.se header.s=mail1 header.b=R2k8RoDv; 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 9168B68A564; Fri, 27 Jul 2018 17:06:51 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail.acc.umu.se (mail.acc.umu.se [130.239.18.156]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8BD3E68A4C8 for ; Fri, 27 Jul 2018 17:06:44 +0300 (EEST) Received: from localhost (localhost.localdomain [127.0.0.1]) by amavisd-new (Postfix) with ESMTP id 2A93644B90 for ; Fri, 27 Jul 2018 16:06:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=acc.umu.se; s=mail1; t=1532700419; bh=szAZirs/fnd66M3cP3zi42WlLRoZ7svO5Pkmr5e0f6M=; h=Subject:From:To:Date:From; b=D3sbZOGM4xb16CbyrIJL1qovZTJNyR87Q9y40yTMoFqn2VqpE6M5bsztsnKRsJ9ga Gm36+PVKPkgvnuM12D2BtpAiRffFRe+uQ86NsAbw3mdnaoyY0pjHmWpPsgmFiIOazf wURI5ulAkWa7zKk64gJeWeZQOJThHTvRFWY9OEhJOrJzGAtn/ByFUqjaHtSbg8HXuB 8PpwQ4K8izRzj8KZyC5HdWXded0hhGlaurBMnrjU9SX/gCHLCK4ZITmLPdZ8YQponb u10HJ8bWIOndX1d8rPhDael5rQRyF70EDKw+L40stdvvRPSK7sfq22oR17dRQ56nwj FQXmxR6Xuq08g== Received: from [192.168.1.158] (h-39-105.A258.priv.bahnhof.se [79.136.39.105]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: tjoppen) by mail.acc.umu.se (Postfix) with ESMTPSA id C057244B8B for ; Fri, 27 Jul 2018 16:06:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=acc.umu.se; s=mail1; t=1532700417; bh=szAZirs/fnd66M3cP3zi42WlLRoZ7svO5Pkmr5e0f6M=; h=Subject:From:To:Date:From; b=R2k8RoDvfGtUyoEq/SwwHxPrSCcdmmMuXmnGw9KGDTxlxTXKfeFvEJ0+IsXtgrsbo 5/AhHrbXmNxt+nilYl7nzO8YW7s48LBxBQShtoxDfGhmOP/XEe34m7DW08j6didvyg yehrOR7aRX6VGocY/4jHjFWdWg+qKgmcPCeIgitNoLJmKL/3uj5rxnT6VrOicQ6rwn 5+bJUqvQgUHcyMtkpmCd6FEY/brFz230QIL+CoURTsys1y3D56DmCRvUBMk29fHwk2 cpy31R/NXNHjsrBPQGlAalfBNVS+/FGNTzkzlBGublsA9fMs/va1mzI2XhBgS/Kxy1 dzMOBPWgXwVoQ== Message-ID: <1532700416.22213.1.camel@acc.umu.se> From: Tomas =?ISO-8859-1?Q?H=E4rdin?= To: ffmpeg-devel Date: Fri, 27 Jul 2018 16:06:56 +0200 X-Mailer: Evolution 3.22.6-1+deb9u1 Mime-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] qt-faststart: Add mode for probing faststart-ness 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Hi This is something the PeerTube guys need, and this seemed a straightforward enough approach. Feedback appreciated /Tomas From 8d5627c02cc2da8708b5342b58d2a6eaebf189c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 27 Jul 2018 13:54:52 +0200 Subject: [PATCH] qt-faststart: Add mode for probing faststart-ness Activated by giving the program only a single filename. There are three cases, with corresponding exit codes: 0: File has moov before mdat, is streamable (not fragmented) 2: File has moov after mdat, not streamable 3: File is fragmented (has moof atoms, is streamable in some players) Fragmented files get a separate exit code since they may not be supported in all players. --- Changelog | 1 + tests/fate/mov.mak | 40 +++++++++++++++++++++++++++ tools/qt-faststart.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 113 insertions(+), 6 deletions(-) diff --git a/Changelog b/Changelog index 807a05dec9..973b1f9fdd 100644 --- a/Changelog +++ b/Changelog @@ -16,6 +16,7 @@ version : - ATRAC9 decoder - lensfun wrapper filter - colorconstancy filter +- added ability to probe faststart-ness with tools/qt-faststart version 4.0: diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 6f0e28d21e..404e6c662e 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -29,6 +29,37 @@ FATE_MOV_FFPROBE = fate-mov-neg-firstpts-discard \ fate-mov-guess-delay-3 \ FATE_MOV_FASTSTART = fate-mov-faststart-4gb-overflow \ + fate-mov-faststart-probe-streamable \ + fate-mov-faststart-probe-fragmented \ + fate-mov-faststart-probe-not-streamable \ + +FATE_MOV_FASTSTART_SAMPLES_STREAMABLE = \ + 440hz-10ms.m4a \ + displaymatrix.mov \ + fcp_export8-236.mov \ + white_zombie_scrunch-part.mov \ + +FATE_MOV_FASTSTART_SAMPLES_FRAGMENTED = \ + buck480p30_na.mp4 \ + frag_overlap.mp4 \ + +FATE_MOV_FASTSTART_SAMPLES_NOT_STREAMABLE = \ + aac-2048-priming.mov \ + elst_ends_betn_b_and_i.mp4 \ + fake-gp-media-with-real-gpmf.mp4 \ + invalid_elst_entry_count.mov \ + mov-1elist-1ctts.mov \ + mov-1elist-ends-last-bframe.mov \ + mov-1elist-noctts.mov \ + mov-2elist-elist1-ends-bframe.mov \ + mov-3elist-1ctts.mov \ + mov-3elist-encrypted.mov \ + mov-3elist.mov \ + mov-elist-starts-ctts-2ndsample.mov \ + mov_ibi_elst_starts_b.mov \ + moviedispmat.mp4 \ + mp4-init-nonkeyframe.mp4 \ + spherical.mov \ FATE_SAMPLES_AVCONV += $(FATE_MOV) FATE_SAMPLES_FFPROBE += $(FATE_MOV_FFPROBE) @@ -116,3 +147,12 @@ fate-mov-guess-delay-3: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stre fate-mov-faststart-4gb-overflow: CMD = run tools/qt-faststart$(EXESUF) $(TARGET_SAMPLES)/mov/faststart-4gb-overflow.mov faststart-4gb-overflow-output.mov > /dev/null ; md5sum faststart-4gb-overflow-output.mov | cut -d " " -f1 ; rm faststart-4gb-overflow-output.mov fate-mov-faststart-4gb-overflow: CMP = oneline fate-mov-faststart-4gb-overflow: REF = bc875921f151871e787c4b4023269b29 + +fate-mov-faststart-probe-streamable: CMD = for f in $(FATE_MOV_FASTSTART_SAMPLES_STREAMABLE); do run tools/qt-faststart$(EXESUF) $(TARGET_SAMPLES)/mov/$$f || exit 1; done +fate-mov-faststart-probe-streamable: CMP = null + +fate-mov-faststart-probe-fragmented: CMD = for f in $(FATE_MOV_FASTSTART_SAMPLES_FRAGMENTED); do run tools/qt-faststart$(EXESUF) $(TARGET_SAMPLES)/mov/$$f; [ $$? -eq 3 ] || exit 1; done +fate-mov-faststart-probe-fragmented: CMP = null + +fate-mov-faststart-probe-not-streamable: CMD = for f in $(FATE_MOV_FASTSTART_SAMPLES_NOT_STREAMABLE); do run tools/qt-faststart$(EXESUF) $(TARGET_SAMPLES)/mov/$$f; [ $$? -eq 2 ] || exit 1; done +fate-mov-faststart-probe-not-streamable: CMP = null diff --git a/tools/qt-faststart.c b/tools/qt-faststart.c index 5e88c38e6b..54f44a78f3 100644 --- a/tools/qt-faststart.c +++ b/tools/qt-faststart.c @@ -6,6 +6,8 @@ * * This utility rearranges a Quicktime file such that the moov atom * is in front of the data, thus facilitating network streaming. + * Alternatively, it can also be used to probe a file for whether it is + * streamable or not, and if it's fragmented. * * To compile this program, start from the base directory from which you * are building FFmpeg and type: @@ -15,6 +17,8 @@ * guaranteed, particularly on 64-bit platforms. * Invoke the program with: * qt-faststart + * To probe a file for faststart-ness, invoke it with: + * qt-faststart * * Notes: Quicktime files can come in many configurations of top-level * atoms. This utility stipulates that the very last atom in the file needs @@ -88,6 +92,9 @@ #define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T') #define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p') #define UUID_ATOM QT_ATOM('u', 'u', 'i', 'd') +#define SIDX_ATOM QT_ATOM('s', 'i', 'd', 'x') +#define STYP_ATOM QT_ATOM('s', 't', 'y', 'p') +#define MOOF_ATOM QT_ATOM('m', 'o', 'o', 'f') #define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v') #define TRAK_ATOM QT_ATOM('t', 'r', 'a', 'k') @@ -443,14 +450,29 @@ int main(int argc, char *argv[]) int64_t start_offset = 0; unsigned char *copy_buffer = NULL; int bytes_to_copy; - - if (argc != 3) { - printf("Usage: qt-faststart \n" - "Note: alternatively you can use -movflags +faststart in ffmpeg\n"); + int probe_only = argc == 2; + int is_fragmented = 0; + uint64_t first_mdat = 0; + uint64_t first_moov = 0; + + if (argc != 2 && argc != 3) { + printf("Usage: qt-faststart []\n" + "Note: alternatively you can use -movflags +faststart in ffmpeg\n" + "\n" + "If both input and output filenames are given then these exit codes may be returned:\n" + " 0: Input file exists and is valid. If the file had to be faststarted then outfile.mov was written. Else nothing was written\n" + " 1: There was some kind of error, for example invalid input file, not enough memory or not enough disk space\n" + "\n" + "If no output filename is given then infile.mov is probed for faststart-ness and the following exit codes may be returned:\n" + " 0: File has moov before mdat, is streamable (not fragmented)\n" + " 1: There was some kind of error\n" + " 2: File has moov after mdat, not streamable\n" + " 3: File is fragmented (has moof atoms, is streamable in some players)\n" + ); return 0; } - if (!strcmp(argv[1], argv[2])) { + if (!probe_only && !strcmp(argv[1], argv[2])) { fprintf(stderr, "input and output files need to be different\n"); return 1; } @@ -515,6 +537,19 @@ int main(int argc, char *argv[]) (atom_type >> 0) & 255, atom_offset, atom_size); + + if (atom_type == MOOV_ATOM && first_moov == 0) { + first_moov = atom_offset; + } else if (atom_type == MDAT_ATOM && first_mdat == 0) { + first_mdat = atom_offset; + } else if (atom_type == MOOF_ATOM) { + is_fragmented = 1; + if (probe_only) { + //we've determined that the file is fragmented - stop + break; + } + } + if ((atom_type != FREE_ATOM) && (atom_type != JUNK_ATOM) && (atom_type != MDAT_ATOM) && @@ -524,7 +559,10 @@ int main(int argc, char *argv[]) (atom_type != WIDE_ATOM) && (atom_type != PICT_ATOM) && (atom_type != UUID_ATOM) && - (atom_type != FTYP_ATOM)) { + (atom_type != FTYP_ATOM) && + (atom_type != SIDX_ATOM) && + (atom_type != STYP_ATOM) && + (atom_type != MOOF_ATOM)) { fprintf(stderr, "encountered non-QT top-level atom (is this a QuickTime file?)\n"); break; } @@ -537,6 +575,34 @@ int main(int argc, char *argv[]) break; } + if (probe_only) { + free(ftyp_atom); + fclose(infile); + + /* try to be a bit more helpful when probing */ + if (is_fragmented) { + if (first_moov == 0) { + printf("fragmented file with no moov before moof, probably invalid\n"); + return 1; + } else { + printf("file is fragmented, streamable in some players\n"); + return 3; + } + } else if (first_moov == 0 || first_mdat == 0) { + printf("file seems to be missing moov and/or mdat\n"); + return 1; + } else if (first_moov > first_mdat) { + printf("file has moov after mdat, not streamable\n"); + return 2; + } else { + printf("file has moov before mdat, streamable\n"); + return 0; + } + } + /* non-probe mode beyond this point */ + + /* this is possibly stricter than necessary, + * but it does ensure fragmented files aren't messed with */ if (atom_type != MOOV_ATOM) { printf("last atom in file was not a moov atom\n"); free(ftyp_atom); -- 2.11.0