diff options
| author | Andreas Brachold <vdr07@deltab.de> | 2007-11-17 08:27:47 +0000 |
|---|---|---|
| committer | Andreas Brachold <vdr07@deltab.de> | 2007-11-17 08:27:47 +0000 |
| commit | a0fb042d1fdf476e60768d86a5f9683e79f080d6 (patch) | |
| tree | 1fb54ffb7c7da222f8847cc3d27cdc847dd017e0 /contrib | |
| parent | af03d0b4d0a51eea8cd4f57c1f559b6add089102 (diff) | |
| download | xxv-a0fb042d1fdf476e60768d86a5f9683e79f080d6.tar.gz xxv-a0fb042d1fdf476e60768d86a5f9683e79f080d6.tar.bz2 | |
* File refactoring
Diffstat (limited to 'contrib')
| -rw-r--r-- | contrib/vdr2jpeg/Makefile | 21 | ||||
| -rw-r--r-- | contrib/vdr2jpeg/ffm.cpp | 14 | ||||
| -rw-r--r-- | contrib/vdr2jpeg/gop.cpp | 798 | ||||
| -rw-r--r-- | contrib/vdr2jpeg/gop.h | 83 | ||||
| -rw-r--r-- | contrib/vdr2jpeg/tools.cpp | 51 | ||||
| -rw-r--r-- | contrib/vdr2jpeg/tools.h | 41 | ||||
| -rw-r--r-- | contrib/vdr2jpeg/vdr2jpeg.cpp | 622 |
7 files changed, 1006 insertions, 624 deletions
diff --git a/contrib/vdr2jpeg/Makefile b/contrib/vdr2jpeg/Makefile index 0c42238..43694c9 100644 --- a/contrib/vdr2jpeg/Makefile +++ b/contrib/vdr2jpeg/Makefile @@ -91,11 +91,14 @@ PRGNAME = vdr2jpeg VERSION = $(shell grep 'static const char \*VERSION *=' vdr2jpeg.cpp | awk '{ print $$6 }' | sed -e 's/[";]//g') ARCHIVE = $(PRGNAME)-$(VERSION) DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -FILES = README LIESMICH HISTORY COPYING Makefile vdr2jpeg.cpp ffm.cpp ffm.h +FILES = README LIESMICH HISTORY COPYING Makefile \ + gop.cpp gop.h vdr2jpeg.cpp ffm.cpp ffm.h \ + tools.cpp tools.h DEBIAN = debian/changelog debian/control debian/dirs debian/rules debian/compat \ debian/copyright debian/docs debian/README.Debian debian/watch DEBPATCH = debian/patches/00list debian/patches/01_changed_api.dpatch -OBJS = vdr2jpeg.o ffm.o +OBJS = tools.o gop.o ffm.o +VDR2JPEGOBJS = vdr2jpeg.o #------------------------------------------------------------------------- @@ -108,24 +111,24 @@ OBJS = vdr2jpeg.o ffm.o #------------------------------------------------------------------------- # Main Targets -all: $(PRGNAME) +all: vdr2jpeg .PHONY: all -$(PRGNAME): $(OBJS) - $(CXX) $(CXXFLAGS) $(OBJS) $(FFOBJS) $(LIBS) -o $(PRGNAME) +vdr2jpeg: $(VDR2JPEGOBJS) $(OBJS) + $(CXX) $(CXXFLAGS) $(VDR2JPEGOBJS) $(OBJS) $(FFOBJS) $(LIBS) -o vdr2jpeg ifndef DEBUG $(STRIP) $@ endif -install: $(PRGNAME) +install: all install -d $(INSTALLDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(INSTALLDIR) + install -m 755 -o root -g root -s vdr2jpeg $(INSTALLDIR) uninstall: - rm -f $(INSTALLDIR)/$(PRGNAME) + rm -f $(INSTALLDIR)/vdr2jpeg clean: - @-rm -f $(PRGNAME) a.out *.o *.tgz core* *~ + @-rm -f vdr2jpeg a.out *.o *.tgz core* *~ distclean: clean @-rm -f *.jpg *.mpv diff --git a/contrib/vdr2jpeg/ffm.cpp b/contrib/vdr2jpeg/ffm.cpp index 2ce18de..e4062cb 100644 --- a/contrib/vdr2jpeg/ffm.cpp +++ b/contrib/vdr2jpeg/ffm.cpp @@ -45,8 +45,8 @@ extern "C" { #endif } -static int frame_width = 160; -static int frame_height = 120; +static int frame_width = 0; +static int frame_height = 0; static float frame_aspect_ratio = 0; static enum PixelFormat frame_pix_fmt = PIX_FMT_YUV420P; static int frame_rate = 25; @@ -691,7 +691,7 @@ static bool av_encode(AVFormatContext **output_files, codec->width, codec->height, codec->pix_fmt, - SWS_BICUBIC, NULL, NULL, NULL); + SWS_FAST_BILINEAR, NULL, NULL, NULL); if (ost->img_resample_ctx == NULL) { fprintf(stderr, "Cannot get resampling context\n"); return false; @@ -1302,8 +1302,14 @@ bool decode (const char* szMPVfile, /* const tPackedList & packed, */ nb_input_files = 0; nb_output_files = 0; + frame_width = 0; + frame_height = 0; + frame_aspect_ratio = 0; + frame_pix_fmt = PIX_FMT_YUV420P; + frame_rate = 25; + frame_rate_base = 1; + keep_aspect_ratio = 1; - /* parse options */ if(!opt_input_file(szMPVfile)) return false; diff --git a/contrib/vdr2jpeg/gop.cpp b/contrib/vdr2jpeg/gop.cpp new file mode 100644 index 0000000..832fd42 --- /dev/null +++ b/contrib/vdr2jpeg/gop.cpp @@ -0,0 +1,798 @@ +/* + * Simple program to grab images from VDR Recording + * + * Copyright(c) 2005-2007 Andreas Brachold + * + * demux ported from vdrsync.pl : Copyright(c) 2005 Peter Sebbel + * + * This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <time.h> +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> +#include <algorithm> +#include "ffm.h" +#include "gop.h" + +bool operator >>(std::istream & i, tFrame & x) +{ + i.read((x.u.rawdata), sizeof(x.u.rawdata)); // Read all data in one step + if(i.gcount() == sizeof(x.u.rawdata)) { + return true; + } else { + return false; + } +} + +std::ostream & operator <<(std::ostream & o, const tFrame & x) +{ + o << "Frame = " << x.nFrame; +#ifdef DEBUG + o << " I-Frame = " << x.nIFrame; +#endif // DEBUG + o << " Offset = " << x.u.f.offset; + o << " File = " <<(int) x.u.f.number; +#ifdef DEBUG + o << " Type = " <<(int) x.u.f.type; + o << " Reserved : " << x.u.f.reserved; +#endif // DEBUG + return o; +} + + +bool ReadIndexFile(const std::string & szFolder, std::vector < int >&nFrames, std::vector < std::pair<tFrame,tFrame> > &nGOP) +{ + if(szFolder.empty()) { + std::cerr << "Missing VDR-recording folder" << std::endl; + return false; + } + + if(nFrames.empty()) { + std::cerr << "Missing wanted frames" << std::endl; + return false; + } + + std::stringstream ss; + ss << szFolder; + if('/' != *szFolder.rbegin()) + ss << '/'; + ss << "index.vdr"; + ss << std::ends; + std::string szFile(ss.str()); + try + { + std::ifstream f(szFile.c_str(), std::ifstream::in | std::ifstream::binary); +
if(f.fail()) { + std::cerr << "Can't open file : " << szFile << std:: + endl; + return false; + } + std::vector < int >::const_iterator i = nFrames.begin(); + std::vector < int >::const_iterator e = nFrames.end(); + for(; i != e && f.good(); ++i) { + std::pair<tFrame,tFrame> gop; + tFrame x( (*i) ); + f.seekg(x.nIFrame * 8, std::ifstream::beg); + do + { + if(!f.good()) + { + std::cerr << + "Seek behind end of file : "; + std::cerr << szFile; + std::cerr << " at Frame "; + std::cerr << x.nIFrame << std::endl; + return false; + } + if(!(f >> x)) { + std::cerr << + "Incomplete struct : "; + std::cerr << szFile; + std::cerr << " at Frame "; + std::cerr << x.nIFrame << std::endl; + return false; + } + if(x.u.f.type != 1) + { + f.seekg(8 * 2 * -1, std::ifstream::cur); + --x.nIFrame; + } + } + while(x.u.f.type != 1); // found I-Frame + + gop.first = x; //Remember I-Frame + + do + { + ++x.nIFrame; + if(!f.good()) + { + std::cerr << + "Seek behind end of file : "; + std::cerr << szFile; + std::cerr << " at Frame "; + std::cerr << x.nIFrame << std::endl; + return false; + } + if(!(f >> x)) { +#ifdef DEBUG + std::cerr << + "Incomplete struct : "; + std::cerr << szFile; + std::cerr << " at Frame "; + std::cerr << x.nIFrame << std::endl; +#endif + return true; + } + } + while(f.good() && x.u.f.type != 1); // Build IBBP..I -> break on next I-Frame + gop.second = x; + nGOP.push_back(gop); //Remember I-Frame + } + f.close(); + return true; + } + catch(...) { + std::cerr << "Something fail at read " << szFile << std::endl; + return false; + } +} + +bool ReadIndexFileFull(const std::string & szFolder, + std::vector < std::pair<tFrame,tFrame> > &nGOP, + bool bIntraOnly, + unsigned int &nFirst, unsigned int nLimit) +{ + if(szFolder.empty()) { + std::cerr << "Missing VDR-recording folder" << std::endl; + return false; + } + + std::stringstream ss; + ss << szFolder; + if('/' != *szFolder.rbegin()) + ss << '/'; + ss << "index.vdr"; + ss << std::ends; + std::string szFile(ss.str()); + + try + { + std::ifstream f(szFile.c_str(), std::ifstream::in | std::ifstream::binary); +
if(f.fail()) { + std::cerr << "Can't open file : " << szFile << std:: + endl; + return false; + } + + std::pair<tFrame,tFrame> gop; + tFrame x(nFirst); + f.seekg(nFirst * 8, std::ifstream::beg); + + // Search first I-Frame + while(bIntraOnly && f.good()) { + if(!(f >> x)) { + std::cerr << + "Incomplete struct : "; + std::cerr << szFile; + std::cerr << " at Frame "; + std::cerr << x.nIFrame << std::endl; + return false; + } + if(x.u.f.type == 1) { + break; + } + ++x.nFrame; + ++x.nIFrame; + } + // Read all frames + while(f.good()) { + + gop.first = x; //First I-Frame + + do // Build IBBP..I -> break on next I-Frame + { + if(!(f >> x)) { +#ifdef DEBUG + std::cerr << + "Incomplete struct : "; + std::cerr << szFile; + std::cerr << " at Frame "; + std::cerr << x.nIFrame << std::endl; +#endif + return true; + } + ++x.nFrame; + ++x.nIFrame; + if(!bIntraOnly || x.u.f.type == 1) { + break; + } + } while(f.good()); + + gop.second = x; //Last I-Frame + +// std::cerr << x << std::endl; + nGOP.push_back(gop); //Remember GOP IBBP..I + if(x.nFrame >= (nFirst + nLimit)) { + nFirst = x.nFrame; + break; + } + } + f.close(); + return true; + } + catch(...) { + std::cerr << "Something fail at read " << szFile << std::endl; + return false; + } +} + +int copy(const char * inn, const char * outn ) +{ + char buffer[8192]; + int count,readed = 0,written = 0; + int in,out; + + in = open(inn,O_RDONLY); + if(in == -1) + return -1; + out = open(outn,O_CREAT|O_TRUNC|O_WRONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if(out == -1) + return -1; + + while(0 < (count = read(in,buffer,sizeof(buffer)))) { + readed += count; + written += write(out,buffer,count); + if(readed != written) + break; + } + return ((readed == written) ? 0 : -1); +} + +bool temppath(const std::string & szOutPath, std::string & szTmpBase ) +{ + unsigned int nT = time(0); + srand(nT); + + std::stringstream so; + so << szOutPath; + if('/' != *szOutPath.rbegin()) + so << '/'; + so << "tmp-vdr2jpeg-"; + so.fill('0'); + so.width(8); + so << std::hex; + so << rand(); + szTmpBase = so.str(); + return true; +} + +void unlinkTmpfiles(const std::string & szTmpBase, bool bJPEG ) +{ + std::stringstream so; + struct stat64 ds; + for(unsigned int i = 1 ; i <= 99 ; ++i) + { + so.str(""); + so << szTmpBase; + so.fill('0'); + so.width(2); + so << i; + so << (bJPEG ? ".jpg" : ".ppm"); + so << std::ends; + std::string szTmp(so.str()); + + if(stat64(szTmp.c_str(), &ds)) { + break; + } + if(-1 == unlink(szTmp.c_str())) { + perror(szTmp.c_str()); + break; + } + } + so.str(""); + so << szTmpBase; + so << ".mpv"; + so << std::ends; + std::string szTmpMVP(so.str()); + if(stat64(szTmpMVP.c_str(), &ds)) { + return; + } + if(-1 == unlink(szTmpMVP.c_str())) { + perror(szTmpMVP.c_str()); + return; + } +} + +bool linkTmpfile(const std::string & szTmp, const std::string & szOutPath, + int nFrame, bool bJPEG) +{ + struct stat64 ds; + std::stringstream so; + + so << szOutPath; + if('/' != *szOutPath.rbegin()) + so << '/'; + so.fill('0'); + so.width(8); + so << nFrame; + so << (bJPEG ? ".jpg" : ".ppm"); + so << std::ends; + std::string szFile(so.str()); + + + if(!stat64(szFile.c_str(), &ds)) { + if(-1 == unlink(szFile.c_str())) { + perror(szFile.c_str()); + return false; + } + } + + int nErr = link(szTmp.c_str(),szFile.c_str()); + if(-1 == nErr && (errno == EXDEV || errno == EPERM )) + { + nErr = copy(szTmp.c_str(),szFile.c_str()); + } + if(0 != nErr || 0 != chmod(szFile.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) ) + { + if(errno == EEXIST || errno == EACCES) + perror(szFile.c_str()); + else + perror(szTmp.c_str()); + return false; + } + return true; +} + +bool handleTmpfile(const std::string & szTmpBase, const std::string & szOutPath, + int nFrame, int nFrameBase, bool exact, bool bJPEG, bool bLink, + unsigned int nWidth,unsigned int nHeight) +{ + struct stat64 ds; + + std::string szTmp; + std::stringstream so; + // started from wantet frame, avoid skipped duplicated frames + // look backward + for(unsigned int n = (nFrame - nFrameBase + 1) ; n > 0 ; --n) + { + so.str(""); + so << szTmpBase; + so.fill('0'); + so.width(2); + so << n; + so << (bJPEG ? ".jpg" : ".ppm"); + so << std::ends; + std::string szTmpTry = so.str(); + + if(stat64(szTmpTry.c_str(), &ds)) { + if(exact) { + std::cerr << "Can't find tmp file : " << szTmpTry.c_str() << std::endl; + return false; + } + } + else + { + szTmp = szTmpTry; + break; + } + } + + if(szTmp.length() == 0) + { + // look forward backward + for(unsigned int n = (nFrame - nFrameBase + 1) ; n <= 99 ; ++n) + { + so.str(""); + so << szTmpBase; + so.fill('0'); + so.width(2); + so << n; + so << (bJPEG ? ".jpg" : ".ppm"); + so << std::ends; + std::string szTmpTry = so.str(); + + if(stat64(szTmpTry.c_str(), &ds)) { + if(exact) { + std::cerr << "Can't find tmp file : " << szTmpTry.c_str() << std::endl; + return false; + } + } + else + { + szTmp = szTmpTry; + break; + } + } + } + if(szTmp.length() == 0) + { + std::cerr << "Can't find any tmp file" << std::endl; + return false; + } + if(bLink) { + return linkTmpfile(szTmp,szOutPath, nFrame, bJPEG ); + } + return false; +} + + +bool ReadGOP(const std::string & szFile, int nBegin, int nLength, char *pMem ) +{ + std::ifstream f(szFile.c_str(), + std::ifstream::in | std::ifstream::binary); + if(f.fail()) { + std::cerr << "Can't open file : " << szFile << std::endl; + return false; + } + + if(nBegin < 0) { + std::cerr << "Negativ seek at file : " << szFile << std::endl; + return false; + } + + if(nLength < 0) { + std::cerr << "Negativ length at file : " << szFile << std::endl; + return false; + } + + if(nBegin != 0) { + f.seekg(nBegin, std::ifstream::beg); // Seek to I-Frame + } + + f.read(pMem, nLength); + if (f.gcount() != nLength) { + std::cerr << "Can't read all from file : " << szFile << std::endl; + return false; + } + return true; +} + +bool ReadRecordings(const std::string & szFolder, + const std::string & szOutPath, const std::string & szTempPath, + const std::vector < std::pair<tFrame,tFrame> > &nGOP, int width, int height, + bool exact, bool bJPEG) +{ + if(szFolder.empty()) + { + std::cerr << "Missing VDR-recording folder" << std::endl; + return false; + } + + if(nGOP.empty()) + { + std::cerr << "Missing wanted GOP" << std::endl; + return false; + } + + std::vector < std::pair<tFrame,tFrame> >::const_iterator i = nGOP.begin(); + std::vector < std::pair<tFrame,tFrame> >::const_iterator e = nGOP.end(); + + for(; i != e; ++i) + { +#ifdef DEBUG + std::cout << "Extract GOP : "; + std::cout << i->first << " / " << i->second << std::endl; +#endif //DEBUG + + //Skip empty frames (most at end) + if(i->first.u.f.offset == i->second.u.f.offset) { + continue; + } + + std::stringstream ss; + std::string szTmpBase; + if(!temppath(szTempPath,szTmpBase)) + { + std::cerr << "Can't get tempname" << std::endl; + return false; + } + + ss << szTmpBase; + ss << ".mpv"; + ss << std::ends; + std::string szTmpMVP(ss.str()); + + try + { + char *pMem = NULL; + int nSize = 0; + + // Offset bigger then current 00x.vdr files, goto next + if((i->first.u.f.offset >= i->second.u.f.offset + || i->first.u.f.number != i->second.u.f.number) + && i->second.u.f.offset != 0) { + + ss.str(""); + ss << szFolder; + if('/' != *szFolder.rbegin()) + ss << '/'; + ss.fill('0'); + ss.width(3); + ss << (int)i->first.u.f.number; // Filenumber 001.vdr ... + ss << ".vdr"; + ss << std::ends; + std::string szFile(ss.str()); + + struct stat64 ds; + if(stat64(szFile.c_str(), &ds)) { + std::cerr << "Can't find file : " << szFile << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + if(i->first.u.f.offset >=(ds.st_size)) { + std::cerr << "Offset bigger than current file : " << szFile << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + nSize = ds.st_size - i->first.u.f.offset + i->second.u.f.offset; + if(nSize <= 0 + || nSize >=(1 << 24) + || NULL ==(pMem = new char[nSize])) { + std::cerr << "Can't alloc memory for file : " << szFile << std::endl; + std::cerr << "want :" << nSize << " bytes" << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + if(!ReadGOP(szFile, i->first.u.f.offset, ds.st_size - i->first.u.f.offset, pMem)) { + delete[]pMem; + return false; + } + + ss.str(""); + ss << szFolder; + if('/' != *szFolder.rbegin()) + ss << '/'; + ss.fill('0'); + ss.width(3); + ss << (int)i->second.u.f.number; // Filenumber 002.vdr ... + ss << ".vdr"; + ss << std::ends; + szFile = ss.str(); + + if(stat64(szFile.c_str(), &ds)) { + std::cerr << "Can't find file : " << szFile << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + if(i->second.u.f.offset >=(ds.st_size)) { + std::cerr << "Offset bigger than current file : " << szFile << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + if(!ReadGOP(szFile, 0, i->second.u.f.offset, pMem + i->first.u.f.offset)) { + delete[]pMem; + return false; + } + + } else { + + ss.str(""); + ss << szFolder; + if('/' != *szFolder.rbegin()) + ss << '/'; + ss.fill('0'); + ss.width(3); + ss << (int)i->first.u.f.number; // Filenumber 001.vdr ... + ss << ".vdr"; + ss << std::ends; + std::string szFile(ss.str()); + + struct stat64 ds; + if(stat64(szFile.c_str(), &ds)) + { + std::cerr << "Can't find file : " << szFile << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + if(i->first.u.f.offset >=(ds.st_size)) { + std::cerr << "Offset bigger than current file : " << szFile << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + // size of GOP + nSize = i->second.u.f.offset ? i->second.u.f.offset - i->first.u.f.offset : ds.st_size - i->first.u.f.offset; + if(nSize <= 0 + || nSize >=(1 << 24) + || NULL ==(pMem = new char[nSize])) + { + std::cerr << "Can't alloc memory for file : " << szFile << std::endl; + std::cerr << "want :" << nSize << " bytes" << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + if(!ReadGOP(szFile, i->first.u.f.offset, nSize, pMem)) { + delete[]pMem; + return false; + } + } + + +/* +00 00 01 // Startcode +e4 // Streamtype +07 fa // Length => 2042 +84 c0 // notused +0b // header_length +*/ + static const unsigned char packetMagic[3] = { 0x00, 0x00, 0x01 }; + if(0 != memcmp(pMem, packetMagic, 3)) + { + std::cerr << "No valid magic found, at current packet, for file : " << szFolder << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + std::cerr.fill('0'); + std::cerr.width(2); + std::cerr << "found : 0x" + << std::hex << (unsigned int)(*(pMem + 0) & 0xFF) + << std::hex << (unsigned int)(*(pMem + 1) & 0xFF) + << std::hex << (unsigned int)(*(pMem + 2) & 0xFF) + << " streamcode : 0x"; + std::cerr.fill('0'); + std::cerr.width(2); + std::cerr <<(unsigned int)(*(pMem + 3)) << std::endl; + delete[]pMem; + return false; + } + int nOffset = 0; + int nPackets = 0; + + + std::ofstream fo; + + while(nOffset < nSize) + { + int pLength =(((unsigned char) *(pMem + nOffset + 4)) << 8) + + (((unsigned char) *(pMem + nOffset + 5)) << 0); + int hLength =(((unsigned char) *(pMem + nOffset + 8)) << 0); + unsigned char cStream =(unsigned char) *(pMem + nOffset + 3); + if((cStream & 0xe0) == 0xe0) + { // Check for Stream 0xE0-0xEF + // Store payload + // |Header|......PaketLength| + unsigned char *pBuffer =(unsigned char *) pMem + nOffset + 9 + hLength; + unsigned int nWrite =(pLength + 6) -(9 + hLength); + + if(!fo.is_open()) // Open on first write. + { + fo.open(szTmpMVP.c_str(), std::ofstream::out | std::ofstream::binary); + if(!fo.good()) + break; + } + fo.write((char *) pBuffer, nWrite); + if(!fo.good()) + break; + + ++nPackets; + } + nOffset +=(pLength + 6); + + + if(nOffset <= 0) // avoid negativ seek + break; + } + if(nPackets == 0 && nOffset >= nSize) + { + std::cerr << "No valid packet found, for file : " << szFolder << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + delete[]pMem; + return false; + } + + std::stringstream so; + so << szTmpBase; + so << "%2d"; + so << (bJPEG ? ".jpg" : ".ppm"); + so << std::ends; + std::string szTmpMask(so.str()); + + bool bRet = decode(szTmpMVP.c_str(), szTmpMask.c_str(), width, height); + if(bRet) + { + if(!handleTmpfile(szTmpBase, szOutPath,i->first.nFrame, + i->first.nIFrame, exact, bJPEG, bJPEG,width, height)) { + std::cerr << "Can't handle file : " << szFolder << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + + // look for more picture from same GOP + std::vector < std::pair<tFrame,tFrame> >::const_iterator j = i + 1; + std::vector < std::pair<tFrame,tFrame> >::const_iterator e = nGOP.end(); + for(;j != e; ++j ,++i) + { + if((i->first.nIFrame != j->first.nIFrame ) + ||(!handleTmpfile(szTmpBase, szOutPath,i->first.nFrame, + i->first.nIFrame, exact, bJPEG, bJPEG, width, height))) + break; + } + } + + unlinkTmpfiles(szTmpBase, bJPEG); + + delete[]pMem; + if(!bRet) + { + std::cerr << "decode failed, for file : " << szFolder << std::endl; + std::cerr << i->first << " / " << i->second << std::endl; + return false; + } + } + catch(...) + { + std::cerr << "Something fail at read " << szFolder << std::endl; + return false; + } + } + return true; +} + +bool decodegop(const std::string & szFile, + const std::string & szOutPath, + int nFrame, int width, int height, + bool exact, bool bJPEG) +{ + struct stat64 ds; + if(stat64(szFile.c_str(), &ds)) { + std::cerr << "Can't stat file : " << szFile << std::endl; + return false; + } + try + { + std::string szTmpBase; + if(!temppath(szOutPath, szTmpBase)) + { + std::cerr << "Can't get tempname" << std::endl; + return false; + } + + std::stringstream so; + so << szTmpBase; + so << "%2d"; + so << (bJPEG ? ".jpg" : ".ppm"); + so << std::ends; + std::string szTmpMask(so.str()); + + bool bRet = decode(szFile.c_str(), szTmpMask.c_str(), width, height) + && handleTmpfile(szTmpBase, szOutPath, exact ? nFrame : 0 , 0, exact, bJPEG, true, width, height ); + + unlinkTmpfiles(szTmpBase, bJPEG); + + return bRet; + } + catch(...) + { + std::cerr << "Something fail at read " << szFile << std::endl; + return -1; + } +} + diff --git a/contrib/vdr2jpeg/gop.h b/contrib/vdr2jpeg/gop.h new file mode 100644 index 0000000..1654058 --- /dev/null +++ b/contrib/vdr2jpeg/gop.h @@ -0,0 +1,83 @@ +/* + * Simple program to grab images from VDR Recording + * + * Copyright(c) 2005-2007 Andreas Brachold + * + * demux ported from vdrsync.pl : Copyright(c) 2005 Peter Sebbel + * + * This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include <iostream> +#include <fstream> +#include <vector> + +struct tFrame +{ + unsigned int nFrame; + unsigned int nIFrame; + union uIndex + { + struct tIndex + { + int32_t offset; + unsigned char type; + unsigned char number; + int16_t reserved; + } f; + char rawdata[8]; + } u; + tFrame() + { + }; + tFrame(int n) + { + nFrame = nIFrame = n; + } +}; + +bool operator >> (std::istream & i, tFrame & x); +std::ostream & operator <<(std::ostream & o, const tFrame & x); + + +bool ReadIndexFile(const std::string & szFolder, std::vector < int >&nFrames, + std::vector < std::pair<tFrame,tFrame> > &nGOP); + +bool ReadIndexFileFull(const std::string & szFolder, + std::vector < std::pair<tFrame,tFrame> > &nGOP, + bool bIntraOnly, + unsigned int &nFirst, unsigned int nLimit); + +int copy(const char * inn, const char * outn ); + +bool temppath(const std::string & szOutPath, std::string & szTmpBase ); + +void unlinkTmpfiles(const std::string & szTmpBase, bool bJPEG ); + +bool handleTmpfile(const std::string & szTmpBase, const std::string & szOutPath, + int nFrame, int nFrameBase, bool exact, bool bJPEG, bool bLink, + unsigned int nWidth,unsigned int nHeight); + +bool ReadRecordings(const std::string & szFolder, + const std::string & szOutPath, const std::string & szTempPath, + const std::vector < std::pair<tFrame,tFrame> > &nGOP, int width, int height, + bool exact, bool bJPEG = true); + +bool decodegop(const std::string & szFile, + const std::string & szOutPath, + int nFrame, int width, int height, + bool exact, bool bJPEG = true); + diff --git a/contrib/vdr2jpeg/tools.cpp b/contrib/vdr2jpeg/tools.cpp new file mode 100644 index 0000000..e15d12c --- /dev/null +++ b/contrib/vdr2jpeg/tools.cpp @@ -0,0 +1,51 @@ +/* + * Simple program to grab images from VDR Recording + * + * Copyright(c) 2007 Andreas Brachold + * + * This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include "tools.h" + +int option(int argc, char *argv[], const char opt, bool bParam, + std::string & param, int n) +{ + for(int i = n; i < argc; ++i) + { + if(argv[i] && strlen(argv[i]) > 1) + { + switch(*(argv[i] + 0)) + { + case '-': + { + if(*(argv[i] + 1) == opt) + { + if(!bParam) + return i + 1; + if(i + 1 < argc) + { + param = argv[i + 1]; + return i + 2; + } + } + } + } + } + } + return -1; +} + diff --git a/contrib/vdr2jpeg/tools.h b/contrib/vdr2jpeg/tools.h new file mode 100644 index 0000000..a0ea91d --- /dev/null +++ b/contrib/vdr2jpeg/tools.h @@ -0,0 +1,41 @@ +/* + * Simple program to grab images from VDR Recording + * + * Copyright(c) 2007 Andreas Brachold + * + * This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include <string> +#include "ffm.h" + +int option(int argc, char *argv[], const char opt, bool bParam, + std::string & param, int n = 1); + +// Helperclass for proper init/deinit ffmpeg +struct ffminit +{ + ffminit() { + ffm_initalize(); + } + + virtual ~ffminit() { + ffm_deinitalize(); + } +}; + + + diff --git a/contrib/vdr2jpeg/vdr2jpeg.cpp b/contrib/vdr2jpeg/vdr2jpeg.cpp index 86a9f60..2a7aa63 100644 --- a/contrib/vdr2jpeg/vdr2jpeg.cpp +++ b/contrib/vdr2jpeg/vdr2jpeg.cpp @@ -24,591 +24,24 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <time.h> #include <iostream> #include <fstream> #include <sstream> #include <vector> -#include <algorithm> +#include "tools.h" #include "ffm.h" +#include "gop.h" -static const char *VERSION = "0.0.12"; - -struct tFrame -{ - unsigned int nFrame; - unsigned int nIFrame; - union uIndex - { - struct tIndex - { - int32_t offset; - unsigned char type; - unsigned char number; - int16_t reserved; - } f; - char rawdata[8]; - } u; - tFrame() - { - }; - tFrame(int n) - { - nFrame = nIFrame = n; - } -}; - -std::istream & operator >>(std::istream & i, tFrame & x) -{ - i.read((x.u.rawdata), sizeof(x.u.rawdata)); // Read all data in one step - return i; -} - -#ifdef DEBUG -std::ostream & operator <<(std::ostream & o, const tFrame & x) -{ - o << "Frame = " << x.nFrame; - o << " I-Frame = " << x.nIFrame; -/* - o << " Offset = " << x.u.f.offset; - o << " Type = " <<(int) x.u.f.type; - o << " Number = " <<(int) x.u.f.number; - o << " Reserved : " << x.u.f.reserved; -*/ - return o; -} -#endif // DEBUG - - -bool ReadIndexFile(const std::string & szFolder, std::vector < int >&nFrames, std::vector < std::pair<tFrame,tFrame> > &nGOP) -{ - if(szFolder.empty()) { - std::cerr << "Missing VDR-recording folder" << std::endl; - return false; - } - - if(nFrames.empty()) { - std::cerr << "Missing wanted frames" << std::endl; - return false; - } - - std::stringstream ss; - ss << szFolder; - if('/' != *szFolder.rbegin()) - ss << '/'; - ss << "index.vdr"; - ss << std::ends; - std::string szFile(ss.str()); - try - { - std::ifstream f(szFile.c_str(), std::ifstream::in | std::ifstream::binary); -
if(f.fail()) { - std::cerr << "Can't open file : " << szFile << std:: - endl; - return false; - } - std::vector < int >::const_iterator i = nFrames.begin(); - std::vector < int >::const_iterator e = nFrames.end(); - for(; i != e && f.good(); ++i) { - std::pair<tFrame,tFrame> gop; - tFrame x( (*i) ); - f.seekg(x.nIFrame * 8, std::ifstream::beg); - do - { - if(!f.good()) - { - std::cerr << - "Seek behind end of file : "; - std::cerr << szFile; - std::cerr << " at Frame "; - std::cerr << x.nIFrame << std::endl; - return false; - } - f >> x; - if(x.u.f.type != 1) - { - f.seekg(8 * 2 * -1, std::ifstream::cur); - --x.nIFrame; - } - } - while(x.u.f.type != 1); // found I-Frame - - gop.first = x; //Remember I-Frame - - do - { - ++x.nIFrame; - if(!f.good()) - { - std::cerr << - "Seek behind end of file : "; - std::cerr << szFile; - std::cerr << " at Frame "; - std::cerr << x.nIFrame << std::endl; - return false; - } - f >> x; - } - while(f.good() && x.u.f.type != 1); // Build IBBP..I -> break on next I-Frame - gop.second = x; - nGOP.push_back(gop); //Remember I-Frame - } - f.close(); - return true; - } - catch(...) { - std::cerr << "Something fail at read " << szFile << std::endl; - return false; - } -} - -int copy(const char * inn, const char * outn ) -{ - char buffer[8192]; - int count,readed = 0,written = 0; - int in,out; - - in = open(inn,O_RDONLY); - if(in == -1) - return -1; - out = open(outn,O_CREAT|O_TRUNC|O_WRONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if(out == -1) - return -1; - - while(0 < (count = read(in,buffer,sizeof(buffer)))) { - readed += count; - written += write(out,buffer,count); - if(readed != written) - break; - } - return ((readed == written) ? 0 : -1); -} - -bool temppath(const std::string & szOutPath, std::string & szTmpBase ) -{ - unsigned int nT = time(0); - srand(nT); - - std::stringstream so; - so << szOutPath; - if('/' != *szOutPath.rbegin()) - so << '/'; - so << "tmp-vdr2jpeg-"; - so.fill('0'); - so.width(8); - so << std::hex; - so << rand(); - szTmpBase = so.str(); - return true; -} - -void unlinkTmpfiles(const std::string & szTmpBase ) -{ - std::stringstream so; - struct stat64 ds; - for(unsigned int i = 1 ; i <= 99 ; ++i) - { - so.str(""); - so << szTmpBase; - so.fill('0'); - so.width(2); - so << i; - so << ".jpg"; - so << std::ends; - std::string szTmp(so.str()); - - if(stat64(szTmp.c_str(), &ds)) { - break; - } - if(-1 == unlink(szTmp.c_str())) { - perror(szTmp.c_str()); - break; - } - } - so.str(""); - so << szTmpBase; - so << ".mpv"; - so << std::ends; - std::string szTmpMVP(so.str()); - if(stat64(szTmpMVP.c_str(), &ds)) { - return; - } - if(-1 == unlink(szTmpMVP.c_str())) { - perror(szTmpMVP.c_str()); - return; - } -} - -bool copyTmpfile(const std::string & szTmpBase, const std::string & szOutPath,int nFrame, int nFrameBase, bool exact ) -{ - struct stat64 ds; - - std::string szTmp; - std::stringstream so; - // started from wantet frame, avoid skipped duplicated frames - // look backward - for(unsigned int n = (nFrame - nFrameBase + 1) ; n > 0 ; --n) - { - so.str(""); - so << szTmpBase; - so.fill('0'); - so.width(2); - so << n; - so << ".jpg"; - so << std::ends; - std::string szTmpTry = so.str(); - - if(stat64(szTmpTry.c_str(), &ds)) { - if(exact) { - std::cerr << "Can't find tmp file : " << szTmpTry.c_str() << std::endl; - return false; - } - } - else - { - szTmp = szTmpTry; - break; - } - } - - if(szTmp.length() == 0) - { - // look forward backward - for(unsigned int n = (nFrame - nFrameBase + 1) ; n <= 99 ; ++n) - { - so.str(""); - so << szTmpBase; - so.fill('0'); - so.width(2); - so << n; - so << ".jpg"; - so << std::ends; - std::string szTmpTry = so.str(); - - if(stat64(szTmpTry.c_str(), &ds)) { - if(exact) { - std::cerr << "Can't find tmp file : " << szTmpTry.c_str() << std::endl; - return false; - } - } - else - { - szTmp = szTmpTry; - break; - } - } - } - if(szTmp.length() == 0) - { - std::cerr << "Can't find any tmp file" << std::endl; - return false; - } - - so.str(""); - so << szOutPath; - if('/' != *szOutPath.rbegin()) - so << '/'; - so.fill('0'); - so.width(8); - so << nFrame; - so << ".jpg"; - so << std::ends; - std::string szFile(so.str()); - - - if(!stat64(szFile.c_str(), &ds)) { - if(-1 == unlink(szFile.c_str())) { - perror(szFile.c_str()); - return false; - } - } - - int nErr = link(szTmp.c_str(),szFile.c_str()); - if(-1 == nErr && (errno == EXDEV || errno == EPERM )) - { - nErr = copy(szTmp.c_str(),szFile.c_str()); - } - if(0 != nErr || 0 != chmod(szFile.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) ) - { - if(errno == EEXIST || errno == EACCES) - perror(szFile.c_str()); - else - perror(szTmp.c_str()); - return false; - } - return true; -} - - - - -bool ReadRecordings(const std::string & szFolder, const std::string & szOutPath, - const std::vector < std::pair<tFrame,tFrame> > &nGOP, int width, int height, - bool exact) -{ - if(szFolder.empty()) - { - std::cerr << "Missing VDR-recording folder" << std::endl; - return false; - } - - if(nGOP.empty()) - { - std::cerr << "Missing wanted GOP" << std::endl; - return false; - } - - std::vector < std::pair<tFrame,tFrame> >::const_iterator i = nGOP.begin(); - std::vector < std::pair<tFrame,tFrame> >::const_iterator e = nGOP.end(); - - int nOffset = 0; - for(; i != e; ++i) - { -#ifdef DEBUG - std::cout << "Extract GOP : "; - std::cout << (const tFrame&)(i->first) << " / " << (const tFrame&)(i->second) << std::endl; -#endif //DEBUG - - std::stringstream ss; - ss << szFolder; - if('/' != *szFolder.rbegin()) - ss << '/'; - ss.fill('0'); - ss.width(3); - ss << (int)i->first.u.f.number; // Filenumber 001.vdr ... - ss << ".vdr"; - ss << std::ends; - std::string szFile(ss.str()); - - - std::string szTmpBase; - if(!temppath(szOutPath,szTmpBase)) - { - std::cerr << "Can't get tempname" << std::endl; - return false; - } - - ss.str(""); - ss << szTmpBase; - ss << ".mpv"; - ss << std::ends; - std::string szTmpMVP(ss.str()); - - try - { - struct stat64 ds; - if(stat64(szFile.c_str(), &ds)) - { - std::cerr << "Can't find file : " << szFile << std::endl; - return false; - } - // Offset bigger then current 00x.vdr files, goto next - if(i->first.u.f.offset >=(ds.st_size)) - { - std::cerr << - "Offset bigger than current file : " - << szFile << std::endl; - return false; - } - - std::ifstream f(szFile.c_str(), - std::ifstream::in | std::ifstream:: - binary); -
if(f.fail()) - { - std::cerr << "Can't open file : " << szFile << std::endl; - return false; - } - int nStart = i->first.u.f.offset; - f.seekg(nStart - nOffset, std::ifstream::beg); // Seek to I-Frame - - // size of GOP - int nSize =i->second.u.f.offset - nStart; - char *pMem = NULL; - if(nSize <= 0 - || nSize >=(1 << 24) - || NULL ==(pMem = new char[nSize])) - { - std::cerr << "Can't alloc memory for file : " - << szFile << std::endl; - std::cerr << "want :" << nSize << " bytes" << - std::endl; - return false; - } - f.read(pMem, nSize); - if (f.gcount() != nSize) - { - std::cerr << "Can't read all from file : " << szFile << std::endl; - delete[]pMem; - return false; - } - -/* -00 00 01 // Startcode -e4 // Streamtype -07 fa // Length => 2042 -84 c0 // notused -0b // header_length -*/ - static const unsigned char packetMagic[3] = { 0x00, 0x00, 0x01 }; - if(0 != memcmp(pMem, packetMagic, 3)) - { - std::cerr << - "No valid magic found, at current packet, for file : " - << szFile << std::endl; - std::cerr.fill('0'); - std::cerr.width(2); - std::cerr << "found : 0x" << std:: - hex <<(unsigned int)(*(pMem + 0) & - 0xFF) << std:: - hex <<(unsigned int)(*(pMem + 1) & - 0xFF) << std:: - hex <<(unsigned int)(*(pMem + 2) & - 0xFF) << - " streamcode : 0x"; - std::cerr.fill('0'); - std::cerr.width(2); - std::cerr <<(unsigned int)(*(pMem + 3)) << - std::endl; - delete[]pMem; - return false; - } - int nOffset = 0; - int nPackets = 0; - - - std::ofstream fo; - - while(nOffset < nSize) - { - int pLength =(((unsigned char) *(pMem + nOffset + 4)) << 8) + - (((unsigned char) *(pMem + nOffset + 5)) << 0); - int hLength =(((unsigned char) *(pMem + nOffset + 8)) << 0); - unsigned char cStream =(unsigned char) *(pMem + nOffset + 3); - if((cStream & 0xe0) == 0xe0) - { // Check for Stream 0xE0-0xEF - // Store payload - // |Header|......PaketLength| - unsigned char *pBuffer =(unsigned char *) pMem + nOffset + 9 + hLength; - unsigned int nWrite =(pLength + 6) -(9 + hLength); - - if(!fo.is_open()) // Open on first write. - { - fo.open(szTmpMVP.c_str(), std::ofstream::out | std::ofstream::binary); - if(!fo.good()) - break; - } - fo.write((char *) pBuffer, nWrite); - if(!fo.good()) - break; - - ++nPackets; - } - nOffset +=(pLength + 6); - - - if(nOffset <= 0) // avoid negativ seek - break; - } - if(nPackets == 0 && nOffset >= nSize) - { - std::cerr << "No valid packet found, for file : " << szFile << std::endl; - delete[]pMem; - return false; - } - - std::stringstream so; - so << szTmpBase; - so << "%2d"; - so << ".jpg"; - so << std::ends; - std::string szTmpMask(so.str()); - - bool bRet = decode(szTmpMVP.c_str(), szTmpMask.c_str(), width, height); - if(bRet) - { - copyTmpfile(szTmpBase, szOutPath,i->first.nFrame, i->first.nIFrame, exact ); - - // look for more picture from same GOP - std::vector < std::pair<tFrame,tFrame> >::const_iterator j = i + 1; - std::vector < std::pair<tFrame,tFrame> >::const_iterator e = nGOP.end(); - for(;j != e; ++j ,++i) - { - if(i->first.nIFrame != j->first.nIFrame - || !copyTmpfile(szTmpBase, szOutPath,j->first.nFrame, j->first.nIFrame, exact )) - break; - } - } - - unlinkTmpfiles(szTmpBase); - - delete[]pMem; - if(!bRet) - { - std::cerr << "decode failed, for file : " << szFile << std::endl; - return false; - } - } - catch(...) - { - std::cerr << "Something fail at read " << szFile << std::endl; - return false; - } - } - return true; -} - -bool decodegop(const std::string & szFile, - const std::string & szOutPath, - int nFrame, int width, int height, - bool exact) -{ - struct stat64 ds; - if(stat64(szFile.c_str(), &ds)) { - std::cerr << "Can't stat file : " << szFile << std::endl; - return false; - } - try - { - std::string szTmpBase; - if(!temppath(szOutPath, szTmpBase)) - { - std::cerr << "Can't get tempname" << std::endl; - return false; - } - - std::stringstream so; - so << szTmpBase; - so << "%2d"; - so << ".jpg"; - so << std::ends; - std::string szTmpMask(so.str()); - - bool bRet = decode(szFile.c_str(), szTmpMask.c_str(), width, height) - && copyTmpfile(szTmpBase, szOutPath, exact ? nFrame : 0 , 0, exact ); - - unlinkTmpfiles(szTmpBase); - - return bRet; - } - catch(...) - { - std::cerr << "Something fail at read " << szFile << std::endl; - return -1; - } -} +static const char *VERSION = "0.1.0"; void help(int argc, char *argv[]) { std::cerr << "Usage: " << argv[0] << " (" << VERSION << ")" << std::endl; std::cerr << " -r recordings : VDR recording folder" << std::endl; std::cerr << " -f frame : wanted frame (resolution at PAL - 1/25s)" << std::endl; - std::cerr << " -o outdirectory : output folder" << std::endl; + std::cerr << " -o directory : output folder" << std::endl; + std::cerr << " -t directory : temporary folder" << std::endl; std::cerr << " -x 160 : scaled width of output image" << std::endl; std::cerr << " -y 120 : scaled height of output image" << std::endl; std::cerr << " -e : exact frame grab, instead of duplicate frame" << std::endl; @@ -621,48 +54,12 @@ void help(int argc, char *argv[]) std::cerr << std::endl << std::endl; } -int option(int argc, char *argv[], const char opt, bool bParam, - std::string & param, int n = 1) -{ - for(int i = n; i < argc; ++i) - { - if(argv[i] && strlen(argv[i]) > 1) - { - switch(*(argv[i] + 0)) - { - case '-': - { - if(*(argv[i] + 1) == opt) - { - if(!bParam) - return i + 1; - if(i + 1 < argc) - { - param = argv[i + 1]; - return i + 2; - } - } - } - } - } - } - return -1; -} - -// Helperclass for proper init/deinit ffmpeg -struct ffminit -{ - ffminit() { ffm_initalize(); } - ~ffminit() { ffm_deinitalize(); } -}; - - int main(int argc, char *argv[]) { int width = -1; int height = -1; bool exact = false; - std::string szGOP, szFolder, szOutPath("."), s; + std::string szGOP, szFolder, szOutPath, szTempPath, s; if(-1 != option(argc, argv, 'x', true, s)) @@ -677,8 +74,11 @@ int main(int argc, char *argv[]) { exact = true; } - option(argc, argv, 'o', true, szOutPath); + szOutPath = ("."); + option(argc, argv, 'o', true, szOutPath); + szTempPath = szOutPath; + option(argc, argv, 't', true, szTempPath); std::vector < int >nFrame; int n = 0; @@ -822,7 +222,7 @@ int main(int argc, char *argv[]) if(ReadIndexFile(szFolder, nFrame, nGOP)) { ffminit x; - if(ReadRecordings(szFolder, szOutPath, nGOP, width, height,exact)) + if(ReadRecordings(szFolder, szOutPath, szTempPath, nGOP, width, height, exact, true)) return 0; // Success } return 1; |
