Backport pull request #11798 from jellyfin/release-10.9.z

Recalculate trickplay image height for anamorphic videos

Original-merge: d9232e05f1

Merged-by: Bond-009 <bond.009@outlook.com>

Backported-by: Joshua M. Boniface <joshua@boniface.me>
pull/11835/head
gnattu 4 months ago committed by Joshua M. Boniface
parent 2af1ae5d8a
commit ac0064110b

@ -3162,7 +3162,9 @@ namespace MediaBrowser.Controller.MediaEncoding
int? requestedMaxHeight)
{
var isV4l2 = string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase);
var isMjpeg = videoEncoder is not null && videoEncoder.Contains("mjpeg", StringComparison.OrdinalIgnoreCase);
var scaleVal = isV4l2 ? 64 : 2;
var targetAr = isMjpeg ? "(a*sar)" : "a"; // manually calculate AR when using mjpeg encoder
// If fixed dimensions were supplied
if (requestedWidth.HasValue && requestedHeight.HasValue)
@ -3191,10 +3193,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
@"scale=trunc(min(max(iw\,ih*a)\,min({0}\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\,ih)\,min({0}/a\,{1}))/2)*2",
@"scale=trunc(min(max(iw\,ih*{3})\,min({0}\,{1}*{3}))/{2})*{2}:trunc(min(max(iw/{3}\,ih)\,min({0}/{3}\,{1}))/2)*2",
maxWidthParam,
maxHeightParam,
scaleVal);
scaleVal,
targetAr);
}
// If a fixed width was requested
@ -3210,8 +3213,9 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
"scale={0}:trunc(ow/a/2)*2",
widthParam);
"scale={0}:trunc(ow/{1}/2)*2",
widthParam,
targetAr);
}
// If a fixed height was requested
@ -3221,9 +3225,10 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
"scale=trunc(oh*a/{1})*{1}:{0}",
"scale=trunc(oh*{2}/{1})*{1}:{0}",
heightParam,
scaleVal);
scaleVal,
targetAr);
}
// If a max width was requested
@ -3233,9 +3238,10 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
@"scale=trunc(min(max(iw\,ih*a)\,{0})/{1})*{1}:trunc(ow/a/2)*2",
@"scale=trunc(min(max(iw\,ih*{2})\,{0})/{1})*{1}:trunc(ow/{2}/2)*2",
maxWidthParam,
scaleVal);
scaleVal,
targetAr);
}
// If a max height was requested
@ -3245,9 +3251,10 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
@"scale=trunc(oh*a/{1})*{1}:min(max(iw/a\,ih)\,{0})",
@"scale=trunc(oh*{2}/{1})*{1}:min(max(iw/{2}\,ih)\,{0})",
maxHeightParam,
scaleVal);
scaleVal,
targetAr);
}
return string.Empty;

@ -822,6 +822,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
options.EnableTonemapping = false;
}
if (imageStream.Width is not null && imageStream.Height is not null && !string.IsNullOrEmpty(imageStream.AspectRatio))
{
// For hardware trickplay encoders, we need to re-calculate the size because they used fixed scale dimensions
var darParts = imageStream.AspectRatio.Split(':');
var (wa, ha) = (double.Parse(darParts[0], CultureInfo.InvariantCulture), double.Parse(darParts[1], CultureInfo.InvariantCulture));
// When dimension / DAR does not equal to 1:1, then the frames are most likely stored stretched.
// Note: this might be incorrect for 3D videos as the SAR stored might be per eye instead of per video, but we really can do little about it.
var shouldResetHeight = Math.Abs((imageStream.Width.Value * ha) - (imageStream.Height.Value * wa)) > .05;
if (shouldResetHeight)
{
// SAR = DAR * Height / Width
// RealHeight = Height / SAR = Height / (DAR * Height / Width) = Width / DAR
imageStream.Height = Convert.ToInt32(imageStream.Width.Value * ha / wa);
}
}
var baseRequest = new BaseEncodingJobOptions { MaxWidth = maxWidth, MaxFramerate = (float)(1.0 / interval.TotalSeconds) };
var jobState = new EncodingJobInfo(TranscodingJobType.Progressive)
{

Loading…
Cancel
Save