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);
}
}