void VideoFrameTransform::calcualteFilteringConfig()

in Transform360/Library/VideoFrameTransform.cpp [389:531]


void VideoFrameTransform::calcualteFilteringConfig(
    int inputWidth,
    int inputHeight,
    int outputWidth,
    int outputHeight,
    int transformMatPlaneIndex) {
  // For stereo videos, we calculate the filtering config
  // only for one single view because the configs are the same
  // for both views. During the final filtering process, we apply
  // the config on both views, respectively.
  switch (ctx_.input_stereo_format) {
    case STEREO_FORMAT_LR:
      inputWidth *= 0.5;
      break;
    case STEREO_FORMAT_TB:
      inputHeight *= 0.5;
      break;
    case STEREO_FORMAT_MONO:
    case STEREO_FORMAT_GUESS:
    case STEREO_FORMAT_N:
      break;
  }

  switch (ctx_.output_stereo_format) {
    case STEREO_FORMAT_LR:
      outputWidth *= 0.5;
      break;
    case STEREO_FORMAT_TB:
      outputHeight *= 0.5;
      break;
    case STEREO_FORMAT_MONO:
    case STEREO_FORMAT_GUESS:
    case STEREO_FORMAT_N:
      break;
  }

  // Calculate the size of the basic 1D filter along Y direction
  float hFov, vFov;
  switch (ctx_.output_layout) {
    case LAYOUT_CUBEMAP_32:
      {
        hFov = 270.0;
        vFov = 180.0;
        break;
      }
    case LAYOUT_CUBEMAP_23_OFFCENTER:
      {
        hFov = 180.0;
        vFov = 270.0;
        break;
      }
#ifdef FACEBOOK_LAYOUT
    case LAYOUT_FB:
      calculateFov(ctx_.fixed_hfov, ctx_.fixed_vfov, hFov, vFov);
      break;
#endif
    case LAYOUT_FLAT_FIXED:
      {
        hFov = ctx_.fixed_hfov;
        vFov = ctx_.fixed_vfov;
        break;
      }
    case LAYOUT_EQUIRECT:
      {
        hFov = 360.0;
        vFov = 180.0;
        break;
      }
    case LAYOUT_BARREL:
    case LAYOUT_BARREL_SPLIT:
      {
        hFov = 450.0;
        vFov = 90.0;
        break;
      }
    case LAYOUT_EAC_32:
      {
        hFov = 270.0;
        vFov = 180.0;
        break;
      }
    case LAYOUT_N:
      {
        printf(
          "Invalid layout type for plane %d.\n", transformMatPlaneIndex);
        return;
      }
  }

  float sigmaY = 0.5f * std::min(
      ctx_.max_kernel_half_height,
      std::max(
        ctx_.min_kernel_half_height,
        ctx_.kernel_height_scale_factor *
          std::min(inputWidth / 360.0f, inputHeight / 180.0f) /
            std::max(outputWidth / hFov, outputHeight / vFov)));

  // Build a basic 1D filter along Y direction
  Mat kernelY = calculateKernel(sigmaY);

  // The maximum height of a segment
  int baseSegmentHeight = ceil(1.0 * inputHeight / ctx_.num_vertical_segments);

  if (ctx_.num_vertical_segments % 2 == 0) {
    // Both top and bottom halves of the frame plane are divided into
    // 0.5 * ctx_.num_vertical_segments segments
    generateKernelsAndFilteringConfigs(
      0.5 * inputHeight,
      0.5 * inputHeight - 1,
      sigmaY,
      kernelY,
      baseSegmentHeight,
      inputWidth,
      inputHeight,
      transformMatPlaneIndex);
  } else {
    // One segment is centered at equator and occupies
    // 0.5 * baseSegmentHeight in top and bottom halves, respectively.
    int top = 0.5 * (inputHeight - baseSegmentHeight);
    int bottom = top + baseSegmentHeight - 1;
    generateKernelAndFilteringConfig(
      top,
      bottom,
      0,
      sigmaY,
      kernelY,
      inputWidth,
      inputHeight,
      transformMatPlaneIndex);

    // Divid the rest of the frame plane into
    // ctx_.num_vertical_segments - 1 segments
    generateKernelsAndFilteringConfigs(
      bottom + 1,
      top - 1,
      sigmaY,
      kernelY,
      baseSegmentHeight,
      inputWidth,
      inputHeight,
      transformMatPlaneIndex);
  }
}