summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorAndreas Brachold <vdr07@deltab.de>2007-11-17 08:27:47 +0000
committerAndreas Brachold <vdr07@deltab.de>2007-11-17 08:27:47 +0000
commita0fb042d1fdf476e60768d86a5f9683e79f080d6 (patch)
tree1fb54ffb7c7da222f8847cc3d27cdc847dd017e0 /contrib
parentaf03d0b4d0a51eea8cd4f57c1f559b6add089102 (diff)
downloadxxv-a0fb042d1fdf476e60768d86a5f9683e79f080d6.tar.gz
xxv-a0fb042d1fdf476e60768d86a5f9683e79f080d6.tar.bz2
* File refactoring
Diffstat (limited to 'contrib')
-rw-r--r--contrib/vdr2jpeg/Makefile21
-rw-r--r--contrib/vdr2jpeg/ffm.cpp14
-rw-r--r--contrib/vdr2jpeg/gop.cpp798
-rw-r--r--contrib/vdr2jpeg/gop.h83
-rw-r--r--contrib/vdr2jpeg/tools.cpp51
-rw-r--r--contrib/vdr2jpeg/tools.h41
-rw-r--r--contrib/vdr2jpeg/vdr2jpeg.cpp622
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;