bool hashVideo()

in tmk/cpp/hashing/filehasher.cpp [28:129]


bool hashVideo(
    int downsampleFrameDimension,
    std::string ffmpegGeneratorCommand,
    io::TMKFramewiseAlgorithm tmkFramewiseAlgorithm,
    int resampleFramesPerSecond,
    facebook::tmk::algo::TMKFeatureVectors& tmkFeatureVectors,
    bool verbose,
    const char* argv0) {
  if (verbose) {
    fprintf(stderr, "%s\n", ffmpegGeneratorCommand.c_str());
  }

  FILE* inputFp = popen(ffmpegGeneratorCommand.c_str(), POPEN_MODE);
  if (inputFp == nullptr) {
    fprintf(stderr, "%s: ffmpeg to generate video stream failed\n", argv0);
    return false;
  }

  // ----------------------------------------------------------------
  std::unique_ptr<tmk::hashing::AbstractFrameBufferHasher> phasher =
      tmk::hashing::FrameBufferHasherFactory::createFrameHasher(
          tmkFramewiseAlgorithm,
          downsampleFrameDimension,
          downsampleFrameDimension);

  if (phasher == nullptr) {
    fprintf(stderr, "Error: Phasher is null");
    return false;
  }

  int frameFeatureDimension = phasher->getFeatureDimension();

  // ----------------------------------------------------------------
  // Allocate this and re-use it over frames, rather than allocating/freeing
  // on each frame.
  std::unique_ptr<uint8_t[]> rawFrameBuffer(
      new uint8_t[downsampleFrameDimension * downsampleFrameDimension * 3]);
  std::vector<float> feature(frameFeatureDimension);

  std::vector<int> periods =
      facebook::tmk::algo::TMKFeatureVectors::makePoullotPeriods();

  std::vector<float> fourierCoefficients =
      facebook::tmk::algo::TMKFeatureVectors::makePoullotFourierCoefficients();

  tmkFeatureVectors = facebook::tmk::algo::TMKFeatureVectors(
      tmkFramewiseAlgorithm,
      resampleFramesPerSecond,
      periods,
      fourierCoefficients,
      frameFeatureDimension);
  try {
    bool eof = false;
    while (!feof(inputFp)) {
      bool read_rc = facebook::tmk::io::readRGBTriples(
          rawFrameBuffer.get(),
          downsampleFrameDimension,
          downsampleFrameDimension,
          inputFp,
          eof);
      if (eof) {
        break;
      }
      if (!read_rc) {
        perror("fread");
        fprintf(
            stderr,
            "%s: failed to read frame buffer %d.\n",
            argv0,
            tmkFeatureVectors.getFrameFeatureCount());
        return false;
      }

      if (!phasher->hashFrame(rawFrameBuffer.get(), feature)) {
        fprintf(
            stderr,
            "%s: failed to hash frame buffer %d.\n",
            argv0,
            tmkFeatureVectors.getFrameFeatureCount());
        return false;
      }

      tmkFeatureVectors.ingestFrameFeature(
          feature, tmkFeatureVectors.getFrameFeatureCount());
    }
  } catch (const exception& e) {
    fprintf(stderr, "%s: failed to download and hash video.\n", argv0);
    fprintf(stderr, "%s\n", e.what());
    return false;
  }
  tmkFeatureVectors.finishFrameFeatureIngest();

  //  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  // This includes failure to exec the subordinate process.
  int pclose_rc = pclose(inputFp);
  if (pclose_rc != 0) {
    fprintf(stderr, "%s: ffmpeg pclose return code %d.\n", argv0, pclose_rc);
    return false;
  }

  return true;
}