EVOLUTION-MANAGER
Edit File: oggSlideshow.cpp
/* * oggSlideshow creates a slideshow from a number of pictures * * Copyright (C) 2008-2009 Joern Seger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifdef __WIN32 #define __GNU_LIBRARY__ #include "../win32/getopt_win.h" #endif #include <iostream> #include <map> #include <vector> #include <string> #include <sstream> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <unistd.h> //#include <cc++/slog.h> #include "th_helper.h" #include "definition.h" #include "theoraEncoder.h" #include "fileRepository.h" #include "streamMux.h" #include "cmdlineextractor.h" #include "effector.h" #include "crossfader.h" #include "kenburnseffect.h" #include "lowpassEffect.h" #include "plainPicture.h" #include "pictureLoader.h" #include "pictureResize.h" void printHelpScreen(std::string& name) { std::cerr << "usage: "<< name <<" [options] <picture1.bmp> <picture2.bmp> \n"; std::cerr << "Options: \n" << " -s <width>x<height>: picture width/height of the output frame\n" << " -f <frames/s> : frames per second\n" << " -o <output file> : name of the output file\n" << " -l <length> : number of frames per picture frequence\n" << " -d <datarate> : datarate in bit/second\n" << " -r <resample> : resizes the original pictures to video frame width/height and the additional resample factor\n" << " -e : reframe picture\n" << " -t <type> : kb - Ken Burns\n" << " cf - cross fade\n" << " p - plain\n" << " bl - blur\n" << " -c : comments in form type=value;type=value\n"; } int main(int argc, char* argv[]) { enum seqType { seqType_KenBurns, seqType_Crossfade, seqType_Plain, seqType_Blur }; uint32 width(480); uint32 height(320); uint32 framesPerSecond(24); std::string outputFile("slideshow.ogv"); uint32 length(8); uint32 datarate(256000); seqType showType(seqType_KenBurns); float resample(1.4); bool reframe(false); std::vector<OggComment> oggComments; srand(time(0)); std::string programName(argv[0]); int opt; while ((opt = getopt(argc, argv, "hp:f:o:l:d:r:t:s:ec:")) != EOF) switch (opt) { case 'h': case '?': printHelpScreen(programName); exit(-1); case 's': { std::deque<uint32> framesize; CmdlineExtractor::extractUint32(framesize, optarg, 'x'); if (framesize.size() != 2) { std::cerr << "please specify the size in the following way: -s320x480\n"; exit(-1); } width = framesize[0]; height = framesize[1]; } break; case 'f': framesPerSecond = atoi(optarg); break; case 'o': outputFile = std::string(optarg); break; case 'l': length = atoi(optarg); // yes, I know the atoi bug break; case 'd': datarate = atoi(optarg); // yes, I know the atoi bug break; case 'r': resample = atof(optarg); if ((resample < 1) || (resample > 2)) resample = 1.2; break; case 'e': { std::cerr << "reframing\n"; reframe = true; break; } case 't': { std::string typeStr(optarg); if ((typeStr == "kb") || (typeStr =="KenBurns")|| (typeStr == "KB")) { showType = seqType_KenBurns; break; } if ((typeStr == "cf") || (typeStr =="crossfade")) { showType = seqType_Crossfade; break; } if ((typeStr == "p") || (typeStr =="plain")|| (typeStr == "simple")) { showType = seqType_Plain; break; } if ((typeStr == "b") || (typeStr =="bl") || (typeStr == "blur") || (typeStr == "lp") || (typeStr == "lowpass")) { showType = seqType_Blur; break; } std::cerr << "Unknown Type: using Ken Burns"; showType = seqType_KenBurns; } break; case 'c': { CmdlineExtractor::extractCommentPairs ( oggComments, optarg, ';', '=' ); } } argc -= optind; argv += optind; if ((argc < 1)) { printHelpScreen(programName); return (-1); } /* create configuration */ TheoraStreamParameter config; // for valgrind #ifdef HAVE_BZERO bzero(&config,sizeof(TheoraStreamParameter)); #else memset(&config, 0x00, sizeof(TheoraStreamParameter)); #endif config.pictureX = width; config.pictureY = height; config.videoBitrate = datarate; config.aspectRatioDenom = 1; config.aspectRatioNum = 1; config.framerateNum = framesPerSecond; config.framerateDenom = 1; config.keyframeShift = 6; /* create stream configuration */ TheoraEncoder theoraEncoder(0); StreamConfig streamConf; /* configure the theora encoder and get a stream config back * which configures the stream multiplexer */ try { theoraEncoder.configureEncoder(config, streamConf, oggComments); } catch (const char* data) { std::cerr << data; exit(-1); } // encoder might want another frame size: // width = config.frameX; // height = config.frameY; std::vector<StreamConfig> configList; configList.push_back(streamConf); /* create a repository, where the data should be placed */ FileRepository* repository = new FileRepository(outputFile, MediaUnit::write); /* create a stream multiplexer */ StreamMux streamCreate(repository); /* configure the stream multiplexer */ streamCreate.configureStreams(configList); /* extract the RGB picture plane */ RGBPlane pictureRGB; /* create the effector */ Effector* effector(0); switch (showType) { case seqType_KenBurns: effector = new KenBurnsEffect; break; case seqType_Crossfade: effector = new Crossfader; break; case seqType_Plain: effector = new PlainPicture; break; case seqType_Blur: effector = new LowpassEffect; break; } bool first(true); // run through all pictures in command line for (int32 i(0); i<argc; ++i) { bool last = (i == (argc-1)); try { std::cout << "\ncreating video stream for picture <"<<argv[i]<<">\n"; uint32 loadWidth; uint32 loadHeight; if (showType == seqType_KenBurns) { loadWidth = (uint32)(width*resample); loadHeight = (uint32)(height*resample); } else { loadWidth = width; loadHeight = height; } bool biggest = (!reframe); if (PictureLoader::load(pictureRGB, argv[i], loadWidth, loadHeight, biggest) == false) { continue; } /* add borders, if aspect ratio does not match and the user wants that */ if (reframe && ((loadWidth != pictureRGB->width) || (loadHeight != pictureRGB->height))) { std::cerr << "Picture aspect ratio does not match, doing reframing\n"; pictureRGB = PictureResize::reframe(pictureRGB, loadWidth, loadHeight); } /* configure the effector */ switch (showType) { case seqType_KenBurns: { KenBurnsEffect::KenBurnsConfig config = KenBurnsEffect::createKBconfigRandom(pictureRGB, loadWidth, loadHeight, width, height, length*framesPerSecond, framesPerSecond); config.first = first; config.last = last; static_cast<KenBurnsEffect*>(effector)->configure(config); break; } case seqType_Crossfade: { Crossfader::CrossfaderConfig config; config.origPlane = pictureRGB; config.blindLength = framesPerSecond; config.sequenceLength = length*framesPerSecond; config.outputWidth = width; config.outputHeight = height; config.first = first; static_cast<Crossfader*>(effector)->configure(config); break; } case seqType_Plain: { PlainPicture::PlainPictureConfig config; config.origPlane = pictureRGB; config.sequenceLength = length*framesPerSecond; config.outputWidth = width; config.outputHeight = height; static_cast<PlainPicture*>(effector)->configure(config); break; } case seqType_Blur : { LowpassEffect::LowPassPictureConfig config; config.origPlane = pictureRGB; config.blindLength = framesPerSecond; config.sequenceLength = length*framesPerSecond; config.outputWidth = width; config.outputHeight = height; config.first = first; config.last = last; static_cast<LowpassEffect*>(effector)->configure(config); break; } } RGBPlane outputPlane; OggPacket packet; th_ycbcr_buffer theoraPictureBuffer; th_clean_ycbcr(theoraPictureBuffer); while (effector->available()) { (*effector) >> outputPlane; PictureLoader::exportYCrCb_theora(outputPlane, theoraPictureBuffer); theoraEncoder << theoraPictureBuffer; theoraEncoder >> packet; std::cerr << "\r " <<std::fixed << packet.getPacketNo()*1.0/(framesPerSecond*1.0)<<" "; streamCreate << packet; } th_free_ycbcr(theoraPictureBuffer); } catch (const char* errorString) { std::cout << errorString << std::endl; exit(-1); } first = false; } streamCreate.setEndOfStream(); streamCreate.close(); delete effector; std::cout << std::endl; #ifdef OSX_MALLOC_DEBUG std::cout << "Done!\n"; while (1==1) { } #endif return(0); }