new api: getMediaInformation for ios
This commit is contained in:
@@ -2,3 +2,8 @@
|
||||
/Makefile
|
||||
/config.status
|
||||
/configure.tmp
|
||||
/.deps/
|
||||
/.libs/
|
||||
*.trs
|
||||
/unittests
|
||||
/test-driver
|
||||
|
||||
Vendored
+5
-5
@@ -9331,20 +9331,20 @@ fi
|
||||
$as_echo "$lt_cv_ld_force_load" >&6; }
|
||||
case $host_os in
|
||||
rhapsody* | darwin1.[012])
|
||||
_lt_dar_allow_undefined='' ;;
|
||||
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
|
||||
darwin1.*)
|
||||
_lt_dar_allow_undefined='' ;;
|
||||
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
|
||||
darwin*) # darwin 5.x on
|
||||
# if running on 10.5 or later, the deployment target defaults
|
||||
# to the OS version, if on x86, and 10.4, the deployment
|
||||
# target defaults to 10.4. Don't you love it?
|
||||
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
|
||||
10.0,*86*-darwin8*|10.0,*-darwin[91]*)
|
||||
_lt_dar_allow_undefined='${wl}dynamic_lookup' ;;
|
||||
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
|
||||
10.[012][,.]*)
|
||||
_lt_dar_allow_undefined='' ;;
|
||||
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
|
||||
10.*)
|
||||
_lt_dar_allow_undefined='${wl}dynamic_lookup' ;;
|
||||
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
+8
-2
@@ -10,21 +10,27 @@ libmobileffmpeg_la_SOURCES = \
|
||||
fftools_ffmpeg_hw.c \
|
||||
fftools_ffmpeg_opt.c \
|
||||
fftools_ffmpeg_videotoolbox.c \
|
||||
MediaInformation.m \
|
||||
MediaInformationParser.m \
|
||||
MobileFFmpeg.m \
|
||||
MobileFFmpegConfig.m \
|
||||
mobileffmpeg_exception.m \
|
||||
Statistics.m
|
||||
Statistics.m \
|
||||
StreamInformation.m
|
||||
|
||||
include_HEADERS = \
|
||||
ArchDetect.h \
|
||||
fftools_cmdutils.h \
|
||||
fftools_ffmpeg.h \
|
||||
LogDelegate.h \
|
||||
MediaInformation.h \
|
||||
MediaInformationParser.h \
|
||||
MobileFFmpeg.h \
|
||||
MobileFFmpegConfig.h \
|
||||
mobileffmpeg_exception.h \
|
||||
Statistics.h \
|
||||
StatisticsDelegate.h
|
||||
StatisticsDelegate.h \
|
||||
StreamInformation.h
|
||||
|
||||
libmobileffmpeg_la_CFLAGS = $(CFLAGS)
|
||||
libmobileffmpeg_la_OBJCFLAGS = $(CFLAGS)
|
||||
|
||||
+45
-3
@@ -139,10 +139,13 @@ am_libmobileffmpeg_la_OBJECTS = libmobileffmpeg_la-ArchDetect.lo \
|
||||
libmobileffmpeg_la-fftools_ffmpeg_hw.lo \
|
||||
libmobileffmpeg_la-fftools_ffmpeg_opt.lo \
|
||||
libmobileffmpeg_la-fftools_ffmpeg_videotoolbox.lo \
|
||||
libmobileffmpeg_la-MediaInformation.lo \
|
||||
libmobileffmpeg_la-MediaInformationParser.lo \
|
||||
libmobileffmpeg_la-MobileFFmpeg.lo \
|
||||
libmobileffmpeg_la-MobileFFmpegConfig.lo \
|
||||
libmobileffmpeg_la-mobileffmpeg_exception.lo \
|
||||
libmobileffmpeg_la-Statistics.lo
|
||||
libmobileffmpeg_la-Statistics.lo \
|
||||
libmobileffmpeg_la-StreamInformation.lo
|
||||
libmobileffmpeg_la_OBJECTS = $(am_libmobileffmpeg_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
@@ -168,9 +171,12 @@ DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__maybe_remake_depfiles = depfiles
|
||||
am__depfiles_remade = ./$(DEPDIR)/libmobileffmpeg_la-ArchDetect.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-MediaInformation.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpegConfig.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-Statistics.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-StreamInformation.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-fftools_cmdutils.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg.Plo \
|
||||
./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg_filter.Plo \
|
||||
@@ -375,21 +381,27 @@ libmobileffmpeg_la_SOURCES = \
|
||||
fftools_ffmpeg_hw.c \
|
||||
fftools_ffmpeg_opt.c \
|
||||
fftools_ffmpeg_videotoolbox.c \
|
||||
MediaInformation.m \
|
||||
MediaInformationParser.m \
|
||||
MobileFFmpeg.m \
|
||||
MobileFFmpegConfig.m \
|
||||
mobileffmpeg_exception.m \
|
||||
Statistics.m
|
||||
Statistics.m \
|
||||
StreamInformation.m
|
||||
|
||||
include_HEADERS = \
|
||||
ArchDetect.h \
|
||||
fftools_cmdutils.h \
|
||||
fftools_ffmpeg.h \
|
||||
LogDelegate.h \
|
||||
MediaInformation.h \
|
||||
MediaInformationParser.h \
|
||||
MobileFFmpeg.h \
|
||||
MobileFFmpegConfig.h \
|
||||
mobileffmpeg_exception.h \
|
||||
Statistics.h \
|
||||
StatisticsDelegate.h
|
||||
StatisticsDelegate.h \
|
||||
StreamInformation.h
|
||||
|
||||
libmobileffmpeg_la_CFLAGS = $(CFLAGS)
|
||||
libmobileffmpeg_la_OBJCFLAGS = $(CFLAGS)
|
||||
@@ -474,9 +486,12 @@ distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-ArchDetect.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-MediaInformation.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpegConfig.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-Statistics.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-StreamInformation.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-fftools_cmdutils.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg_filter.Plo@am__quote@ # am--include-marker
|
||||
@@ -588,6 +603,20 @@ libmobileffmpeg_la-ArchDetect.lo: ArchDetect.m
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libmobileffmpeg_la-ArchDetect.lo `test -f 'ArchDetect.m' || echo '$(srcdir)/'`ArchDetect.m
|
||||
|
||||
libmobileffmpeg_la-MediaInformation.lo: MediaInformation.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -MT libmobileffmpeg_la-MediaInformation.lo -MD -MP -MF $(DEPDIR)/libmobileffmpeg_la-MediaInformation.Tpo -c -o libmobileffmpeg_la-MediaInformation.lo `test -f 'MediaInformation.m' || echo '$(srcdir)/'`MediaInformation.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmobileffmpeg_la-MediaInformation.Tpo $(DEPDIR)/libmobileffmpeg_la-MediaInformation.Plo
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformation.m' object='libmobileffmpeg_la-MediaInformation.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libmobileffmpeg_la-MediaInformation.lo `test -f 'MediaInformation.m' || echo '$(srcdir)/'`MediaInformation.m
|
||||
|
||||
libmobileffmpeg_la-MediaInformationParser.lo: MediaInformationParser.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -MT libmobileffmpeg_la-MediaInformationParser.lo -MD -MP -MF $(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Tpo -c -o libmobileffmpeg_la-MediaInformationParser.lo `test -f 'MediaInformationParser.m' || echo '$(srcdir)/'`MediaInformationParser.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Tpo $(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Plo
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformationParser.m' object='libmobileffmpeg_la-MediaInformationParser.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libmobileffmpeg_la-MediaInformationParser.lo `test -f 'MediaInformationParser.m' || echo '$(srcdir)/'`MediaInformationParser.m
|
||||
|
||||
libmobileffmpeg_la-MobileFFmpeg.lo: MobileFFmpeg.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -MT libmobileffmpeg_la-MobileFFmpeg.lo -MD -MP -MF $(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Tpo -c -o libmobileffmpeg_la-MobileFFmpeg.lo `test -f 'MobileFFmpeg.m' || echo '$(srcdir)/'`MobileFFmpeg.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Tpo $(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Plo
|
||||
@@ -616,6 +645,13 @@ libmobileffmpeg_la-Statistics.lo: Statistics.m
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libmobileffmpeg_la-Statistics.lo `test -f 'Statistics.m' || echo '$(srcdir)/'`Statistics.m
|
||||
|
||||
libmobileffmpeg_la-StreamInformation.lo: StreamInformation.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -MT libmobileffmpeg_la-StreamInformation.lo -MD -MP -MF $(DEPDIR)/libmobileffmpeg_la-StreamInformation.Tpo -c -o libmobileffmpeg_la-StreamInformation.lo `test -f 'StreamInformation.m' || echo '$(srcdir)/'`StreamInformation.m
|
||||
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmobileffmpeg_la-StreamInformation.Tpo $(DEPDIR)/libmobileffmpeg_la-StreamInformation.Plo
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='StreamInformation.m' object='libmobileffmpeg_la-StreamInformation.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmobileffmpeg_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libmobileffmpeg_la-StreamInformation.lo `test -f 'StreamInformation.m' || echo '$(srcdir)/'`StreamInformation.m
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
@@ -772,9 +808,12 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-ArchDetect.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MediaInformation.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpegConfig.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-Statistics.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-StreamInformation.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-fftools_cmdutils.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg_filter.Plo
|
||||
@@ -828,9 +867,12 @@ installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-ArchDetect.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MediaInformation.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MediaInformationParser.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpeg.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-MobileFFmpegConfig.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-Statistics.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-StreamInformation.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-fftools_cmdutils.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg.Plo
|
||||
-rm -f ./$(DEPDIR)/libmobileffmpeg_la-fftools_ffmpeg_filter.Plo
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include "StreamInformation.h"
|
||||
|
||||
@interface MediaInformation : NSObject
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
/**
|
||||
* Returns format.
|
||||
*
|
||||
* \return media format
|
||||
*/
|
||||
- (NSString*)getFormat;
|
||||
|
||||
/**
|
||||
* Sets media format.
|
||||
*
|
||||
* \param media format
|
||||
*/
|
||||
- (void)setFormat:(NSString*)format;
|
||||
|
||||
/**
|
||||
* Returns path.
|
||||
*
|
||||
* \return media path
|
||||
*/
|
||||
- (NSString*)getPath;
|
||||
|
||||
/**
|
||||
* Sets media path.
|
||||
*
|
||||
* \param media path
|
||||
*/
|
||||
- (void)setPath:(NSString*)path;
|
||||
|
||||
/**
|
||||
* Returns duration.
|
||||
*
|
||||
* \return media duration in milliseconds
|
||||
*/
|
||||
- (NSNumber*)getDuration;
|
||||
|
||||
/**
|
||||
* Sets media duration.
|
||||
*
|
||||
* \param media duration in milliseconds
|
||||
*/
|
||||
- (void)setDuration:(NSNumber*) duration;
|
||||
|
||||
/**
|
||||
* Returns start time.
|
||||
*
|
||||
* \return media start time in milliseconds
|
||||
*/
|
||||
- (NSNumber*)getStartTime;
|
||||
|
||||
/**
|
||||
* Sets media start time.
|
||||
*
|
||||
* \param media start time in milliseconds
|
||||
*/
|
||||
- (void)setStartTime:(NSNumber*)startTime;
|
||||
|
||||
/**
|
||||
* Returns bitrate.
|
||||
*
|
||||
* \return media bitrate in kb/s
|
||||
*/
|
||||
- (NSNumber*)getBitrate;
|
||||
|
||||
/**
|
||||
* Sets bitrate.
|
||||
*
|
||||
* \param media bitrate in kb/s
|
||||
*/
|
||||
- (void)setBitrate:(NSNumber*) bitrate;
|
||||
|
||||
/**
|
||||
* Returns unparsed media information.
|
||||
*
|
||||
* \return unparsed media information data
|
||||
*/
|
||||
- (NSString*)getRawInformation;
|
||||
|
||||
/**
|
||||
* Sets unparsed media information.
|
||||
*
|
||||
* \param unparsed media information data
|
||||
*/
|
||||
- (void)setRawInformation:(NSString*)rawInformation;
|
||||
|
||||
/**
|
||||
* Adds metadata.
|
||||
*
|
||||
* \param metadata key and value
|
||||
*/
|
||||
- (void)addMetadata:(NSString*)key :(NSString*)value;
|
||||
|
||||
/**
|
||||
* Returns all metadata entries.
|
||||
*
|
||||
* \return metadata dictionary
|
||||
*/
|
||||
- (NSDictionary*)getMetadataEntries;
|
||||
|
||||
/**
|
||||
* Adds new stream.
|
||||
*
|
||||
* \param new stream information
|
||||
*/
|
||||
- (void)addStream:(StreamInformation*) stream;
|
||||
|
||||
/**
|
||||
* Returns all streams
|
||||
*
|
||||
* \return streams array
|
||||
*/
|
||||
- (NSArray*)getStreams;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "MediaInformation.h"
|
||||
|
||||
@implementation MediaInformation {
|
||||
|
||||
/**
|
||||
* Format
|
||||
*/
|
||||
NSString *format;
|
||||
|
||||
/**
|
||||
* Path
|
||||
*/
|
||||
NSString *path;
|
||||
|
||||
/**
|
||||
* Duration, in milliseconds
|
||||
*/
|
||||
NSNumber *duration;
|
||||
|
||||
/**
|
||||
* Start time, in milliseconds
|
||||
*/
|
||||
NSNumber *startTime;
|
||||
|
||||
/**
|
||||
* Bitrate, kb/s
|
||||
*/
|
||||
NSNumber *bitrate;
|
||||
|
||||
/**
|
||||
* Metadata map
|
||||
*/
|
||||
NSMutableDictionary *metadata;
|
||||
|
||||
/**
|
||||
* List of streams
|
||||
*/
|
||||
NSMutableArray *streams;
|
||||
|
||||
/**
|
||||
* Raw unparsed media information
|
||||
*/
|
||||
NSString *rawInformation;
|
||||
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
format = nil;
|
||||
path = nil;
|
||||
duration = nil;
|
||||
startTime = nil;
|
||||
bitrate = nil;
|
||||
metadata = [[NSMutableDictionary alloc] init];
|
||||
streams = [[NSMutableArray alloc] init];
|
||||
rawInformation = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString*)getFormat {
|
||||
return format;
|
||||
}
|
||||
|
||||
- (void)setFormat:(NSString*)newFormat {
|
||||
format = newFormat;
|
||||
}
|
||||
|
||||
- (NSString*)getPath {
|
||||
return path;
|
||||
}
|
||||
|
||||
- (void)setPath:(NSString*)newPath {
|
||||
path = newPath;
|
||||
}
|
||||
|
||||
- (NSNumber*)getDuration {
|
||||
return duration;
|
||||
}
|
||||
|
||||
- (void)setDuration:(NSNumber*)newDuration {
|
||||
duration = newDuration;
|
||||
}
|
||||
|
||||
- (NSNumber*)getStartTime {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
- (void)setStartTime:(NSNumber*)newStartTime {
|
||||
startTime = newStartTime;
|
||||
}
|
||||
|
||||
- (NSNumber*)getBitrate {
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
- (void)setBitrate:(NSNumber*)newBitrate {
|
||||
bitrate = newBitrate;
|
||||
}
|
||||
|
||||
- (NSString*)getRawInformation {
|
||||
return rawInformation;
|
||||
}
|
||||
|
||||
- (void)setRawInformation:(NSString*)newRawInformation {
|
||||
rawInformation = newRawInformation;
|
||||
}
|
||||
|
||||
- (void)addMetadata:(NSString*)key :(NSString*)value {
|
||||
metadata[key] = value;
|
||||
}
|
||||
|
||||
- (NSDictionary*)getMetadataEntries {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
- (void)addStream:(StreamInformation*)stream {
|
||||
[streams addObject:stream];
|
||||
}
|
||||
|
||||
- (NSArray*)getStreams {
|
||||
return streams;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include "MediaInformation.h"
|
||||
|
||||
@interface MediaInformationParser : NSObject
|
||||
|
||||
/**
|
||||
* Extracts MediaInformation from given command output.
|
||||
*/
|
||||
+ (MediaInformation*)from: (NSString*)rawCommandOutput;
|
||||
|
||||
/**
|
||||
* Extracts StreamInformation from given input.
|
||||
*/
|
||||
+ (StreamInformation*)parseStreamBlock:(NSString*)input;
|
||||
|
||||
+ (void (^)(NSString *__autoreleasing*, NSString *__autoreleasing*))parseInputBlock:(NSString*)input;
|
||||
+ (void (^)(NSNumber *__autoreleasing*, NSNumber *__autoreleasing*, NSNumber *__autoreleasing*))parseDurationBlock:(NSString*)input;
|
||||
+ (void (^)(NSString *__autoreleasing*, NSString *__autoreleasing*))parseMetadataBlock:(NSString*)input;
|
||||
+ (void (^)(NSNumber *__autoreleasing*, NSNumber *__autoreleasing*))parseVideoDimensions: (NSString*)input;
|
||||
|
||||
+ (NSString*)parseVideoStreamSampleAspectRatio: (NSString*)input;
|
||||
+ (NSString*)parseVideoStreamDisplayAspectRatio: (NSString*)input;
|
||||
+ (NSNumber*)parseAudioStreamSampleRate: (NSString*)input;
|
||||
+ (NSString*)parseStreamType: (NSString*)input;
|
||||
+ (NSString*)parseStreamCodec: (NSString*)input;
|
||||
+ (NSString*)parseStreamFullCodec: (NSString*)input;
|
||||
+ (NSNumber*)parseStreamIndex: (NSString*)input;
|
||||
+ (NSNumber*)parseDuration: (NSString*)input;
|
||||
+ (NSNumber*)parseStartTime: (NSString*)input;
|
||||
+ (NSString*)substring:(NSString*)string from:(NSString*)start to:(NSString*)end ignoring:(NSArray*)ignoredTokens;
|
||||
+ (NSString*)substring:(NSString*)string from:(NSString*)start ignoring:(NSArray*)ignoredTokens;
|
||||
+ (NSString*)substring:(NSString*)string to:(NSString*)start ignoring:(NSArray*)ignoredTokens;
|
||||
+ (int)index:(NSString*)string of:(NSString*)substring from:(int)startIndex times:(int)n;
|
||||
+ (int)count:(NSString*)string of:(NSString*)substring;
|
||||
+ (NSNumber*)toInteger: (NSString*)input;
|
||||
+ (NSNumber*)toIntegerObject: (NSString*)input;
|
||||
+ (NSString*)safeGet:(NSArray*)array from:(int)index;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,590 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "MediaInformationParser.h"
|
||||
|
||||
static NSDateFormatter* durationFormat;
|
||||
static NSDate* referenceDuration;
|
||||
static NSRegularExpression *parenthesesRegex;
|
||||
static NSRegularExpression *bracketsRegex;
|
||||
|
||||
@implementation MediaInformationParser
|
||||
|
||||
+ (void)initialize {
|
||||
NSError *localError = nil;
|
||||
durationFormat = [[NSDateFormatter alloc] init];
|
||||
[durationFormat setDateFormat:@"HH:mm:ss"];
|
||||
|
||||
referenceDuration = [durationFormat dateFromString: @"00:00:00"];
|
||||
parenthesesRegex = [NSRegularExpression regularExpressionWithPattern:@"\\(.*\\)" options:NSRegularExpressionCaseInsensitive error:&localError];
|
||||
bracketsRegex = [NSRegularExpression regularExpressionWithPattern:@"\\[.*\\]" options:NSRegularExpressionCaseInsensitive error:&localError];
|
||||
}
|
||||
|
||||
+ (MediaInformation*)from: (NSString*)rawCommandOutput {
|
||||
MediaInformation* mediaInformation = [[MediaInformation alloc] init];
|
||||
|
||||
if (rawCommandOutput != nil) {
|
||||
NSArray* split = [rawCommandOutput componentsSeparatedByString:@"\n"];
|
||||
Boolean metadata = false;
|
||||
StreamInformation *lastCreatedStream = nil;
|
||||
NSMutableString *rawInformation = [[NSMutableString alloc] init];
|
||||
|
||||
for (int i=0; i < [split count]; i++) {
|
||||
NSString *outputLine = [split objectAtIndex:i];
|
||||
|
||||
if ([outputLine hasPrefix:@"["]) {
|
||||
metadata = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *trimmedLine = [outputLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
if ([trimmedLine hasPrefix:@"Input"]) {
|
||||
metadata = false;
|
||||
lastCreatedStream = nil;
|
||||
|
||||
void(^blockPair)(NSString **, NSString **) = [MediaInformationParser parseInputBlock:trimmedLine];
|
||||
|
||||
NSString *format;
|
||||
NSString *path;
|
||||
blockPair(&format, &path);
|
||||
|
||||
[mediaInformation setFormat:format];
|
||||
[mediaInformation setPath:path];
|
||||
} else if ([trimmedLine hasPrefix:@"Duration"]) {
|
||||
metadata = false;
|
||||
lastCreatedStream = nil;
|
||||
|
||||
void(^blockTrio)(NSNumber **, NSNumber **, NSNumber **) = [MediaInformationParser parseDurationBlock:trimmedLine];
|
||||
|
||||
NSNumber *duration;
|
||||
NSNumber *startTime;
|
||||
NSNumber *bitrate;
|
||||
|
||||
blockTrio(&duration, &startTime, &bitrate);
|
||||
|
||||
[mediaInformation setDuration:duration];
|
||||
[mediaInformation setStartTime:startTime];
|
||||
[mediaInformation setBitrate:bitrate];
|
||||
} else if ([trimmedLine hasPrefix:@"Metadata"]) {
|
||||
metadata = true;
|
||||
} else if ([trimmedLine hasPrefix:@"Stream mapping"] || [trimmedLine hasPrefix:@"Press [q] to stop"] || [trimmedLine hasPrefix:@"Output"]) {
|
||||
break;
|
||||
} else if ([trimmedLine hasPrefix:@"Stream"]) {
|
||||
metadata = false;
|
||||
lastCreatedStream = [MediaInformationParser parseStreamBlock:trimmedLine];
|
||||
[mediaInformation addStream:lastCreatedStream];
|
||||
} else if (metadata) {
|
||||
void(^blockPair)(NSString **, NSString **) = [MediaInformationParser parseMetadataBlock:trimmedLine];
|
||||
|
||||
NSString *key;
|
||||
NSString *value;
|
||||
blockPair(&key, &value);
|
||||
|
||||
if (key != nil && value != nil) {
|
||||
if (lastCreatedStream != nil) {
|
||||
[lastCreatedStream addMetadata:key:value];
|
||||
} else {
|
||||
[mediaInformation addMetadata:key:value];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[rawInformation appendString:outputLine];
|
||||
[rawInformation appendString:@"\n"];
|
||||
}
|
||||
|
||||
[mediaInformation setRawInformation:rawInformation];
|
||||
}
|
||||
|
||||
return mediaInformation;
|
||||
}
|
||||
|
||||
+ (void (^)(NSString *__autoreleasing*, NSString *__autoreleasing*))parseInputBlock:(NSString*)input {
|
||||
NSString *format = [MediaInformationParser substring:input from:@"," to:@", from" ignoring:nil];
|
||||
NSString *path = [MediaInformationParser substring:input from:@"'" to:@"'" ignoring:nil];
|
||||
|
||||
return ^(NSString **s1, NSString **s2){
|
||||
*s1 = format;
|
||||
*s2 = path;
|
||||
};
|
||||
}
|
||||
|
||||
+ (void (^)(NSNumber *__autoreleasing*, NSNumber *__autoreleasing*, NSNumber *__autoreleasing*))parseDurationBlock:(NSString*)input {
|
||||
NSNumber *duration = [MediaInformationParser parseDuration:[MediaInformationParser substring:input from:@"Duration:" to:@"," ignoring:[[NSMutableArray alloc] initWithObjects:@"uration:", nil]]];
|
||||
NSNumber *start = [MediaInformationParser parseStartTime:[MediaInformationParser substring:input from:@"start:" to:@"," ignoring:[[NSMutableArray alloc] initWithObjects:@"tart:", nil]]];
|
||||
NSString *bitrateString = [MediaInformationParser substring:input from:@"bitrate:" ignoring:[[NSMutableArray alloc] initWithObjects:@"itrate:", @"kb/s", nil]];
|
||||
|
||||
NSNumber *bitrate = nil;
|
||||
if (bitrateString != nil && ![bitrateString isEqualToString:@"N/A"]) {
|
||||
bitrate = [MediaInformationParser toIntegerObject:bitrateString];
|
||||
}
|
||||
|
||||
return ^(NSNumber **n1, NSNumber **n2, NSNumber **n3){
|
||||
*n1 = duration;
|
||||
*n2 = start;
|
||||
*n3 = bitrate;
|
||||
};
|
||||
}
|
||||
|
||||
+ (void (^)(NSString *__autoreleasing*, NSString *__autoreleasing*))parseMetadataBlock:(NSString*)input {
|
||||
NSString *key = nil;
|
||||
NSString *value = nil;
|
||||
|
||||
if (input != nil) {
|
||||
key = [MediaInformationParser substring:input to:@":" ignoring:[[NSMutableArray alloc] init]];
|
||||
value = [MediaInformationParser substring:input from:@":" ignoring:[[NSMutableArray alloc] init]];
|
||||
}
|
||||
|
||||
return ^(NSString **s1, NSString **s2){
|
||||
*s1 = key;
|
||||
*s2 = value;
|
||||
};
|
||||
}
|
||||
|
||||
+ (StreamInformation*)parseStreamBlock:(NSString*)input {
|
||||
StreamInformation* streamInformation = [[StreamInformation alloc] init];
|
||||
|
||||
if (input != nil) {
|
||||
[streamInformation setIndex:[MediaInformationParser parseStreamIndex:input]];
|
||||
|
||||
int typeBlockStartIndex = [MediaInformationParser index:input of:@":" from:0 times:2];
|
||||
if ((typeBlockStartIndex > -1) && (typeBlockStartIndex < [input length])) {
|
||||
|
||||
NSString *streamBlock = [input substringFromIndex:(typeBlockStartIndex + 1)];
|
||||
|
||||
NSArray* parts = [streamBlock componentsSeparatedByString:@","];
|
||||
NSString *typePart = [MediaInformationParser safeGet:parts from:0];
|
||||
NSString *type = [MediaInformationParser parseStreamType:typePart];
|
||||
|
||||
[streamInformation setType:type];
|
||||
[streamInformation setCodec:[MediaInformationParser parseStreamCodec:typePart]];
|
||||
[streamInformation setFullCodec:[MediaInformationParser parseStreamFullCodec:typePart]];
|
||||
|
||||
NSString *part2 = [MediaInformationParser safeGet:parts from:1];
|
||||
NSString *part3 = [MediaInformationParser safeGet:parts from:2];
|
||||
NSString *part4 = [MediaInformationParser safeGet:parts from:3];
|
||||
NSString *part5 = [MediaInformationParser safeGet:parts from:4];
|
||||
|
||||
if ([@"video" isEqualToString:type]) {
|
||||
int lastUsedPart = 1;
|
||||
|
||||
if (part2 != nil) {
|
||||
int pStart = [MediaInformationParser count:part2 of:@"("];
|
||||
int pEnd = [MediaInformationParser count:part2 of:@")"];
|
||||
|
||||
while (pStart != pEnd) {
|
||||
lastUsedPart++;
|
||||
NSString *newPart = [MediaInformationParser safeGet:parts from:lastUsedPart];
|
||||
if (newPart == nil) {
|
||||
break;
|
||||
}
|
||||
part2 = [NSString stringWithFormat:@"%@,%@", part2, newPart];
|
||||
pStart = [MediaInformationParser count:part2 of:@"("];
|
||||
pEnd = [MediaInformationParser count:part2 of:@")"];
|
||||
}
|
||||
|
||||
part2 = [part2 lowercaseString];
|
||||
part2 = [part2 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
[streamInformation setFullFormat:part2];
|
||||
|
||||
NSString *formattedPart2 = [parenthesesRegex stringByReplacingMatchesInString:part2 options:0 range:NSMakeRange(0, [part2 length]) withTemplate:@""];
|
||||
formattedPart2 = [formattedPart2 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setFormat:formattedPart2];
|
||||
}
|
||||
|
||||
lastUsedPart++;
|
||||
NSString *videoDimensionPart = [MediaInformationParser safeGet:parts from:lastUsedPart];
|
||||
if (videoDimensionPart != nil) {
|
||||
NSString *videoLayout = [videoDimensionPart lowercaseString];
|
||||
videoLayout = [videoLayout stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
void(^dimensions)(NSNumber **, NSNumber **) = [MediaInformationParser parseVideoDimensions:videoLayout];
|
||||
NSNumber *width;
|
||||
NSNumber *height;
|
||||
dimensions(&width, &height);
|
||||
|
||||
[streamInformation setWidth:width];
|
||||
[streamInformation setHeight:height];
|
||||
|
||||
[streamInformation setSampleAspectRatio:[MediaInformationParser parseVideoStreamSampleAspectRatio:videoLayout]];
|
||||
[streamInformation setDisplayAspectRatio:[MediaInformationParser parseVideoStreamDisplayAspectRatio:videoLayout]];
|
||||
}
|
||||
|
||||
for (int i = lastUsedPart + 1; i < [parts count]; i++) {
|
||||
NSString *part = [parts objectAtIndex:i];
|
||||
|
||||
part = [parenthesesRegex stringByReplacingMatchesInString:part options:0 range:NSMakeRange(0, [part length]) withTemplate:@""];
|
||||
part = [part lowercaseString];
|
||||
|
||||
if ([part rangeOfString:@"kb/s"].location != NSNotFound) {
|
||||
part = [part stringByReplacingOccurrencesOfString:@"kb/s" withString:@""];
|
||||
part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
NSNumber *bitrate = [MediaInformationParser toIntegerObject:part];
|
||||
[streamInformation setBitrate:bitrate];
|
||||
} else if ([part rangeOfString:@"fps"].location != NSNotFound) {
|
||||
part = [part stringByReplacingOccurrencesOfString:@"fps" withString:@""];
|
||||
part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setAverageFrameRate:part];
|
||||
} else if ([part rangeOfString:@"tbr"].location != NSNotFound) {
|
||||
part = [part stringByReplacingOccurrencesOfString:@"tbr" withString:@""];
|
||||
part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setRealFrameRate:part];
|
||||
} else if ([part rangeOfString:@"tbn"].location != NSNotFound) {
|
||||
part = [part stringByReplacingOccurrencesOfString:@"tbn" withString:@""];
|
||||
part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setTimeBase:part];
|
||||
} else if ([part rangeOfString:@"tbc"].location != NSNotFound) {
|
||||
part = [part stringByReplacingOccurrencesOfString:@"tbc" withString:@""];
|
||||
part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setCodecTimeBase:part];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ([@"audio" isEqualToString:type]) {
|
||||
if (part2 != nil) {
|
||||
[streamInformation setSampleRate:[MediaInformationParser parseAudioStreamSampleRate:part2]];
|
||||
}
|
||||
if (part3 != nil) {
|
||||
NSString *formattedPart3 = [part3 lowercaseString];
|
||||
formattedPart3 = [formattedPart3 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setChannelLayout:formattedPart3];
|
||||
}
|
||||
if (part4 != nil) {
|
||||
NSString *formattedPart4 = [part4 lowercaseString];
|
||||
formattedPart4 = [formattedPart4 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setSampleFormat:formattedPart4];
|
||||
}
|
||||
if (part5 != nil) {
|
||||
NSString *formattedPart5 = [part5 lowercaseString];
|
||||
formattedPart5 = [parenthesesRegex stringByReplacingMatchesInString:formattedPart5 options:0 range:NSMakeRange(0, [formattedPart5 length]) withTemplate:@""];
|
||||
formattedPart5 = [formattedPart5 stringByReplacingOccurrencesOfString:@"kb/s" withString:@""];
|
||||
formattedPart5 = [formattedPart5 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
[streamInformation setBitrate:[MediaInformationParser toIntegerObject:formattedPart5]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return streamInformation;
|
||||
}
|
||||
|
||||
+ (void (^)(NSNumber *__autoreleasing*, NSNumber *__autoreleasing*))parseVideoDimensions: (NSString*)input {
|
||||
NSNumber *width = nil;
|
||||
NSNumber *height = nil;
|
||||
|
||||
if (input != nil) {
|
||||
|
||||
NSString *formattedString = [input lowercaseString];
|
||||
formattedString = [bracketsRegex stringByReplacingMatchesInString:formattedString options:0 range:NSMakeRange(0, [formattedString length]) withTemplate:@""];
|
||||
|
||||
NSString *widthString = [MediaInformationParser substring:formattedString to:@"x" ignoring:[[NSMutableArray alloc] init]];
|
||||
NSString *heightString = [MediaInformationParser substring:formattedString from:@"x" ignoring:[[NSMutableArray alloc] init]];
|
||||
|
||||
width = [MediaInformationParser toIntegerObject:widthString];
|
||||
height = [MediaInformationParser toIntegerObject:heightString];
|
||||
}
|
||||
|
||||
return ^(NSNumber **n1, NSNumber **n2){
|
||||
*n1 = width;
|
||||
*n2 = height;
|
||||
};
|
||||
}
|
||||
|
||||
+ (NSString*)parseVideoStreamSampleAspectRatio: (NSString*)input {
|
||||
if (input != nil) {
|
||||
|
||||
NSString *formattedString = [input lowercaseString];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"[" withString:@""];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"]" withString:@""];
|
||||
|
||||
NSArray* parts = [formattedString componentsSeparatedByString:@" "];
|
||||
|
||||
for (int i=0; i < [parts count]; i++) {
|
||||
NSString *token = [parts objectAtIndex:i];
|
||||
if ([token isEqualToString:@"sar"]) {
|
||||
return [MediaInformationParser safeGet:parts from:(i + 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString*)parseVideoStreamDisplayAspectRatio: (NSString*)input {
|
||||
if (input != nil) {
|
||||
|
||||
NSString *formattedString = [input lowercaseString];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"[" withString:@""];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"]" withString:@""];
|
||||
|
||||
NSArray* parts = [formattedString componentsSeparatedByString:@" "];
|
||||
|
||||
for (int i=0; i < [parts count]; i++) {
|
||||
NSString *token = [parts objectAtIndex:i];
|
||||
if ([token isEqualToString:@"dar"]) {
|
||||
return [MediaInformationParser safeGet:parts from:(i + 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSNumber*)parseAudioStreamSampleRate: (NSString*)input {
|
||||
if (input != nil) {
|
||||
Boolean khz = false;
|
||||
Boolean mhz = false;
|
||||
NSString *lowerCaseString = [input lowercaseString];
|
||||
|
||||
if ([lowerCaseString rangeOfString:@"khz"].location != NSNotFound) {
|
||||
khz = true;
|
||||
}
|
||||
if ([lowerCaseString rangeOfString:@"mhz"].location != NSNotFound) {
|
||||
mhz = true;
|
||||
}
|
||||
|
||||
lowerCaseString = [lowerCaseString stringByReplacingOccurrencesOfString:@"khz" withString:@""];
|
||||
lowerCaseString = [lowerCaseString stringByReplacingOccurrencesOfString:@"mhz" withString:@""];
|
||||
lowerCaseString = [lowerCaseString stringByReplacingOccurrencesOfString:@"hz" withString:@""];
|
||||
|
||||
NSNumber *sampleRate = [MediaInformationParser toInteger:[lowerCaseString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
|
||||
if (khz) {
|
||||
return [NSNumber numberWithInteger:(1000*sampleRate.intValue)];
|
||||
} else if (mhz) {
|
||||
return [NSNumber numberWithInteger:(1000000*sampleRate.intValue)];
|
||||
} else {
|
||||
return sampleRate;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString*)parseStreamType: (NSString*)input {
|
||||
if (input != nil) {
|
||||
NSString *formattedString = [input lowercaseString];
|
||||
|
||||
if ([formattedString rangeOfString:@"audio:"].location != NSNotFound) {
|
||||
return @"audio";
|
||||
} else if ([formattedString rangeOfString:@"video:"].location != NSNotFound) {
|
||||
return @"video";
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString*)parseStreamCodec: (NSString*)input {
|
||||
if (input != nil) {
|
||||
NSString *formattedString = [input lowercaseString];
|
||||
formattedString = [parenthesesRegex stringByReplacingMatchesInString:formattedString options:0 range:NSMakeRange(0, [formattedString length]) withTemplate:@""];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"video:" withString:@""];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"audio:" withString:@""];
|
||||
|
||||
return [formattedString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString*)parseStreamFullCodec: (NSString*)input {
|
||||
if (input != nil) {
|
||||
NSString *formattedString = [input lowercaseString];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"video:" withString:@""];
|
||||
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"audio:" withString:@""];
|
||||
|
||||
return [formattedString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSNumber*)parseStreamIndex: (NSString*)input {
|
||||
NSString *substring = [MediaInformationParser substring:input from:@"Stream #0:" to:@":" ignoring:[[NSMutableArray alloc] initWithObjects:@"tream #0", nil]];
|
||||
if (substring != nil) {
|
||||
substring = [substring stringByReplacingOccurrencesOfString:@":" withString:@""];
|
||||
substring = [parenthesesRegex stringByReplacingMatchesInString:substring options:0 range:NSMakeRange(0, [substring length]) withTemplate:@""];
|
||||
|
||||
return [MediaInformationParser toIntegerObject:substring];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSNumber*)parseDuration: (NSString*)input {
|
||||
if (input != nil && ![input isEqualToString:@"N/A"]) {
|
||||
NSString *seconds = [MediaInformationParser substring:input to:@"." ignoring:[[NSMutableArray alloc] init]];
|
||||
if (seconds != nil) {
|
||||
NSDate* durationDate = [durationFormat dateFromString: seconds];
|
||||
if (durationDate != nil) {
|
||||
NSTimeInterval secondsInMilliseconds = [durationDate timeIntervalSinceDate:referenceDuration]*1000;
|
||||
NSNumber *centiSeconds = [MediaInformationParser toInteger:[MediaInformationParser substring:input from:@"." ignoring:[[NSMutableArray alloc] init]]];
|
||||
|
||||
secondsInMilliseconds += centiSeconds.intValue*10;
|
||||
|
||||
return [NSNumber numberWithInteger:secondsInMilliseconds];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSNumber*)parseStartTime: (NSString*)input {
|
||||
if (input != nil && ![input isEqualToString:@"N/A"] && ([input length]>0)) {
|
||||
double inputAsDouble = [input doubleValue];
|
||||
return [NSNumber numberWithInteger:ceil(inputAsDouble*1000)];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString*)substring:(NSString*)string from:(NSString*)start to:(NSString*)end ignoring:(NSArray*)ignoredTokens {
|
||||
NSString *extractedSubstring = nil;
|
||||
|
||||
if (string != nil) {
|
||||
NSRange formatStart = [string rangeOfString:start];
|
||||
if (formatStart.location != NSNotFound && (formatStart.location + start.length < [string length])) {
|
||||
|
||||
NSRange formatEnd = [string rangeOfString:end options:NSLiteralSearch range:NSMakeRange(formatStart.location + start.length, string.length - (formatStart.location + start.length + 1))];
|
||||
|
||||
if (formatEnd.location != NSNotFound) {
|
||||
extractedSubstring = [string substringWithRange:NSMakeRange(formatStart.location + start.length, formatEnd.location - (formatStart.location + start.length))];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ignoredTokens != nil) && (extractedSubstring != nil)) {
|
||||
for (int i=0; i < [ignoredTokens count]; i++) {
|
||||
NSString *token = [ignoredTokens objectAtIndex:i];
|
||||
extractedSubstring = [extractedSubstring stringByReplacingOccurrencesOfString:token withString:@""];
|
||||
}
|
||||
}
|
||||
|
||||
return (extractedSubstring == nil) ? nil : [extractedSubstring stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
}
|
||||
|
||||
+ (NSString*)substring:(NSString*)string from:(NSString*)start ignoring:(NSArray*)ignoredTokens {
|
||||
NSString *extractedSubstring = nil;
|
||||
|
||||
if (string != nil) {
|
||||
NSRange formatStart = [string rangeOfString:start];
|
||||
if (formatStart.location != NSNotFound) {
|
||||
extractedSubstring = [string substringWithRange:NSMakeRange(formatStart.location + start.length, string.length - (formatStart.location + start.length))];
|
||||
}
|
||||
}
|
||||
|
||||
if ((ignoredTokens != nil) && (extractedSubstring != nil)) {
|
||||
for (int i=0; i < [ignoredTokens count]; i++) {
|
||||
NSString *token = [ignoredTokens objectAtIndex:i];
|
||||
extractedSubstring = [extractedSubstring stringByReplacingOccurrencesOfString:token withString:@""];
|
||||
}
|
||||
}
|
||||
|
||||
return (extractedSubstring == nil) ? nil : [extractedSubstring stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
}
|
||||
|
||||
+ (NSString*)substring:(NSString*)string to:(NSString*)start ignoring:(NSArray*)ignoredTokens {
|
||||
NSString *extractedSubstring = nil;
|
||||
|
||||
if (string != nil) {
|
||||
NSRange formatStart = [string rangeOfString:start];
|
||||
if (formatStart.location != NSNotFound) {
|
||||
extractedSubstring = [string substringWithRange:NSMakeRange(0, formatStart.location)];
|
||||
}
|
||||
}
|
||||
|
||||
if ((ignoredTokens != nil) && (extractedSubstring != nil)) {
|
||||
for (int i=0; i < [ignoredTokens count]; i++) {
|
||||
NSString *token = [ignoredTokens objectAtIndex:i];
|
||||
extractedSubstring = [extractedSubstring stringByReplacingOccurrencesOfString:token withString:@""];
|
||||
}
|
||||
}
|
||||
|
||||
return (extractedSubstring == nil) ? nil : [extractedSubstring stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
}
|
||||
|
||||
+ (int)index:(NSString*)string of:(NSString*)substring from:(int)startIndex times:(int)n {
|
||||
int count = 1;
|
||||
startIndex -= substring.length;
|
||||
|
||||
while (count <= n) {
|
||||
unsigned long searchIndex = startIndex + (int)substring.length;
|
||||
NSRange currentRange = [string rangeOfString:substring options:NSLiteralSearch range:NSMakeRange(searchIndex, string.length - searchIndex)];
|
||||
if (currentRange.location != NSNotFound) {
|
||||
startIndex = (int)currentRange.location;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return startIndex;
|
||||
}
|
||||
|
||||
+ (int)count:(NSString*)string of:(NSString*)substring {
|
||||
int count = 0;
|
||||
int index = 0 - (int)substring.length;
|
||||
|
||||
do {
|
||||
int searchIndex = index + (int)substring.length;
|
||||
NSRange currentRange = [string rangeOfString:substring options:NSLiteralSearch range:NSMakeRange(searchIndex, string.length - searchIndex)];
|
||||
if (currentRange.location != NSNotFound) {
|
||||
count++;
|
||||
index = (int)currentRange.location;
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
} while (index >= 0);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
+ (NSNumber*)toInteger: (NSString*)input {
|
||||
if (input == nil) {
|
||||
return [NSNumber numberWithInt:0];
|
||||
}
|
||||
|
||||
return [NSNumber numberWithInteger:input.integerValue];
|
||||
}
|
||||
|
||||
+ (NSNumber*)toIntegerObject: (NSString*)input {
|
||||
if (input == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [NSNumber numberWithInteger:input.integerValue];
|
||||
}
|
||||
|
||||
+ (NSString*)safeGet:(NSArray*)array from:(int)index {
|
||||
if (array == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
unsigned long size = [array count];
|
||||
if (size > index) {
|
||||
return [array objectAtIndex:index];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
@interface StreamInformation : NSObject
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
/**
|
||||
* Returns stream index.
|
||||
*
|
||||
* \return stream index, starting from zero
|
||||
*/
|
||||
- (NSNumber*)getIndex;
|
||||
|
||||
/**
|
||||
* Sets stream index.
|
||||
*
|
||||
* \param stream index, starting from zero
|
||||
*/
|
||||
- (void)setIndex:(NSNumber*) index;
|
||||
|
||||
/**
|
||||
* Returns stream type.
|
||||
*
|
||||
* \return stream type; audio or video
|
||||
*/
|
||||
- (NSString*)getType;
|
||||
|
||||
/**
|
||||
* Sets stream type.
|
||||
*
|
||||
* \param stream type; audio or video
|
||||
*/
|
||||
- (void)setType:(NSString*) type;
|
||||
|
||||
/**
|
||||
* Returns stream codec.
|
||||
*
|
||||
* \return stream codec
|
||||
*/
|
||||
- (NSString*)getCodec;
|
||||
|
||||
/**
|
||||
* Sets stream codec.
|
||||
*
|
||||
* \param stream codec
|
||||
*/
|
||||
- (void)setCodec:(NSString*) codec;
|
||||
|
||||
/**
|
||||
* Returns full stream codec.
|
||||
*
|
||||
* \return stream codec with additional profile and mode information
|
||||
*/
|
||||
- (NSString*)getFullCodec;
|
||||
|
||||
/**
|
||||
* Sets full stream codec.
|
||||
*
|
||||
* \param stream codec with additional profile and mode information
|
||||
*/
|
||||
- (void)setFullCodec:(NSString*) fullCodec;
|
||||
|
||||
/**
|
||||
* Returns stream format.
|
||||
*
|
||||
* \return stream format
|
||||
*/
|
||||
- (NSString*)getFormat;
|
||||
|
||||
/**
|
||||
* Sets stream format.
|
||||
*
|
||||
* \param stream format
|
||||
*/
|
||||
- (void)setFormat:(NSString*) format;
|
||||
|
||||
/**
|
||||
* Returns full stream format.
|
||||
*
|
||||
* \return stream format with
|
||||
*/
|
||||
- (NSString*)getFullFormat;
|
||||
|
||||
/**
|
||||
* Sets full stream format.
|
||||
*
|
||||
* \param stream format with
|
||||
*/
|
||||
- (void)setFullFormat:(NSString*) fullFormat;
|
||||
|
||||
/**
|
||||
* Returns width.
|
||||
*
|
||||
* \return width in pixels
|
||||
*/
|
||||
- (NSNumber*)getWidth;
|
||||
|
||||
/**
|
||||
* Sets width.
|
||||
*
|
||||
* \param width in pixels
|
||||
*/
|
||||
- (void)setWidth:(NSNumber*) width;
|
||||
|
||||
/**
|
||||
* Returns height.
|
||||
*
|
||||
* \return height in pixels
|
||||
*/
|
||||
- (NSNumber*)getHeight;
|
||||
|
||||
/**
|
||||
* Sets height.
|
||||
*
|
||||
* \param height in pixels
|
||||
*/
|
||||
- (void)setHeight:(NSNumber*) height;
|
||||
|
||||
/**
|
||||
* Returns bitrate.
|
||||
*
|
||||
* \return bitrate in kb/s
|
||||
*/
|
||||
- (NSNumber*)getBitrate;
|
||||
|
||||
/**
|
||||
* Sets bitrate.
|
||||
*
|
||||
* \param bitrate in kb/s
|
||||
*/
|
||||
- (void)setBitrate:(NSNumber*) bitrate;
|
||||
|
||||
/**
|
||||
* Returns sample rate.
|
||||
*
|
||||
* \return sample rate in hz
|
||||
*/
|
||||
- (NSNumber*)getSampleRate;
|
||||
|
||||
/**
|
||||
* Sets sample rate.
|
||||
*
|
||||
* \param sample rate in hz
|
||||
*/
|
||||
- (void)setSampleRate:(NSNumber*) sampleRate;
|
||||
|
||||
/**
|
||||
* Returns sample format.
|
||||
*
|
||||
* \return sample format
|
||||
*/
|
||||
- (NSString*)getSampleFormat;
|
||||
|
||||
/**
|
||||
* Sets sample format.
|
||||
*
|
||||
* \param sample format
|
||||
*/
|
||||
- (void)setSampleFormat:(NSString*) sampleFormat;
|
||||
|
||||
/**
|
||||
* Returns channel layout.
|
||||
*
|
||||
* \return channel layout
|
||||
*/
|
||||
- (NSString*)getChannelLayout;
|
||||
|
||||
/**
|
||||
* Sets channel layout.
|
||||
*
|
||||
* \param channel layout
|
||||
*/
|
||||
- (void)setChannelLayout:(NSString*) channelLayout;
|
||||
|
||||
/**
|
||||
* Returns sample aspect ratio.
|
||||
*
|
||||
* \return sample aspect ratio
|
||||
*/
|
||||
- (NSString*)getSampleAspectRatio;
|
||||
|
||||
/**
|
||||
* Sets sample aspect ratio.
|
||||
*
|
||||
* \param sample aspect ratio
|
||||
*/
|
||||
- (void)setSampleAspectRatio:(NSString*) sampleAspectRatio;
|
||||
|
||||
/**
|
||||
* Returns display aspect ratio.
|
||||
*
|
||||
* \return display aspect ratio
|
||||
*/
|
||||
- (NSString*)getDisplayAspectRatio;
|
||||
|
||||
/**
|
||||
* Sets display aspect ratio.
|
||||
*
|
||||
* \param display aspect ratio
|
||||
*/
|
||||
- (void)setDisplayAspectRatio:(NSString*) displayAspectRatio;
|
||||
|
||||
/**
|
||||
* Returns average frame rate.
|
||||
*
|
||||
* \return average frame rate in fps
|
||||
*/
|
||||
- (NSString*)getAverageFrameRate;
|
||||
|
||||
/**
|
||||
* Sets average frame rate.
|
||||
*
|
||||
* \param average frame rate in fps
|
||||
*/
|
||||
- (void)setAverageFrameRate:(NSString*) averageFrameRatehn;
|
||||
|
||||
/**
|
||||
* Returns real frame rate.
|
||||
*
|
||||
* \return real frame rate in tbr
|
||||
*/
|
||||
- (NSString*)getRealFrameRate;
|
||||
|
||||
/**
|
||||
* Sets real frame rate.
|
||||
*
|
||||
* \param real frame rate in tbr
|
||||
*/
|
||||
- (void)setRealFrameRate:(NSString*) realFrameRate;
|
||||
|
||||
/**
|
||||
* Returns time base.
|
||||
*
|
||||
* \return time base in tbn
|
||||
*/
|
||||
- (NSString*)getTimeBase;
|
||||
|
||||
/**
|
||||
* Sets time base.
|
||||
*
|
||||
* \param time base in tbn
|
||||
*/
|
||||
- (void)setTimeBase:(NSString*) timeBase;
|
||||
|
||||
/**
|
||||
* Returns codec time base.
|
||||
*
|
||||
* \return codec time base in tbc
|
||||
*/
|
||||
- (NSString*)getCodecTimeBase;
|
||||
|
||||
/**
|
||||
* Sets codec time base.
|
||||
*
|
||||
* \param codec time base in tbc
|
||||
*/
|
||||
- (void)setCodecTimeBase:(NSString*) codecTimeBase;
|
||||
|
||||
/**
|
||||
* Adds metadata.
|
||||
*
|
||||
* \param metadata key and value
|
||||
*/
|
||||
- (void)addMetadata:(NSString*)key :(NSString*)value;
|
||||
|
||||
/**
|
||||
* Returns all metadata entries.
|
||||
*
|
||||
* \return metadata dictionary
|
||||
*/
|
||||
- (NSDictionary*)getMetadataEntries;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "StreamInformation.h"
|
||||
|
||||
@implementation StreamInformation {
|
||||
|
||||
/**
|
||||
* Stream index
|
||||
*/
|
||||
NSNumber *index;
|
||||
|
||||
NSString *type;
|
||||
NSString *codec;
|
||||
NSString *fullCodec;
|
||||
NSString *format;
|
||||
NSString *fullFormat;
|
||||
|
||||
NSNumber *width;
|
||||
NSNumber *height;
|
||||
|
||||
NSNumber *bitrate;
|
||||
NSNumber *sampleRate;
|
||||
NSString *sampleFormat;
|
||||
NSString *channelLayout;
|
||||
|
||||
/**
|
||||
* SAR
|
||||
*/
|
||||
NSString *sampleAspectRatio;
|
||||
|
||||
/**
|
||||
* DAR
|
||||
*/
|
||||
NSString *displayAspectRatio;
|
||||
|
||||
/**
|
||||
* fps
|
||||
*/
|
||||
NSString *averageFrameRate;
|
||||
|
||||
/**
|
||||
* tbr
|
||||
*/
|
||||
NSString *realFrameRate;
|
||||
|
||||
/**
|
||||
* tbn
|
||||
*/
|
||||
NSString *timeBase;
|
||||
|
||||
/**
|
||||
* tbc
|
||||
*/
|
||||
NSString *codecTimeBase;
|
||||
|
||||
/**
|
||||
* Metadata map
|
||||
*/
|
||||
NSMutableDictionary *metadata;
|
||||
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
index = nil;
|
||||
type = nil;
|
||||
codec = nil;
|
||||
fullCodec = nil;
|
||||
format = nil;
|
||||
fullFormat = nil;
|
||||
width = nil;
|
||||
height = nil;
|
||||
bitrate = nil;
|
||||
sampleRate = nil;
|
||||
sampleFormat = nil;
|
||||
channelLayout = nil;
|
||||
sampleAspectRatio = nil;
|
||||
displayAspectRatio = nil;
|
||||
averageFrameRate = nil;
|
||||
realFrameRate = nil;
|
||||
timeBase = nil;
|
||||
codecTimeBase = nil;
|
||||
metadata = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSNumber*)getIndex {
|
||||
return index;
|
||||
}
|
||||
|
||||
- (void)setIndex:(NSNumber*) newIndex {
|
||||
index = newIndex;
|
||||
}
|
||||
|
||||
- (NSString*)getType {
|
||||
return type;
|
||||
}
|
||||
|
||||
- (void)setType:(NSString*) newType {
|
||||
type = newType;
|
||||
}
|
||||
|
||||
- (NSString*)getCodec {
|
||||
return codec;
|
||||
}
|
||||
|
||||
- (void)setCodec:(NSString*) newCodec {
|
||||
codec = newCodec;
|
||||
}
|
||||
|
||||
- (NSString*)getFullCodec {
|
||||
return fullCodec;
|
||||
}
|
||||
|
||||
- (void)setFullCodec:(NSString*) newFullCodec {
|
||||
fullCodec = newFullCodec;
|
||||
}
|
||||
|
||||
- (NSString*)getFormat {
|
||||
return format;
|
||||
}
|
||||
|
||||
- (void)setFormat:(NSString*) newFormat {
|
||||
format = newFormat;
|
||||
}
|
||||
|
||||
- (NSString*)getFullFormat {
|
||||
return fullFormat;
|
||||
}
|
||||
|
||||
- (void)setFullFormat:(NSString*) newFullFormat {
|
||||
fullFormat = newFullFormat;
|
||||
}
|
||||
|
||||
- (NSNumber*)getWidth {
|
||||
return width;
|
||||
}
|
||||
|
||||
- (void)setWidth:(NSNumber*) newWidth {
|
||||
width = newWidth;
|
||||
}
|
||||
|
||||
- (NSNumber*)getHeight {
|
||||
return height;
|
||||
}
|
||||
|
||||
- (void)setHeight:(NSNumber*) newHeight {
|
||||
height = newHeight;
|
||||
}
|
||||
|
||||
- (NSNumber*)getBitrate {
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
- (void)setBitrate:(NSNumber*) newBitrate {
|
||||
bitrate = newBitrate;
|
||||
}
|
||||
|
||||
- (NSNumber*)getSampleRate {
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
- (void)setSampleRate:(NSNumber*) newSampleRate {
|
||||
sampleRate = newSampleRate;
|
||||
}
|
||||
|
||||
- (NSString*)getSampleFormat {
|
||||
return sampleFormat;
|
||||
}
|
||||
|
||||
- (void)setSampleFormat:(NSString*) newSampleFormat {
|
||||
sampleFormat = newSampleFormat;
|
||||
}
|
||||
|
||||
- (NSString*)getChannelLayout {
|
||||
return channelLayout;
|
||||
}
|
||||
|
||||
- (void)setChannelLayout:(NSString*) newChannelLayout {
|
||||
channelLayout = newChannelLayout;
|
||||
}
|
||||
|
||||
- (NSString*)getSampleAspectRatio {
|
||||
return sampleAspectRatio;
|
||||
}
|
||||
|
||||
- (void)setSampleAspectRatio:(NSString*) newSampleAspectRatio {
|
||||
sampleAspectRatio = newSampleAspectRatio;
|
||||
}
|
||||
|
||||
- (NSString*)getDisplayAspectRatio {
|
||||
return displayAspectRatio;
|
||||
}
|
||||
|
||||
- (void)setDisplayAspectRatio:(NSString*) newDisplayAspectRatio {
|
||||
displayAspectRatio = newDisplayAspectRatio;
|
||||
}
|
||||
|
||||
- (NSString*)getAverageFrameRate {
|
||||
return averageFrameRate;
|
||||
}
|
||||
|
||||
- (void)setAverageFrameRate:(NSString*) newAverageFrameRatehn {
|
||||
averageFrameRate = newAverageFrameRatehn;
|
||||
}
|
||||
|
||||
- (NSString*)getRealFrameRate {
|
||||
return realFrameRate;
|
||||
}
|
||||
|
||||
- (void)setRealFrameRate:(NSString*) newRealFrameRate {
|
||||
realFrameRate = newRealFrameRate;
|
||||
}
|
||||
|
||||
- (NSString*)getTimeBase {
|
||||
return timeBase;
|
||||
}
|
||||
|
||||
- (void)setTimeBase:(NSString*) newTimeBase {
|
||||
timeBase = newTimeBase;
|
||||
}
|
||||
|
||||
- (NSString*)getCodecTimeBase {
|
||||
return codecTimeBase;
|
||||
}
|
||||
|
||||
- (void)setCodecTimeBase:(NSString*) newCodecTimeBase {
|
||||
codecTimeBase = newCodecTimeBase;
|
||||
}
|
||||
|
||||
- (void)addMetadata:(NSString*)key :(NSString*)value {
|
||||
metadata[key] = value;
|
||||
}
|
||||
|
||||
- (NSDictionary*)getMetadataEntries {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -9,6 +9,8 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
340FABBE2115A17600B33CE7 /* VidStabViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 340FABBC2115A17600B33CE7 /* VidStabViewController.h */; };
|
||||
340FABBF2115A17600B33CE7 /* VidStabViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FABBD2115A17600B33CE7 /* VidStabViewController.m */; };
|
||||
3423D267217F7CC100C3C7ED /* MediaInformationParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3423D266217F7CC100C3C7ED /* MediaInformationParserTests.m */; };
|
||||
3423D269217F7D4E00C3C7ED /* MediaInformationParserTests.h in Headers */ = {isa = PBXBuildFile; fileRef = 3423D268217F7D4E00C3C7ED /* MediaInformationParserTests.h */; };
|
||||
343E66B5210784BD00F95E5B /* HttpsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E66B3210784BD00F95E5B /* HttpsViewController.h */; };
|
||||
343E66B6210784BD00F95E5B /* HttpsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 343E66B4210784BD00F95E5B /* HttpsViewController.m */; };
|
||||
343E66B9210789DE00F95E5B /* Constants.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E66B7210789DE00F95E5B /* Constants.h */; };
|
||||
@@ -24,6 +26,22 @@
|
||||
348439EE20B2EFAF001A3990 /* tajmahal.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 348439EB20B2EFAF001A3990 /* tajmahal.jpg */; };
|
||||
348439EF20B2EFAF001A3990 /* colosseum.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 348439EC20B2EFAF001A3990 /* colosseum.jpg */; };
|
||||
34BB547C2109D44800606B7C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BB547B2109D44800606B7C /* Constants.m */; };
|
||||
34C5E89E217F7F86001DCD99 /* libavfilter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E896217F7F86001DCD99 /* libavfilter.framework */; };
|
||||
34C5E89F217F7F86001DCD99 /* libavcodec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E897217F7F86001DCD99 /* libavcodec.framework */; };
|
||||
34C5E8A0217F7F86001DCD99 /* libswresample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E898217F7F86001DCD99 /* libswresample.framework */; };
|
||||
34C5E8A1217F7F86001DCD99 /* libavutil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E899217F7F86001DCD99 /* libavutil.framework */; };
|
||||
34C5E8A2217F7F86001DCD99 /* libswscale.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89A217F7F86001DCD99 /* libswscale.framework */; };
|
||||
34C5E8A3217F7F86001DCD99 /* libavformat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89B217F7F86001DCD99 /* libavformat.framework */; };
|
||||
34C5E8A4217F7F86001DCD99 /* mobileffmpeg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89C217F7F86001DCD99 /* mobileffmpeg.framework */; };
|
||||
34C5E8A5217F7F86001DCD99 /* libavdevice.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89D217F7F86001DCD99 /* libavdevice.framework */; };
|
||||
34C5E8A6217F7F92001DCD99 /* libavcodec.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E897217F7F86001DCD99 /* libavcodec.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8A7217F7F92001DCD99 /* libavdevice.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89D217F7F86001DCD99 /* libavdevice.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8A8217F7F92001DCD99 /* libavfilter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E896217F7F86001DCD99 /* libavfilter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8A9217F7F92001DCD99 /* libavformat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89B217F7F86001DCD99 /* libavformat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8AA217F7F92001DCD99 /* libavutil.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E899217F7F86001DCD99 /* libavutil.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8AB217F7F92001DCD99 /* libswresample.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E898217F7F86001DCD99 /* libswresample.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8AC217F7F92001DCD99 /* libswscale.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89A217F7F86001DCD99 /* libswscale.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34C5E8AD217F7F92001DCD99 /* mobileffmpeg.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34C5E89C217F7F86001DCD99 /* mobileffmpeg.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
34DC789B21215B5800C3486C /* truenorg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789721215B5800C3486C /* truenorg.otf */; };
|
||||
34DC789C21215B5800C3486C /* subtitle.srt in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789821215B5800C3486C /* subtitle.srt */; };
|
||||
34DC789D21215B5800C3486C /* doppioone_regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789921215B5800C3486C /* doppioone_regular.ttf */; };
|
||||
@@ -45,6 +63,14 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
34C5E8A6217F7F92001DCD99 /* libavcodec.framework in Embed Frameworks */,
|
||||
34C5E8A7217F7F92001DCD99 /* libavdevice.framework in Embed Frameworks */,
|
||||
34C5E8A8217F7F92001DCD99 /* libavfilter.framework in Embed Frameworks */,
|
||||
34C5E8A9217F7F92001DCD99 /* libavformat.framework in Embed Frameworks */,
|
||||
34C5E8AA217F7F92001DCD99 /* libavutil.framework in Embed Frameworks */,
|
||||
34C5E8AB217F7F92001DCD99 /* libswresample.framework in Embed Frameworks */,
|
||||
34C5E8AC217F7F92001DCD99 /* libswscale.framework in Embed Frameworks */,
|
||||
34C5E8AD217F7F92001DCD99 /* mobileffmpeg.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -55,6 +81,8 @@
|
||||
09762EB4030C758C5727BD68 /* Pods-MobileFFmpegTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MobileFFmpegTest.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MobileFFmpegTest/Pods-MobileFFmpegTest.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
340FABBC2115A17600B33CE7 /* VidStabViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VidStabViewController.h; sourceTree = "<group>"; };
|
||||
340FABBD2115A17600B33CE7 /* VidStabViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VidStabViewController.m; sourceTree = "<group>"; };
|
||||
3423D266217F7CC100C3C7ED /* MediaInformationParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaInformationParserTests.m; sourceTree = "<group>"; };
|
||||
3423D268217F7D4E00C3C7ED /* MediaInformationParserTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaInformationParserTests.h; sourceTree = "<group>"; };
|
||||
343E66B3210784BD00F95E5B /* HttpsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HttpsViewController.h; sourceTree = "<group>"; };
|
||||
343E66B4210784BD00F95E5B /* HttpsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HttpsViewController.m; sourceTree = "<group>"; };
|
||||
343E66B7210789DE00F95E5B /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
|
||||
@@ -70,6 +98,14 @@
|
||||
348439EB20B2EFAF001A3990 /* tajmahal.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = tajmahal.jpg; sourceTree = "<group>"; };
|
||||
348439EC20B2EFAF001A3990 /* colosseum.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = colosseum.jpg; sourceTree = "<group>"; };
|
||||
34BB547B2109D44800606B7C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = "<group>"; };
|
||||
34C5E896217F7F86001DCD99 /* libavfilter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavfilter.framework; sourceTree = "<group>"; };
|
||||
34C5E897217F7F86001DCD99 /* libavcodec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavcodec.framework; sourceTree = "<group>"; };
|
||||
34C5E898217F7F86001DCD99 /* libswresample.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswresample.framework; sourceTree = "<group>"; };
|
||||
34C5E899217F7F86001DCD99 /* libavutil.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavutil.framework; sourceTree = "<group>"; };
|
||||
34C5E89A217F7F86001DCD99 /* libswscale.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswscale.framework; sourceTree = "<group>"; };
|
||||
34C5E89B217F7F86001DCD99 /* libavformat.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavformat.framework; sourceTree = "<group>"; };
|
||||
34C5E89C217F7F86001DCD99 /* mobileffmpeg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = mobileffmpeg.framework; sourceTree = "<group>"; };
|
||||
34C5E89D217F7F86001DCD99 /* libavdevice.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavdevice.framework; sourceTree = "<group>"; };
|
||||
34DC789721215B5800C3486C /* truenorg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = truenorg.otf; sourceTree = "<group>"; };
|
||||
34DC789821215B5800C3486C /* subtitle.srt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = subtitle.srt; sourceTree = "<group>"; };
|
||||
34DC789921215B5800C3486C /* doppioone_regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = doppioone_regular.ttf; sourceTree = "<group>"; };
|
||||
@@ -95,7 +131,15 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
34C5E8A1217F7F86001DCD99 /* libavutil.framework in Frameworks */,
|
||||
34C5E89F217F7F86001DCD99 /* libavcodec.framework in Frameworks */,
|
||||
34C5E8A0217F7F86001DCD99 /* libswresample.framework in Frameworks */,
|
||||
34C5E8A2217F7F86001DCD99 /* libswscale.framework in Frameworks */,
|
||||
34C5E8A5217F7F86001DCD99 /* libavdevice.framework in Frameworks */,
|
||||
8A776E4D8F4EB85888ADFB99 /* Pods_MobileFFmpegTest.framework in Frameworks */,
|
||||
34C5E89E217F7F86001DCD99 /* libavfilter.framework in Frameworks */,
|
||||
34C5E8A3217F7F86001DCD99 /* libavformat.framework in Frameworks */,
|
||||
34C5E8A4217F7F86001DCD99 /* mobileffmpeg.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -119,6 +163,14 @@
|
||||
3498DC65209F7F1C005F5883 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34C5E897217F7F86001DCD99 /* libavcodec.framework */,
|
||||
34C5E89D217F7F86001DCD99 /* libavdevice.framework */,
|
||||
34C5E896217F7F86001DCD99 /* libavfilter.framework */,
|
||||
34C5E89B217F7F86001DCD99 /* libavformat.framework */,
|
||||
34C5E899217F7F86001DCD99 /* libavutil.framework */,
|
||||
34C5E898217F7F86001DCD99 /* libswresample.framework */,
|
||||
34C5E89A217F7F86001DCD99 /* libswscale.framework */,
|
||||
34C5E89C217F7F86001DCD99 /* mobileffmpeg.framework */,
|
||||
F4B824D376F9CD476C761D40 /* Pods_MobileFFmpegTest.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
@@ -147,30 +199,32 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34FAE213209F7DDD005CE2AE /* AppDelegate.h */,
|
||||
345745492113B8AD00059043 /* AudioViewController.h */,
|
||||
34FAE216209F7DDD005CE2AE /* CommandViewController.h */,
|
||||
343E66B7210789DE00F95E5B /* Constants.h */,
|
||||
343E66B3210784BD00F95E5B /* HttpsViewController.h */,
|
||||
3457454D2113B8D300059043 /* SubtitleViewController.h */,
|
||||
343E67072107C27600F95E5B /* TabBarController.h */,
|
||||
343E67032107AD0100F95E5B /* Util.h */,
|
||||
34FAE219209F7DDD005CE2AE /* VideoViewController.h */,
|
||||
340FABBC2115A17600B33CE7 /* VidStabViewController.h */,
|
||||
34FAE214209F7DDD005CE2AE /* AppDelegate.m */,
|
||||
3457454A2113B8AD00059043 /* AudioViewController.m */,
|
||||
34FAE217209F7DDD005CE2AE /* CommandViewController.m */,
|
||||
34BB547B2109D44800606B7C /* Constants.m */,
|
||||
343E66B4210784BD00F95E5B /* HttpsViewController.m */,
|
||||
34FAE225209F7DDE005CE2AE /* main.m */,
|
||||
3457454E2113B8D300059043 /* SubtitleViewController.m */,
|
||||
343E67082107C27600F95E5B /* TabBarController.m */,
|
||||
343E67042107AD0100F95E5B /* Util.m */,
|
||||
34FAE21A209F7DDD005CE2AE /* VideoViewController.m */,
|
||||
340FABBD2115A17600B33CE7 /* VidStabViewController.m */,
|
||||
34FAE224209F7DDE005CE2AE /* Info.plist */,
|
||||
34FAE21F209F7DDE005CE2AE /* Assets.xcassets */,
|
||||
345745492113B8AD00059043 /* AudioViewController.h */,
|
||||
3457454A2113B8AD00059043 /* AudioViewController.m */,
|
||||
34FAE216209F7DDD005CE2AE /* CommandViewController.h */,
|
||||
34FAE217209F7DDD005CE2AE /* CommandViewController.m */,
|
||||
343E66B7210789DE00F95E5B /* Constants.h */,
|
||||
34BB547B2109D44800606B7C /* Constants.m */,
|
||||
343E66B3210784BD00F95E5B /* HttpsViewController.h */,
|
||||
343E66B4210784BD00F95E5B /* HttpsViewController.m */,
|
||||
34FAE224209F7DDE005CE2AE /* Info.plist */,
|
||||
34FAE221209F7DDE005CE2AE /* LaunchScreen.storyboard */,
|
||||
34FAE225209F7DDE005CE2AE /* main.m */,
|
||||
34FAE21C209F7DDD005CE2AE /* Main.storyboard */,
|
||||
3423D268217F7D4E00C3C7ED /* MediaInformationParserTests.h */,
|
||||
3423D266217F7CC100C3C7ED /* MediaInformationParserTests.m */,
|
||||
3457454D2113B8D300059043 /* SubtitleViewController.h */,
|
||||
3457454E2113B8D300059043 /* SubtitleViewController.m */,
|
||||
343E67072107C27600F95E5B /* TabBarController.h */,
|
||||
343E67082107C27600F95E5B /* TabBarController.m */,
|
||||
343E67032107AD0100F95E5B /* Util.h */,
|
||||
343E67042107AD0100F95E5B /* Util.m */,
|
||||
34FAE219209F7DDD005CE2AE /* VideoViewController.h */,
|
||||
34FAE21A209F7DDD005CE2AE /* VideoViewController.m */,
|
||||
340FABBC2115A17600B33CE7 /* VidStabViewController.h */,
|
||||
340FABBD2115A17600B33CE7 /* VidStabViewController.m */,
|
||||
);
|
||||
path = MobileFFmpegTest;
|
||||
sourceTree = "<group>";
|
||||
@@ -192,6 +246,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
343E67092107C27600F95E5B /* TabBarController.h in Headers */,
|
||||
3423D269217F7D4E00C3C7ED /* MediaInformationParserTests.h in Headers */,
|
||||
3457454B2113B8AD00059043 /* AudioViewController.h in Headers */,
|
||||
3457454F2113B8D300059043 /* SubtitleViewController.h in Headers */,
|
||||
343E66B9210789DE00F95E5B /* Constants.h in Headers */,
|
||||
@@ -345,6 +400,7 @@
|
||||
343E66B6210784BD00F95E5B /* HttpsViewController.m in Sources */,
|
||||
340FABBF2115A17600B33CE7 /* VidStabViewController.m in Sources */,
|
||||
34FAE218209F7DDD005CE2AE /* CommandViewController.m in Sources */,
|
||||
3423D267217F7CC100C3C7ED /* MediaInformationParserTests.m in Sources */,
|
||||
343E670A2107C27600F95E5B /* TabBarController.m in Sources */,
|
||||
345745502113B8D300059043 /* SubtitleViewController.m in Sources */,
|
||||
343E67062107AD0100F95E5B /* Util.m in Sources */,
|
||||
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// MediaInformationParserTests.h
|
||||
//
|
||||
// Copyright (c) 2018 Taner Sener
|
||||
//
|
||||
// This file is part of MobileFFmpeg.
|
||||
//
|
||||
// MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
/**
|
||||
* All parsing tests are initiated from this method
|
||||
*/
|
||||
void runMediaInformationParserTests();
|
||||
@@ -0,0 +1,841 @@
|
||||
//
|
||||
// MediaInformationParserTests.m
|
||||
//
|
||||
// Copyright (c) 2018 Taner Sener
|
||||
//
|
||||
// This file is part of MobileFFmpeg.
|
||||
//
|
||||
// MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
#include <mobileffmpeg/MediaInformationParser.h>
|
||||
|
||||
static NSString *MEDIA_INFORMATION_MP3;
|
||||
static NSString *MEDIA_INFORMATION_JPG;
|
||||
static NSString *MEDIA_INFORMATION_GIF;
|
||||
static NSString *MEDIA_INFORMATION_H264;
|
||||
static NSString *MEDIA_INFORMATION_PNG;
|
||||
static NSString *MEDIA_INFORMATION_H264_2;
|
||||
static NSString *MEDIA_INFORMATION_MP4;
|
||||
static NSString *MEDIA_INFORMATION_MP4_2;
|
||||
static NSString *MEDIA_INFORMATION_OGG;
|
||||
|
||||
static void initTests() {
|
||||
MEDIA_INFORMATION_MP3 = [NSString stringWithFormat:
|
||||
@"Unknown attached picture mimetype: audio/x-wav, skipping.\n"
|
||||
"[mp3 @ 0x7ffb94805800] Estimating duration from bitrate, this may be inaccurate\n"
|
||||
"Input #0, mp3, from 'beethoven_-_symphony_no_9.mp3':\n"
|
||||
" Metadata:\n"
|
||||
" comment : \n"
|
||||
" album : Symphony No.9\n"
|
||||
" compilation : 0\n"
|
||||
" date : -1\n"
|
||||
" title : Symphony No.9\n"
|
||||
" artist : Beethoven\n"
|
||||
" album_artist : Beethoven\n"
|
||||
" track : -1\n"
|
||||
" lyrics-XXX : \n"
|
||||
" Duration: 00:03:33.24, start: 0.000000, bitrate: 320 kb/s\n"
|
||||
" Stream #0:0: Audio: mp3, 48000 Hz, stereo, fltp, 320 kb/s\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (mp3 (mp3float) -> pcm_s16le (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" comment : \n"
|
||||
" album : Symphony No.9\n"
|
||||
" compilation : 0\n"
|
||||
" date : -1\n"
|
||||
" title : Symphony No.9\n"
|
||||
" artist : Beethoven\n"
|
||||
" album_artist : Beethoven\n"
|
||||
" track : -1\n"
|
||||
" lyrics-XXX : \n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.18.100 pcm_s16le\n"
|
||||
"size=N/A time=00:03:33.24 bitrate=N/A speed= 618x \n"
|
||||
"video:0kB audio:39982kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
|
||||
MEDIA_INFORMATION_JPG = [NSString stringWithFormat:
|
||||
@"Input #0, image2, from '/data/user/0/com.arthenica.mobileffmpeg.test/cache/colosseum.jpg':\n"
|
||||
" Duration: 00:00:00.04, start: 0.000000, bitrate: 391187 kb/s\n"
|
||||
" Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 2560x1708 [SAR 1:1 DAR 640:427], 25 tbr, 25 tbn, 25 tbc\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (mjpeg (native) -> wrapped_avframe (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavf58.18.104\n"
|
||||
" Stream #0:0: Video: wrapped_avframe, yuvj420p, 2560x1708 [SAR 1:1 DAR 640:427], q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.31.102 wrapped_avframe\n"
|
||||
"frame= 1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=0.668x \n"
|
||||
"video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown\n"];
|
||||
|
||||
MEDIA_INFORMATION_GIF = [NSString stringWithFormat:
|
||||
@"Input #0, gif, from 'advanced_zoom_in_and_pan_with_fade_in_out.gif':\n"
|
||||
" Duration: N/A, bitrate: N/A\n"
|
||||
" Stream #0:0: Video: gif, bgra, 420x236, 6 fps, 6 tbr, 100 tbn, 100 tbc\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (gif (native) -> wrapped_avframe (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0: Video: wrapped_avframe, bgra, 420x236 [SAR 63:64 DAR 6615:3776], q=2-31, 200 kb/s, 6 fps, 6 tbn, 6 tbc\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
"frame= 61 fps=0.0 q=-0.0 Lsize=N/A time=00:00:10.16 bitrate=N/A speed= 219x \n"
|
||||
"video:32kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
|
||||
MEDIA_INFORMATION_H264 = [NSString stringWithFormat:
|
||||
@"Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'transition_rotate.mp4':\n"
|
||||
" Metadata:\n"
|
||||
" major_brand : isom\n"
|
||||
" minor_version : 512\n"
|
||||
" compatible_brands: isomiso2avc1mp41\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Duration: 00:00:15.00, start: 0.000000, bitrate: 7764 kb/s\n"
|
||||
" Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 7762 kb/s, 25 fps, 30 tbr, 15360 tbn, 60 tbc (default)\n"
|
||||
" Metadata:\n"
|
||||
" handler_name : VideoHandler\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" major_brand : isom\n"
|
||||
" minor_version : 512\n"
|
||||
" compatible_brands: isomiso2avc1mp41\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 30 fps, 30 tbn, 30 tbc (default)\n"
|
||||
" Metadata:\n"
|
||||
" handler_name : VideoHandler\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
"frame= 375 fps=0.0 q=-0.0 Lsize=N/A time=00:00:15.00 bitrate=N/A speed=35.9x \n"
|
||||
"video:196kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
|
||||
MEDIA_INFORMATION_PNG = [NSString stringWithFormat:
|
||||
@"Input #0, png_pipe, from 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png':\n"
|
||||
" Duration: N/A, bitrate: N/A\n"
|
||||
" Stream #0:0: Video: png, rgba(pc), 544x184, 25 tbr, 25 tbn, 25 tbc\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (png (native) -> wrapped_avframe (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0: Video: wrapped_avframe, rgba, 544x184, q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
"frame= 1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=27.1x \n"
|
||||
"video:1kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
|
||||
MEDIA_INFORMATION_H264_2 = [NSString stringWithFormat:
|
||||
@"Input #0, h264, from 'test.h264':\n"
|
||||
" Duration: N/A, bitrate: N/A\n"
|
||||
" Stream #0:0: Video: h264 (Main), yuv420p(tv, bt709, progressive), 1920x1080, 25 fps, 25 tbr, 1200k tbn, 50 tbc\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0: Video: wrapped_avframe, yuv420p, 1920x1080, q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
"frame= 360 fps=0.0 q=-0.0 Lsize=N/A time=00:00:14.40 bitrate=N/A speed=25.5x \n"
|
||||
"video:188kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
|
||||
MEDIA_INFORMATION_MP4 = [NSString stringWithFormat:
|
||||
@"Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_2160p_30fps_stereo_abl.mp4':\n"
|
||||
" Metadata:\n"
|
||||
" major_brand : isom\n"
|
||||
" minor_version : 1\n"
|
||||
" compatible_brands: isomavc1\n"
|
||||
" creation_time : 2013-12-16T17:21:55.000000Z\n"
|
||||
" title : Big Buck Bunny, Sunflower version\n"
|
||||
" artist : Blender Foundation 2008, Janus Bager Kristensen 2013\n"
|
||||
" comment : Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net\n"
|
||||
" genre : Animation\n"
|
||||
" composer : Sacha Goedegebure\n"
|
||||
" Duration: 00:10:34.53, start: 0.000000, bitrate: 10385 kb/s\n"
|
||||
" Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 3840x4320 [SAR 1:1 DAR 8:9], 9902 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:21:55.000000Z\n"
|
||||
" handler_name : GPAC ISO Video Handler\n"
|
||||
" Stream #0:1(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 160 kb/s (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:21:58.000000Z\n"
|
||||
" handler_name : GPAC ISO Audio Handler\n"
|
||||
" Stream #0:2(und): Audio: ac3 (ac-3 / 0x332D6361), 48000 Hz, 5.1(side), fltp, 320 kb/s (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:21:58.000000Z\n"
|
||||
" handler_name : GPAC ISO Audio Handler\n"
|
||||
" Side data:\n"
|
||||
" audio service type: main\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))\n"
|
||||
" Stream #0:2 -> #0:1 (ac3 (native) -> pcm_s16le (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" major_brand : isom\n"
|
||||
" minor_version : 1\n"
|
||||
" compatible_brands: isomavc1\n"
|
||||
" composer : Sacha Goedegebure\n"
|
||||
" title : Big Buck Bunny, Sunflower version\n"
|
||||
" artist : Blender Foundation 2008, Janus Bager Kristensen 2013\n"
|
||||
" comment : Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net\n"
|
||||
" genre : Animation\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0(und): Video: wrapped_avframe, yuv420p(progressive), 3840x4320 [SAR 1:1 DAR 8:9], q=2-31, 200 kb/s, 30 fps, 30 tbn, 30 tbc (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:21:55.000000Z\n"
|
||||
" handler_name : GPAC ISO Video Handler\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
" Stream #0:1(und): Audio: pcm_s16le, 48000 Hz, 5.1(side), s16, 4608 kb/s (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:21:58.000000Z\n"
|
||||
" handler_name : GPAC ISO Audio Handler\n"
|
||||
" encoder : Lavc58.18.100 pcm_s16le\n"
|
||||
" Side data:\n"
|
||||
" audio service type: main\n"
|
||||
"frame= 2798 fps= 85 q=-0.0 size=N/A time=00:01:33.33 bitrate=N/A speed=2.85x \n"];
|
||||
|
||||
MEDIA_INFORMATION_MP4_2 = [NSString stringWithFormat:
|
||||
@"Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_stereo_arcd.mp4':\n"
|
||||
" Metadata:\n"
|
||||
" major_brand : isom\n"
|
||||
" minor_version : 1\n"
|
||||
" compatible_brands: isomavc1\n"
|
||||
" creation_time : 2013-12-16T17:49:59.000000Z\n"
|
||||
" title : Big Buck Bunny, Sunflower version\n"
|
||||
" artist : Blender Foundation 2008, Janus Bager Kristensen 2013\n"
|
||||
" comment : Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net\n"
|
||||
" genre : Animation\n"
|
||||
" composer : Sacha Goedegebure\n"
|
||||
" Duration: 00:10:34.53, start: 0.000000, bitrate: 4474 kb/s\n"
|
||||
" Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 3992 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:49:59.000000Z\n"
|
||||
" handler_name : GPAC ISO Video Handler\n"
|
||||
" Stream #0:1(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 160 kb/s (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:50:04.000000Z\n"
|
||||
" handler_name : GPAC ISO Audio Handler\n"
|
||||
" Stream #0:2(und): Audio: ac3 (ac-3 / 0x332D6361), 48000 Hz, 5.1(side), fltp, 320 kb/s (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:50:04.000000Z\n"
|
||||
" handler_name : GPAC ISO Audio Handler\n"
|
||||
" Side data:\n"
|
||||
" audio service type: main\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))\n"
|
||||
" Stream #0:2 -> #0:1 (ac3 (native) -> pcm_s16le (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" major_brand : isom\n"
|
||||
" minor_version : 1\n"
|
||||
" compatible_brands: isomavc1\n"
|
||||
" composer : Sacha Goedegebure\n"
|
||||
" title : Big Buck Bunny, Sunflower version\n"
|
||||
" artist : Blender Foundation 2008, Janus Bager Kristensen 2013\n"
|
||||
" comment : Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net\n"
|
||||
" genre : Animation\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0(und): Video: wrapped_avframe, yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 30 fps, 30 tbn, 30 tbc (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:49:59.000000Z\n"
|
||||
" handler_name : GPAC ISO Video Handler\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
" Stream #0:1(und): Audio: pcm_s16le, 48000 Hz, 5.1(side), s16, 4608 kb/s (default)\n"
|
||||
" Metadata:\n"
|
||||
" creation_time : 2013-12-16T17:50:04.000000Z\n"
|
||||
" handler_name : GPAC ISO Audio Handler\n"
|
||||
" encoder : Lavc58.18.100 pcm_s16le\n"
|
||||
" Side data:\n"
|
||||
" audio service type: main\n"
|
||||
"frame=19036 fps=401 q=-0.0 Lsize=N/A time=00:10:34.60 bitrate=N/A speed=13.4x \n"
|
||||
"video:9964kB audio:356706kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
|
||||
MEDIA_INFORMATION_OGG = [NSString stringWithFormat:
|
||||
@"[theora @ 0x7fa30c026e00] 7 bits left in packet 82\n"
|
||||
"[ogg @ 0x7fa30c005e00] Broken file, keyframe not correctly marked.\n"
|
||||
"Input #0, ogg, from 'trailer_400p.ogg':\n"
|
||||
" Duration: 00:00:33.00, start: 0.000000, bitrate: 1057 kb/s\n"
|
||||
" Stream #0:0: Video: theora, yuv420p(bt470bg/bt470bg/bt709), 720x400, 25 fps, 25 tbr, 25 tbn, 25 tbc\n"
|
||||
" Metadata:\n"
|
||||
" ENCODER : ffmpeg2theora 0.19\n"
|
||||
" Stream #0:1: Audio: vorbis, 48000 Hz, stereo, fltp, 80 kb/s\n"
|
||||
" Metadata:\n"
|
||||
" ENCODER : ffmpeg2theora 0.19\n"
|
||||
"[theora @ 0x7fa30c1bd600] 7 bits left in packet 82\n"
|
||||
"Stream mapping:\n"
|
||||
" Stream #0:0 -> #0:0 (theora (native) -> wrapped_avframe (native))\n"
|
||||
" Stream #0:1 -> #0:1 (vorbis (native) -> pcm_s16le (native))\n"
|
||||
"Press [q] to stop, [?] for help\n"
|
||||
"Output #0, null, to 'pipe:':\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavf58.12.100\n"
|
||||
" Stream #0:0: Video: wrapped_avframe, yuv420p(progressive), 720x400, q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.18.100 wrapped_avframe\n"
|
||||
" Stream #0:1: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s\n"
|
||||
" Metadata:\n"
|
||||
" encoder : Lavc58.18.100 pcm_s16le\n"
|
||||
"[ogg @ 0x7fa30c005e00] Broken file, keyframe not correctly marked.\n"
|
||||
" Last message repeated 5 times\n"
|
||||
"frame= 813 fps=0.0 q=-0.0 Lsize=N/A time=00:00:33.01 bitrate=N/A speed= 234x \n"
|
||||
"video:426kB audio:6190kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"];
|
||||
}
|
||||
|
||||
void assertNumber(NSNumber *expected, NSNumber *real) {
|
||||
if (expected == nil) {
|
||||
assert(real == nil);
|
||||
} else {
|
||||
assert([expected isEqualToNumber:real]);
|
||||
}
|
||||
}
|
||||
|
||||
void assertString(NSString *expected, NSString *real) {
|
||||
if (expected == nil) {
|
||||
assert(real == nil);
|
||||
} else {
|
||||
assert([expected isEqualToString:real]);
|
||||
}
|
||||
}
|
||||
|
||||
void assertVideoStream(StreamInformation *stream, NSNumber *index, NSString *codec, NSString *fullCodec, NSString *format, NSString *fullFormat, NSNumber *width, NSNumber *height, NSString *sampleAspectRatio, NSString *displayAspectRatio, NSNumber *bitrate, NSString *averageFrameRate, NSString *realFrameRate, NSString *timeBase, NSString *codecTimeBase) {
|
||||
|
||||
assert(stream != nil);
|
||||
assertNumber(index, [stream getIndex]);
|
||||
assertString(@"video", [stream getType]);
|
||||
assertString(codec, [stream getCodec]);
|
||||
assertString(fullCodec, [stream getFullCodec]);
|
||||
|
||||
assertString(format, [stream getFormat]);
|
||||
assertString(fullFormat, [stream getFullFormat]);
|
||||
|
||||
assertNumber(width, [stream getWidth]);
|
||||
assertNumber(height, [stream getHeight]);
|
||||
assertString(sampleAspectRatio, [stream getSampleAspectRatio]);
|
||||
assertString(displayAspectRatio, [stream getDisplayAspectRatio]);
|
||||
|
||||
assertNumber(bitrate, [stream getBitrate]);
|
||||
assertString(averageFrameRate, [stream getAverageFrameRate]);
|
||||
assertString(realFrameRate, [stream getRealFrameRate]);
|
||||
assertString(timeBase, [stream getTimeBase]);
|
||||
assertString(codecTimeBase, [stream getCodecTimeBase]);
|
||||
}
|
||||
|
||||
void parseVideoStreamBlock(NSString *input, NSNumber *index, NSString *codec, NSString *fullCodec, NSString *format, NSString *fullFormat, NSNumber *width, NSNumber *height, NSString *sampleAspectRatio, NSString *displayAspectRatio, NSNumber *bitrate, NSString *averageFrameRate, NSString *realFrameRate, NSString *timeBase, NSString *codecTimeBase) {
|
||||
StreamInformation *stream = [MediaInformationParser parseStreamBlock:input];
|
||||
|
||||
assertVideoStream(stream, index, codec, fullCodec, format, fullFormat, width, height, sampleAspectRatio, displayAspectRatio, bitrate, averageFrameRate, realFrameRate, timeBase, codecTimeBase);
|
||||
}
|
||||
|
||||
void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *codec, NSString *fullCodec, NSNumber *sampleRate, NSString *channelLayout, NSString *sampleFormat, NSNumber *bitrate) {
|
||||
|
||||
assert(stream != nil);
|
||||
assertNumber(index, [stream getIndex]);
|
||||
assertString(@"audio", [stream getType]);
|
||||
assertString(codec, [stream getCodec]);
|
||||
assertString(fullCodec, [stream getFullCodec]);
|
||||
assertNumber(sampleRate, [stream getSampleRate]);
|
||||
assertString(channelLayout, [stream getChannelLayout]);
|
||||
assertString(sampleFormat, [stream getSampleFormat]);
|
||||
assertNumber(bitrate, [stream getBitrate]);
|
||||
}
|
||||
|
||||
void parseAudioStreamBlock(NSString *input, NSNumber *index, NSString *codec, NSString *fullCodec, NSNumber *sampleRate, NSString *channelLayout, NSString *sampleFormat, NSNumber *bitrate) {
|
||||
StreamInformation *stream = [MediaInformationParser parseStreamBlock:input];
|
||||
|
||||
assertAudioStream(stream, index, codec, fullCodec, sampleRate, channelLayout, sampleFormat, bitrate);
|
||||
}
|
||||
|
||||
void parseVideoDimensions(NSString *input, NSNumber *expectedWidth, NSNumber *expectedHeight) {
|
||||
void(^pair)(NSNumber **, NSNumber **) = [MediaInformationParser parseVideoDimensions:input];
|
||||
|
||||
NSNumber *width;
|
||||
NSNumber *height;
|
||||
pair(&width, &height);
|
||||
|
||||
assert(pair != nil);
|
||||
if (width == nil) {
|
||||
assert(expectedWidth == nil);
|
||||
} else {
|
||||
assert([width isEqualToNumber:expectedWidth]);
|
||||
}
|
||||
if (height == nil) {
|
||||
assert(expectedHeight == nil);
|
||||
} else {
|
||||
assert([height isEqualToNumber:expectedHeight]);
|
||||
}
|
||||
}
|
||||
|
||||
void parseDuration(NSString *input, NSNumber *expectedDuration) {
|
||||
NSNumber *duration = [MediaInformationParser parseDuration:input];
|
||||
|
||||
if (duration == nil) {
|
||||
assert(expectedDuration == nil);
|
||||
} else {
|
||||
assert([duration isEqualToNumber:expectedDuration]);
|
||||
}
|
||||
}
|
||||
|
||||
void parseStartTime(NSString *input, NSNumber *expectedStartTime) {
|
||||
NSNumber *startTime = [MediaInformationParser parseStartTime:input];
|
||||
|
||||
if (startTime == nil) {
|
||||
assert(expectedStartTime == nil);
|
||||
} else {
|
||||
assert([startTime isEqualToNumber:expectedStartTime]);
|
||||
}
|
||||
}
|
||||
|
||||
void parseDurationBlock(NSString *input, NSNumber *expectedDuration, NSNumber *expectedStartTime, NSNumber *expectedBitrate) {
|
||||
void(^trio)(NSNumber **, NSNumber **, NSNumber **) = [MediaInformationParser parseDurationBlock:input];
|
||||
|
||||
NSNumber *duration;
|
||||
NSNumber *startTime;
|
||||
NSNumber *bitrate;
|
||||
trio(&duration, &startTime, &bitrate);
|
||||
|
||||
assert(trio != nil);
|
||||
if (duration == nil) {
|
||||
assert(expectedDuration == nil);
|
||||
} else {
|
||||
assert([duration isEqualToNumber:expectedDuration]);
|
||||
}
|
||||
if (startTime == nil) {
|
||||
assert(expectedStartTime == nil);
|
||||
} else {
|
||||
assert([startTime isEqualToNumber:expectedStartTime]);
|
||||
}
|
||||
if (bitrate == nil) {
|
||||
assert(expectedBitrate == nil);
|
||||
} else {
|
||||
assert([bitrate isEqualToNumber:expectedBitrate]);
|
||||
}
|
||||
}
|
||||
|
||||
void parseMetadataBlock(NSString *input, NSString *expectedKey, NSString *expectedValue) {
|
||||
void(^pair)(NSString **, NSString **) = [MediaInformationParser parseMetadataBlock:input];
|
||||
|
||||
NSString *key;
|
||||
NSString *value;
|
||||
pair(&key, &value);
|
||||
|
||||
assert(pair != nil);
|
||||
assert(key != nil);
|
||||
assert(value != nil);
|
||||
assert([key isEqualToString:expectedKey]);
|
||||
assert([value isEqualToString:expectedValue]);
|
||||
}
|
||||
|
||||
void parseInputBlock(NSString *input, NSString *expectedFormat, NSString *expectedPath) {
|
||||
void(^pair)(NSString **, NSString **) = [MediaInformationParser parseInputBlock:input];
|
||||
|
||||
NSString *format;
|
||||
NSString *path;
|
||||
pair(&format, &path);
|
||||
|
||||
assert(pair != nil);
|
||||
if (format == nil) {
|
||||
assert(expectedFormat == nil);
|
||||
} else {
|
||||
assert([format isEqualToString:expectedFormat]);
|
||||
}
|
||||
if (path == nil) {
|
||||
assert(expectedPath == nil);
|
||||
} else {
|
||||
assert([path isEqualToString:expectedPath]);
|
||||
}
|
||||
}
|
||||
|
||||
void testParseVideoStream() {
|
||||
parseVideoStreamBlock(@" Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 2560x1708 [SAR 1:1 DAR 640:427], 25 tbr, 25 tbn, 25 tbc", [[NSNumber alloc] initWithInt:0], @"mjpeg", @"mjpeg", @"yuvj420p", @"yuvj420p(pc, bt470bg/unknown/unknown)", [[NSNumber alloc] initWithInt:2560], [[NSNumber alloc] initWithInt:1708], @"1:1", @"640:427", nil, nil, @"25", @"25", @"25");
|
||||
parseVideoStreamBlock(@" Stream #0:0: Video: gif, bgra, 420x236, 6 fps, 6 tbr, 100 tbn, 100 tbc", [[NSNumber alloc] initWithInt:0], @"gif", @"gif", @"bgra", @"bgra", [[NSNumber alloc] initWithInt:420], [[NSNumber alloc] initWithInt:236], nil, nil, nil, @"6", @"6", @"100", @"100");
|
||||
parseVideoStreamBlock(@" Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 7762 kb/s, 25 fps, 30 tbr, 15360 tbn, 60 tbc (default)", [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (main) (avc1 / 0x31637661)", @"yuv420p", @"yuv420p", [[NSNumber alloc] initWithInt:1280], [[NSNumber alloc] initWithInt:720], @"1:1", @"16:9", [[NSNumber alloc] initWithInt:7762], @"25", @"30", @"15360", @"60");
|
||||
parseVideoStreamBlock(@" Stream #0:0: Video: png, rgba(pc), 544x184, 25 tbr, 25 tbn, 25 tbc", [[NSNumber alloc] initWithInt:0], @"png", @"png", @"rgba", @"rgba(pc)", [[NSNumber alloc] initWithInt:544], [[NSNumber alloc] initWithInt:184], nil, nil, nil, nil, @"25", @"25", @"25");
|
||||
parseVideoStreamBlock(@" Stream #0:0: Video: h264 (Main), yuv420p(tv, bt709, progressive), 1920x1080, 25 fps, 25 tbr, 1200k tbn, 50 tbc", [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (main)", @"yuv420p", @"yuv420p(tv, bt709, progressive)", [[NSNumber alloc] initWithInt:1920], [[NSNumber alloc] initWithInt:1080], nil, nil, nil, @"25", @"25", @"1200k", @"50");
|
||||
parseVideoStreamBlock(@" Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 3840x4320 [SAR 1:1 DAR 8:9], 9902 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc (default)", [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (high) (avc1 / 0x31637661)", @"yuv420p", @"yuv420p", [[NSNumber alloc] initWithInt:3840], [[NSNumber alloc] initWithInt:4320], @"1:1", @"8:9", [[NSNumber alloc] initWithInt:9902], @"30", @"30", @"30k", @"60");
|
||||
parseVideoStreamBlock(@" Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 3992 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc (default)", [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (high) (avc1 / 0x31637661)", @"yuv420p", @"yuv420p", [[NSNumber alloc] initWithInt:1920], [[NSNumber alloc] initWithInt:1080], @"1:1", @"16:9", [[NSNumber alloc] initWithInt:3992], @"30", @"30", @"30k", @"60");
|
||||
parseVideoStreamBlock(@" Stream #0:0: Video: theora, yuv420p(bt470bg/bt470bg/bt709), 720x400, 25 fps, 25 tbr, 25 tbn, 25 tbc", [[NSNumber alloc] initWithInt:0], @"theora", @"theora", @"yuv420p", @"yuv420p(bt470bg/bt470bg/bt709)", [[NSNumber alloc] initWithInt:720], [[NSNumber alloc] initWithInt:400], nil, nil, nil, @"25", @"25", @"25", @"25");
|
||||
}
|
||||
|
||||
void testParseAudioStream() {
|
||||
parseAudioStreamBlock(@"Stream #0:0: Audio: adpcm_ms ([2][0][0][0] / 0x0002), 22050 Hz, stereo, s16, 176 kb/s", [[NSNumber alloc] initWithInt:0], @"adpcm_ms", @"adpcm_ms ([2][0][0][0] / 0x0002)", [[NSNumber alloc] initWithInt:22050], @"stereo", @"s16", [[NSNumber alloc] initWithInt:176]);
|
||||
parseAudioStreamBlock(@"Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, mono, s16, 705 kb/s",[[NSNumber alloc] initWithInt:0], @"pcm_s16le", @"pcm_s16le ([1][0][0][0] / 0x0001)", [[NSNumber alloc] initWithInt:44100], @"mono", @"s16", [[NSNumber alloc] initWithInt:705]);
|
||||
parseAudioStreamBlock(@"Stream #0:0: Audio: pcm_s24le ([1][0][0][0] / 0x0001), 48000 Hz, mono, s32 (24 bit), 1152 kb/s", [[NSNumber alloc] initWithInt:0], @"pcm_s24le", @"pcm_s24le ([1][0][0][0] / 0x0001)", [[NSNumber alloc] initWithInt:48000], @"mono", @"s32 (24 bit)", [[NSNumber alloc] initWithInt:1152]);
|
||||
parseAudioStreamBlock(@"Stream #0:0: Audio: mp3, 48000 Hz, stereo, fltp, 192 kb/s", [[NSNumber alloc] initWithInt:0], @"mp3", @"mp3", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:192]);
|
||||
parseAudioStreamBlock(@"Stream #0:0: Audio: vorbis, 44100 Hz, stereo, fltp, 128 kb/s", [[NSNumber alloc] initWithInt:0], @"vorbis", @"vorbis", [[NSNumber alloc] initWithInt:44100], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:128]);
|
||||
parseAudioStreamBlock(@"Stream #0:0: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 44100 Hz, stereo, u8, 705 kb/s", [[NSNumber alloc] initWithInt:0], @"pcm_u8", @"pcm_u8 ([1][0][0][0] / 0x0001)", [[NSNumber alloc] initWithInt:44100], @"stereo", @"u8", [[NSNumber alloc] initWithInt:705]);
|
||||
parseAudioStreamBlock(@"Stream #0:1(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 160 kb/s (default)", [[NSNumber alloc] initWithInt:1], @"mp3", @"mp3 (mp4a / 0x6134706d)", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:160]);
|
||||
parseAudioStreamBlock(@"Stream #0:2(und): Audio: ac3 (ac-3 / 0x332D6361), 48000 Hz, 5.1(side), fltp, 320 kb/s (default)", [[NSNumber alloc] initWithInt:2], @"ac3", @"ac3 (ac-3 / 0x332d6361)", [[NSNumber alloc] initWithInt:48000], @"5.1(side)", @"fltp", [[NSNumber alloc] initWithInt:320]);
|
||||
parseAudioStreamBlock(@"Stream #0:1(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 160 kb/s (default)", [[NSNumber alloc] initWithInt:1], @"mp3", @"mp3 (mp4a / 0x6134706d)", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:160]);
|
||||
parseAudioStreamBlock(@"Stream #0:2(und): Audio: ac3 (ac-3 / 0x332D6361), 48000 Hz, 5.1(side), fltp, 320 kb/s (default)", [[NSNumber alloc] initWithInt:2], @"ac3", @"ac3 (ac-3 / 0x332d6361)", [[NSNumber alloc] initWithInt:48000], @"5.1(side)", @"fltp", [[NSNumber alloc] initWithInt:320]);
|
||||
}
|
||||
|
||||
void testIndex() {
|
||||
assert(7 == [MediaInformationParser index:@"one:two:three:" of:@":" from:0 times:2]);
|
||||
assert(13 == [MediaInformationParser index:@"one:two:three:" of:@":" from:0 times:3]);
|
||||
assert(8 == [MediaInformationParser index:@"one::two::three::" of:@"::" from:0 times:2]);
|
||||
}
|
||||
|
||||
void testCount() {
|
||||
assert(3 == [MediaInformationParser count:@"one:two:three:" of:@":"]);
|
||||
assert(2 == [MediaInformationParser count:@"one,two:three,four" of:@","]);
|
||||
}
|
||||
|
||||
void testParseVideoStreamDisplayAspectRatio() {
|
||||
assert(nil == [MediaInformationParser parseVideoStreamDisplayAspectRatio:@""]);
|
||||
assert(nil == [MediaInformationParser parseVideoStreamDisplayAspectRatio:@"544x184"]);
|
||||
assert([@"640:427" isEqualToString:[MediaInformationParser parseVideoStreamDisplayAspectRatio:@"2560x1708 [SAR 1:1 DAR 640:427]"]]);
|
||||
assert([@"8:9" isEqualToString:[MediaInformationParser parseVideoStreamDisplayAspectRatio:@"3840x4320 [SAR 1:1 DAR 8:9]"]]);
|
||||
}
|
||||
|
||||
void testParseVideoStreamSampleAspectRatio() {
|
||||
assert(nil == [MediaInformationParser parseVideoStreamSampleAspectRatio:@""]);
|
||||
assert(nil == [MediaInformationParser parseVideoStreamSampleAspectRatio:@"544x184"]);
|
||||
assert([@"1:1" isEqualToString:[MediaInformationParser parseVideoStreamSampleAspectRatio:@"2560x1708 [SAR 1:1 DAR 640:427]"]]);
|
||||
assert([@"1:1" isEqualToString:[MediaInformationParser parseVideoStreamSampleAspectRatio:@"3840x4320 [SAR 1:1 DAR 8:9]"]]);
|
||||
}
|
||||
|
||||
void testParseVideoDimensions() {
|
||||
parseVideoDimensions(@"", nil, nil);
|
||||
parseVideoDimensions(@"544x184", [[NSNumber alloc] initWithInt:544], [[NSNumber alloc] initWithInt:184]);
|
||||
parseVideoDimensions(@"720x400", [[NSNumber alloc] initWithInt:720], [[NSNumber alloc] initWithInt:400]);
|
||||
parseVideoDimensions(@"2560x1708 [SAR 1:1 DAR 640:427]", [[NSNumber alloc] initWithInt:2560], [[NSNumber alloc] initWithInt:1708]);
|
||||
parseVideoDimensions(@"3840x4320 [SAR 1:1 DAR 8:9]", [[NSNumber alloc] initWithInt:3840], [[NSNumber alloc] initWithInt:4320]);
|
||||
}
|
||||
|
||||
void testParseAudioSampleRate() {
|
||||
assert([[[NSNumber alloc] initWithInt:44000] isEqualToNumber:[MediaInformationParser parseAudioStreamSampleRate:@"44000"]]);
|
||||
assert([[[NSNumber alloc] initWithInt:44000] isEqualToNumber:[MediaInformationParser parseAudioStreamSampleRate:@"44 khz"]]);
|
||||
assert([[[NSNumber alloc] initWithInt:44100] isEqualToNumber:[MediaInformationParser parseAudioStreamSampleRate:@"44100"]]);
|
||||
assert([[[NSNumber alloc] initWithInt:5000000] isEqualToNumber:[MediaInformationParser parseAudioStreamSampleRate:@"5 mhz"]]);
|
||||
}
|
||||
|
||||
void testParseAudioStreamType() {
|
||||
assert([@"video" isEqualToString:[MediaInformationParser parseStreamType:@"Video: theora"]]);
|
||||
assert([@"video" isEqualToString:[MediaInformationParser parseStreamType:@"Video: png"]]);
|
||||
assert([@"video" isEqualToString:[MediaInformationParser parseStreamType:@"Video: h264 (Main)"]]);
|
||||
assert([@"audio" isEqualToString:[MediaInformationParser parseStreamType:@"Audio: adpcm_ms ([2][0][0][0] / 0x0002)"]]);
|
||||
assert([@"audio" isEqualToString:[MediaInformationParser parseStreamType:@"Audio: mp3 (mp4a / 0x6134706D)"]]);
|
||||
assert([@"audio" isEqualToString:[MediaInformationParser parseStreamType:@"Audio: pcm_u8 ([1][0][0][0] / 0x0001)"]]);
|
||||
}
|
||||
|
||||
void testParseStreamCodec() {
|
||||
assert([@"theora" isEqualToString:[MediaInformationParser parseStreamCodec:@"Video: theora"]]);
|
||||
assert([@"png" isEqualToString:[MediaInformationParser parseStreamCodec:@"Video: png"]]);
|
||||
assert([@"h264" isEqualToString:[MediaInformationParser parseStreamCodec:@"Video: h264 (Main)"]]);
|
||||
assert([@"adpcm_ms" isEqualToString:[MediaInformationParser parseStreamCodec:@"Audio: adpcm_ms ([2][0][0][0] / 0x0002)"]]);
|
||||
assert([@"mp3" isEqualToString:[MediaInformationParser parseStreamCodec:@"Audio: mp3 (mp4a / 0x6134706D)"]]);
|
||||
assert([@"pcm_u8" isEqualToString:[MediaInformationParser parseStreamCodec:@"Audio: pcm_u8 ([1][0][0][0] / 0x0001)"]]);
|
||||
}
|
||||
|
||||
void testParseStreamFullCodec() {
|
||||
assert([@"theora" isEqualToString:[MediaInformationParser parseStreamFullCodec:@"Video: theora"]]);
|
||||
assert([@"png" isEqualToString:[MediaInformationParser parseStreamFullCodec:@"Video: png"]]);
|
||||
assert([@"h264 (main)" isEqualToString:[MediaInformationParser parseStreamFullCodec:@"Video: h264 (Main)"]]);
|
||||
assert([@"adpcm_ms ([2][0][0][0] / 0x0002)" isEqualToString:[MediaInformationParser parseStreamFullCodec:@"Audio: adpcm_ms ([2][0][0][0] / 0x0002)"]]);
|
||||
assert([@"mp3 (mp4a / 0x6134706d)" isEqualToString:[MediaInformationParser parseStreamFullCodec:@"Audio: mp3 (mp4a / 0x6134706D)"]]);
|
||||
assert([@"pcm_u8 ([1][0][0][0] / 0x0001)" isEqualToString:[MediaInformationParser parseStreamFullCodec:@"Audio: pcm_u8 ([1][0][0][0] / 0x0001)"]]);
|
||||
}
|
||||
|
||||
void testParseStreamIndex() {
|
||||
assert([[[NSNumber alloc] initWithInt: 0] isEqualToNumber:[MediaInformationParser parseStreamIndex:@"Stream #0:0(und): Audio"]]);
|
||||
assert([[[NSNumber alloc] initWithInt: 1] isEqualToNumber:[MediaInformationParser parseStreamIndex:@"Stream #0:1(und): Video"]]);
|
||||
assert([[[NSNumber alloc] initWithInt: 2] isEqualToNumber:[MediaInformationParser parseStreamIndex:@"Stream #0:2(und): Audio"]]);
|
||||
assert([[[NSNumber alloc] initWithInt: 0] isEqualToNumber:[MediaInformationParser parseStreamIndex:@"Stream #0:0: Video"]]);
|
||||
assert([[[NSNumber alloc] initWithInt: 1] isEqualToNumber:[MediaInformationParser parseStreamIndex:@"Stream #0:1: Audio"]]);
|
||||
assert([[[NSNumber alloc] initWithInt: 2] isEqualToNumber:[MediaInformationParser parseStreamIndex:@"Stream #0:2: Video"]]);
|
||||
}
|
||||
|
||||
void testParseDuration() {
|
||||
parseDuration(nil, nil);
|
||||
parseDuration(@"", nil);
|
||||
parseDuration(@"N/A", nil);
|
||||
parseDuration(@"00:03:33.24", [[NSNumber alloc] initWithInt: 213240]);
|
||||
parseDuration(@"00:10:34.53", [[NSNumber alloc] initWithInt: 634530]);
|
||||
parseDuration(@"00:00:00.04", [[NSNumber alloc] initWithInt: 40]);
|
||||
parseDuration(@"00:00:15.00", [[NSNumber alloc] initWithInt: 15000]);
|
||||
}
|
||||
|
||||
void testParseStartTime() {
|
||||
parseStartTime(nil, nil);
|
||||
parseStartTime(@"", nil);
|
||||
parseStartTime(@"N/A", nil);
|
||||
parseStartTime(@"0.000000", [[NSNumber alloc] initWithInt:0]);
|
||||
parseStartTime(@"10.003000", [[NSNumber alloc] initWithInt:10003]);
|
||||
parseStartTime(@"324.000000", [[NSNumber alloc] initWithInt:324000]);
|
||||
parseStartTime(@"-4.000000", [[NSNumber alloc] initWithInt:-4000]);
|
||||
parseStartTime(@"14.00030", [[NSNumber alloc] initWithInt:14001]);
|
||||
parseStartTime(@"14.00080", [[NSNumber alloc] initWithInt:14001]);
|
||||
}
|
||||
|
||||
void testParseDurationBlock() {
|
||||
parseDurationBlock(@" Duration: 00:03:33.24, start: 0.000000, bitrate: 320 kb/s", [[NSNumber alloc] initWithInt:213240], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:320]);
|
||||
parseDurationBlock(@" Duration: 00:00:00.04, start: 0.000000, bitrate: 391187 kb/s", [[NSNumber alloc] initWithInt:40], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:391187]);
|
||||
parseDurationBlock(@" Duration: N/A, bitrate: N/A", nil, nil, nil);
|
||||
parseDurationBlock(@" Duration: 00:00:15.00, start: 0.000000, bitrate: 7764 kb/s", [[NSNumber alloc] initWithInt:15000], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:7764]);
|
||||
parseDurationBlock(@" Duration: 00:10:34.53, start: 0.000000, bitrate: 4474 kb/s", [[NSNumber alloc] initWithInt:634530], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:4474]);
|
||||
}
|
||||
|
||||
void testParseInputBlock() {
|
||||
parseInputBlock(@"Input #0,", nil, nil);
|
||||
parseInputBlock(@"Input #0, ogg, from 'trailer_400p.ogg':", @"ogg", @"trailer_400p.ogg");
|
||||
parseInputBlock(@"Input #0, mp3, from 'beethoven_-_symphony_no_9.mp3':", @"mp3", @"beethoven_-_symphony_no_9.mp3");
|
||||
parseInputBlock(@"Input #0, image2, from '/data/user/0/com.arthenica.mobileffmpeg.test/cache/colosseum.jpg':", @"image2", @"/data/user/0/com.arthenica.mobileffmpeg.test/cache/colosseum.jpg");
|
||||
parseInputBlock(@"Input #0, gif, from 'advanced_zoom_in_and_pan_with_fade_in_out.gif':", @"gif", @"advanced_zoom_in_and_pan_with_fade_in_out.gif");
|
||||
parseInputBlock(@"Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'transition_rotate.mp4':", @"mov,mp4,m4a,3gp,3g2,mj2", @"transition_rotate.mp4");
|
||||
parseInputBlock(@"Input #0, png_pipe, from 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png':", @"png_pipe", @"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png");
|
||||
}
|
||||
|
||||
void testParseMetadataBlock() {
|
||||
parseMetadataBlock(@" ENCODER:", @"ENCODER", @"");
|
||||
parseMetadataBlock(@" ENCODER:ffmpeg2theora 0.19", @"ENCODER", @"ffmpeg2theora 0.19");
|
||||
parseMetadataBlock(@" ENCODER : ffmpeg2theora 0.19", @"ENCODER", @"ffmpeg2theora 0.19");
|
||||
parseMetadataBlock(@" creation_time : 2013-12-16T17:50:04.000000Z", @"creation_time", @"2013-12-16T17:50:04.000000Z");
|
||||
parseMetadataBlock(@" handler_name : GPAC ISO Audio Handler", @"handler_name", @"GPAC ISO Audio Handler");
|
||||
parseMetadataBlock(@" comment : Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net", @"comment", @"Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net");
|
||||
parseMetadataBlock(@" minor_version : 1", @"minor_version", @"1");
|
||||
parseMetadataBlock(@" encoder : Lavf58.12.100", @"encoder", @"Lavf58.12.100");
|
||||
parseMetadataBlock(@" title : Planet X", @"title", @"Planet X");
|
||||
parseMetadataBlock(@" compatible_brands: isomiso2avc1mp41", @"compatible_brands", @"isomiso2avc1mp41");
|
||||
}
|
||||
|
||||
void assertNotNull(NSObject *object) {
|
||||
assert(object != nil);
|
||||
}
|
||||
|
||||
void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedPath) {
|
||||
NSString *format = [mediaInformation getFormat];
|
||||
NSString *path = [mediaInformation getPath];
|
||||
if (format == nil) {
|
||||
assert(expectedFormat == nil);
|
||||
} else {
|
||||
assert([format isEqualToString:expectedFormat]);
|
||||
}
|
||||
if (path == nil) {
|
||||
assert(expectedPath == nil);
|
||||
} else {
|
||||
assert([path isEqualToString:expectedPath]);
|
||||
}
|
||||
}
|
||||
|
||||
void assertMediaDuration(MediaInformation *mediaInformation, NSNumber *expectedDuration, NSNumber *expectedStartTime, NSNumber *expectedBitrate) {
|
||||
NSNumber *duration = [mediaInformation getDuration];
|
||||
NSNumber *startTime = [mediaInformation getStartTime];
|
||||
NSNumber *bitrate = [mediaInformation getBitrate];
|
||||
|
||||
if (duration == nil) {
|
||||
assert(expectedDuration == nil);
|
||||
} else {
|
||||
assert([duration isEqualToNumber:expectedDuration]);
|
||||
}
|
||||
if (startTime == nil) {
|
||||
assert(expectedStartTime == nil);
|
||||
} else {
|
||||
assert([startTime isEqualToNumber:expectedStartTime]);
|
||||
}
|
||||
if (bitrate == nil) {
|
||||
assert(expectedBitrate == nil);
|
||||
} else {
|
||||
assert([bitrate isEqualToNumber:expectedBitrate]);
|
||||
}
|
||||
}
|
||||
|
||||
void testMediaInformationMp3() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_MP3];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"mp3", @"beethoven_-_symphony_no_9.mp3");
|
||||
assertMediaDuration(mediaInformation, [[NSNumber alloc] initWithInt: 213240], [[NSNumber alloc] initWithInt: 0], [[NSNumber alloc] initWithInt: 320]);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(1 == [streams count]);
|
||||
|
||||
assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"mp3", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:320]);
|
||||
}
|
||||
|
||||
void testMediaInformationJpg() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_JPG];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"image2", @"/data/user/0/com.arthenica.mobileffmpeg.test/cache/colosseum.jpg");
|
||||
assertMediaDuration(mediaInformation, [[NSNumber alloc] initWithInt:40], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:391187]);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(1 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mjpeg", @"mjpeg", @"yuvj420p", @"yuvj420p(pc, bt470bg/unknown/unknown)", [[NSNumber alloc] initWithInt:2560], [[NSNumber alloc] initWithInt:1708], @"1:1", @"640:427", nil, nil, @"25", @"25", @"25");
|
||||
}
|
||||
|
||||
void testMediaInformationGif() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_GIF];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"gif", @"advanced_zoom_in_and_pan_with_fade_in_out.gif");
|
||||
assertMediaDuration(mediaInformation, nil, nil, nil);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(1 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"gif", @"gif", @"bgra", @"bgra", [[NSNumber alloc] initWithInt:420], [[NSNumber alloc] initWithInt:236], nil, nil, nil, @"6", @"6", @"100", @"100");
|
||||
}
|
||||
|
||||
void testMediaInformationH264() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_H264];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"mov,mp4,m4a,3gp,3g2,mj2", @"transition_rotate.mp4");
|
||||
assertMediaDuration(mediaInformation, [[NSNumber alloc] initWithInt:15000], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:7764]);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(1 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (main) (avc1 / 0x31637661)", @"yuv420p", @"yuv420p", [[NSNumber alloc] initWithInt:1280], [[NSNumber alloc] initWithInt:720], @"1:1", @"16:9", [[NSNumber alloc] initWithInt:7762], @"25", @"30", @"15360", @"60");
|
||||
}
|
||||
|
||||
void testMediaInformationPng() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_PNG];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"png_pipe", @"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png");
|
||||
assertMediaDuration(mediaInformation, nil, nil, nil);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(1 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"png", @"png", @"rgba", @"rgba(pc)", [[NSNumber alloc] initWithInt:544], [[NSNumber alloc] initWithInt:184], nil, nil, nil, nil, @"25", @"25", @"25");
|
||||
}
|
||||
|
||||
void testMediaInformationH2642() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_H264_2];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"h264", @"test.h264");
|
||||
assertMediaDuration(mediaInformation, nil, nil, nil);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(1 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (main)", @"yuv420p", @"yuv420p(tv, bt709, progressive)", [[NSNumber alloc] initWithInt:1920], [[NSNumber alloc] initWithInt:1080], nil, nil, nil, @"25", @"25", @"1200k", @"50");
|
||||
}
|
||||
|
||||
void testMediaInformationMp4() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_MP4];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"mov,mp4,m4a,3gp,3g2,mj2", @"http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_2160p_30fps_stereo_abl.mp4");
|
||||
assertMediaDuration(mediaInformation, [[NSNumber alloc] initWithInt:634530], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:10385]);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(3 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (high) (avc1 / 0x31637661)", @"yuv420p", @"yuv420p", [[NSNumber alloc] initWithInt:3840], [[NSNumber alloc] initWithInt:4320], @"1:1", @"8:9", [[NSNumber alloc] initWithInt:9902], @"30", @"30", @"30k", @"60");
|
||||
assertAudioStream([streams objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"mp3", @"mp3 (mp4a / 0x6134706d)", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:160]);
|
||||
assertAudioStream([streams objectAtIndex:2], [[NSNumber alloc] initWithInt:2], @"ac3", @"ac3 (ac-3 / 0x332d6361)", [[NSNumber alloc] initWithInt:48000], @"5.1(side)", @"fltp", [[NSNumber alloc] initWithInt:320]);
|
||||
}
|
||||
|
||||
void testMediaInformationMp42() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_MP4_2];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"mov,mp4,m4a,3gp,3g2,mj2", @"http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_stereo_arcd.mp4");
|
||||
assertMediaDuration(mediaInformation, [[NSNumber alloc] initWithInt:634530], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:4474]);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(3 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"h264", @"h264 (high) (avc1 / 0x31637661)", @"yuv420p", @"yuv420p", [[NSNumber alloc] initWithInt:1920], [[NSNumber alloc] initWithInt:1080], @"1:1", @"16:9", [[NSNumber alloc] initWithInt:3992], @"30", @"30", @"30k", @"60");
|
||||
assertAudioStream([streams objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"mp3", @"mp3 (mp4a / 0x6134706d)", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:160]);
|
||||
assertAudioStream([streams objectAtIndex:2], [[NSNumber alloc] initWithInt:2], @"ac3", @"ac3 (ac-3 / 0x332d6361)", [[NSNumber alloc] initWithInt:48000], @"5.1(side)", @"fltp", [[NSNumber alloc] initWithInt:320]);
|
||||
}
|
||||
|
||||
void testMediaInformationOgg() {
|
||||
MediaInformation *mediaInformation = [MediaInformationParser from:MEDIA_INFORMATION_OGG];
|
||||
|
||||
assertNotNull(mediaInformation);
|
||||
assertMediaInput(mediaInformation, @"ogg", @"trailer_400p.ogg");
|
||||
assertMediaDuration(mediaInformation, [[NSNumber alloc] initWithInt:33000], [[NSNumber alloc] initWithInt:0], [[NSNumber alloc] initWithInt:1057]);
|
||||
|
||||
NSArray *streams = [mediaInformation getStreams];
|
||||
assertNotNull(streams);
|
||||
assert(2 == [streams count]);
|
||||
|
||||
assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"theora", @"theora", @"yuv420p", @"yuv420p(bt470bg/bt470bg/bt709)", [[NSNumber alloc] initWithInt:720], [[NSNumber alloc] initWithInt:400], nil, nil, nil, @"25", @"25", @"25", @"25");
|
||||
assertAudioStream([streams objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"vorbis", @"vorbis", [[NSNumber alloc] initWithInt:48000], @"stereo", @"fltp", [[NSNumber alloc] initWithInt:80]);
|
||||
}
|
||||
|
||||
/**
|
||||
* All parsing tests are initiated from this method
|
||||
*/
|
||||
void runMediaInformationParserTests() {
|
||||
|
||||
initTests();
|
||||
|
||||
testParseMetadataBlock();
|
||||
testParseInputBlock();
|
||||
|
||||
testParseDurationBlock();
|
||||
testParseStartTime();
|
||||
testParseDuration();
|
||||
|
||||
testParseStreamIndex();
|
||||
testParseStreamFullCodec();
|
||||
testParseStreamCodec();
|
||||
|
||||
testParseAudioStreamType();
|
||||
testParseAudioSampleRate();
|
||||
testParseVideoDimensions();
|
||||
|
||||
testParseVideoStreamSampleAspectRatio();
|
||||
testParseVideoStreamDisplayAspectRatio();
|
||||
|
||||
testCount();
|
||||
testIndex();
|
||||
|
||||
testParseAudioStream();
|
||||
testParseVideoStream();
|
||||
|
||||
testMediaInformationMp3();
|
||||
testMediaInformationJpg();
|
||||
testMediaInformationGif();
|
||||
testMediaInformationH264();
|
||||
testMediaInformationPng();
|
||||
testMediaInformationH2642();
|
||||
testMediaInformationMp4();
|
||||
testMediaInformationMp42();
|
||||
testMediaInformationOgg();
|
||||
|
||||
|
||||
NSLog(@"MediaInformationParserTests passed.");
|
||||
}
|
||||
@@ -20,10 +20,16 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "MediaInformationParserTests.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
|
||||
// RUN UNIT TESTS BEFORE STARTING THE APPLICATION
|
||||
runMediaInformationParserTests();
|
||||
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user