tmk/cpp/io/tmkio.cpp (396 lines of code) (raw):

// ================================================================ // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved // ================================================================ // ================================================================ // Methods for reading/writing TMK file formats: .vstr/.feat/.tmk file // headers, RGB frame-raster contents, and float-array contents. // ================================================================ #include <tmk/cpp/io/tmkio.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> namespace facebook { namespace tmk { namespace io { // ---------------------------------------------------------------- FILE* openFileOrDie(const char* filename, const char* mode, const char* argv0) { FILE* fp = fopen(filename, mode); if (fp == nullptr) { perror("fopen"); fprintf( stderr, "%s: could not open \"%s\" for mode \"%s\".\n", argv0, filename, mode); exit(1); } return fp; } // ---------------------------------------------------------------- TMKFramewiseAlgorithm algoFromMagic(char magic[4]) { if (!memcmp(&magic[0], PDQ_FLOAT_ALGO_MAGIC, TMK_MAGIC_LENGTH)) { return TMKFramewiseAlgorithm::PDQ_FLOAT; } else { return TMKFramewiseAlgorithm::UNRECOGNIZED; } } // ---------------------------------------------------------------- TMKFramewiseAlgorithm algoFromMagicOrDie(char* argv0, char magic[4], char* fromFileName) { TMKFramewiseAlgorithm algorithm = algoFromMagic(magic); if (algorithm == TMKFramewiseAlgorithm::UNRECOGNIZED) { reportUnrecognizedAlgorithmMagic(argv0, magic, fromFileName); exit(1); } return algorithm; } // ---------------------------------------------------------------- void reportUnrecognizedAlgorithmMagic( char* argv0, char magic[4], char* fromFileName) { fprintf( stderr, "%s: unrecognized algorithm %c%c%c%c (%02x%02x%02x%02x) in \"%s\".\n", argv0, makePrintable(magic[0]), makePrintable(magic[1]), makePrintable(magic[2]), makePrintable(magic[3]), magic[0], magic[1], magic[2], magic[3], fromFileName); } // ---------------------------------------------------------------- bool algoToMagic( TMKFramewiseAlgorithm algorithm, char magic[TMK_MAGIC_LENGTH]) { bool rv = false; switch (algorithm) { case TMKFramewiseAlgorithm::PDQ_FLOAT: memcpy(&magic[0], PDQ_FLOAT_ALGO_MAGIC, TMK_MAGIC_LENGTH); rv = true; break; default: break; } return rv; } // ---------------------------------------------------------------- TMKFramewiseAlgorithm algoFromLowercaseName(std::string name) { if (name == "pdqf") { return TMKFramewiseAlgorithm::PDQ_FLOAT; } else if (name == "pdqfloat") { return TMKFramewiseAlgorithm::PDQ_FLOAT; } else { return TMKFramewiseAlgorithm::UNRECOGNIZED; } } // ---------------------------------------------------------------- std::string algorithmToName(TMKFramewiseAlgorithm algorithm) { switch (algorithm) { case TMKFramewiseAlgorithm::PDQ_FLOAT: return std::string("PDQF"); break; default: return std::string("????"); break; } } // ---------------------------------------------------------------- bool readDecodedVideoStreamFileHeader( FILE* fp, DecodedVideoStreamFileHeader* pheader, const char* programName) { size_t rc = fread(pheader, sizeof(*pheader), 1, fp); if (rc != 1) { perror("fread"); fprintf( stderr, "%s: failed to read decodedVideoStreamFileHeader.\n", programName); return false; } if (!checkMagic( pheader->projectMagic, (char*)TMK_PROJECT_MAGIC, programName)) { return false; } if (!checkMagic( pheader->fileTypeMagic, (char*)VSTR_FILETYPE_MAGIC, programName)) { return false; } return true; } // ---------------------------------------------------------------- bool readFrameFeaturesFileHeader( FILE* fp, FrameFeaturesFileHeader* pheader, TMKFramewiseAlgorithm& algorithm, const char* programName) { size_t rc = fread(pheader, sizeof(*pheader), 1, fp); if (rc != 1) { perror("fread"); fprintf( stderr, "%s: failed to read decodedVideoStreamFileHeader.\n", programName); return false; } if (!checkMagic( pheader->projectMagic, (char*)TMK_PROJECT_MAGIC, programName)) { return false; } if (!checkMagic( pheader->fileTypeMagic, (char*)FEAT_FILETYPE_MAGIC, programName)) { return false; } algorithm = algoFromMagic(pheader->frameFeatureAlgorithmMagic); return true; } // ---------------------------------------------------------------- bool readFeatureVectorFileHeader( FILE* fp, FeatureVectorFileHeader* pheader, TMKFramewiseAlgorithm& algorithm, const char* programName) { size_t rc = fread(pheader, sizeof(*pheader), 1, fp); if (rc != 1) { perror("fread"); fprintf( stderr, "%s: failed to read decodedVideoStreamFileHeader.\n", programName); return false; } if (!checkMagic( pheader->projectMagic, (char*)TMK_PROJECT_MAGIC, programName)) { return false; } if (!checkMagic( pheader->fileTypeMagic, (char*)FVEC_FILETYPE_MAGIC, programName)) { return false; } algorithm = algoFromMagic(pheader->frameFeatureAlgorithmMagic); return true; } // ---------------------------------------------------------------- bool writeDecodedVideoStreamFileHeader( FILE* fp, int frameHeight, int frameWidth, int framesPerSecond, const char* programName) { DecodedVideoStreamFileHeader header; memset(&header, 0, sizeof(header)); for (int i = 0; i < TMK_MAGIC_LENGTH; i++) { header.projectMagic[i] = TMK_PROJECT_MAGIC[i]; header.fileTypeMagic[i] = VSTR_FILETYPE_MAGIC[i]; } header.frameHeight = frameHeight; header.frameWidth = frameWidth; header.framesPerSecond = framesPerSecond; size_t rc = fwrite(&header, sizeof(header), 1, fp); if (rc != 1) { perror("fwrite"); fprintf( stderr, "%s: failed to write decodedVideoStreamFileHeader.\n", programName); return false; } return true; } // ---------------------------------------------------------------- bool writeFrameFeaturesFileHeader( FILE* fp, TMKFramewiseAlgorithm algorithm, int frameFeatureDimension, int framesPerSecond, const char* programName) { FrameFeaturesFileHeader header; memset(&header, 0, sizeof(header)); for (int i = 0; i < TMK_MAGIC_LENGTH; i++) { header.projectMagic[i] = TMK_PROJECT_MAGIC[i]; header.fileTypeMagic[i] = FEAT_FILETYPE_MAGIC[i]; } char algorithmMagic[TMK_MAGIC_LENGTH]; if (!algoToMagic(algorithm, algorithmMagic)) { fprintf( stderr, "%s: Internal coding error: algorithm %d unmapped.\n", programName, (int)algorithm); return false; } memcpy( &header.frameFeatureAlgorithmMagic[0], &algorithmMagic[0], TMK_MAGIC_LENGTH); header.frameFeatureDimension = frameFeatureDimension; header.framesPerSecond = framesPerSecond; size_t rc = fwrite(&header, sizeof(header), 1, fp); if (rc != 1) { perror("fwrite"); fprintf( stderr, "%s: failed to write frameFeaturesFileHeader.\n", programName); return false; } return true; } // ---------------------------------------------------------------- bool writeFeatureVectorFileHeader( FILE* fp, TMKFramewiseAlgorithm algorithm, int framesPerSecond, int numPeriods, // a.k.a. P int numFourierCoefficients, // a.k.a m int frameFeatureDimension, // a.k.a d int frameFeatureCount, const char* programName) { FeatureVectorFileHeader header; memset(&header, 0, sizeof(header)); for (int i = 0; i < TMK_MAGIC_LENGTH; i++) { header.projectMagic[i] = TMK_PROJECT_MAGIC[i]; header.fileTypeMagic[i] = FVEC_FILETYPE_MAGIC[i]; } char algorithmMagic[TMK_MAGIC_LENGTH]; if (!algoToMagic(algorithm, algorithmMagic)) { fprintf( stderr, "%s: Internal coding error: algorithm %d unmapped.\n", programName, (int)algorithm); return false; } memcpy( &header.frameFeatureAlgorithmMagic[0], &algorithmMagic[0], TMK_MAGIC_LENGTH); header.framesPerSecond = framesPerSecond; header.numPeriods = numPeriods; header.numFourierCoefficients = numFourierCoefficients; header.frameFeatureDimension = frameFeatureDimension; header.frameFeatureCount = frameFeatureCount; size_t rc = fwrite(&header, sizeof(header), 1, fp); if (rc != 1) { perror("fwrite"); fprintf( stderr, "%s: failed to write featureVectorFileHeader.\n", programName); return false; } return true; } // ---------------------------------------------------------------- char makePrintable(char c) { return isprint(c) ? c : '?'; } // ---------------------------------------------------------------- bool checkMagic( char actual[TMK_MAGIC_LENGTH], char* expected, const char* programName) { bool ok = true; if (strlen(expected) != TMK_MAGIC_LENGTH) { ok = false; } else { for (int i = 0; i < TMK_MAGIC_LENGTH; i++) { if (actual[i] != expected[i]) { ok = false; break; } } } if (!ok) { fprintf( stderr, "%s: got magic number %c%c%c%c (%02x%02x%02x%02x); " "expected %c%c%c%c (%02x%02x%02x%02x).\n", programName, makePrintable(actual[0]), makePrintable(actual[1]), makePrintable(actual[2]), makePrintable(actual[3]), actual[0], actual[1], actual[2], actual[3], makePrintable(expected[0]), makePrintable(expected[1]), makePrintable(expected[2]), makePrintable(expected[3]), expected[0], expected[1], expected[2], expected[3]); } return ok; } // ---------------------------------------------------------------- bool readRGBTriples( unsigned char* buffer, int height, int width, FILE* fp, bool& eof) { eof = false; int numRGBTriples = height * width; size_t fread_rc = fread(buffer, 3, numRGBTriples, fp); if (fread_rc == 0) { eof = true; return false; } if (fread_rc != numRGBTriples) { perror("fread"); fprintf( stderr, "Expected %d RGB triples; got %d\n", numRGBTriples, (int)fread_rc); return false; } return true; } // ---------------------------------------------------------------- bool readFloatVector(std::vector<float>& vector, FILE* fp, bool& eof) { eof = false; size_t fread_rc = fread(vector.data(), sizeof(float), vector.size(), fp); if (fread_rc == 0) { eof = true; return false; } if (fread_rc != vector.size()) { perror("fread"); fprintf( stderr, "Expected %d floats; got %d\n", (int)vector.size(), (int)fread_rc); return false; } return true; } // ---------------------------------------------------------------- bool writeFloatVector(const std::vector<float>& vector, FILE* fp) { size_t fwrite_rc = fwrite(vector.data(), sizeof(float), vector.size(), fp); if (fwrite_rc != vector.size()) { perror("fwrite"); fprintf( stderr, "Expected %d floats; got %d\n", (int)vector.size(), (int)fwrite_rc); return false; } return true; } // ---------------------------------------------------------------- bool readIntVector(std::vector<int>& vector, FILE* fp) { size_t fread_rc = fread(vector.data(), sizeof(int), vector.size(), fp); if (fread_rc == 0) { return false; } if (fread_rc != vector.size()) { perror("fread"); fprintf( stderr, "Expected %d ints; got %d\n", (int)vector.size(), (int)fread_rc); return false; } return true; } // ---------------------------------------------------------------- bool writeIntVector(const std::vector<int>& vector, FILE* fp) { size_t fwrite_rc = fwrite(vector.data(), sizeof(int), vector.size(), fp); if (fwrite_rc != vector.size()) { perror("fwrite"); fprintf( stderr, "Expected %d ints; got %d\n", (int)vector.size(), (int)fwrite_rc); return false; } return true; } } // namespace io } // namespace tmk } // namespace facebook