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?= <tjop...@acc.umu.se>
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 <next>:
- 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 <infile.mov> <outfile.mov>
+ * To probe a file for faststart-ness, invoke it with:
+ * qt-faststart <infile.mov>
*
* 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 <infile.mov> <outfile.mov>\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 <infile.mov> [<outfile.mov>]\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
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel