From 3c4dba55bb7ae712cbba65685d56d188640db266 Mon Sep 17 00:00:00 2001 From: Ernest Wilkerson Date: Thu, 5 Nov 2020 10:35:07 -0800 Subject: [PATCH 1/3] Switch to a simple, binary format. Reduces tranform file output by 40%+ (depending on input size) --- CMakeLists.txt | 5 + src/serialize.c | 290 ++++++++++++++++++++++++++++++++++++++++-- src/serialize.h | 2 + src/transformtype.h | 10 +- tests/CMakeLists.txt | 5 + tests/testframework.h | 3 + tests/tests.c | 3 + 7 files changed, 303 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a453b1f..0d40418 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ option(BUILD_SHARED_LIBS "build shared libraries instead of static libraries" ON) option(USE_OMP "use parallelization use OMP" ON) +option(USE_BINARY_FILE_FORMAT "use binary file format" ON) set(CMAKE_C_STANDARD 99) @@ -50,6 +51,10 @@ if(USE_OMP) add_definitions(-fopenmp -DUSE_OMP) endif() +if(USE_BINARY_FILE_FORMAT) +add_compile_definitions(USE_BINARY_FILE_FORMAT=1) +endif() + set(SOURCES src/frameinfo.c src/transformtype.c src/libvidstab.c src/transform.c src/transformfixedpoint.c src/motiondetect.c src/motiondetect_opt.c src/serialize.c src/localmotion2transform.c diff --git a/src/serialize.c b/src/serialize.c index e3ee68d..81a84f0 100644 --- a/src/serialize.c +++ b/src/serialize.c @@ -30,19 +30,147 @@ #include "transformtype_operations.h" #include "motiondetect.h" +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ + defined(__BIG_ENDIAN__) || \ + defined(__ARMEB__) || \ + defined(__THUMBEB__) || \ + defined(__AARCH64EB__) || \ + defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) +// It's a big-endian target architecture +#define __IS_BIG_ENDIAN__ +#include +static double byteSwapDouble(double v) +{ + char in[8], out[8]; + double result; + memcpy(in, &v, 8); + out[0] = in[7]; + out[1] = in[6]; + out[2] = in[5]; + out[3] = in[4]; + out[4] = in[3]; + out[5] = in[2]; + out[6] = in[1]; + out[7] = in[0]; + memcpy(&result, out, 8); + return result; +} +#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ + defined(__LITTLE_ENDIAN__) || \ + defined(__ARMEL__) || \ + defined(__THUMBEL__) || \ + defined(__AARCH64EL__) || \ + defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) +// It's a little-endian target architecture +#define __IS_LITTLE_ENDIAN__ +#else +#error "I don't know what architecture this is!" +#endif + const char* modname = "vid.stab - serialization"; +int vsPrepareFileText(const VSMotionDetect* md, FILE* f); +int vsPrepareFileBinary(const VSMotionDetect* md, FILE* f); +int vsWriteToFileText(const VSMotionDetect* md, FILE* f, const LocalMotions* lms); +int vsWriteToFileBinary(const VSMotionDetect* md, FILE* f, const LocalMotions* lms); +int vsStoreLocalmotionsText(FILE* f, const LocalMotions* lms); +int vsStoreLocalmotionsBinary(FILE* f, const LocalMotions* lms); +int storeLocalmotionText(FILE* f, const LocalMotion* lm); +int storeLocalmotionBinary(FILE* f, const LocalMotion* lm); +LocalMotions vsRestoreLocalmotionsText(FILE* f); +LocalMotions vsRestoreLocalmotionsBinary(FILE* f); +LocalMotion restoreLocalmotionText(FILE* f); +LocalMotion restoreLocalmotionBinary(FILE* f); +int vsReadFileVersionText(FILE* f); +int vsReadFileVersionBinary(FILE* f); +int vsReadFromFileText(FILE* f, LocalMotions* lms); +int vsReadFromFileBinary(FILE* f, LocalMotions* lms); + +int readInt16(int16_t* i, FILE* f){ + int result = fread(i, sizeof(int16_t), 1, f); + #ifdef __IS_BIG_ENDIAN__ + if(result>0) *i = __bswap_16(*i); + #endif + return result; +} + +int readInt32(int32_t* i, FILE* f){ + int result = fread(i, sizeof(int32_t), 1, f); + #ifdef __IS_BIG_ENDIAN__ + if(result>0) *i = __bswap_32(*i); + #endif + return result; +} + +int readDouble(double* d, FILE* f){ + int result = fread(d, sizeof(double), 1, f); + #ifdef __IS_BIG_ENDIAN__ + if(result>0) *d = byteSwapDouble(*d); + #endif + return result; +} + +int writeInt16(const int16_t* i, FILE* f){ + int16_t val = *i; + #ifdef __IS_BIG_ENDIAN__ + val = __bswap_16(val); + #endif + return fwrite((const void*)&val, sizeof(int16_t), 1, f); +} + +int writeInt32(const int32_t* i, FILE* f){ + int32_t val = *i; + #ifdef __IS_BIG_ENDIAN__ + val = __bswap_32(val); + #endif + return fwrite((const void*)&val, sizeof(int32_t), 1, f); +} + +int writeDouble(const double* d, FILE* f){ + double val = *d; + #ifdef __IS_BIG_ENDIAN__ + val = byteSwapDouble(val); + #endif + return fwrite((const void*)&val, sizeof(double), 1, f); +} int storeLocalmotion(FILE* f, const LocalMotion* lm){ - return fprintf(f,"(LM %i %i %i %i %i %lf %lf)", lm->v.x,lm->v.y,lm->f.x,lm->f.y,lm->f.size, + #ifdef USE_BINARY_FILE_FORMAT + return storeLocalmotionBinary(f, lm); + #else + return storeLocalmotionText(f, lm); + #endif +} + +int storeLocalmotionText(FILE* f, const LocalMotion* lm) { + return fprintf(f,"(LM %hi %hi %hi %hi %hi %lf %lf)", lm->v.x,lm->v.y,lm->f.x,lm->f.y,lm->f.size, lm->contrast, lm->match); } +int storeLocalmotionBinary(FILE* f, const LocalMotion* lm) { + if (writeInt16(&lm->v.x, f)<=0) return 0; + if (writeInt16(&lm->v.y, f)<=0) return 0; + if (writeInt16(&lm->f.x, f)<=0) return 0; + if (writeInt16(&lm->f.y, f)<=0) return 0; + if (writeInt16(&lm->f.size, f)<=0) return 0; + if (writeDouble(&lm->contrast, f)<=0) return 0; + if (writeDouble(&lm->match, f)<=0) return 0; + return 1; +} + /// restore local motion from file LocalMotion restoreLocalmotion(FILE* f){ + #ifdef USE_BINARY_FILE_FORMAT + return restoreLocalmotionBinary(f); + #else + return restoreLocalmotionText(f); + #endif +} + +LocalMotion restoreLocalmotionText(FILE* f){ LocalMotion lm; char c; - if(fscanf(f,"(LM %i %i %i %i %i %lf %lf", &lm.v.x,&lm.v.y,&lm.f.x,&lm.f.y,&lm.f.size, + if(fscanf(f,"(LM %hi %hi %hi %hi %hi %lf %lf", &lm.v.x,&lm.v.y,&lm.f.x,&lm.f.y,&lm.f.size, &lm.contrast, &lm.match) != 7) { vs_log_error(modname, "Cannot parse localmotion!\n"); return null_localmotion(); @@ -55,7 +183,33 @@ LocalMotion restoreLocalmotion(FILE* f){ return lm; } +LocalMotion restoreLocalmotionBinary(FILE* f){ + LocalMotion lm; + + if (readInt16(&lm.v.x, f)<=0) goto parse_error_handling; + if (readInt16(&lm.v.y, f)<=0) goto parse_error_handling; + if (readInt16(&lm.f.x, f)<=0) goto parse_error_handling; + if (readInt16(&lm.f.y, f)<=0) goto parse_error_handling; + if (readInt16(&lm.f.size, f)<=0) goto parse_error_handling; + if (readDouble(&lm.contrast, f)<=0) goto parse_error_handling; + if (readDouble(&lm.match, f)<=0) goto parse_error_handling; + + return lm; + +parse_error_handling: + vs_log_error(modname, "Cannot parse localmotion!\n"); + return null_localmotion(); +} + int vsStoreLocalmotions(FILE* f, const LocalMotions* lms){ + #ifdef USE_BINARY_FILE_FORMAT + return vsStoreLocalmotionsBinary(f, lms); + #else + return vsStoreLocalmotionsText(f, lms); + #endif +} + +int vsStoreLocalmotionsText(FILE* f, const LocalMotions* lms){ int len = vs_vector_size(lms); int i; fprintf(f,"List %i [",len); @@ -67,8 +221,26 @@ int vsStoreLocalmotions(FILE* f, const LocalMotions* lms){ return 1; } +int vsStoreLocalmotionsBinary(FILE* f, const LocalMotions* lms){ + const int len = vs_vector_size(lms); + int i; + if(writeInt32(&len, f)<=0) return 0; + for (i=0; i0){ + vs_vector_init(&lms,len); + for (i=0; iconf.accuracy); - fprintf(f, "# shakiness = %d\n", md->conf.shakiness); - fprintf(f, "# stepsize = %d\n", md->conf.stepSize); - fprintf(f, "# mincontrast = %f\n", md->conf.contrastThreshold); - return VS_OK; + #ifdef USE_BINARY_FILE_FORMAT + return vsPrepareFileBinary(md, f); + #else + return vsPrepareFileText(md, f); + #endif +} + +int vsPrepareFileText(const VSMotionDetect* md, FILE* f){ + if(!f) return VS_ERROR; + fprintf(f, "VID.STAB %i\n", LIBVIDSTAB_FILE_FORMAT_VERSION); + fprintf(f, "# accuracy = %d\n", md->conf.accuracy); + fprintf(f, "# shakiness = %d\n", md->conf.shakiness); + fprintf(f, "# stepsize = %d\n", md->conf.stepSize); + fprintf(f, "# mincontrast = %f\n", md->conf.contrastThreshold); + return VS_OK; +} + +int vsPrepareFileBinary(const VSMotionDetect* md, FILE* f){ + static const int kFileFormatVersion = LIBVIDSTAB_FILE_FORMAT_VERSION; + + if(!f) return VS_ERROR; + writeInt32(&kFileFormatVersion, f); + writeInt32(&md->conf.accuracy, f); + writeInt32(&md->conf.shakiness, f); + writeInt32(&md->conf.stepSize, f); + writeDouble(&md->conf.contrastThreshold, f); + return VS_OK; } int vsWriteToFile(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ + #ifdef USE_BINARY_FILE_FORMAT + return vsWriteToFileBinary(md, f, lms); + #else + return vsWriteToFileText(md, f, lms); + #endif +} + +int vsWriteToFileText(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ if(!f || !lms) return VS_ERROR; if(fprintf(f, "Frame %i (", md->frameNum)>0 @@ -118,16 +340,57 @@ int vsWriteToFile(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ return VS_ERROR; } +int vsWriteToFileBinary(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ + if(!f || !lms) return VS_ERROR; + + if(writeInt32(&md->frameNum, f)<=0) return VS_ERROR; + if(vsStoreLocalmotions(f,lms)<=0) return VS_ERROR; + + return VS_OK; +} + /// reads the header of the file and return the version number int vsReadFileVersion(FILE* f){ + #ifdef USE_BINARY_FILE_FORMAT + return vsReadFileVersionBinary(f); + #else + return vsReadFileVersionText(f); + #endif +} + +int vsReadFileVersionText(FILE* f){ if(!f) return VS_ERROR; int version; - if(fscanf(f, "VID.STAB %i\n", &version)!=1) + if(fscanf(f, "VID.STAB %i\n", &version)!=LIBVIDSTAB_FILE_FORMAT_VERSION) return VS_ERROR; else return version; } +int vsReadFileVersionBinary(FILE* f){ + if(!f) return VS_ERROR; + int version; + VSMotionDetectConfig conf; + + if(readInt32(&version, f)<=0||version!=LIBVIDSTAB_FILE_FORMAT_VERSION) goto parse_error_handling; + if(readInt32(&conf.accuracy, f)<=0) goto parse_error_handling; + if(readInt32(&conf.shakiness, f)<=0) goto parse_error_handling; + if(readInt32(&conf.stepSize, f)<=0) goto parse_error_handling; + if(readDouble(&conf.contrastThreshold, f)<=0) goto parse_error_handling; + + return version; +parse_error_handling: + return VS_ERROR; +} + int vsReadFromFile(FILE* f, LocalMotions* lms){ + #ifdef USE_BINARY_FILE_FORMAT + return vsReadFromFileBinary(f,lms); + #else + return vsReadFromFileText(f,lms); + #endif +} + +int vsReadFromFileText(FILE* f, LocalMotions* lms){ char c = fgetc(f); if(c=='F') { int num; @@ -156,6 +419,13 @@ int vsReadFromFile(FILE* f, LocalMotions* lms){ } } +int vsReadFromFileBinary(FILE* f, LocalMotions* lms){ + int frameNum; + if(readInt32(&frameNum, f)<=0) return VS_ERROR; + *lms = vsRestoreLocalmotions(f); + return frameNum; +} + int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* mlms){ int version = vsReadFileVersion(f); if(version<1) // old format or unknown diff --git a/src/serialize.h b/src/serialize.h index 2142a7d..5cdcc97 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -25,6 +25,8 @@ #ifndef __SERIALIZE_H #define __SERIALIZE_H +#define LIBVIDSTAB_FILE_FORMAT_VERSION 1 + #include "transformtype.h" #include "motiondetect.h" #include "transform.h" diff --git a/src/transformtype.h b/src/transformtype.h index 2439bff..0369010 100644 --- a/src/transformtype.h +++ b/src/transformtype.h @@ -44,15 +44,15 @@ typedef struct _transform { /** stores x y and size of a measurement field */ typedef struct _field { - int x; // middle position x - int y; // middle position y - int size; // size of field + int16_t x; // middle position x + int16_t y; // middle position y + int16_t size; // size of field } Field; /** stores x y coordinates (integer) */ typedef struct _vec { - int x; // middle position x - int y; // middle position y + int16_t x; // middle position x + int16_t y; // middle position y } Vec; /* structure to hold information about local motion. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6812916..6d33f64 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../CMakeModules/ include (FindSSE) option(USE_OMP "use parallelization use OMP" ON) +option(USE_BINARY_FILE_FORMAT "use binary file format" ON) # Default to debug builds if no explicit build type specified. if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -33,6 +34,10 @@ if(USE_OMP) add_definitions(-fopenmp -DUSE_OMP) endif() +if(USE_BINARY_FILE_FORMAT) +add_compile_definitions(USE_BINARY_FILE_FORMAT=1) +endif() + # Make sure the compiler can find include files from transcode include_directories (../src) diff --git a/tests/testframework.h b/tests/testframework.h index 6997f6a..c0c21e2 100644 --- a/tests/testframework.h +++ b/tests/testframework.h @@ -2,7 +2,10 @@ #define __TESTFRAMEWORK_H #include + +#if defined(__linux__) #include +#endif int contains(char **list, int len, const char *str, const char* descr); void unittest_init(); diff --git a/tests/tests.c b/tests/tests.c index 0530730..b52aeec 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -3,7 +3,10 @@ #include #include #include + +#if defined(__linux__) #include +#endif #ifdef USE_OMP #include From 9d9066dcac6edfc3724d417e3522a747590c706a Mon Sep 17 00:00:00 2001 From: Ernest Wilkerson Date: Thu, 5 Nov 2020 13:09:11 -0800 Subject: [PATCH 2/3] Make file format serialization configurable with arguments Add file format guessing logic for reading local motions files --- CMakeLists.txt | 7 +-- src/motiondetect.c | 4 ++ src/motiondetect.h | 4 ++ src/serialize.c | 108 ++++++++++++++++++++--------------- src/serialize.h | 10 ++-- tests/CMakeLists.txt | 5 -- tests/test_store_restore.c | 17 +++--- tests/tests.c | 4 +- transcode/filter_deshake.c | 1 + transcode/filter_stabilize.c | 1 + 10 files changed, 91 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d40418..09cb526 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ include (FindSSE) include (GNUInstallDirs) set(MAJOR_VERSION 1) -set(MINOR_VERSION 1) +set(MINOR_VERSION 2) set(PATCH_VERSION 0) set(VIDSTAB_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}${PATCH_VERSION}) @@ -20,7 +20,6 @@ option(BUILD_SHARED_LIBS "build shared libraries instead of static libraries" ON) option(USE_OMP "use parallelization use OMP" ON) -option(USE_BINARY_FILE_FORMAT "use binary file format" ON) set(CMAKE_C_STANDARD 99) @@ -51,10 +50,6 @@ if(USE_OMP) add_definitions(-fopenmp -DUSE_OMP) endif() -if(USE_BINARY_FILE_FORMAT) -add_compile_definitions(USE_BINARY_FILE_FORMAT=1) -endif() - set(SOURCES src/frameinfo.c src/transformtype.c src/libvidstab.c src/transform.c src/transformfixedpoint.c src/motiondetect.c src/motiondetect_opt.c src/serialize.c src/localmotion2transform.c diff --git a/src/motiondetect.c b/src/motiondetect.c index c271f0d..76e9eca 100644 --- a/src/motiondetect.c +++ b/src/motiondetect.c @@ -107,6 +107,10 @@ int vsMotionDetectInit(VSMotionDetect* md, const VSMotionDetectConfig* conf, con md->hasSeenOneFrame = 0; md->frameNum = 0; + if(md->serializationMode != ASCII_SERIALIZATION_MODE && md->serializationMode != BINARY_SERIALIZATION_MODE) { + md->serializationMode = BINARY_SERIALIZATION_MODE; + } + // TODO: get rid of shakiness parameter in the long run md->conf.shakiness = VS_MIN(10,VS_MAX(1,md->conf.shakiness)); md->conf.accuracy = VS_MIN(15,VS_MAX(1,md->conf.accuracy)); diff --git a/src/motiondetect.h b/src/motiondetect.h index e8bc455..f1018de 100644 --- a/src/motiondetect.h +++ b/src/motiondetect.h @@ -36,6 +36,9 @@ #include "vsvector.h" #include "frameinfo.h" +#define ASCII_SERIALIZATION_MODE 1 +#define BINARY_SERIALIZATION_MODE 2 + typedef struct _vsmotiondetectconfig { /* meta parameter for maxshift and fieldsize between 1 and 15 */ int shakiness; @@ -81,6 +84,7 @@ typedef struct _vsmotiondetect { VSFrame prev; // frame buffer for last frame (copied) short hasSeenOneFrame; // true if we have a valid previous frame int initialized; // 1 if initialized and 2 if configured + int serializationMode; // 1 if ascii and 2 if binary int frameNum; } VSMotionDetect; diff --git a/src/serialize.c b/src/serialize.c index 81a84f0..82324b3 100644 --- a/src/serialize.c +++ b/src/serialize.c @@ -134,12 +134,12 @@ int writeDouble(const double* d, FILE* f){ return fwrite((const void*)&val, sizeof(double), 1, f); } -int storeLocalmotion(FILE* f, const LocalMotion* lm){ - #ifdef USE_BINARY_FILE_FORMAT +int storeLocalmotion(FILE* f, const LocalMotion* lm, int serializationMode){ + if(serializationMode == BINARY_SERIALIZATION_MODE){ return storeLocalmotionBinary(f, lm); - #else + } else { return storeLocalmotionText(f, lm); - #endif + } } int storeLocalmotionText(FILE* f, const LocalMotion* lm) { @@ -159,12 +159,12 @@ int storeLocalmotionBinary(FILE* f, const LocalMotion* lm) { } /// restore local motion from file -LocalMotion restoreLocalmotion(FILE* f){ - #ifdef USE_BINARY_FILE_FORMAT +LocalMotion restoreLocalmotion(FILE* f, const int serializationMode){ + if(serializationMode == BINARY_SERIALIZATION_MODE) { return restoreLocalmotionBinary(f); - #else + } else { return restoreLocalmotionText(f); - #endif + } } LocalMotion restoreLocalmotionText(FILE* f){ @@ -201,12 +201,12 @@ LocalMotion restoreLocalmotionBinary(FILE* f){ return null_localmotion(); } -int vsStoreLocalmotions(FILE* f, const LocalMotions* lms){ - #ifdef USE_BINARY_FILE_FORMAT +int vsStoreLocalmotions(FILE* f, const LocalMotions* lms, const int serializationMode){ + if(serializationMode == BINARY_SERIALIZATION_MODE) { return vsStoreLocalmotionsBinary(f, lms); - #else + } else { return vsStoreLocalmotionsText(f, lms); - #endif + } } int vsStoreLocalmotionsText(FILE* f, const LocalMotions* lms){ @@ -215,7 +215,7 @@ int vsStoreLocalmotionsText(FILE* f, const LocalMotions* lms){ fprintf(f,"List %i [",len); for (i=0; i0) fprintf(f,","); - if(storeLocalmotion(f,LMGet(lms,i)) <= 0) return 0; + if(storeLocalmotion(f,LMGet(lms,i),ASCII_SERIALIZATION_MODE) <= 0) return 0; } fprintf(f,"]"); return 1; @@ -226,18 +226,18 @@ int vsStoreLocalmotionsBinary(FILE* f, const LocalMotions* lms){ int i; if(writeInt32(&len, f)<=0) return 0; for (i=0; i0) while((c=fgetc(f)) && c!=',' && c!=EOF); - LocalMotion lm = restoreLocalmotion(f); + LocalMotion lm = restoreLocalmotion(f,ASCII_SERIALIZATION_MODE); vs_vector_append_dup(&lms,&lm,sizeof(LocalMotion)); } } @@ -282,7 +282,7 @@ LocalMotions vsRestoreLocalmotionsBinary(FILE* f){ if (len>0){ vs_vector_init(&lms,len); for (i=0; iserializationMode == BINARY_SERIALIZATION_MODE) { return vsPrepareFileBinary(md, f); - #else + } else { return vsPrepareFileText(md, f); - #endif + } } int vsPrepareFileText(const VSMotionDetect* md, FILE* f){ @@ -311,10 +311,9 @@ int vsPrepareFileText(const VSMotionDetect* md, FILE* f){ } int vsPrepareFileBinary(const VSMotionDetect* md, FILE* f){ - static const int kFileFormatVersion = LIBVIDSTAB_FILE_FORMAT_VERSION; - + static const unsigned char kFileFormatVersion = LIBVIDSTAB_FILE_FORMAT_VERSION; if(!f) return VS_ERROR; - writeInt32(&kFileFormatVersion, f); + fprintf(f, "TRF%hhu", kFileFormatVersion); writeInt32(&md->conf.accuracy, f); writeInt32(&md->conf.shakiness, f); writeInt32(&md->conf.stepSize, f); @@ -323,18 +322,18 @@ int vsPrepareFileBinary(const VSMotionDetect* md, FILE* f){ } int vsWriteToFile(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ - #ifdef USE_BINARY_FILE_FORMAT + if(md->serializationMode == BINARY_SERIALIZATION_MODE) { return vsWriteToFileBinary(md, f, lms); - #else + } else { return vsWriteToFileText(md, f, lms); - #endif + } } int vsWriteToFileText(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ if(!f || !lms) return VS_ERROR; if(fprintf(f, "Frame %i (", md->frameNum)>0 - && vsStoreLocalmotions(f,lms)>0 && fprintf(f, ")\n")) + && vsStoreLocalmotions(f, lms, ASCII_SERIALIZATION_MODE)>0 && fprintf(f, ")\n")) return VS_OK; else return VS_ERROR; @@ -344,18 +343,32 @@ int vsWriteToFileBinary(const VSMotionDetect* md, FILE* f, const LocalMotions* l if(!f || !lms) return VS_ERROR; if(writeInt32(&md->frameNum, f)<=0) return VS_ERROR; - if(vsStoreLocalmotions(f,lms)<=0) return VS_ERROR; + if(vsStoreLocalmotions(f, lms, BINARY_SERIALIZATION_MODE)<=0) return VS_ERROR; return VS_OK; } +int vsGuessSerializationMode(FILE* f){ + int serializationMode = ASCII_SERIALIZATION_MODE; + const int pos = ftell(f); + + if(fgetc(f) == 'T' + && fgetc(f) == 'R' + && fgetc(f) == 'F') { + serializationMode = BINARY_SERIALIZATION_MODE; + } + + fseek(f, pos, SEEK_SET); + return serializationMode; +} + /// reads the header of the file and return the version number -int vsReadFileVersion(FILE* f){ - #ifdef USE_BINARY_FILE_FORMAT +int vsReadFileVersion(FILE* f, const int serializationMode){ + if(serializationMode == BINARY_SERIALIZATION_MODE) { return vsReadFileVersionBinary(f); - #else + } else { return vsReadFileVersionText(f); - #endif + } } int vsReadFileVersionText(FILE* f){ @@ -368,10 +381,10 @@ int vsReadFileVersionText(FILE* f){ int vsReadFileVersionBinary(FILE* f){ if(!f) return VS_ERROR; - int version; + unsigned char version; VSMotionDetectConfig conf; - if(readInt32(&version, f)<=0||version!=LIBVIDSTAB_FILE_FORMAT_VERSION) goto parse_error_handling; + if(fscanf(f, "TRF%hhu\n", &version)!=LIBVIDSTAB_FILE_FORMAT_VERSION) goto parse_error_handling; if(readInt32(&conf.accuracy, f)<=0) goto parse_error_handling; if(readInt32(&conf.shakiness, f)<=0) goto parse_error_handling; if(readInt32(&conf.stepSize, f)<=0) goto parse_error_handling; @@ -382,12 +395,12 @@ int vsReadFileVersionBinary(FILE* f){ return VS_ERROR; } -int vsReadFromFile(FILE* f, LocalMotions* lms){ - #ifdef USE_BINARY_FILE_FORMAT +int vsReadFromFile(FILE* f, LocalMotions* lms, const int serializationMode){ + if(serializationMode == BINARY_SERIALIZATION_MODE) { return vsReadFromFileBinary(f,lms); - #else + } else { return vsReadFromFileText(f,lms); - #endif + } } int vsReadFromFileText(FILE* f, LocalMotions* lms){ @@ -398,7 +411,7 @@ int vsReadFromFileText(FILE* f, LocalMotions* lms){ vs_log_error(modname,"cannot read file, expect 'Frame num (...'"); return VS_ERROR; } - *lms = vsRestoreLocalmotions(f); + *lms = vsRestoreLocalmotions(f,ASCII_SERIALIZATION_MODE); if(fscanf(f,")\n")<0) { vs_log_error(modname,"cannot read file, expect '...)'"); return VS_ERROR; @@ -407,9 +420,9 @@ int vsReadFromFileText(FILE* f, LocalMotions* lms){ } else if(c=='#') { char l[1024]; if(fgets(l, sizeof(l), f)==0) return VS_ERROR; - return vsReadFromFile(f,lms); + return vsReadFromFile(f,lms,ASCII_SERIALIZATION_MODE); } else if(c=='\n' || c==' ') { - return vsReadFromFile(f,lms); + return vsReadFromFile(f,lms,ASCII_SERIALIZATION_MODE); } else if(c==EOF) { return VS_ERROR; } else { @@ -422,12 +435,13 @@ int vsReadFromFileText(FILE* f, LocalMotions* lms){ int vsReadFromFileBinary(FILE* f, LocalMotions* lms){ int frameNum; if(readInt32(&frameNum, f)<=0) return VS_ERROR; - *lms = vsRestoreLocalmotions(f); + *lms = vsRestoreLocalmotions(f, BINARY_SERIALIZATION_MODE); return frameNum; } int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* mlms){ - int version = vsReadFileVersion(f); + const int serializationMode = vsGuessSerializationMode(f); + int version = vsReadFileVersion(f, serializationMode); if(version<1) // old format or unknown return VS_ERROR; if(version>1){ @@ -441,7 +455,7 @@ int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* mlms){ int index; int oldindex = 0; LocalMotions lms; - while((index = vsReadFromFile(f,&lms)) != VS_ERROR){ + while((index = vsReadFromFile(f,&lms,serializationMode)) != VS_ERROR){ if(index > oldindex+1){ vs_log_info(modname,"VID.STAB file: index of frames is not continuous %i -< %i", oldindex, index); diff --git a/src/serialize.h b/src/serialize.h index 5cdcc97..7985982 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -38,12 +38,14 @@ typedef VSVector VSManyLocalMotions; #define VSMLMGet(manylocalmotions,index) \ ((LocalMotions*)vs_vector_get(manylocalmotions,index)) +/// guess the serialization mode of the local motions file +int vsGuessSerializationMode(FILE* f); /// stores local motions to file -int vsStoreLocalmotions(FILE* f, const LocalMotions* lms); +int vsStoreLocalmotions(FILE* f, const LocalMotions* lms, const int serializationMode); /// restores local motions from file -LocalMotions vsRestoreLocalmotions(FILE* f); +LocalMotions vsRestoreLocalmotions(FILE* f, const int serializationMode); /// writes the header to the file that is to be holding the local motions @@ -53,13 +55,13 @@ int vsPrepareFile(const VSMotionDetect* td, FILE* f); int vsWriteToFile(const VSMotionDetect* td, FILE* f, const LocalMotions* lms); /// reads the header of the file and return the version number (used by readLocalmotionsFile) -int vsReadFileVersion(FILE* f); +int vsReadFileVersion(FILE* f, const int serializationMode); /* * reads the next set of localmotions from the file, return VS_ERROR on error or * if nothing is read (used by readLocalmotionsFile) */ -int vsReadFromFile(FILE* f, LocalMotions* lms); +int vsReadFromFile(FILE* f, LocalMotions* lms, const int serializationMode); /* * reads the entire file of localmotions, return VS_ERROR on error or if nothing is read diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6d33f64..6812916 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../CMakeModules/ include (FindSSE) option(USE_OMP "use parallelization use OMP" ON) -option(USE_BINARY_FILE_FORMAT "use binary file format" ON) # Default to debug builds if no explicit build type specified. if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -34,10 +33,6 @@ if(USE_OMP) add_definitions(-fopenmp -DUSE_OMP) endif() -if(USE_BINARY_FILE_FORMAT) -add_compile_definitions(USE_BINARY_FILE_FORMAT=1) -endif() - # Make sure the compiler can find include files from transcode include_directories (../src) diff --git a/tests/test_store_restore.c b/tests/test_store_restore.c index 961f80e..36168e0 100644 --- a/tests/test_store_restore.c +++ b/tests/test_store_restore.c @@ -8,10 +8,13 @@ int compare_localmotions(const LocalMotions* lms1, const LocalMotions* lms2){ return 1; } -int test_store_restore(TestData* testdata){ +int test_store_restore(TestData* testdata, int serializationMode){ VSMotionDetectConfig mdconf = vsMotionDetectGetDefaultConfig("test_motionDetect"); VSMotionDetect md; + + md.serializationMode = serializationMode; test_bool(vsMotionDetectInit(&md, &mdconf, &testdata->fi) == VS_OK); + serializationMode = md.serializationMode; LocalMotions lms; int i; @@ -21,12 +24,12 @@ int test_store_restore(TestData* testdata){ } FILE* f = fopen("lmtest","w"); - vsStoreLocalmotions(f,&lms); + vsStoreLocalmotions(f,&lms,serializationMode); fclose(f); f = fopen("lmtest","r"); - LocalMotions test = vsRestoreLocalmotions(f); + LocalMotions test = vsRestoreLocalmotions(f,serializationMode); fclose(f); - vsStoreLocalmotions(stderr,&test); + vsStoreLocalmotions(stderr,&test,serializationMode); compare_localmotions(&lms,&test); fprintf(stderr,"\n** LM and LMS OKAY\n"); @@ -39,12 +42,12 @@ int test_store_restore(TestData* testdata){ fclose(f); f = fopen("lmstest","r"); - test_bool(vsReadFileVersion(f)==1); + test_bool(vsReadFileVersion(f,serializationMode)==1); LocalMotions read1; - test_bool(vsReadFromFile(f,&read1)==1); + test_bool(vsReadFromFile(f,&read1,serializationMode)==1); compare_localmotions(&lms,&read1); LocalMotions read2; - test_bool(vsReadFromFile(f,&read2)==2); + test_bool(vsReadFromFile(f,&read2,serializationMode)==2); compare_localmotions(&test,&read2); fclose(f); fprintf(stderr,"** Reading file stepwise OKAY\n"); diff --git a/tests/tests.c b/tests/tests.c index b52aeec..3fc2c15 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -120,7 +120,9 @@ int main(int argc, char** argv){ } if(all || contains(argv,argc,"--testSR", "store_restore")){ - UNIT(test_store_restore(&testdata)); + UNIT(test_store_restore(&testdata, ASCII_SERIALIZATION_MODE)); + UNIT(test_store_restore(&testdata, BINARY_SERIALIZATION_MODE)); + UNIT(test_store_restore(&testdata, 0)); // test default binary selection } if(all || contains(argv,argc,"--testCT", "contrastImg")){ diff --git a/transcode/filter_deshake.c b/transcode/filter_deshake.c index b49f076..38d7fd5 100644 --- a/transcode/filter_deshake.c +++ b/transcode/filter_deshake.c @@ -213,6 +213,7 @@ static int deshake_configure(TCModuleInstance *self, return(TC_IMPORT_ERROR); } + optstr_get(options, "fileformat", "%d", &md->serializationMode); optstr_get(options, "result", "%[^:]", sd->result); optstr_get(options, "shakiness", "%d", &mdconf.shakiness); optstr_get(options, "accuracy", "%d", &mdconf.accuracy); diff --git a/transcode/filter_stabilize.c b/transcode/filter_stabilize.c index 264118d..9b9e962 100644 --- a/transcode/filter_stabilize.c +++ b/transcode/filter_stabilize.c @@ -173,6 +173,7 @@ static int stabilize_configure(TCModuleInstance *self, return(TC_IMPORT_ERROR); } + optstr_get(options, "fileformat", "%d", &md->serializationMode); optstr_get(options, "result", "%[^:]", sd->result); optstr_get(options, "shakiness", "%d", &conf.shakiness); optstr_get(options, "accuracy", "%d", &conf.accuracy); From bd6f643be838a2771e002b995e98abbbb5fbc46c Mon Sep 17 00:00:00 2001 From: Ernest Wilkerson Date: Thu, 5 Nov 2020 13:14:15 -0800 Subject: [PATCH 3/3] Update help options to include file format information --- src/motiondetect.h | 2 ++ transcode/filter_deshake.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/motiondetect.h b/src/motiondetect.h index f1018de..c7573e3 100644 --- a/src/motiondetect.h +++ b/src/motiondetect.h @@ -95,6 +95,8 @@ static const char vs_motiondetect_help[] = "" " (translation, rotation) about subsequent frames." " See also transform.\n" "Options\n" + " 'fileformat' the type of file format used to write the transforms\n" + " 1: ascii (human readable) file format 2: binary (smaller) file format\n" " 'result' path to the file used to write the transforms\n" " (def:inputfile.stab)\n" " 'shakiness' how shaky is the video and how quick is the camera?\n" diff --git a/transcode/filter_deshake.c b/transcode/filter_deshake.c index 38d7fd5..35160ac 100644 --- a/transcode/filter_deshake.c +++ b/transcode/filter_deshake.c @@ -79,6 +79,8 @@ static const char deshake_help[] = "" " It also generates a file with relative transform information\n" " to be used by the transform filter separately." "Options\n" + " 'fileformat' the type of file format used to write the transforms\n" + " 1: ascii (human readable) file format 2: binary (smaller) file format\n" " 'smoothing' number of frames*2 + 1 used for lowpass filtering \n" " used for stabilizing (def: 10)\n" " 'shakiness' how shaky is the video and how quick is the camera?\n"