├── encoder ├── vp8Encoder.cpp ├── subdir.mk ├── vp8Encoder.h ├── IEncoder.h ├── EncoderFactory.h ├── ffmpegAACEncoder.h ├── AbstractAudioEncoder.cpp ├── AbstractAudioEncoder.h ├── AbstractEncoder.cpp ├── AbstractVideoEncoder.cpp ├── AbstractEncoder.h ├── x264Encoder.h ├── ffmpegAACEncoder.cpp ├── AbstractVideoEncoder.h ├── EncoderFactory.cpp └── x264Encoder.cpp ├── makefile ├── subdir.mk ├── mpdgenerator ├── subdir.mk ├── MPDGenerator.h └── MPDGenerator.cpp ├── multiplexer ├── subdir.mk ├── IMultiplexer.h ├── MP4BoxMultiplexer.h ├── AbstractMultiplexer.cpp ├── AbstractMultiplexer.h └── MP4BoxMultiplexer.cpp ├── DASHEncoder_howto_compile.txt ├── DASHHelper.h ├── DASHEncoder.config ├── README.md ├── AnyOption.h ├── DASHEncoder.cpp └── AnyOption.cpp /encoder/vp8Encoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * vp8Encoder.cpp 3 | * 4 | * Created on: May 5, 2011 5 | * Author: stefan 6 | */ 7 | 8 | #include "vp8Encoder.h" 9 | 10 | 11 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | RM := rm -rf 4 | 5 | USER_OBJS := 6 | 7 | LIBS := 8 | 9 | SUBDIRS := \ 10 | multiplexer \ 11 | mpdgenerator \ 12 | encoder \ 13 | 14 | -include subdir.mk 15 | -include multiplexer/subdir.mk 16 | -include mpdgenerator/subdir.mk 17 | -include encoder/subdir.mk 18 | 19 | 20 | # Add inputs and outputs from these tool invocations to the build variables 21 | 22 | # All Target 23 | all: DASHEncoder 24 | 25 | # Tool invocations 26 | DASHEncoder: $(OBJS) $(USER_OBJS) 27 | @echo 'Building target: $@' 28 | @echo 'Invoking: GCC C++ Linker' 29 | g++ -o"DASHEncoder" $(OBJS) $(USER_OBJS) $(LIBS) 30 | @echo 'Finished building target: $@' 31 | @echo ' ' 32 | 33 | # Other Targets 34 | clean: 35 | -$(RM) $(OBJS)$(C++_DEPS)$(C_DEPS)$(CC_DEPS)$(CPP_DEPS)$(EXECUTABLES)$(CXX_DEPS)$(C_UPPER_DEPS) DASHEncoder 36 | -@echo ' ' 37 | -------------------------------------------------------------------------------- /subdir.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | # Add inputs and outputs from these tool invocations to the build variables 6 | CPP_SRCS += \ 7 | ./AnyOption.cpp \ 8 | ./DASHEncoder.cpp 9 | 10 | OBJS += \ 11 | ./AnyOption.o \ 12 | ./DASHEncoder.o 13 | 14 | CPP_DEPS += \ 15 | ./AnyOption.d \ 16 | ./DASHEncoder.d 17 | 18 | 19 | # Each subdirectory must supply rules for building sources it contributes 20 | %.o: ./%.cpp 21 | @echo 'Building file: $<' 22 | @echo 'Invoking: GCC C++ Compiler' 23 | g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<" 24 | @echo 'Finished building: $<' 25 | @echo ' ' 26 | 27 | 28 | -------------------------------------------------------------------------------- /mpdgenerator/subdir.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | # Add inputs and outputs from these tool invocations to the build variables 6 | CPP_SRCS += \ 7 | ./mpdgenerator/MPDGenerator.cpp 8 | 9 | OBJS += \ 10 | ./mpdgenerator/MPDGenerator.o 11 | 12 | CPP_DEPS += \ 13 | ./mpdgenerator/MPDGenerator.d 14 | 15 | 16 | # Each subdirectory must supply rules for building sources it contributes 17 | mpdgenerator/%.o: ./mpdgenerator/%.cpp 18 | @echo 'Building file: $<' 19 | @echo 'Invoking: GCC C++ Compiler' 20 | g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<" 21 | @echo 'Finished building: $<' 22 | @echo ' ' 23 | 24 | 25 | -------------------------------------------------------------------------------- /multiplexer/subdir.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | # Add inputs and outputs from these tool invocations to the build variables 6 | CPP_SRCS += \ 7 | ./multiplexer/AbstractMultiplexer.cpp \ 8 | ./multiplexer/MP4BoxMultiplexer.cpp 9 | 10 | OBJS += \ 11 | ./multiplexer/AbstractMultiplexer.o \ 12 | ./multiplexer/MP4BoxMultiplexer.o 13 | 14 | CPP_DEPS += \ 15 | ./multiplexer/AbstractMultiplexer.d \ 16 | ./multiplexer/MP4BoxMultiplexer.d 17 | 18 | 19 | # Each subdirectory must supply rules for building sources it contributes 20 | multiplexer/%.o: ./multiplexer/%.cpp 21 | @echo 'Building file: $<' 22 | @echo 'Invoking: GCC C++ Compiler' 23 | g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<" 24 | @echo 'Finished building: $<' 25 | @echo ' ' 26 | 27 | 28 | -------------------------------------------------------------------------------- /DASHEncoder_howto_compile.txt: -------------------------------------------------------------------------------- 1 | DASHEncoder - How to Install: 2 | ============================== 3 | 4 | Dependencies: 5 | 6 | * x264: use a version with scaling enabled. To be sure, get the latest version from the x264 git repository and compile it by your own. 7 | 8 | * MP4Box: ATTENTION: use revision 3744 of the gpac code! 9 | Command: svn co https://gpac.svn.sourceforge.net/svnroot/gpac/trunk/gpac@3744 gpac 10 | use the actual version from the SVN repository of GPAC (this will support dash multiplexing) 11 | http://gpac.wp.institut-telecom.fr/2011/04/20/compiling-gpac-on-ubuntu/ 12 | 13 | * ffmepg (optional): if you use other input source formats than YUV, use ffmpeg for the pipe to x264 14 | 15 | * MySQL: No need any more, it's disabled in this version 16 | 17 | Installation: 18 | * Get the actual version from the git repository 19 | * run: make 20 | * Finished! 21 | 22 | Run: 23 | * Edit the paramters of the example config file 24 | * run: ./DASHEncoder 25 | 26 | -------------------------------------------------------------------------------- /encoder/subdir.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | # Add inputs and outputs from these tool invocations to the build variables 6 | CPP_SRCS += \ 7 | ./encoder/AbstractAudioEncoder.cpp \ 8 | ./encoder/AbstractEncoder.cpp \ 9 | ./encoder/AbstractVideoEncoder.cpp \ 10 | ./encoder/EncoderFactory.cpp \ 11 | ./encoder/ffmpegAACEncoder.cpp \ 12 | ./encoder/vp8Encoder.cpp \ 13 | ./encoder/x264Encoder.cpp 14 | 15 | OBJS += \ 16 | ./encoder/AbstractAudioEncoder.o \ 17 | ./encoder/AbstractEncoder.o \ 18 | ./encoder/AbstractVideoEncoder.o \ 19 | ./encoder/EncoderFactory.o \ 20 | ./encoder/ffmpegAACEncoder.o \ 21 | ./encoder/vp8Encoder.o \ 22 | ./encoder/x264Encoder.o 23 | 24 | CPP_DEPS += \ 25 | ./encoder/AbstractAudioEncoder.d \ 26 | ./encoder/AbstractEncoder.d \ 27 | ./encoder/AbstractVideoEncoder.d \ 28 | ./encoder/EncoderFactory.d \ 29 | ./encoder/ffmpegAACEncoder.d \ 30 | ./encoder/vp8Encoder.d \ 31 | ./encoder/x264Encoder.d 32 | 33 | 34 | # Each subdirectory must supply rules for building sources it contributes 35 | encoder/%.o: ./encoder/%.cpp 36 | @echo 'Building file: $<' 37 | @echo 'Invoking: GCC C++ Compiler' 38 | g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<" 39 | @echo 'Finished building: $<' 40 | @echo ' ' 41 | 42 | 43 | -------------------------------------------------------------------------------- /encoder/vp8Encoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vp8Encoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | #ifndef VP8ENCODER_H_ 25 | #define VP8ENCODER_H_ 26 | 27 | #include "AbstractVideoEncoder.h" 28 | 29 | class vp8Encoder: public AbstractVideoEncoder 30 | { 31 | public: 32 | 33 | std::string encode (std::string input); 34 | std::string encode (); 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /multiplexer/IMultiplexer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IMultiplexer.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef IMULTIPLEXER_H_ 26 | #define IMULTIPLEXER_H_ 27 | 28 | 29 | 30 | #include 31 | 32 | class IMultiplexer 33 | { 34 | public: 35 | virtual std::string multiplex (std::string input) = 0; 36 | virtual std::string multiplex () = 0; 37 | }; 38 | 39 | #endif /* IMULTIPLEXER_H_ */ 40 | -------------------------------------------------------------------------------- /DASHHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DASHHelper.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | #ifndef DASHHELPER_H_ 25 | #define DASHHELPER_H_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | class DASHHelper 33 | { 34 | public: 35 | static std::string itos (int i){ 36 | std::stringstream out; 37 | out << i; 38 | return out.str(); 39 | } 40 | }; 41 | 42 | #endif /* DASHHELPER_H_ */ 43 | -------------------------------------------------------------------------------- /encoder/IEncoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IEncoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | 26 | #ifndef IENCODER_H_ 27 | #define IENCODER_H_ 28 | 29 | #include 30 | 31 | class IEncoder 32 | { 33 | public: 34 | enum EncoderType 35 | { 36 | x264, 37 | vp8, 38 | ffmpegAAC 39 | }; 40 | 41 | virtual std::string encode (std::string input) = 0; 42 | virtual std::string encode () = 0; 43 | }; 44 | 45 | #endif /* IENCODER_H_ */ 46 | -------------------------------------------------------------------------------- /encoder/EncoderFactory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EncoderFactory.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef ENCODERFACTORY_H_ 26 | #define ENCODERFACTORY_H_ 27 | 28 | #include "../AnyOption.h" 29 | #include "IEncoder.h" 30 | #include "vp8Encoder.h" 31 | #include "x264Encoder.h" 32 | #include "ffmpegAACEncoder.h" 33 | 34 | class EncoderFactory 35 | { 36 | public: 37 | EncoderFactory(); 38 | virtual ~EncoderFactory(); 39 | 40 | IEncoder* getEncoder (AnyOption* opt, IEncoder::EncoderType type); 41 | }; 42 | 43 | #endif /* ENCODERFACTORY_H_ */ 44 | -------------------------------------------------------------------------------- /encoder/ffmpegAACEncoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ffmpegAACEncoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef FFMPEGAACENCODER_H_ 26 | #define FFMPEGAACENCODER_H_ 27 | 28 | #include "AbstractAudioEncoder.h" 29 | 30 | class ffmpegAACEncoder: public AbstractAudioEncoder 31 | { 32 | private: 33 | std::string codec; 34 | 35 | public: 36 | 37 | std::string encode (std::string input); 38 | std::string encode (); 39 | 40 | void setCodec (std::string c); 41 | std::string getCodec (); 42 | }; 43 | 44 | #endif /* FFMPEGAACENCODER_H_ */ 45 | -------------------------------------------------------------------------------- /mpdgenerator/MPDGenerator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MPDGnerator.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | #ifndef MPDGENERATOR_H_ 25 | #define MPDGENERATOR_H_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | class MPDGenerator 33 | { 34 | std::string finalMPDhead; 35 | std::string finalMPDbody; 36 | std::string finalMPDfoot; 37 | std::string version; 38 | 39 | public: 40 | MPDGenerator(); 41 | virtual ~MPDGenerator(); 42 | 43 | void appendMPDbody(std::string s); 44 | std::string getMPD(); 45 | }; 46 | 47 | #endif /* MPDGENERATOR_H_ */ 48 | -------------------------------------------------------------------------------- /encoder/AbstractAudioEncoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractAudioEncoder.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "AbstractAudioEncoder.h" 26 | 27 | AbstractAudioEncoder::AbstractAudioEncoder() 28 | { 29 | // TODO Auto-generated constructor stub 30 | 31 | } 32 | 33 | AbstractAudioEncoder::~AbstractAudioEncoder() 34 | { 35 | // TODO Auto-generated destructor stub 36 | } 37 | void AbstractAudioEncoder::setChannels(int c){ 38 | this->channels = c; 39 | } 40 | int AbstractAudioEncoder::getChannels(){ 41 | return this->channels; 42 | } 43 | void AbstractAudioEncoder::setSamplingRate(int r){ 44 | this->srate = r; 45 | } 46 | int AbstractAudioEncoder::getSamplingRate(){ 47 | return this->srate; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /multiplexer/MP4BoxMultiplexer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MP4BoxMultiplexer.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef MP4BOXMULTIPLEXER_H_ 26 | #define MP4BOXMULTIPLEXER_H_ 27 | 28 | #include 29 | 30 | #include "AbstractMultiplexer.h" 31 | 32 | 33 | class MP4BoxMultiplexer : public AbstractMultiplexer 34 | { 35 | public: 36 | MP4BoxMultiplexer(); 37 | ~MP4BoxMultiplexer(); 38 | 39 | std::string multiplex (std::string input); 40 | std::string multiplex (); 41 | std::string unSegment (std::string input); 42 | int fileSize (const char* sFileName); 43 | }; 44 | 45 | #endif /* MP4BOXMULTIPLEXER_H_ */ 46 | -------------------------------------------------------------------------------- /encoder/AbstractAudioEncoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractAudioEncoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef ABSTRACTAUDIOENCODER_H_ 26 | #define ABSTRACTAUDIOENCODER_H_ 27 | 28 | #include "AbstractEncoder.h" 29 | 30 | class AbstractAudioEncoder: public AbstractEncoder 31 | { 32 | protected: 33 | 34 | int channels; 35 | int srate; 36 | 37 | 38 | public: 39 | AbstractAudioEncoder(); 40 | virtual ~AbstractAudioEncoder(); 41 | 42 | virtual std::string encode(std::string) =0; 43 | virtual std::string encode() =0; 44 | 45 | void setChannels(int c); 46 | int getChannels(); 47 | void setSamplingRate(int srate); 48 | int getSamplingRate(); 49 | 50 | }; 51 | 52 | #endif /* ABSTRACTAUDIOENCODER_H_ */ 53 | -------------------------------------------------------------------------------- /encoder/AbstractEncoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractEncoder.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "AbstractEncoder.h" 26 | 27 | AbstractEncoder::AbstractEncoder() 28 | { 29 | // TODO Auto-generated constructor stub 30 | 31 | } 32 | 33 | AbstractEncoder::~AbstractEncoder() 34 | { 35 | // TODO Auto-generated destructor stub 36 | } 37 | void AbstractEncoder::setBitrate (int br){ 38 | this->bitrate = br; 39 | } 40 | int AbstractEncoder::getBitrate (){ 41 | return this->bitrate; 42 | } 43 | void AbstractEncoder::setOutputDir (std::string out){ 44 | this->outputDir = out; 45 | } 46 | std::string AbstractEncoder::getOutputDir (){ 47 | return this->outputDir; 48 | } 49 | void AbstractEncoder::setInput (std::string in){ 50 | this->input = in; 51 | } 52 | std::string AbstractEncoder::getInput (){ 53 | return this->input; 54 | } 55 | -------------------------------------------------------------------------------- /encoder/AbstractVideoEncoder.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "AbstractVideoEncoder.h" 3 | 4 | AbstractVideoEncoder::AbstractVideoEncoder() 5 | { 6 | this->width = 0; 7 | this->height = 0; 8 | this->passes = 1; 9 | this->isConstFS = false; 10 | } 11 | 12 | AbstractVideoEncoder::~AbstractVideoEncoder() 13 | { 14 | } 15 | 16 | void AbstractVideoEncoder::setStatisticFile (std::string stat){ 17 | this->statfile = stat; 18 | } 19 | std::string AbstractVideoEncoder::getStatisticFile (){ 20 | return this->statfile; 21 | } 22 | void AbstractVideoEncoder::setGOPSize (int gop){ 23 | this->gopsize = gop; 24 | } 25 | int AbstractVideoEncoder::getGOPSize (){ 26 | return this->gopsize; 27 | } 28 | void AbstractVideoEncoder::setSceneCut (int scene){ 29 | this->scenecut = scene; 30 | } 31 | int AbstractVideoEncoder::getSceneCut (){ 32 | return this->scenecut; 33 | } 34 | void AbstractVideoEncoder::setSpecFirstPassOpt (std::string opt){ 35 | this->firstPassOpt = opt; 36 | } 37 | std::string AbstractVideoEncoder::getSpecFirstPassOpt (){ 38 | return this->firstPassOpt; 39 | } 40 | void AbstractVideoEncoder::setSpecSecPassOpt (std::string opt){ 41 | this->secondPassOpt = opt; 42 | } 43 | std::string AbstractVideoEncoder::getSpecSecPassOpt (){ 44 | return this->secondPassOpt; 45 | } 46 | void AbstractVideoEncoder::setWidth (int w){ 47 | this->width = w; 48 | } 49 | int AbstractVideoEncoder::getWidth (){ 50 | return this->width; 51 | } 52 | void AbstractVideoEncoder::setHeight (int h){ 53 | this->height = h; 54 | } 55 | int AbstractVideoEncoder::getHeight (){ 56 | return this->height; 57 | } 58 | void AbstractVideoEncoder::setConstFileSize (bool c){ 59 | isConstFS = c; 60 | } 61 | bool AbstractVideoEncoder::isConstFileSize (){ 62 | return isConstFS; 63 | } 64 | void AbstractVideoEncoder::setPasses (int p){ 65 | this->passes = p; 66 | } 67 | int AbstractVideoEncoder::getPasses (){ 68 | return this->passes; 69 | } 70 | -------------------------------------------------------------------------------- /encoder/AbstractEncoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractEncoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef ABSTRACTENCODER_H_ 26 | #define ABSTRACTENCODER_H_ 27 | 28 | #include "IEncoder.h" 29 | #include "../DASHHelper.h" 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | class AbstractEncoder: public IEncoder 36 | { 37 | protected: 38 | int bitrate; 39 | std::string outputDir; 40 | std::string input; 41 | 42 | public: 43 | AbstractEncoder(); 44 | virtual ~AbstractEncoder(); 45 | 46 | virtual std::string encode(std::string) =0; 47 | virtual std::string encode() =0; 48 | 49 | void setBitrate (int br); 50 | int getBitrate (); 51 | void setOutputDir (std::string out); 52 | std::string getOutputDir (); 53 | void setInput (std::string in); 54 | std::string getInput (); 55 | }; 56 | 57 | #endif /* ABSTRACTENCODER_H_ */ 58 | -------------------------------------------------------------------------------- /encoder/x264Encoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * x264Encoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef X264ENCODER_H_ 26 | #define X264ENCODER_H_ 27 | 28 | #include "AbstractVideoEncoder.h" 29 | 30 | class x264Encoder : public AbstractVideoEncoder 31 | { 32 | protected: 33 | 34 | std::string preset; 35 | std::string profile; 36 | bool pipe; 37 | std::string ffmpegopt; 38 | std::string inputres; 39 | public: 40 | 41 | std::string encode (std::string input); 42 | std::string encode (); 43 | 44 | void setPreset (std::string pre); 45 | std::string getPreset (); 46 | void setProfile (std::string pro); 47 | std::string getProfile (); 48 | void setFFMpegOpt (std::string opt); 49 | std::string getFFMpegOpt (); 50 | void setInputRes (std::string opt); 51 | std::string getInputRes (); 52 | void usePipe (bool b); 53 | 54 | 55 | }; 56 | 57 | #endif /* X264ENCODER_H_ */ 58 | -------------------------------------------------------------------------------- /DASHEncoder.config: -------------------------------------------------------------------------------- 1 | #======================================== 2 | # Config File for DASH Encoder 3 | #======================================== 4 | 5 | #======================================== 6 | # General Options 7 | #======================================== 8 | 9 | dest-directory : /opt/lampp/htdocs/tests_updates/ 10 | 11 | 12 | video-encoder : x264 13 | audio-encoder : ffmpegAAC 14 | multiplexer : mp4box 15 | 16 | #store-psnr 17 | sql-host : localhost 18 | sql-user : root 19 | sql-pw : 20 | sql-database : dash 21 | 22 | add-non-segmented 23 | 24 | #use-ffmpeg-pipe 25 | ffmpeg-opt : -f rawvideo 26 | #input-res : 384x208 27 | #input-res : 352x288 28 | input-res : 854x480 29 | #======================================== 30 | # x264 Options 31 | #======================================== 32 | 33 | bitrate : 300 34 | 35 | #bitrate : 250@480x360|500@480x360|1000 36 | #bitrate : 200|400|600|1000 37 | statistics : stat.temp 38 | gop : 48 39 | scenecut : 0 40 | profile : baseline 41 | preset : slow 42 | input : /home/stefan/sintel_trailer_2k_480p24.y4m 43 | #input : /home/stefan/foreman_cif.y4m 44 | #input : /home/stefan/kingkong.mp4 45 | #input : /media/Volume/MI200802010028-video_newsroom_hd_1080_p29_97-channelSelectionT0C0_T0C1.mp4 46 | passes : 1 47 | const-filesize : 0 48 | 49 | #Additional Options for Encoding 50 | 51 | #pass1 : --frames 500 --fps 29.970029 52 | pass1 : --verbose --fps 24 53 | pass2 : --verbose --psnr 54 | 55 | #======================================== 56 | # FFMPEG AAC Options 57 | #======================================== 58 | 59 | # [channels, samplerate, bitrate] 60 | #audio-quality : 2,44100,48|2,44000,128 61 | #audio-quality : 2,44100,48 62 | audio-quality : 63 | 64 | audio-input : /home/stefan/sintel_trailer-audio.flac 65 | audio-codec : libfaac 66 | 67 | #======================================== 68 | # MP4Box Options 69 | #======================================== 70 | 71 | #AV Muxing 72 | #mux-combi : 300@48|600@128 73 | mux-combi : 74 | 75 | fragment-size : 2000 76 | segment-size : 2000 77 | rap-aligned 78 | segment-name : sintel 79 | folder-prefix : sintel 80 | 81 | 82 | #======================================== 83 | # MPD Options 84 | #======================================== 85 | mpd-name : sintel.mpd 86 | url-root : http://localhost/tests_updates/ 87 | #set-base-url 88 | mpdActStandardPostfix : _actVersion.mpd 89 | duration : 9M4S 90 | transform-mpd 91 | minBufferTime : 2.0S 92 | segDuration : 2 93 | #======================================== 94 | # Other Options 95 | #======================================== 96 | -------------------------------------------------------------------------------- /mpdgenerator/MPDGenerator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MPDGnerator.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "MPDGenerator.h" 26 | 27 | MPDGenerator::MPDGenerator() 28 | { 29 | finalMPDhead.append("\n"); 30 | finalMPDhead.append(" \n"); 37 | finalMPDhead.append(" \n"); 38 | finalMPDhead.append(" \n"); 39 | 40 | finalMPDfoot.append(" \n"); 41 | finalMPDfoot.append(" \n"); 42 | finalMPDfoot.append("\n"); 43 | } 44 | 45 | MPDGenerator::~MPDGenerator() 46 | { 47 | // TODO Auto-generated destructor stub 48 | } 49 | 50 | void MPDGenerator::appendMPDbody(std::string s){ 51 | this->finalMPDbody.append(s); 52 | } 53 | std::string MPDGenerator::getMPD(){ 54 | std::string str = ""; 55 | 56 | str.append(this->finalMPDhead); 57 | str.append(this->finalMPDbody); 58 | str.append(this->finalMPDfoot); 59 | 60 | return str; 61 | } 62 | -------------------------------------------------------------------------------- /multiplexer/AbstractMultiplexer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractMultiplexer.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "AbstractMultiplexer.h" 26 | 27 | AbstractMultiplexer::AbstractMultiplexer() 28 | { 29 | this->audioFile = ""; 30 | } 31 | 32 | AbstractMultiplexer::~AbstractMultiplexer() 33 | { 34 | // TODO Auto-generated destructor stub 35 | } 36 | void AbstractMultiplexer::setInput(std::string in) 37 | { 38 | this->input = in; 39 | } 40 | std::string AbstractMultiplexer::getInput() 41 | { 42 | return this->input; 43 | } 44 | void AbstractMultiplexer::setFragSize(int frag) 45 | { 46 | this->fragSize = frag; 47 | } 48 | int AbstractMultiplexer::getFragSize() 49 | { 50 | return this->fragSize; 51 | } 52 | void AbstractMultiplexer::setSegSize(int seg) 53 | { 54 | this->segSize = seg; 55 | } 56 | int AbstractMultiplexer::getSegSize() 57 | { 58 | return this->segSize; 59 | } 60 | void AbstractMultiplexer::setRAPAligned(bool rap) 61 | { 62 | this->rapAligned = rap; 63 | } 64 | bool AbstractMultiplexer::isRAPAligned() 65 | { 66 | return this->rapAligned; 67 | } 68 | void AbstractMultiplexer::setSegName(std::string name) 69 | { 70 | this->segName = name; 71 | } 72 | std::string AbstractMultiplexer::getSegName() 73 | { 74 | return this->segName; 75 | } 76 | void AbstractMultiplexer::setOutputDir (std::string out){ 77 | this->outputDir = out; 78 | } 79 | std::string AbstractMultiplexer::getOutputDir (){ 80 | return this->outputDir; 81 | } 82 | void AbstractMultiplexer::setAudioFile (std::string file){ 83 | this->audioFile = file; 84 | } 85 | std::string AbstractMultiplexer::getAudioFile (){ 86 | return this->audioFile; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /encoder/ffmpegAACEncoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ffmpegAACEncoder.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "ffmpegAACEncoder.h" 26 | 27 | 28 | std::string ffmpegAACEncoder::encode (std::string input){ 29 | this->setInput(input); 30 | return this->encode(); 31 | } 32 | std::string ffmpegAACEncoder::encode (){ 33 | std::cout << "AUDIO FFMPEG AAC Encoding: " << this->input << " \n"; 34 | 35 | std::string out = ""; 36 | 37 | std::string aac = "ffmpeg "; 38 | 39 | aac.append("-i "); 40 | aac.append(this->input); 41 | aac.append(" "); 42 | 43 | aac.append("-acodec "); 44 | aac.append(this->codec); 45 | aac.append(" "); 46 | 47 | aac.append("-ac "); 48 | aac.append(DASHHelper::itos(this->channels)); 49 | aac.append(" "); 50 | 51 | aac.append("-ar "); 52 | aac.append(DASHHelper::itos(this->srate)); 53 | aac.append(" "); 54 | 55 | aac.append("-ab "); 56 | aac.append(DASHHelper::itos(this->bitrate)); 57 | aac.append("k "); 58 | 59 | out.append(this->outputDir); 60 | out.append(this->input.substr(this->input.find_last_of("/")+1,this->input.find_last_of(".")-this->input.find_last_of("/")-1)); 61 | out.append("_"); 62 | out.append(DASHHelper::itos(this->channels)); 63 | out.append("ch_"); 64 | out.append(DASHHelper::itos(this->bitrate)); 65 | out.append("kbit.aac "); 66 | 67 | aac.append(out); 68 | 69 | std::cout <codec = c; 78 | } 79 | std::string ffmpegAACEncoder::getCodec (){ 80 | return this->codec; 81 | } 82 | -------------------------------------------------------------------------------- /multiplexer/AbstractMultiplexer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractMultiplexer.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef ABSTRACTMULTIPLEXER_H_ 26 | #define ABSTRACTMULTIPLEXER_H_ 27 | 28 | #include "IMultiplexer.h" 29 | #include "../DASHHelper.h" 30 | 31 | class AbstractMultiplexer : public IMultiplexer 32 | { 33 | protected: 34 | std::string input; 35 | int fragSize; 36 | int segSize; 37 | bool rapAligned; 38 | std::string segName; 39 | std::string outputDir; 40 | std::string audioFile; 41 | 42 | public: 43 | AbstractMultiplexer(); 44 | virtual ~AbstractMultiplexer(); 45 | 46 | virtual std::string multiplex (std::string input) = 0; 47 | virtual std::string multiplex () = 0; 48 | virtual std::string unSegment (std::string input) = 0; 49 | 50 | void setInput (std::string in); 51 | std::string getInput (); 52 | void setFragSize (int frag); 53 | int getFragSize (); 54 | void setSegSize (int seg); 55 | int getSegSize (); 56 | void setRAPAligned (bool rap); 57 | bool isRAPAligned (); 58 | void setSegName (std::string name); 59 | std::string getSegName (); 60 | void setOutputDir (std::string out); 61 | std::string getOutputDir (); 62 | void setAudioFile (std::string file); 63 | std::string getAudioFile (); 64 | 65 | 66 | }; 67 | #endif /* ABSTRACTMULTIPLEXER_H_ */ 68 | -------------------------------------------------------------------------------- /encoder/AbstractVideoEncoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AbstractEncoder.h 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #ifndef ABSTRACTVIDEOENCODER_H_ 26 | #define ABSTRACTVIDEOENCODER_H_ 27 | 28 | #include "AbstractEncoder.h" 29 | 30 | 31 | class AbstractVideoEncoder : public AbstractEncoder 32 | { 33 | 34 | protected: 35 | 36 | std::string statfile; 37 | int gopsize; 38 | int scenecut; 39 | std::string firstPassOpt; 40 | std::string secondPassOpt; 41 | int width; 42 | int height; 43 | bool isConstFS; 44 | int passes; 45 | 46 | public: 47 | AbstractVideoEncoder(); 48 | virtual ~AbstractVideoEncoder(); 49 | 50 | virtual std::string encode(std::string) =0; 51 | virtual std::string encode() =0; 52 | 53 | 54 | void setStatisticFile (std::string stat); 55 | std::string getStatisticFile (); 56 | void setGOPSize (int gop); 57 | int getGOPSize (); 58 | void setSceneCut (int scene); 59 | int getSceneCut (); 60 | void setSpecFirstPassOpt (std::string opt); 61 | std::string getSpecFirstPassOpt (); 62 | void setSpecSecPassOpt (std::string opt); 63 | std::string getSpecSecPassOpt (); 64 | void setWidth (int w); 65 | int getWidth (); 66 | void setHeight (int h); 67 | int getHeight (); 68 | void setConstFileSize (bool c); 69 | bool isConstFileSize (); 70 | void setPasses (int p); 71 | int getPasses (); 72 | 73 | }; 74 | #endif /* ABSTRACTVIDEOENCODER_H_ */ 75 | -------------------------------------------------------------------------------- /encoder/EncoderFactory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * EncoderFactory.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "EncoderFactory.h" 26 | 27 | EncoderFactory::EncoderFactory() 28 | { 29 | // TODO Auto-generated constructor stub 30 | 31 | } 32 | 33 | EncoderFactory::~EncoderFactory() 34 | { 35 | // TODO Auto-generated destructor stub 36 | } 37 | 38 | IEncoder* EncoderFactory::getEncoder (AnyOption* opt, IEncoder::EncoderType type){ 39 | IEncoder* retval = NULL; 40 | if(type == IEncoder::x264){ 41 | x264Encoder* e = new x264Encoder(); 42 | e->setProfile(opt->getValue("profile")); 43 | e->setPreset(opt->getValue("preset")); 44 | e->setSceneCut(atoi(opt->getValue("scenecut"))); 45 | e->setGOPSize(atoi(opt->getValue("gop"))); 46 | e->setPasses(atoi(opt->getValue("passes"))); 47 | e->setStatisticFile(opt->getValue("statistics")); 48 | e->setInput(opt->getValue("input")); 49 | e->setInputRes(opt->getValue("input-res")); 50 | e->setOutputDir(opt->getValue("dest-directory")); 51 | e->setSpecFirstPassOpt(opt->getValue("pass1")); 52 | e->setSpecSecPassOpt(opt->getValue("pass2")); 53 | if(atoi(opt->getValue("const-filesize")) ==1) 54 | e->setConstFileSize(true); 55 | else 56 | e->setConstFileSize(false); 57 | 58 | if(opt->getFlag("use-ffmpeg-pipe")){ 59 | e->setFFMpegOpt(opt->getValue("ffmpeg-opt")); 60 | e->usePipe(true); 61 | } 62 | else 63 | e->usePipe(false); 64 | 65 | retval = e; 66 | 67 | } 68 | else if(type == IEncoder::vp8){ 69 | 70 | } 71 | else if(type == IEncoder::ffmpegAAC){ 72 | ffmpegAACEncoder* a = new ffmpegAACEncoder(); 73 | a->setInput(opt->getValue("audio-input")); 74 | a->setOutputDir(opt->getValue("dest-directory")); 75 | a->setCodec(opt->getValue("audio-codec")); 76 | retval = a; 77 | } 78 | 79 | return retval; 80 | } 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Welcome to DASHEncoder 2 | We (http://dash.itec.aau.at and http://www.bitmovin.com) have developed a new content generation tool – on top of GPAC’s MP4Box and x264 – for MPEG-DASH content generation, called DASHEncoder. 3 | 4 | Alternatively, it is possible to generate MPEG-DASH and Apple HLS content with the cloud based transcoding service [Bitmovin](http://www.bitmovin.com). Visit [www.bitmovin.com](http://www.bitmovin.com) and experience easy access to MPEG-DASH and Apple HLS video transcoding with $ 25 of transcoding credits for free. 5 | 6 | [![Bitmovin](https://bitmovin.com/wp-content/uploads/2016/07/Encoder-signup.jpg)](http://www.bitmovin.com) 7 | 8 | ### How does it work? 9 | The DASHEncoder steps are depicted here: 10 | DASHEncoder generates the desired representations (quality/bitrate levels), fragmented MP4 files, and a MPD file based on a given config file or by command line parameters respectively. Given the set of parameters the user has a wide range of possibilities for the content generation, including the variation of the segment size, bitrate, resolution, encoding settings, URL , etc., which is shown by the example of a DASHEncoder config file in the git repository of DASHEncoder. 11 | 12 | The DASHEncoder is available as open source with the aim that other developers will join this project. The content generated by DASHEncoder is compatible with our DASH VLC plugin which can be used as a decoder and player respectively. 13 | 14 | ### Current features and restrictions 15 | * Generation of video only, audio only or audio+video DASH content 16 | * H.264 encoding based on x264: Constant and variable bitrate encoding 17 | * PSNR logging and MySQL interface for storing in a database (only for common resolution representations) 18 | * There are currently problems with the playback of the content containing Audio with the DASH VLC plugin 19 | 20 | ### Compilation and installation 21 | 22 | You can find the git repository here: https://github.com/slederer/DASHEncoder 23 | 24 | For compilation just read the “DASHEncoder-howto.txt” of the git repository. Alternatively follow this instructions: 25 | 26 | Installation: 27 | * Get the actual version from the git repository 28 | * run: make 29 | * Finished! 30 | 31 | Run: 32 | * Edit the parameters of the example config file 33 | * run: ./DASHEncoder 34 | 35 | If you're using the GitHub for Mac, simply sync your repository and you'll see the new branch. 36 | 37 | ### Dependencies 38 | * x264: use a version with scaling enabled. To be sure, get the latest version from the x264 git repository and compile it on your own. 39 | * MP4Box: use the actual version from the SVN repository of GPAC (this will support dash multiplexing) 40 | http://gpac.wp.institut-telecom.fr/2011/04/20/compiling-gpac-on-ubuntu/ 41 | * FFmpeg (optional): if you use other input source formats than YUV, may use FFmpeg for the pipe to x264 42 | * MySQL (optional) client libraries (may needs some changes in the make file of DASHEncoder because of the paths) 43 | 44 | ### Authors and Contributors 45 | We kindly ask you to refer the following paper in any publication mentioning DASHEncoder: 46 | 47 | Stefan Lederer, Christopher Müller and Christian Timmerer, “Dynamic Adaptive Streaming over HTTP Dataset”, In Proceedings of the ACM Multimedia Systems Conference 2012, Chapel Hill, North Carolina, February 22-24, 2012. [[PDF]](http://www-itec.uni-klu.ac.at/bib/files/p89-lederer.pdf) 48 | 49 | ### Support or Contact 50 | Having trouble? Check out the documentation at [http://dash.itec.aau.at](http://www-itec.uni-klu.ac.at/dash/?page_id=282). We also offer professional services via [www.bitmovin.com/support](https://bitmovin.com/support/), so you are warmly invited to contact sales@bitmovin.com and we’ll get in touch with you. 51 | 52 | -------------------------------------------------------------------------------- /multiplexer/MP4BoxMultiplexer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MP4BoxMultiplexer.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "MP4BoxMultiplexer.h" 26 | 27 | 28 | MP4BoxMultiplexer::MP4BoxMultiplexer() 29 | { 30 | // TODO Auto-generated constructor stub 31 | 32 | } 33 | 34 | MP4BoxMultiplexer::~MP4BoxMultiplexer() 35 | { 36 | // TODO Auto-generated destructor stub 37 | } 38 | 39 | std::string MP4BoxMultiplexer::multiplex (std::string in) 40 | { 41 | this->input = in; 42 | return this->multiplex(); 43 | } 44 | std::string MP4BoxMultiplexer::multiplex (){ 45 | 46 | std::cout << "MP4Box multiplexing Video: " << this->input << " \n"; 47 | 48 | std::string mp4box = "MP4Box "; 49 | mp4box.append("-add "); 50 | mp4box.append(this->input); 51 | mp4box.append(" "); 52 | mp4box.append(this->input.substr(0,this->input.find_last_of("."))); 53 | mp4box.append(".mp4"); 54 | 55 | std::cout << "mp4box: " <audioFile.size()>0){ 59 | std::cout << "MP4Box multiplexing Audio:" << this->audioFile << " \n"; 60 | 61 | std::string mp4box = "MP4Box "; 62 | mp4box.append("-add "); 63 | mp4box.append(this->audioFile); 64 | mp4box.append(" "); 65 | mp4box.append(this->input.substr(0,this->input.find_last_of("."))); 66 | mp4box.append(".mp4"); 67 | 68 | std::cout << "mp4box: " <input.substr(0,this->input.find_last_of("."))); 78 | mp4box.append(".mp4"); 79 | 80 | std::cout << "mp4box: " <input << " \n"; 85 | 86 | mp4box = "MP4Box "; 87 | 88 | mp4box.append("-frag "); 89 | mp4box.append(DASHHelper::itos(this->fragSize)); 90 | mp4box.append(" "); 91 | 92 | mp4box.append("-dash "); 93 | mp4box.append(DASHHelper::itos(this->segSize)); 94 | mp4box.append(" "); 95 | 96 | if(this->isRAPAligned()){ 97 | mp4box.append("-rap "); 98 | } 99 | 100 | mp4box.append("-segment-name "); 101 | mp4box.append(this->segName); 102 | mp4box.append(" "); 103 | 104 | mp4box.append(this->input.substr(0,this->input.find_last_of("."))); 105 | mp4box.append(".mp4"); 106 | 107 | std::cout << "mp4box: " <input.substr(0,this->input.find_last_of(".")); 111 | mpd.append("_dash.mpd"); 112 | return mpd; 113 | } 114 | 115 | std::string MP4BoxMultiplexer::unSegment (std::string act_rep){ 116 | std::string mpd = ""; 117 | std::string byterange = ""; 118 | int actpos = 0; 119 | int size = 0; 120 | std::string path = ""; 121 | std::string mainfile = ""; 122 | std::string catcmd = ""; 123 | 124 | int s_pos = act_rep.find("fileSize(path.c_str()); 129 | 130 | mainfile = path; 131 | mainfile.replace(mainfile.find_last_of("."), 1, "NonSeg."); 132 | 133 | byterange = " range=\""; 134 | byterange.append(DASHHelper::itos(actpos)); 135 | byterange.append("-"); 136 | byterange.append(DASHHelper::itos(actpos+size)); 137 | byterange.append("\" />"); 138 | actpos += size+1; 139 | 140 | act_rep.replace(act_rep.find("/>", s_pos),2,byterange); 141 | act_rep.replace(act_rep.find(path), path.length(), mainfile); 142 | 143 | s_pos +=26; 144 | 145 | catcmd = "cat "; 146 | catcmd.append(path); 147 | catcmd.append(" > "); 148 | catcmd.append(mainfile); 149 | 150 | system(catcmd.c_str()); 151 | 152 | while (act_rep.find("fileSize(path.c_str()); 159 | 160 | byterange = " range=\""; 161 | byterange.append(DASHHelper::itos(actpos)); 162 | byterange.append("-"); 163 | byterange.append(DASHHelper::itos(actpos+size)); 164 | byterange.append("\" />"); 165 | actpos += size+1; 166 | 167 | catcmd = "cat "; 168 | catcmd.append(path); 169 | catcmd.append(" >> "); 170 | catcmd.append(mainfile); 171 | 172 | system(catcmd.c_str()); 173 | 174 | act_rep.replace(act_rep.find("/>", s_pos),2,byterange); 175 | act_rep.replace(act_rep.find(path), path.length(), mainfile); 176 | s_pos +=5; 177 | } 178 | return act_rep; 179 | } 180 | 181 | 182 | int MP4BoxMultiplexer::fileSize(const char* sFileName) 183 | { 184 | std::ifstream f; 185 | f.open(sFileName, std::ios_base::binary | std::ios_base::in); 186 | if (!f.good() || f.eof() || !f.is_open()) { return 0; } 187 | f.seekg(0, std::ios_base::beg); 188 | std::ifstream::pos_type begin_pos = f.tellg(); 189 | f.seekg(0, std::ios_base::end); 190 | return static_cast(f.tellg() - begin_pos); 191 | } 192 | -------------------------------------------------------------------------------- /encoder/x264Encoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * x264Encoder.cpp 3 | ***************************************************************************** 4 | * Copyright (C) 2011 Klagenfurt University 5 | * 6 | * Created on: Jun 01, 2011 7 | * Authors: Stefan Lederer 8 | * Christian Timmerer 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation; either version 2.1 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 23 | *****************************************************************************/ 24 | 25 | #include "x264Encoder.h" 26 | 27 | 28 | 29 | 30 | std::string x264Encoder::encode (std::string in){ 31 | this->input = in; 32 | return this->encode(); 33 | } 34 | std::string x264Encoder::encode (){ 35 | std::cout << "x264 encoding @ " << this->bitrate << " kbps: Pass 1 \n"; 36 | 37 | std::string x264 = "x264 "; 38 | x264.append("--profile "); 39 | x264.append(this->profile); 40 | x264.append(" "); 41 | x264.append("--preset "); 42 | x264.append(this->preset); 43 | x264.append(" "); 44 | 45 | if(this->passes > 1) 46 | x264.append("--pass 1 "); 47 | 48 | x264.append(this->getSpecFirstPassOpt()); 49 | x264.append(" "); 50 | 51 | if(this->isConstFileSize()){ 52 | x264.append("--bitrate "); 53 | x264.append(DASHHelper::itos(this->bitrate)); 54 | x264.append(" "); 55 | } 56 | else{ 57 | x264.append("--vbv-maxrate "); 58 | x264.append(DASHHelper::itos(this->bitrate)); 59 | x264.append(" "); 60 | 61 | x264.append("--vbv-bufsize "); 62 | x264.append(DASHHelper::itos(this->bitrate*2)); 63 | x264.append(" "); 64 | } 65 | 66 | x264.append("--scenecut "); 67 | x264.append(DASHHelper::itos(this->scenecut)); 68 | x264.append(" "); 69 | 70 | if(this->width>0 && this->height>0){ 71 | x264.append("--video-filter resize:width="); 72 | x264.append(DASHHelper::itos(this->width)); 73 | x264.append(",height="); 74 | x264.append(DASHHelper::itos(this->height)); 75 | x264.append(" "); 76 | } 77 | 78 | x264.append("--keyint "); 79 | x264.append(DASHHelper::itos(this->gopsize)); 80 | x264.append(" "); 81 | 82 | if(this->passes > 1){ 83 | x264.append("--stat "); 84 | x264.append(this->outputDir); 85 | x264.append(this->statfile); 86 | x264.append(" "); 87 | x264.append("--output NUL "); 88 | } 89 | else { 90 | x264.append("--output "); 91 | x264.append(this->outputDir); 92 | x264.append(this->input.substr(this->input.find_last_of("/")+1,this->input.find_last_of(".")-this->input.find_last_of("/")-1)); 93 | x264.append("_"); 94 | x264.append(DASHHelper::itos(this->bitrate)); 95 | x264.append("kbit.h264 "); 96 | } 97 | 98 | 99 | if(pipe) 100 | { 101 | std::string ffmpeg = "ffmpeg -i "; 102 | ffmpeg.append(this->input); 103 | ffmpeg.append(" "); 104 | ffmpeg.append(ffmpegopt); 105 | ffmpeg.append(" - | "); 106 | ffmpeg.append(x264); 107 | x264 = ffmpeg; 108 | x264.append("--input-res "); 109 | x264.append(inputres); 110 | x264.append(" -"); 111 | } 112 | else 113 | x264.append(this->input); 114 | 115 | x264.append(" >out.txt 2>&1 "); 116 | std::cout << "x264: " <passes > 1){ 120 | std::cout << "x264 encoding @ " << this->bitrate << " kbps: Pass 2 \n"; 121 | 122 | x264 = "x264 "; 123 | 124 | x264.append("--profile "); 125 | x264.append(this->profile); 126 | x264.append(" "); 127 | 128 | x264.append("--preset "); 129 | x264.append(this->preset); 130 | x264.append(" "); 131 | 132 | x264.append("--pass 2 "); 133 | 134 | x264.append(this->getSpecSecPassOpt()); 135 | x264.append(" "); 136 | 137 | if(this->isConstFileSize()){ 138 | x264.append("--bitrate "); 139 | x264.append(DASHHelper::itos(this->bitrate)); 140 | x264.append(" "); 141 | } 142 | else{ 143 | x264.append("--vbv-maxrate "); 144 | x264.append(DASHHelper::itos(this->bitrate)); 145 | x264.append(" "); 146 | 147 | x264.append("--vbv-bufsize "); 148 | x264.append(DASHHelper::itos(this->bitrate*2)); 149 | x264.append(" "); 150 | } 151 | 152 | x264.append("--scenecut "); 153 | x264.append(DASHHelper::itos(this->scenecut)); 154 | x264.append(" "); 155 | 156 | x264.append("--keyint "); 157 | x264.append(DASHHelper::itos(this->gopsize)); 158 | x264.append(" "); 159 | 160 | if(this->width>0 && this->height>0){ 161 | x264.append("--video-filter resize:width="); 162 | x264.append(DASHHelper::itos(this->width)); 163 | x264.append(",height="); 164 | x264.append(DASHHelper::itos(this->height)); 165 | x264.append(" "); 166 | } 167 | 168 | x264.append("--stat "); 169 | x264.append(this->outputDir); 170 | x264.append(this->statfile); 171 | x264.append(" "); 172 | 173 | x264.append("--output "); 174 | x264.append(this->outputDir); 175 | x264.append(this->input.substr(this->input.find_last_of("/")+1,this->input.find_last_of(".")-this->input.find_last_of("/")-1)); 176 | x264.append("_"); 177 | x264.append(DASHHelper::itos(this->bitrate)); 178 | x264.append("kbit.h264 "); 179 | 180 | x264.append(this->input); 181 | x264.append(" >out.txt 2>&1 "); 182 | 183 | std::cout <input.substr(this->input.find_last_of("/")+1,this->input.find_last_of(".")-this->input.find_last_of("/")-1)); 189 | out.append("_"); 190 | out.append(DASHHelper::itos(this->bitrate)); 191 | out.append("kbit.h264 "); 192 | 193 | return out; 194 | } 195 | 196 | 197 | void x264Encoder::setPreset (std::string pre){ 198 | this->preset = pre; 199 | } 200 | std::string x264Encoder::getPreset (){ 201 | return this->preset; 202 | } 203 | void x264Encoder::setProfile (std::string pro){ 204 | this->profile = pro; 205 | } 206 | std::string x264Encoder::getProfile (){ 207 | return this->profile; 208 | } 209 | void x264Encoder::setFFMpegOpt (std::string opt){ 210 | this->ffmpegopt = opt; 211 | } 212 | std::string x264Encoder::getFFMpegOpt (){ 213 | return this->ffmpegopt; 214 | } 215 | void x264Encoder::usePipe (bool b){ 216 | this->pipe = b; 217 | } 218 | void x264Encoder::setInputRes (std::string opt){ 219 | this->inputres = opt; 220 | } 221 | std::string x264Encoder::getInputRes (){ 222 | return this->inputres; 223 | } 224 | 225 | -------------------------------------------------------------------------------- /AnyOption.h: -------------------------------------------------------------------------------- 1 | #ifndef _ANYOPTION_H 2 | #define _ANYOPTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define COMMON_OPT 1 11 | #define COMMAND_OPT 2 12 | #define FILE_OPT 3 13 | #define COMMON_FLAG 4 14 | #define COMMAND_FLAG 5 15 | #define FILE_FLAG 6 16 | 17 | #define COMMAND_OPTION_TYPE 1 18 | #define COMMAND_FLAG_TYPE 2 19 | #define FILE_OPTION_TYPE 3 20 | #define FILE_FLAG_TYPE 4 21 | #define UNKNOWN_TYPE 5 22 | 23 | #define DEFAULT_MAXOPTS 10 24 | #define MAX_LONG_PREFIX_LENGTH 2 25 | 26 | #define DEFAULT_MAXUSAGE 3 27 | #define DEFAULT_MAXHELP 10 28 | 29 | #define TRUE_FLAG "true" 30 | 31 | using namespace std; 32 | 33 | class AnyOption 34 | { 35 | 36 | public: /* the public interface */ 37 | AnyOption(); 38 | AnyOption(int maxoptions ); 39 | AnyOption(int maxoptions , int maxcharoptions); 40 | ~AnyOption(); 41 | 42 | /* 43 | * following set methods specifies the 44 | * special characters and delimiters 45 | * if not set traditional defaults will be used 46 | */ 47 | 48 | void setCommandPrefixChar( char _prefix ); /* '-' in "-w" */ 49 | void setCommandLongPrefix( char *_prefix ); /* '--' in "--width" */ 50 | void setFileCommentChar( char _comment ); /* '#' in shellscripts */ 51 | void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */ 52 | 53 | /* 54 | * provide the input for the options 55 | * like argv[] for commndline and the 56 | * option file name to use; 57 | */ 58 | 59 | void useCommandArgs( int _argc, char **_argv ); 60 | void useFiileName( const char *_filename ); 61 | 62 | /* 63 | * turn off the POSIX style options 64 | * this means anything starting with a '-' or "--" 65 | * will be considered a valid option 66 | * which alo means you cannot add a bunch of 67 | * POIX options chars together like "-lr" for "-l -r" 68 | * 69 | */ 70 | 71 | void noPOSIX(); 72 | 73 | /* 74 | * prints warning verbose if you set anything wrong 75 | */ 76 | void setVerbose(); 77 | 78 | 79 | /* 80 | * there are two types of options 81 | * 82 | * Option - has an associated value ( -w 100 ) 83 | * Flag - no value, just a boolean flag ( -nogui ) 84 | * 85 | * the options can be either a string ( GNU style ) 86 | * or a character ( traditional POSIX style ) 87 | * or both ( --width, -w ) 88 | * 89 | * the options can be common to the commandline and 90 | * the optionfile, or can belong only to either of 91 | * commandline and optionfile 92 | * 93 | * following set methods, handle all the aboove 94 | * cases of options. 95 | */ 96 | 97 | /* options comman to command line and option file */ 98 | void setOption( const char *opt_string ); 99 | void setOption( char opt_char ); 100 | void setOption( const char *opt_string , char opt_char ); 101 | void setFlag( const char *opt_string ); 102 | void setFlag( char opt_char ); 103 | void setFlag( const char *opt_string , char opt_char ); 104 | 105 | /* options read from commandline only */ 106 | void setCommandOption( const char *opt_string ); 107 | void setCommandOption( char opt_char ); 108 | void setCommandOption( const char *opt_string , char opt_char ); 109 | void setCommandFlag( const char *opt_string ); 110 | void setCommandFlag( char opt_char ); 111 | void setCommandFlag( const char *opt_string , char opt_char ); 112 | 113 | /* options read from an option file only */ 114 | void setFileOption( const char *opt_string ); 115 | void setFileOption( char opt_char ); 116 | void setFileOption( const char *opt_string , char opt_char ); 117 | void setFileFlag( const char *opt_string ); 118 | void setFileFlag( char opt_char ); 119 | void setFileFlag( const char *opt_string , char opt_char ); 120 | 121 | /* 122 | * process the options, registerd using 123 | * useCommandArgs() and useFileName(); 124 | */ 125 | void processOptions(); 126 | void processCommandArgs(); 127 | void processCommandArgs( int max_args ); 128 | bool processFile(); 129 | 130 | /* 131 | * process the specified options 132 | */ 133 | void processCommandArgs( int _argc, char **_argv ); 134 | void processCommandArgs( int _argc, char **_argv, int max_args ); 135 | bool processFile( const char *_filename ); 136 | 137 | /* 138 | * get the value of the options 139 | * will return NULL if no value is set 140 | */ 141 | char *getValue( const char *_option ); 142 | bool getFlag( const char *_option ); 143 | char *getValue( char _optchar ); 144 | bool getFlag( char _optchar ); 145 | 146 | /* 147 | * Print Usage 148 | */ 149 | void printUsage(); 150 | void printAutoUsage(); 151 | void addUsage( const char *line ); 152 | void printHelp(); 153 | /* print auto usage printing for unknown options or flag */ 154 | void autoUsagePrint(bool flag); 155 | 156 | /* 157 | * get the argument count and arguments sans the options 158 | */ 159 | int getArgc(); 160 | char* getArgv( int index ); 161 | bool hasOptions(); 162 | 163 | private: /* the hidden data structure */ 164 | int argc; /* commandline arg count */ 165 | char **argv; /* commndline args */ 166 | const char* filename; /* the option file */ 167 | char* appname; /* the application name from argv[0] */ 168 | 169 | int *new_argv; /* arguments sans options (index to argv) */ 170 | int new_argc; /* argument count sans the options */ 171 | int max_legal_args; /* ignore extra arguments */ 172 | 173 | 174 | /* option strings storage + indexing */ 175 | int max_options; /* maximum number of options */ 176 | const char **options; /* storage */ 177 | int *optiontype; /* type - common, command, file */ 178 | int *optionindex; /* index into value storage */ 179 | int option_counter; /* counter for added options */ 180 | 181 | /* option chars storage + indexing */ 182 | int max_char_options; /* maximum number options */ 183 | char *optionchars; /* storage */ 184 | int *optchartype; /* type - common, command, file */ 185 | int *optcharindex; /* index into value storage */ 186 | int optchar_counter; /* counter for added options */ 187 | 188 | /* values */ 189 | char **values; /* common value storage */ 190 | int g_value_counter; /* globally updated value index LAME! */ 191 | 192 | /* help and usage */ 193 | const char **usage; /* usage */ 194 | int max_usage_lines; /* max usage lines reseverd */ 195 | int usage_lines; /* number of usage lines */ 196 | 197 | bool command_set; /* if argc/argv were provided */ 198 | bool file_set; /* if a filename was provided */ 199 | bool mem_allocated; /* if memory allocated in init() */ 200 | bool posix_style; /* enables to turn off POSIX style options */ 201 | bool verbose; /* silent|verbose */ 202 | bool print_usage; /* usage verbose */ 203 | bool print_help; /* help verbose */ 204 | 205 | char opt_prefix_char; /* '-' in "-w" */ 206 | char long_opt_prefix[MAX_LONG_PREFIX_LENGTH]; /* '--' in "--width" */ 207 | char file_delimiter_char; /* ':' in width : 100 */ 208 | char file_comment_char; /* '#' in "#this is a comment" */ 209 | char equalsign; 210 | char comment; 211 | char delimiter; 212 | char endofline; 213 | char whitespace; 214 | char nullterminate; 215 | 216 | bool set; //was static member 217 | bool once; //was static member 218 | 219 | bool hasoptions; 220 | bool autousage; 221 | 222 | private: /* the hidden utils */ 223 | void init(); 224 | void init(int maxopt, int maxcharopt ); 225 | bool alloc(); 226 | void cleanup(); 227 | bool valueStoreOK(); 228 | 229 | /* grow storage arrays as required */ 230 | bool doubleOptStorage(); 231 | bool doubleCharStorage(); 232 | bool doubleUsageStorage(); 233 | 234 | bool setValue( const char *option , char *value ); 235 | bool setFlagOn( const char *option ); 236 | bool setValue( char optchar , char *value); 237 | bool setFlagOn( char optchar ); 238 | 239 | void addOption( const char* option , int type ); 240 | void addOption( char optchar , int type ); 241 | void addOptionError( const char *opt); 242 | void addOptionError( char opt); 243 | bool findFlag( char* value ); 244 | void addUsageError( const char *line ); 245 | bool CommandSet(); 246 | bool FileSet(); 247 | bool POSIX(); 248 | 249 | char parsePOSIX( char* arg ); 250 | int parseGNU( char *arg ); 251 | bool matchChar( char c ); 252 | int matchOpt( char *opt ); 253 | 254 | /* dot file methods */ 255 | char *readFile(); 256 | char *readFile( const char* fname ); 257 | bool consumeFile( char *buffer ); 258 | void processLine( char *theline, int length ); 259 | char *chomp( char *str ); 260 | void valuePairs( char *type, char *value ); 261 | void justValue( char *value ); 262 | 263 | void printVerbose( const char *msg ); 264 | void printVerbose( char *msg ); 265 | void printVerbose( char ch ); 266 | void printVerbose( ); 267 | 268 | 269 | }; 270 | 271 | #endif /* ! _ANYOPTION_H */ 272 | -------------------------------------------------------------------------------- /DASHEncoder.cpp: -------------------------------------------------------------------------------- 1 | #include "AnyOption.h" 2 | #include "multiplexer/MP4BoxMultiplexer.h" 3 | #include "encoder/IEncoder.h" 4 | #include "encoder/AbstractAudioEncoder.h" 5 | #include "encoder/AbstractVideoEncoder.h" 6 | #include "encoder/EncoderFactory.h" 7 | #include "mpdgenerator/MPDGenerator.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | //#include "mysql/mysql.h" 14 | 15 | void parse(int argc, char* argv[]); 16 | void setHelp(AnyOption*); 17 | void setOptions(AnyOption*); 18 | IEncoder::EncoderType getEncoder(std::string); 19 | int convertMPD(std::string input, std::string output, std::string duration, std::string baseurl, std::string minbuffer, std::string segduration); 20 | 21 | AnyOption *opt; 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | parse(argc, argv); 26 | return 0; 27 | } 28 | 29 | void parse(int argc, char* argv[]) 30 | { 31 | std::cout << "==========DASH ENCODER===============\n"; 32 | AnyOption *opt = new AnyOption(); 33 | 34 | /* COMMAND LINE PREFERENCES */ 35 | opt->setVerbose(); /* print warnings about unknown options */ 36 | opt->autoUsagePrint(true); /* print usage for bad options */ 37 | 38 | /* SET THE USAGE/HELP */ 39 | setHelp(opt); 40 | 41 | /* SET THE OPTION STRINGS/CHARACTERS */ 42 | 43 | setOptions(opt); 44 | 45 | /* PROCESS THE RESOURCE FILE */ 46 | opt->processFile("./DASHEncoder.config"); 47 | /* PROCESS THE COMMANDLINE */ 48 | opt->processCommandArgs(argc, argv); 49 | 50 | /* Run DASH Encoding */ 51 | 52 | EncoderFactory* encoder_factory= new EncoderFactory(); 53 | std::cout << "current encoder " << opt->getValue("video-encoder") << "\n"; 54 | if(getEncoder(opt->getValue("video-encoder")) == IEncoder::x264) 55 | std::cout << "YES\n"; 56 | 57 | AbstractVideoEncoder* e = (AbstractVideoEncoder*)encoder_factory->getEncoder(opt, getEncoder(opt->getValue("video-encoder"))); 58 | AbstractAudioEncoder* a = (AbstractAudioEncoder*)encoder_factory->getEncoder(opt, getEncoder(opt->getValue("audio-encoder"))); 59 | 60 | MPDGenerator* mpdgen = new MPDGenerator(); 61 | MPDGenerator* mpdgenNonSeg = new MPDGenerator(); 62 | MP4BoxMultiplexer* m = new MP4BoxMultiplexer(); 63 | 64 | std::map audio_files; 65 | std::map av_mux_mapping; 66 | 67 | /* MySQL Support Disabled 68 | 69 | MYSQL_RES *result; 70 | 71 | MYSQL_ROW row; 72 | 73 | MYSQL *connection, mysql; 74 | 75 | */ 76 | 77 | int state; 78 | 79 | m->setFragSize(atoi(opt->getValue("fragment-size"))); 80 | m->setRAPAligned(opt->getFlag("rap-aligned")); 81 | m->setOutputDir(opt->getValue("dest-directory")); 82 | m->setSegSize(atoi(opt->getValue("segment-size"))); 83 | 84 | std::string h264file; 85 | vector mpds; 86 | std::string folder; 87 | std::string foldername; 88 | std::string h264new; 89 | ifstream infile; 90 | std::string finalMPDhead = ""; 91 | std::string finalMPDbody = ""; 92 | std::string finalMPDfoot = ""; 93 | std::string video_length = ""; 94 | 95 | std::string baseURL = ""; 96 | 97 | std::string exp_name = opt->getValue("dest-directory"); 98 | exp_name.append(opt->getValue("mpd-name")); 99 | 100 | std::string exp_nameNonSeg = opt->getValue("dest-directory"); 101 | exp_nameNonSeg.append("NonSeg"); 102 | exp_nameNonSeg.append(opt->getValue("mpd-name")); 103 | 104 | ofstream mpdexportfile; 105 | mpdexportfile.open(exp_name.c_str()); 106 | 107 | ofstream mpdexportfileNonSeg; 108 | mpdexportfileNonSeg.open(exp_nameNonSeg.c_str()); 109 | 110 | 111 | std::string act = ""; 112 | std::string mpd_temp; 113 | std::string act_line; 114 | std::string act_rep; 115 | 116 | if(opt->getFlag("set-base-url")){ 117 | baseURL = ""; 118 | baseURL.append(opt->getValue("url-root")); 119 | baseURL.append(""); 120 | } 121 | 122 | /************* AUDIO/VIDEO MULTIPLEXING INFORMATION ******************************/ 123 | 124 | if(opt->getValue("mux-combi")!=NULL){ 125 | std::string muxconfig = opt->getValue("mux-combi"); 126 | std::string currentaudio; 127 | std::string bitrates; 128 | do{ 129 | bitrates = muxconfig.substr(0,muxconfig.find('@')); 130 | if(muxconfig.find('|') == std::string::npos){ 131 | currentaudio = muxconfig.substr(muxconfig.find('@')+1); 132 | muxconfig = ""; 133 | } 134 | else{ 135 | currentaudio = muxconfig.substr(muxconfig.find('@')+1, muxconfig.find('|') ); 136 | muxconfig = muxconfig.substr(muxconfig.find('|')+1); 137 | } 138 | do{ 139 | if(bitrates.find(',') == std::string::npos){ 140 | av_mux_mapping[atoi(bitrates.c_str())] = atoi(currentaudio.c_str()); 141 | bitrates = ""; 142 | } 143 | else{ 144 | av_mux_mapping[atoi(bitrates.substr(0,',').c_str())] = atoi(currentaudio.c_str()); 145 | bitrates = bitrates.substr(bitrates.find(',')+1); 146 | } 147 | }while(bitrates.size()>0); 148 | }while(muxconfig.size()>0); 149 | } 150 | 151 | /************************ AUDIO PROCESSING ******************************/ 152 | std::string audio_quality = opt->getValue("audio-quality"); 153 | char*c2 = (char*) malloc(audio_quality.length() * sizeof(char)); 154 | strcpy(c2, audio_quality.c_str()); 155 | char* act_audio = strtok(c2, "|"); 156 | 157 | std::string act_quality = ""; 158 | std::string act_audio_encoding; 159 | std::string act_audio_seg; 160 | 161 | while (act_audio != NULL) 162 | { 163 | 164 | act_quality = act_audio; 165 | a->setChannels(atoi(act_quality.substr(0, act_quality.find(',')).c_str())); 166 | 167 | act_quality = act_quality.substr(act_quality.find(',') + 1); 168 | a->setSamplingRate(atoi(act_quality.substr(0, act_quality.find(',')).c_str())); 169 | 170 | a->setBitrate(atoi(act_quality.substr(act_quality.find(',') + 1).c_str())); 171 | 172 | act_audio_encoding = a->encode(); 173 | 174 | audio_files[a->getBitrate()] = act_audio_encoding; 175 | 176 | if (opt->getValue("mux-combi") == NULL) 177 | { 178 | /************ FOLDER CREATION **********************/ 179 | 180 | foldername = opt->getValue("folder-prefix"); 181 | foldername.append("_"); 182 | foldername.append(DASHHelper::itos(a->getChannels())); 183 | foldername.append("ch_audio_"); 184 | foldername.append(DASHHelper::itos(a->getBitrate())); 185 | foldername.append("kbit"); 186 | 187 | folder = "mkdir "; 188 | folder.append(opt->getValue("dest-directory")); 189 | folder.append(foldername); 190 | system(folder.c_str()); 191 | 192 | folder = "mv "; 193 | folder.append(opt->getValue("dest-directory")); 194 | folder.append(act_audio_encoding); 195 | folder.append(" "); 196 | folder.append(opt->getValue("dest-directory")); 197 | folder.append(foldername); 198 | system(folder.c_str()); 199 | 200 | /************ MULTIPLEXING & SEGMENTATION **************/ 201 | 202 | act_audio_seg = opt->getValue("dest-directory"); 203 | act_audio_seg.append(foldername); 204 | act_audio_seg.append("/"); 205 | act_audio_seg.append(opt->getValue("segment-name")); 206 | 207 | m->setSegName(act_audio_seg); 208 | 209 | act_audio_seg = opt->getValue("dest-directory"); 210 | act_audio_seg.append(foldername); 211 | act_audio_seg.append("/"); 212 | act_audio_seg.append(act_audio_encoding); 213 | 214 | std::string mpd = m->multiplex(act_audio_seg); 215 | 216 | mpds.push_back(mpd); 217 | 218 | /************ MPD READ **********************/ 219 | 220 | mpd_temp = opt->getValue("dest-directory"); 221 | mpd_temp.append(foldername); 222 | mpd_temp.append("/"); 223 | mpd_temp.append(h264file.substr(0, h264file.find_last_of('.'))); 224 | mpd_temp.append("_dash.mpd"); 225 | 226 | infile.open(mpd_temp.c_str(), ifstream::in); 227 | 228 | act_rep = ""; 229 | 230 | if (infile.is_open()) 231 | { 232 | while (infile.good()) 233 | { 234 | getline(infile, act_line); 235 | act_rep.append(act_line); 236 | act_rep.append("\n"); 237 | } 238 | infile.close(); 239 | } 240 | else 241 | cout << "Error: Unable to open MPD file!"; 242 | 243 | act_rep = act_rep.substr(act_rep.find("") - act_rep.find("getOutputDir()) != std::string::npos) 245 | { 246 | act_rep.replace(act_rep.find(m->getOutputDir()), m->getOutputDir().size(), opt->getValue("url-root")); 247 | } 248 | std::cout << "\nDone...\n"; 249 | 250 | mpdgen->appendMPDbody(act_rep); 251 | mpdgen->appendMPDbody("\n"); 252 | } 253 | 254 | act_audio = strtok(NULL, "|"); 255 | } 256 | 257 | /************************ VIDEO PROCESSING ******************************/ 258 | 259 | string bitrates = opt->getValue('b'); 260 | char*c1 = (char*) malloc(bitrates.length() * sizeof(char)); 261 | strcpy(c1, bitrates.c_str()); 262 | char* pch = strtok(c1, "|"); 263 | 264 | 265 | 266 | while (pch != NULL) 267 | { 268 | /************ ENCODING *****************************/ 269 | act = pch; 270 | 271 | if (act.find('@') != std::string::npos) 272 | { 273 | std::cout << act << "\n"; 274 | e->setWidth(atoi(act.substr(act.find('@') + 1, act.find('x') - act.find('@') - 1).c_str())); 275 | e->setHeight(atoi(act.substr(act.find('x') + 1).c_str())); 276 | e->setBitrate(atoi(act.substr(0, act.find('@')).c_str())); 277 | } 278 | else 279 | { 280 | e->setBitrate(atoi(pch)); 281 | } 282 | 283 | h264file = e->encode(); 284 | 285 | 286 | /************ FOLDER CREATION **********************/ 287 | 288 | foldername = opt->getValue("folder-prefix"); 289 | foldername.append("_"); 290 | foldername.append(DASHHelper::itos(e->getBitrate())); 291 | foldername.append("kbit"); 292 | 293 | folder = "mkdir "; 294 | folder.append(opt->getValue("dest-directory")); 295 | folder.append(foldername); 296 | system(folder.c_str()); 297 | 298 | folder = "mv "; 299 | folder.append(opt->getValue("dest-directory")); 300 | folder.append(h264file); 301 | folder.append(" "); 302 | folder.append(opt->getValue("dest-directory")); 303 | folder.append(foldername); 304 | system(folder.c_str()); 305 | 306 | if(opt->getValue("mux-combi")!=NULL){ 307 | 308 | folder = "cp "; 309 | folder.append(opt->getValue("dest-directory")); 310 | folder.append(audio_files[av_mux_mapping[e->getBitrate()]]); 311 | folder.append(" "); 312 | folder.append(opt->getValue("dest-directory")); 313 | folder.append(foldername); 314 | folder.append("/"); 315 | folder.append(audio_files[av_mux_mapping[e->getBitrate()]]); 316 | std::cout << "copy audio: " << folder; 317 | system(folder.c_str()); 318 | } 319 | 320 | /************ STORE STATISTICS *********************/ 321 | /* MySQL Support Disabled 322 | if(opt->getFlag("store-psnr")){ 323 | 324 | mysql_init(&mysql); 325 | 326 | mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, "/opt/lampp/etc/my.cnf"); 327 | //mysql_options(&mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, "/etc/ssl/certs/ComodoIntermediate.pem"); 328 | //mysql_ssl_set(&mysql, NULL, NULL, "/etc/ssl/certs/ComodoIntermediate.pem",NULL, NULL); 329 | 330 | connection = mysql_real_connect(&mysql,opt->getValue("sql-host"),opt->getValue("sql-user"),opt->getValue("sql-pw"),opt->getValue("sql-database"),0,0,0); 331 | 332 | if (connection == NULL) 333 | { 334 | std::cout << "MySQL Error: " << mysql_error(&mysql) << "\n"; 335 | return ; 336 | } 337 | infile.open("out.txt", ifstream::in); 338 | 339 | act_rep = ""; 340 | std::string query; 341 | int posStart; 342 | int posEnd; 343 | 344 | if (infile.is_open()) 345 | { 346 | while (infile.good()) 347 | { 348 | getline(infile, act_line); 349 | if(act_line.find("x264 [debug]: frame=") != std::string::npos){ 350 | //std::cout << act_line << "\n"; 351 | query = "INSERT INTO frames (framenr, type, ypsnr,upsnr, vpsnr, representation) Values ("; 352 | 353 | posStart = act_line.find("frame=")+6; 354 | query.append(act_line.substr(posStart, act_line.find("QP")-posStart)); 355 | query.append(", \""); 356 | 357 | query.append(act_line.substr(act_line.find("Slice:")+6, 1)); 358 | query.append("\", "); 359 | 360 | posStart = act_line.find("Y:")+2; 361 | query.append(act_line.substr(posStart, act_line.find("U:")-posStart)); 362 | query.append(", "); 363 | 364 | posStart = act_line.find("U:")+2; 365 | query.append(act_line.substr(posStart, act_line.find("V:")-posStart)); 366 | query.append(", "); 367 | 368 | query.append(act_line.substr(act_line.find("V:")+2)); 369 | query.append(", \""); 370 | 371 | query.append(foldername); 372 | query.append("\")"); 373 | //std::cout << "\n" << query; 374 | mysql_query(connection, query.c_str()); 375 | } 376 | } 377 | std::cout << "PSNR data stored in MySQL database!"; 378 | infile.close(); 379 | } 380 | else 381 | cout << "Error: Unable to open Log file!"; 382 | } 383 | 384 | */ 385 | /************ MULTIPLEXING & SEGMENTATION **************/ 386 | 387 | h264new = opt->getValue("dest-directory"); 388 | h264new.append(foldername); 389 | h264new.append("/"); 390 | h264new.append(opt->getValue("segment-name")); 391 | 392 | m->setSegName(h264new); 393 | 394 | h264new = opt->getValue("dest-directory"); 395 | h264new.append(foldername); 396 | h264new.append("/"); 397 | h264new.append(h264file); 398 | 399 | if(opt->getValue("mux-combi")!=NULL){ 400 | 401 | std::string af =opt->getValue("dest-directory"); 402 | af.append(foldername); 403 | af.append("/"); 404 | af.append(audio_files[av_mux_mapping[e->getBitrate()]]); 405 | 406 | m->setAudioFile(af); 407 | } 408 | 409 | std::string mpd = m->multiplex(h264new); 410 | mpds.push_back(mpd); 411 | 412 | 413 | 414 | /************ MPD READ **********************/ 415 | 416 | mpd_temp = opt->getValue("dest-directory"); 417 | mpd_temp.append(foldername); 418 | mpd_temp.append("/"); 419 | mpd_temp.append(h264file.substr(0, h264file.find_last_of('.'))); 420 | mpd_temp.append("_dash.mpd"); 421 | 422 | infile.open(mpd_temp.c_str(), ifstream::in); 423 | 424 | act_rep = ""; 425 | 426 | if (infile.is_open()) 427 | { 428 | while (infile.good()) 429 | { 430 | getline(infile, act_line); 431 | act_rep.append(act_line); 432 | act_rep.append("\n"); 433 | } 434 | infile.close(); 435 | } 436 | else 437 | cout << "Error: Unable to open MPD file!"; 438 | 439 | act_rep = act_rep.substr(act_rep.find("") - act_rep.find("getFlag("add-non-segmented")){ 444 | /************ GENERATE UNSEGMENTED FILE *****/ 445 | std::string tmp_rep = act_rep; 446 | tmp_rep = m->unSegment(tmp_rep); 447 | 448 | while (tmp_rep.find(m->getOutputDir()) != std::string::npos) 449 | { 450 | if(opt->getFlag("set-base-url")) 451 | tmp_rep.replace(tmp_rep.find(m->getOutputDir()), m->getOutputDir().size(), ""); 452 | else 453 | tmp_rep.replace(tmp_rep.find(m->getOutputDir()), m->getOutputDir().size(), opt->getValue("url-root")); 454 | } 455 | 456 | if(opt->getFlag("set-base-url")){ 457 | std::string tmp_base = baseURL; 458 | tmp_base.append("\nappendMPDbody(tmp_rep); 462 | mpdgenNonSeg->appendMPDbody("\n"); 463 | } 464 | 465 | while (act_rep.find(m->getOutputDir()) != std::string::npos) 466 | { 467 | if(opt->getFlag("set-base-url")) 468 | act_rep.replace(act_rep.find(m->getOutputDir()), m->getOutputDir().size(), ""); 469 | else 470 | act_rep.replace(act_rep.find(m->getOutputDir()), m->getOutputDir().size(), opt->getValue("url-root")); 471 | } 472 | 473 | if(opt->getFlag("set-base-url")){ 474 | std::string tmp_base = baseURL; 475 | tmp_base.append("\nappendMPDbody(act_rep); 482 | mpdgen->appendMPDbody("\n"); 483 | 484 | e->setWidth(0); 485 | e->setHeight(0); 486 | 487 | pch = strtok(NULL, "|"); 488 | } 489 | 490 | /* MPD Gneration */ 491 | std::cout << "\nWriting final MPD...\n"; 492 | 493 | mpdexportfile << mpdgen->getMPD(); 494 | mpdexportfile.close(); 495 | 496 | if(opt->getFlag("transform-mpd")){ 497 | std::cout << "\nConverting MPDs to actual standard ..."; 498 | convertMPD(exp_name.c_str(), opt->getValue("mpdActStandardPostfix"), opt->getValue("duration"), opt->getValue("url-root"), opt->getValue("minBufferTime"), opt->getValue("segDuration")); 499 | } 500 | 501 | /* Non-Segmented MPD Gneration */ 502 | if(opt->getFlag("add-non-segmented")){ 503 | mpdexportfileNonSeg << mpdgenNonSeg->getMPD(); 504 | mpdexportfileNonSeg.close(); 505 | 506 | /* Run MPD Converion */ 507 | if(opt->getFlag("transform-mpd")){ 508 | std::cout << "\nConverting MPDs to actual standard ..."; 509 | convertMPD(exp_nameNonSeg.c_str(), opt->getValue("mpdActStandardPostfix"), opt->getValue("duration"), opt->getValue("url-root"),opt->getValue("minBufferTime"), opt->getValue("segDuration")); 510 | } 511 | } 512 | std::cout << "\nFINISHED\n"; 513 | delete opt; 514 | } 515 | 516 | void setHelp(AnyOption* opt) 517 | { 518 | opt->addUsage(""); 519 | opt->addUsage("Usage: "); 520 | opt->addUsage(""); 521 | opt->addUsage(" -h --help Print help "); 522 | opt->addUsage(" -i --input Input file"); 523 | opt->addUsage(" -x --pass1 Additional Options: 1st pass video encoding"); 524 | opt->addUsage(" -X --pass2 Additional Options: 2nd pass video encoding"); 525 | opt->addUsage(" -b --bitrate Video bitrates (exmaple: see config file)"); 526 | opt->addUsage(" -s --statistics Statistic file for multi pass video encoding"); 527 | opt->addUsage(" -g --gop GOP Size"); 528 | opt->addUsage(" -c --scenecut Scenecut sensitivity"); 529 | opt->addUsage(" -p --profile h.264 profile"); 530 | opt->addUsage(" -P --preset x264 preset"); 531 | opt->addUsage(" -f --fragment-size Fragment size in seconds"); 532 | opt->addUsage(" -r --rap-aligned Muliplexing at GOP boundaries"); 533 | opt->addUsage(" -o --store-psnr Store PSNR statistics to database"); 534 | opt->addUsage(" -y --sql-host MySQL host"); 535 | opt->addUsage(" -z --sql-user MySQL user"); 536 | opt->addUsage(" -Z --sql-pw MySQL password"); 537 | opt->addUsage(" -Y --sql-database MySQL database"); 538 | opt->addUsage(" -N --segment-name DASH segment name"); 539 | opt->addUsage(" -S --segment-size DASH segment size in seconds"); 540 | opt->addUsage(" -F --folder-prefix Represenation folder prefix"); 541 | opt->addUsage(" -d --dest-directory Destination directory"); 542 | opt->addUsage(" -m --mpd-name MPD name"); 543 | opt->addUsage(" -u --url-root Base url"); 544 | opt->addUsage(" -a --audio-quality Audio qualities (see config file)"); 545 | opt->addUsage(" -I --audio-input Audio source"); 546 | opt->addUsage(" -C --audio-codec Audio codec"); 547 | opt->addUsage(" -M --mux-combi A/V muxing combinations"); 548 | opt->addUsage(" -V --video-encoder Video encoder"); 549 | opt->addUsage(" -A --audio-encoder Audio encoder"); 550 | opt->addUsage(" -R --multiplexer Multiplexing tool"); 551 | opt->addUsage(" -K --const-filesize Encode using constant filesize"); 552 | opt->addUsage(" -k --passes Encoding passes"); 553 | opt->addUsage(" -D --add-non-segmented Generate also non-segmented version"); 554 | opt->addUsage(" -J --set-base-url Use the base url"); 555 | opt->addUsage(" -G --use-ffmpeg-pipe FFMPEG input conversion pipe"); 556 | opt->addUsage(" -g --ffmpeg-opt Additional FFMPEG options"); 557 | opt->addUsage(" -I --input-res Resolution of input video"); 558 | opt->addUsage(" -t --transform-mpd Transform MPD to act standard"); 559 | opt->addUsage(" -T --duration Content duration for MPD"); 560 | opt->addUsage(" -a --mpdActStandardPostfix "); 561 | opt->addUsage(" -B --minBufferTime Minimum Buffer in MPD"); 562 | opt->addUsage(" -e --segDuration Segment Duration for MPD"); 563 | opt->addUsage(""); 564 | } 565 | void setOptions(AnyOption* opt) 566 | { 567 | opt->setFlag("help", 'h'); 568 | opt->setOption("input", 'i'); 569 | opt->setOption("pass1", 'x'); 570 | opt->setOption("pass2", 'X'); 571 | opt->setOption("bitrate", 'b'); 572 | opt->setOption("statistics", 's'); 573 | opt->setOption("gop", 'g'); 574 | opt->setOption("scenecut", 'c'); 575 | opt->setOption("profile", 'p'); 576 | opt->setOption("preset", 'P'); 577 | opt->setOption("fragment-size", 'f'); 578 | opt->setFlag("rap-aligned", 'r'); 579 | opt->setFlag("store-psnr", 'o'); 580 | opt->setOption("segment-name", 'N'); 581 | opt->setOption("segment-size", 'S'); 582 | opt->setOption("folder-prefix", 'F'); 583 | opt->setOption("dest-directory", 'd'); 584 | opt->setOption("mpd-name", 'm'); 585 | opt->setOption("url-root", 'u'); 586 | opt->setOption("audio-quality", 'a'); 587 | opt->setOption("audio-input", 'I'); 588 | opt->setOption("audio-codec", 'C'); 589 | opt->setOption("mux-combi", 'M'); 590 | opt->setOption("video-encoder", 'V'); 591 | opt->setOption("audio-encoder", 'A'); 592 | opt->setOption("multiplexer", 'R'); 593 | opt->setOption("const-filesize", 'K'); 594 | opt->setOption("passes", 'k'); 595 | opt->setOption("sql-host", 'y'); 596 | opt->setOption("sql-user", 'z'); 597 | opt->setOption("sql-pw", 'Z'); 598 | opt->setOption("sql-database", 'Y'); 599 | opt->setFlag("add-non-segmented", 'D'); 600 | opt->setFlag("set-base-url", 'J'); 601 | opt->setFlag("use-ffmpeg-pipe", 'G'); 602 | opt->setOption("ffmpeg-opt", 'g'); 603 | opt->setOption("input-res", 'I'); 604 | opt->setFlag("transform-mpd", 't'); 605 | opt->setOption("duration", 'T'); 606 | opt->setOption("mpdActStandardPostfix", 'a'); 607 | opt->setOption("minBufferTime", 'B'); 608 | opt->setOption("segDuration", 'e'); 609 | } 610 | 611 | IEncoder::EncoderType getEncoder(std::string e){ 612 | if(e.compare("vp8")==0) 613 | return IEncoder::vp8; 614 | else if(e.compare("ffmpegAAC")==0) 615 | return IEncoder::ffmpegAAC; 616 | else if(e.compare("x264")==0) 617 | return IEncoder::x264; 618 | 619 | return IEncoder::x264; 620 | } 621 | int convertMPD(std::string input, std::string output, std::string duration, std::string baseurl, std::string minbuffer, std::string segduration){ 622 | std::cout << "\nConvert the to act DASH standard: " << input << "\nto: " << output << "\n"; 623 | 624 | string mpd_temp = "", act_line = "", temp; 625 | string filename = input; 626 | 627 | temp = ".mpd"; 628 | filename.replace(filename.find(temp), temp.length(),output); 629 | 630 | ofstream mpdexportfile; 631 | mpdexportfile.open(filename.c_str()); 632 | 633 | 634 | ifstream infile; 635 | 636 | infile.open(input.c_str(), ifstream::in); 637 | 638 | 639 | 640 | if (infile.is_open()) 641 | { 642 | while (infile.good()) 643 | { 644 | getline(infile, act_line); 645 | mpd_temp.append(act_line); 646 | mpd_temp.append("\n"); 647 | } 648 | infile.close(); 649 | } 650 | else 651 | cout << "Error: Unable to open MPD file!"; 652 | 653 | string finalMPDhead, finalMPDfoot, finalMPDbody; 654 | int pos; 655 | 656 | finalMPDhead.append("\n"); 657 | finalMPDhead.append(" \n"); 672 | /* pos = mpd_temp.find("minBufferTime"); 673 | if(pos != std::string::npos){ 674 | pos = pos + 15; 675 | temp = mpd_temp.substr(pos,mpd_temp.find("\"", pos)- pos ); 676 | pos = temp.length(); //1000 677 | string millisec, sec; 678 | millisec = temp.substr(pos-3,1); 679 | sec = temp.substr(0,pos-3); 680 | finalMPDhead.append(sec); 681 | finalMPDhead.append("."); 682 | finalMPDhead.append(millisec); 683 | finalMPDhead.append("\"> \n"); 684 | } 685 | else{ 686 | std::cout << "ERROR: Could not find buffer time!\n"; 687 | std::cout << mpd_temp; 688 | return 1; 689 | }*/ 690 | 691 | //adding base URL 692 | finalMPDhead.append(" "); 693 | finalMPDhead.append(baseurl); 694 | finalMPDhead.append("\n"); 695 | finalMPDhead.append(" \n"); 696 | finalMPDhead.append(" \n"); 697 | mpdexportfile << finalMPDhead; 698 | 699 | 700 | finalMPDfoot.append(" \n"); 701 | finalMPDfoot.append(" \n"); 702 | finalMPDfoot.append("\n"); 703 | 704 | 705 | finalMPDbody = ""; 706 | 707 | int lastRep = 0, id = 0; 708 | string act_rep, finalRep, temp2; 709 | 710 | 711 | while(mpd_temp.find("", lastRep)+ 17 - mpd_temp.find("", lastRep)+ 17; 714 | 715 | finalRep = ""; 716 | 717 | string addID = "")); 730 | temp.append(">\n"); 731 | finalRep.append(temp); 732 | 733 | 734 | //add init segment 735 | pos = act_rep.find("", pos)+2 - pos); 737 | temp2 = "InitialisationSegmentURL"; 738 | temp.replace(temp.find(temp2), temp2.length(), "Initialisation"); 739 | pos = act_rep.find("/>", pos)+2; 740 | 741 | finalRep.append("\n "); 742 | finalRep.append(temp); 743 | finalRep.append("\n\n"); 744 | 745 | //add segments 746 | finalRep.append(""); 749 | temp = act_rep.substr(pos, act_rep.find("",pos) -pos); 750 | temp2 = "\n"); 761 | finalRep.append("\n"); 762 | 763 | mpdexportfile << finalRep; 764 | id++; 765 | } 766 | 767 | 768 | mpdexportfile << finalMPDfoot; 769 | mpdexportfile.close(); 770 | 771 | return 0; 772 | } 773 | -------------------------------------------------------------------------------- /AnyOption.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AnyOption 1.3 3 | * 4 | * kishan at hackorama dot com www.hackorama.com JULY 2001 5 | * 6 | * + Acts as a common facade class for reading 7 | * commandline options as well as options from 8 | * an optionfile with delimited type value pairs 9 | * 10 | * + Handles the POSIX style single character options ( -w ) 11 | * as well as the newer GNU long options ( --width ) 12 | * 13 | * + The option file assumes the traditional format of 14 | * first character based comment lines and type value 15 | * pairs with a delimiter , and flags which are not pairs 16 | * 17 | * # this is a coment 18 | * # next line is an option value pair 19 | * width : 100 20 | * # next line is a flag 21 | * noimages 22 | * 23 | * + Supports printing out Help and Usage 24 | * 25 | * + Why not just use getopt() ? 26 | * 27 | * getopt() Its a POSIX standard not part of ANSI-C. 28 | * So it may not be available on platforms like Windows. 29 | * 30 | * + Why it is so long ? 31 | * 32 | * The actual code which does command line parsing 33 | * and option file parsing are done in few methods. 34 | * Most of the extra code are for providing a flexible 35 | * common public interface to both a resourcefile and 36 | * and command line supporting POSIX style and 37 | * GNU long option as well as mixing of both. 38 | * 39 | * + Please see "anyoption.h" for public method descriptions 40 | * 41 | */ 42 | 43 | /* Updated Auguest 2004 44 | * Fix from Michael D Peters (mpeters at sandia.gov) 45 | * to remove static local variables, allowing multiple instantiations 46 | * of the reader (for using multiple configuration files). There is 47 | * an error in the destructor when using multiple instances, so you 48 | * cannot delete your objects (it will crash), but not calling the 49 | * destructor only introduces a small memory leak, so I 50 | * have not bothered tracking it down. 51 | * 52 | * Also updated to use modern C++ style headers, rather than 53 | * depricated iostream.h (it was causing my compiler problems) 54 | */ 55 | 56 | /* 57 | * Updated September 2006 58 | * Fix from Boyan Asenov for a bug in mixing up option indexes 59 | * leading to exception when mixing different options types 60 | */ 61 | 62 | #include "AnyOption.h" 63 | 64 | 65 | 66 | AnyOption::AnyOption() 67 | { 68 | init(); 69 | } 70 | 71 | AnyOption::AnyOption(int maxopt) 72 | { 73 | init( maxopt , maxopt ); 74 | } 75 | 76 | AnyOption::AnyOption(int maxopt, int maxcharopt) 77 | { 78 | init( maxopt , maxcharopt ); 79 | } 80 | 81 | AnyOption::~AnyOption() 82 | { 83 | if( mem_allocated ) 84 | cleanup(); 85 | } 86 | 87 | void 88 | AnyOption::init() 89 | { 90 | init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS ); 91 | } 92 | 93 | void 94 | AnyOption::init(int maxopt, int maxcharopt ) 95 | { 96 | 97 | max_options = maxopt; 98 | max_char_options = maxcharopt; 99 | max_usage_lines = DEFAULT_MAXUSAGE; 100 | usage_lines = 0 ; 101 | argc = 0; 102 | argv = NULL; 103 | posix_style = true; 104 | verbose = false; 105 | filename = NULL; 106 | appname = NULL; 107 | option_counter = 0; 108 | optchar_counter = 0; 109 | new_argv = NULL; 110 | new_argc = 0 ; 111 | max_legal_args = 0 ; 112 | command_set = false; 113 | file_set = false; 114 | values = NULL; 115 | g_value_counter = 0; 116 | mem_allocated = false; 117 | command_set = false; 118 | file_set = false; 119 | opt_prefix_char = '-'; 120 | file_delimiter_char = ':'; 121 | file_comment_char = '#'; 122 | equalsign = '='; 123 | comment = '#' ; 124 | delimiter = ':' ; 125 | endofline = '\n'; 126 | whitespace = ' ' ; 127 | nullterminate = '\0'; 128 | set = false; 129 | once = true; 130 | hasoptions = false; 131 | autousage = false; 132 | 133 | strcpy( long_opt_prefix , "--" ); 134 | 135 | if( alloc() == false ){ 136 | cout << endl << "OPTIONS ERROR : Failed allocating memory" ; 137 | cout << endl ; 138 | cout << "Exiting." << endl ; 139 | exit (0); 140 | } 141 | } 142 | 143 | bool 144 | AnyOption::alloc() 145 | { 146 | int i = 0 ; 147 | int size = 0 ; 148 | 149 | if( mem_allocated ) 150 | return true; 151 | 152 | size = (max_options+1) * sizeof(const char*); 153 | options = (const char**)malloc( size ); 154 | optiontype = (int*) malloc( (max_options+1)*sizeof(int) ); 155 | optionindex = (int*) malloc( (max_options+1)*sizeof(int) ); 156 | if( options == NULL || optiontype == NULL || optionindex == NULL ) 157 | return false; 158 | else 159 | mem_allocated = true; 160 | for( i = 0 ; i < max_options ; i++ ){ 161 | options[i] = NULL; 162 | optiontype[i] = 0 ; 163 | optionindex[i] = -1 ; 164 | } 165 | optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) ); 166 | optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) ); 167 | optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) ); 168 | if( optionchars == NULL || 169 | optchartype == NULL || 170 | optcharindex == NULL ) 171 | { 172 | mem_allocated = false; 173 | return false; 174 | } 175 | for( i = 0 ; i < max_char_options ; i++ ){ 176 | optionchars[i] = '0'; 177 | optchartype[i] = 0 ; 178 | optcharindex[i] = -1 ; 179 | } 180 | 181 | size = (max_usage_lines+1) * sizeof(const char*) ; 182 | usage = (const char**) malloc( size ); 183 | 184 | if( usage == NULL ){ 185 | mem_allocated = false; 186 | return false; 187 | } 188 | for( i = 0 ; i < max_usage_lines ; i++ ) 189 | usage[i] = NULL; 190 | 191 | return true; 192 | } 193 | 194 | bool 195 | AnyOption::doubleOptStorage() 196 | { 197 | options = (const char**)realloc( options, 198 | ((2*max_options)+1) * sizeof( const char*) ); 199 | optiontype = (int*) realloc( optiontype , 200 | ((2 * max_options)+1)* sizeof(int) ); 201 | optionindex = (int*) realloc( optionindex, 202 | ((2 * max_options)+1) * sizeof(int) ); 203 | if( options == NULL || optiontype == NULL || optionindex == NULL ) 204 | return false; 205 | /* init new storage */ 206 | for( int i = max_options ; i < 2*max_options ; i++ ){ 207 | options[i] = NULL; 208 | optiontype[i] = 0 ; 209 | optionindex[i] = -1 ; 210 | } 211 | max_options = 2 * max_options ; 212 | return true; 213 | } 214 | 215 | bool 216 | AnyOption::doubleCharStorage() 217 | { 218 | optionchars = (char*) realloc( optionchars, 219 | ((2*max_char_options)+1)*sizeof(char) ); 220 | optchartype = (int*) realloc( optchartype, 221 | ((2*max_char_options)+1)*sizeof(int) ); 222 | optcharindex = (int*) realloc( optcharindex, 223 | ((2*max_char_options)+1)*sizeof(int) ); 224 | if( optionchars == NULL || 225 | optchartype == NULL || 226 | optcharindex == NULL ) 227 | return false; 228 | /* init new storage */ 229 | for( int i = max_char_options ; i < 2*max_char_options ; i++ ){ 230 | optionchars[i] = '0'; 231 | optchartype[i] = 0 ; 232 | optcharindex[i] = -1 ; 233 | } 234 | max_char_options = 2 * max_char_options; 235 | return true; 236 | } 237 | 238 | bool 239 | AnyOption::doubleUsageStorage() 240 | { 241 | usage = (const char**)realloc( usage, 242 | ((2*max_usage_lines)+1) * sizeof( const char*) ); 243 | if ( usage == NULL ) 244 | return false; 245 | for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ ) 246 | usage[i] = NULL; 247 | max_usage_lines = 2 * max_usage_lines ; 248 | return true; 249 | 250 | } 251 | 252 | 253 | void 254 | AnyOption::cleanup() 255 | { 256 | free (options); 257 | free (optiontype); 258 | free (optionindex); 259 | free (optionchars); 260 | free (optchartype); 261 | free (optcharindex); 262 | free (usage); 263 | if( values != NULL ) 264 | free (values); 265 | if( new_argv != NULL ) 266 | free (new_argv); 267 | } 268 | 269 | void 270 | AnyOption::setCommandPrefixChar( char _prefix ) 271 | { 272 | opt_prefix_char = _prefix; 273 | } 274 | 275 | void 276 | AnyOption::setCommandLongPrefix( char *_prefix ) 277 | { 278 | if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){ 279 | *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; 280 | } 281 | 282 | strcpy (long_opt_prefix, _prefix); 283 | } 284 | 285 | void 286 | AnyOption::setFileCommentChar( char _comment ) 287 | { 288 | file_delimiter_char = _comment; 289 | } 290 | 291 | 292 | void 293 | AnyOption::setFileDelimiterChar( char _delimiter ) 294 | { 295 | file_comment_char = _delimiter ; 296 | } 297 | 298 | bool 299 | AnyOption::CommandSet() 300 | { 301 | return( command_set ); 302 | } 303 | 304 | bool 305 | AnyOption::FileSet() 306 | { 307 | return( file_set ); 308 | } 309 | 310 | void 311 | AnyOption::noPOSIX() 312 | { 313 | posix_style = false; 314 | } 315 | 316 | bool 317 | AnyOption::POSIX() 318 | { 319 | return posix_style; 320 | } 321 | 322 | 323 | void 324 | AnyOption::setVerbose() 325 | { 326 | verbose = true ; 327 | } 328 | 329 | void 330 | AnyOption::printVerbose() 331 | { 332 | if( verbose ) 333 | cout << endl ; 334 | } 335 | void 336 | AnyOption::printVerbose( const char *msg ) 337 | { 338 | if( verbose ) 339 | cout << msg ; 340 | } 341 | 342 | void 343 | AnyOption::printVerbose( char *msg ) 344 | { 345 | if( verbose ) 346 | cout << msg ; 347 | } 348 | 349 | void 350 | AnyOption::printVerbose( char ch ) 351 | { 352 | if( verbose ) 353 | cout << ch ; 354 | } 355 | 356 | bool 357 | AnyOption::hasOptions() 358 | { 359 | return hasoptions; 360 | } 361 | 362 | void 363 | AnyOption::autoUsagePrint(bool _autousage) 364 | { 365 | autousage = _autousage; 366 | } 367 | 368 | void 369 | AnyOption::useCommandArgs( int _argc, char **_argv ) 370 | { 371 | argc = _argc; 372 | argv = _argv; 373 | command_set = true; 374 | appname = argv[0]; 375 | if(argc > 1) hasoptions = true; 376 | } 377 | 378 | void 379 | AnyOption::useFiileName( const char *_filename ) 380 | { 381 | filename = _filename; 382 | file_set = true; 383 | } 384 | 385 | /* 386 | * set methods for options 387 | */ 388 | 389 | void 390 | AnyOption::setCommandOption( const char *opt ) 391 | { 392 | addOption( opt , COMMAND_OPT ); 393 | g_value_counter++; 394 | } 395 | 396 | void 397 | AnyOption::setCommandOption( char opt ) 398 | { 399 | addOption( opt , COMMAND_OPT ); 400 | g_value_counter++; 401 | } 402 | 403 | void 404 | AnyOption::setCommandOption( const char *opt , char optchar ) 405 | { 406 | addOption( opt , COMMAND_OPT ); 407 | addOption( optchar , COMMAND_OPT ); 408 | g_value_counter++; 409 | } 410 | 411 | void 412 | AnyOption::setCommandFlag( const char *opt ) 413 | { 414 | addOption( opt , COMMAND_FLAG ); 415 | g_value_counter++; 416 | } 417 | 418 | void 419 | AnyOption::setCommandFlag( char opt ) 420 | { 421 | addOption( opt , COMMAND_FLAG ); 422 | g_value_counter++; 423 | } 424 | 425 | void 426 | AnyOption::setCommandFlag( const char *opt , char optchar ) 427 | { 428 | addOption( opt , COMMAND_FLAG ); 429 | addOption( optchar , COMMAND_FLAG ); 430 | g_value_counter++; 431 | } 432 | 433 | void 434 | AnyOption::setFileOption( const char *opt ) 435 | { 436 | addOption( opt , FILE_OPT ); 437 | g_value_counter++; 438 | } 439 | 440 | void 441 | AnyOption::setFileOption( char opt ) 442 | { 443 | addOption( opt , FILE_OPT ); 444 | g_value_counter++; 445 | } 446 | 447 | void 448 | AnyOption::setFileOption( const char *opt , char optchar ) 449 | { 450 | addOption( opt , FILE_OPT ); 451 | addOption( optchar, FILE_OPT ); 452 | g_value_counter++; 453 | } 454 | 455 | void 456 | AnyOption::setFileFlag( const char *opt ) 457 | { 458 | addOption( opt , FILE_FLAG ); 459 | g_value_counter++; 460 | } 461 | 462 | void 463 | AnyOption::setFileFlag( char opt ) 464 | { 465 | addOption( opt , FILE_FLAG ); 466 | g_value_counter++; 467 | } 468 | 469 | void 470 | AnyOption::setFileFlag( const char *opt , char optchar ) 471 | { 472 | addOption( opt , FILE_FLAG ); 473 | addOption( optchar , FILE_FLAG ); 474 | g_value_counter++; 475 | } 476 | 477 | void 478 | AnyOption::setOption( const char *opt ) 479 | { 480 | addOption( opt , COMMON_OPT ); 481 | g_value_counter++; 482 | } 483 | 484 | void 485 | AnyOption::setOption( char opt ) 486 | { 487 | addOption( opt , COMMON_OPT ); 488 | g_value_counter++; 489 | } 490 | 491 | void 492 | AnyOption::setOption( const char *opt , char optchar ) 493 | { 494 | addOption( opt , COMMON_OPT ); 495 | addOption( optchar , COMMON_OPT ); 496 | g_value_counter++; 497 | } 498 | 499 | void 500 | AnyOption::setFlag( const char *opt ) 501 | { 502 | addOption( opt , COMMON_FLAG ); 503 | g_value_counter++; 504 | } 505 | 506 | void 507 | AnyOption::setFlag( const char opt ) 508 | { 509 | addOption( opt , COMMON_FLAG ); 510 | g_value_counter++; 511 | } 512 | 513 | void 514 | AnyOption::setFlag( const char *opt , char optchar ) 515 | { 516 | addOption( opt , COMMON_FLAG ); 517 | addOption( optchar , COMMON_FLAG ); 518 | g_value_counter++; 519 | } 520 | 521 | void 522 | AnyOption::addOption( const char *opt, int type ) 523 | { 524 | if( option_counter >= max_options ){ 525 | if( doubleOptStorage() == false ){ 526 | addOptionError( opt ); 527 | return; 528 | } 529 | } 530 | options[ option_counter ] = opt ; 531 | optiontype[ option_counter ] = type ; 532 | optionindex[ option_counter ] = g_value_counter; 533 | option_counter++; 534 | } 535 | 536 | void 537 | AnyOption::addOption( char opt, int type ) 538 | { 539 | if( !POSIX() ){ 540 | printVerbose("Ignoring the option character \""); 541 | printVerbose( opt ); 542 | printVerbose( "\" ( POSIX options are turned off )" ); 543 | printVerbose(); 544 | return; 545 | } 546 | 547 | 548 | if( optchar_counter >= max_char_options ){ 549 | if( doubleCharStorage() == false ){ 550 | addOptionError( opt ); 551 | return; 552 | } 553 | } 554 | optionchars[ optchar_counter ] = opt ; 555 | optchartype[ optchar_counter ] = type ; 556 | optcharindex[ optchar_counter ] = g_value_counter; 557 | optchar_counter++; 558 | } 559 | 560 | void 561 | AnyOption::addOptionError( const char *opt ) 562 | { 563 | cout << endl ; 564 | cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; 565 | cout << "While adding the option : \""<< opt << "\"" << endl; 566 | cout << "Exiting." << endl ; 567 | cout << endl ; 568 | exit(0); 569 | } 570 | 571 | void 572 | AnyOption::addOptionError( char opt ) 573 | { 574 | cout << endl ; 575 | cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; 576 | cout << "While adding the option: \""<< opt << "\"" << endl; 577 | cout << "Exiting." << endl ; 578 | cout << endl ; 579 | exit(0); 580 | } 581 | 582 | void 583 | AnyOption::processOptions() 584 | { 585 | if( ! valueStoreOK() ) 586 | return; 587 | } 588 | 589 | void 590 | AnyOption::processCommandArgs(int max_args) 591 | { 592 | max_legal_args = max_args; 593 | processCommandArgs(); 594 | } 595 | 596 | void 597 | AnyOption::processCommandArgs( int _argc, char **_argv, int max_args ) 598 | { 599 | max_legal_args = max_args; 600 | processCommandArgs( _argc, _argv ); 601 | } 602 | 603 | void 604 | AnyOption::processCommandArgs( int _argc, char **_argv ) 605 | { 606 | useCommandArgs( _argc, _argv ); 607 | processCommandArgs(); 608 | } 609 | 610 | void 611 | AnyOption::processCommandArgs() 612 | { 613 | if( ! ( valueStoreOK() && CommandSet() ) ) 614 | return; 615 | 616 | if( max_legal_args == 0 ) 617 | max_legal_args = argc; 618 | new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) ); 619 | for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */ 620 | if( argv[i][0] == long_opt_prefix[0] && 621 | argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */ 622 | int match_at = parseGNU( argv[i]+2 ); /* skip -- */ 623 | if( match_at >= 0 && i < argc-1 ) /* found match */ 624 | setValue( options[match_at] , argv[++i] ); 625 | }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */ 626 | if( POSIX() ){ 627 | char ch = parsePOSIX( argv[i]+1 );/* skip - */ 628 | if( ch != '0' && i < argc-1 ) /* matching char */ 629 | setValue( ch , argv[++i] ); 630 | } else { /* treat it as GNU option with a - */ 631 | int match_at = parseGNU( argv[i]+1 ); /* skip - */ 632 | if( match_at >= 0 && i < argc-1 ) /* found match */ 633 | setValue( options[match_at] , argv[++i] ); 634 | } 635 | }else { /* not option but an argument keep index */ 636 | if( new_argc < max_legal_args ){ 637 | new_argv[ new_argc ] = i ; 638 | new_argc++; 639 | }else{ /* ignore extra arguments */ 640 | printVerbose( "Ignoring extra argument: " ); 641 | printVerbose( argv[i] ); 642 | printVerbose( ); 643 | printAutoUsage(); 644 | } 645 | printVerbose( "Unknown command argument option : " ); 646 | printVerbose( argv[i] ); 647 | printVerbose( ); 648 | printAutoUsage(); 649 | } 650 | } 651 | } 652 | 653 | char 654 | AnyOption::parsePOSIX( char* arg ) 655 | { 656 | 657 | for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 658 | char ch = arg[i] ; 659 | if( matchChar(ch) ) { /* keep matching flags till an option */ 660 | /*if last char argv[++i] is the value */ 661 | if( i == strlen(arg)-1 ){ 662 | return ch; 663 | }else{/* else the rest of arg is the value */ 664 | i++; /* skip any '=' and ' ' */ 665 | while( arg[i] == whitespace 666 | || arg[i] == equalsign ) 667 | i++; 668 | setValue( ch , arg+i ); 669 | return '0'; 670 | } 671 | } 672 | } 673 | printVerbose( "Unknown command argument option : " ); 674 | printVerbose( arg ); 675 | printVerbose( ); 676 | printAutoUsage(); 677 | return '0'; 678 | } 679 | 680 | int 681 | AnyOption::parseGNU( char *arg ) 682 | { 683 | int split_at = 0; 684 | /* if has a '=' sign get value */ 685 | for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 686 | if(arg[i] == equalsign ){ 687 | split_at = i ; /* store index */ 688 | i = strlen(arg); /* get out of loop */ 689 | } 690 | } 691 | if( split_at > 0 ){ /* it is an option value pair */ 692 | char* tmp = (char*) malloc( (split_at+1)*sizeof(char) ); 693 | for( int i = 0 ; i < split_at ; i++ ) 694 | tmp[i] = arg[i]; 695 | tmp[split_at] = '\0'; 696 | 697 | if ( matchOpt( tmp ) >= 0 ){ 698 | setValue( options[matchOpt(tmp)] , arg+split_at+1 ); 699 | free (tmp); 700 | }else{ 701 | printVerbose( "Unknown command argument option : " ); 702 | printVerbose( arg ); 703 | printVerbose( ); 704 | printAutoUsage(); 705 | free (tmp); 706 | return -1; 707 | } 708 | }else{ /* regular options with no '=' sign */ 709 | return matchOpt(arg); 710 | } 711 | return -1; 712 | } 713 | 714 | 715 | int 716 | AnyOption::matchOpt( char *opt ) 717 | { 718 | for( int i = 0 ; i < option_counter ; i++ ){ 719 | if( strcmp( options[i], opt ) == 0 ){ 720 | if( optiontype[i] == COMMON_OPT || 721 | optiontype[i] == COMMAND_OPT ) 722 | { /* found option return index */ 723 | return i; 724 | }else if( optiontype[i] == COMMON_FLAG || 725 | optiontype[i] == COMMAND_FLAG ) 726 | { /* found flag, set it */ 727 | setFlagOn( opt ); 728 | return -1; 729 | } 730 | } 731 | } 732 | printVerbose( "Unknown command argument option : " ); 733 | printVerbose( opt ) ; 734 | printVerbose( ); 735 | printAutoUsage(); 736 | return -1; 737 | } 738 | bool 739 | AnyOption::matchChar( char c ) 740 | { 741 | for( int i = 0 ; i < optchar_counter ; i++ ){ 742 | if( optionchars[i] == c ) { /* found match */ 743 | if(optchartype[i] == COMMON_OPT || 744 | optchartype[i] == COMMAND_OPT ) 745 | { /* an option store and stop scanning */ 746 | return true; 747 | }else if( optchartype[i] == COMMON_FLAG || 748 | optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */ 749 | setFlagOn( c ); 750 | return false; 751 | } 752 | } 753 | } 754 | printVerbose( "Unknown command argument option : " ); 755 | printVerbose( c ) ; 756 | printVerbose( ); 757 | printAutoUsage(); 758 | return false; 759 | } 760 | 761 | bool 762 | AnyOption::valueStoreOK( ) 763 | { 764 | int size= 0; 765 | if( !set ){ 766 | if( g_value_counter > 0 ){ 767 | size = g_value_counter * sizeof(char*); 768 | values = (char**)malloc( size ); 769 | for( int i = 0 ; i < g_value_counter ; i++) 770 | values[i] = NULL; 771 | set = true; 772 | } 773 | } 774 | return set; 775 | } 776 | 777 | /* 778 | * public get methods 779 | */ 780 | char* 781 | AnyOption::getValue( const char *option ) 782 | { 783 | if( !valueStoreOK() ) 784 | return NULL; 785 | 786 | for( int i = 0 ; i < option_counter ; i++ ){ 787 | if( strcmp( options[i], option ) == 0 ) 788 | return values[ optionindex[i] ]; 789 | } 790 | return NULL; 791 | } 792 | 793 | bool 794 | AnyOption::getFlag( const char *option ) 795 | { 796 | if( !valueStoreOK() ) 797 | return false; 798 | for( int i = 0 ; i < option_counter ; i++ ){ 799 | if( strcmp( options[i], option ) == 0 ) 800 | return findFlag( values[ optionindex[i] ] ); 801 | } 802 | return false; 803 | } 804 | 805 | char* 806 | AnyOption::getValue( char option ) 807 | { 808 | if( !valueStoreOK() ) 809 | return NULL; 810 | for( int i = 0 ; i < optchar_counter ; i++ ){ 811 | if( optionchars[i] == option ) 812 | return values[ optcharindex[i] ]; 813 | } 814 | return NULL; 815 | } 816 | 817 | bool 818 | AnyOption::getFlag( char option ) 819 | { 820 | if( !valueStoreOK() ) 821 | return false; 822 | for( int i = 0 ; i < optchar_counter ; i++ ){ 823 | if( optionchars[i] == option ) 824 | return findFlag( values[ optcharindex[i] ] ) ; 825 | } 826 | return false; 827 | } 828 | 829 | bool 830 | AnyOption::findFlag( char* val ) 831 | { 832 | if( val == NULL ) 833 | return false; 834 | 835 | if( strcmp( TRUE_FLAG , val ) == 0 ) 836 | return true; 837 | 838 | return false; 839 | } 840 | 841 | /* 842 | * private set methods 843 | */ 844 | bool 845 | AnyOption::setValue( const char *option , char *value ) 846 | { 847 | if( !valueStoreOK() ) 848 | return false; 849 | for( int i = 0 ; i < option_counter ; i++ ){ 850 | if( strcmp( options[i], option ) == 0 ){ 851 | values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char)); 852 | strcpy( values[ optionindex[i] ], value ); 853 | return true; 854 | } 855 | } 856 | return false; 857 | } 858 | 859 | bool 860 | AnyOption::setFlagOn( const char *option ) 861 | { 862 | if( !valueStoreOK() ) 863 | return false; 864 | for( int i = 0 ; i < option_counter ; i++ ){ 865 | if( strcmp( options[i], option ) == 0 ){ 866 | values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char)); 867 | strcpy( values[ optionindex[i] ] , TRUE_FLAG ); 868 | return true; 869 | } 870 | } 871 | return false; 872 | } 873 | 874 | bool 875 | AnyOption::setValue( char option , char *value ) 876 | { 877 | if( !valueStoreOK() ) 878 | return false; 879 | for( int i = 0 ; i < optchar_counter ; i++ ){ 880 | if( optionchars[i] == option ){ 881 | values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char)); 882 | strcpy( values[ optcharindex[i] ], value ); 883 | return true; 884 | } 885 | } 886 | return false; 887 | } 888 | 889 | bool 890 | AnyOption::setFlagOn( char option ) 891 | { 892 | if( !valueStoreOK() ) 893 | return false; 894 | for( int i = 0 ; i < optchar_counter ; i++ ){ 895 | if( optionchars[i] == option ){ 896 | values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char)); 897 | strcpy( values[ optcharindex[i] ] , TRUE_FLAG ); 898 | return true; 899 | } 900 | } 901 | return false; 902 | } 903 | 904 | 905 | int 906 | AnyOption::getArgc( ) 907 | { 908 | return new_argc; 909 | } 910 | 911 | char* 912 | AnyOption::getArgv( int index ) 913 | { 914 | if( index < new_argc ){ 915 | return ( argv[ new_argv[ index ] ] ); 916 | } 917 | return NULL; 918 | } 919 | 920 | /* dotfile sub routines */ 921 | 922 | bool 923 | AnyOption::processFile() 924 | { 925 | if( ! (valueStoreOK() && FileSet()) ) 926 | return false; 927 | return ( consumeFile(readFile()) ); 928 | } 929 | 930 | bool 931 | AnyOption::processFile( const char *filename ) 932 | { 933 | useFiileName(filename ); 934 | return ( processFile() ); 935 | } 936 | 937 | char* 938 | AnyOption::readFile() 939 | { 940 | return ( readFile(filename) ); 941 | } 942 | 943 | /* 944 | * read the file contents to a character buffer 945 | */ 946 | 947 | char* 948 | AnyOption::readFile( const char* fname ) 949 | { 950 | int length; 951 | char *buffer; 952 | ifstream is; 953 | is.open ( fname , ifstream::in ); 954 | if( ! is.good() ){ 955 | is.close(); 956 | return NULL; 957 | } 958 | is.seekg (0, ios::end); 959 | length = is.tellg(); 960 | is.seekg (0, ios::beg); 961 | buffer = (char*) malloc(length*sizeof(char)); 962 | is.read (buffer,length); 963 | is.close(); 964 | return buffer; 965 | } 966 | 967 | /* 968 | * scans a char* buffer for lines that does not 969 | * start with the specified comment character. 970 | */ 971 | bool 972 | AnyOption::consumeFile( char *buffer ) 973 | { 974 | 975 | if( buffer == NULL ) 976 | return false; 977 | 978 | char *cursor = buffer;/* preserve the ptr */ 979 | char *pline = NULL ; 980 | int linelength = 0; 981 | bool newline = true; 982 | for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){ 983 | if( *cursor == endofline ) { /* end of line */ 984 | if( pline != NULL ) /* valid line */ 985 | processLine( pline, linelength ); 986 | pline = NULL; 987 | newline = true; 988 | }else if( newline ){ /* start of line */ 989 | newline = false; 990 | if( (*cursor != comment ) ){ /* not a comment */ 991 | pline = cursor ; 992 | linelength = 0 ; 993 | } 994 | } 995 | cursor++; /* keep moving */ 996 | linelength++; 997 | } 998 | free (buffer); 999 | return true; 1000 | } 1001 | 1002 | 1003 | /* 1004 | * find a valid type value pair separated by a delimiter 1005 | * character and pass it to valuePairs() 1006 | * any line which is not valid will be considered a value 1007 | * and will get passed on to justValue() 1008 | * 1009 | * assuming delimiter is ':' the behaviour will be, 1010 | * 1011 | * width:10 - valid pair valuePairs( width, 10 ); 1012 | * width : 10 - valid pair valuepairs( width, 10 ); 1013 | * 1014 | * :::: - not valid 1015 | * width - not valid 1016 | * :10 - not valid 1017 | * width: - not valid 1018 | * :: - not valid 1019 | * : - not valid 1020 | * 1021 | */ 1022 | 1023 | void 1024 | AnyOption::processLine( char *theline, int length ) 1025 | { 1026 | bool found = false; 1027 | char *pline = (char*) malloc( (length+1)*sizeof(char) ); 1028 | for( int i = 0 ; i < length ; i ++ ) 1029 | pline[i]= *(theline++); 1030 | pline[length] = nullterminate; 1031 | char *cursor = pline ; /* preserve the ptr */ 1032 | if( *cursor == delimiter || *(cursor+length-1) == delimiter ){ 1033 | justValue( pline );/* line with start/end delimiter */ 1034 | }else{ 1035 | for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */ 1036 | if( *cursor == delimiter ){ 1037 | *(cursor-1) = nullterminate; /* two strings */ 1038 | found = true; 1039 | valuePairs( pline , cursor+1 ); 1040 | } 1041 | cursor++; 1042 | } 1043 | cursor++; 1044 | if( !found ) /* not a pair */ 1045 | justValue( pline ); 1046 | } 1047 | free (pline); 1048 | } 1049 | 1050 | /* 1051 | * removes trailing and preceeding whitespaces from a string 1052 | */ 1053 | char* 1054 | AnyOption::chomp( char *str ) 1055 | { 1056 | while( *str == whitespace ) 1057 | str++; 1058 | char *end = str+strlen(str)-1; 1059 | while( *end == whitespace ) 1060 | end--; 1061 | *(end+1) = nullterminate; 1062 | return str; 1063 | } 1064 | 1065 | void 1066 | AnyOption::valuePairs( char *type, char *value ) 1067 | { 1068 | if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ 1069 | for( int i = 0 ; i < optchar_counter ; i++ ){ 1070 | if( optionchars[i] == type[0] ){ /* match */ 1071 | if( optchartype[i] == COMMON_OPT || 1072 | optchartype[i] == FILE_OPT ) 1073 | { 1074 | setValue( type[0] , chomp(value) ); 1075 | return; 1076 | } 1077 | } 1078 | } 1079 | } 1080 | /* if no char options matched */ 1081 | for( int i = 0 ; i < option_counter ; i++ ){ 1082 | if( strcmp( options[i], type ) == 0 ){ /* match */ 1083 | if( optiontype[i] == COMMON_OPT || 1084 | optiontype[i] == FILE_OPT ) 1085 | { 1086 | setValue( type , chomp(value) ); 1087 | return; 1088 | } 1089 | } 1090 | } 1091 | printVerbose( "Unknown option in resourcefile : " ); 1092 | printVerbose( type ); 1093 | printVerbose( ); 1094 | } 1095 | 1096 | void 1097 | AnyOption::justValue( char *type ) 1098 | { 1099 | 1100 | if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ 1101 | for( int i = 0 ; i < optchar_counter ; i++ ){ 1102 | if( optionchars[i] == type[0] ){ /* match */ 1103 | if( optchartype[i] == COMMON_FLAG || 1104 | optchartype[i] == FILE_FLAG ) 1105 | { 1106 | setFlagOn( type[0] ); 1107 | return; 1108 | } 1109 | } 1110 | } 1111 | } 1112 | /* if no char options matched */ 1113 | for( int i = 0 ; i < option_counter ; i++ ){ 1114 | if( strcmp( options[i], type ) == 0 ){ /* match */ 1115 | if( optiontype[i] == COMMON_FLAG || 1116 | optiontype[i] == FILE_FLAG ) 1117 | { 1118 | setFlagOn( type ); 1119 | return; 1120 | } 1121 | } 1122 | } 1123 | printVerbose( "Unknown option in resourcefile : " ); 1124 | printVerbose( type ); 1125 | printVerbose( ); 1126 | } 1127 | 1128 | /* 1129 | * usage and help 1130 | */ 1131 | 1132 | 1133 | void 1134 | AnyOption::printAutoUsage() 1135 | { 1136 | if( autousage ) printUsage(); 1137 | } 1138 | 1139 | void 1140 | AnyOption::printUsage() 1141 | { 1142 | 1143 | if( once ) { 1144 | once = false ; 1145 | cout << endl ; 1146 | for( int i = 0 ; i < usage_lines ; i++ ) 1147 | cout << usage[i] << endl ; 1148 | cout << endl ; 1149 | } 1150 | } 1151 | 1152 | 1153 | void 1154 | AnyOption::addUsage( const char *line ) 1155 | { 1156 | if( usage_lines >= max_usage_lines ){ 1157 | if( doubleUsageStorage() == false ){ 1158 | addUsageError( line ); 1159 | exit(1); 1160 | } 1161 | } 1162 | usage[ usage_lines ] = line ; 1163 | usage_lines++; 1164 | } 1165 | 1166 | void 1167 | AnyOption::addUsageError( const char *line ) 1168 | { 1169 | cout << endl ; 1170 | cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; 1171 | cout << "While adding the usage/help : \""<< line << "\"" << endl; 1172 | cout << "Exiting." << endl ; 1173 | cout << endl ; 1174 | exit(0); 1175 | 1176 | } 1177 | --------------------------------------------------------------------------------