mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-04-24 22:17:25 -04:00
Merge pull request #11798 from gnattu/fix-trickplay-image-height
Recalculate trickplay image height for anamorphic videos
This commit is contained in:
commit
d9232e05f1
2 changed files with 33 additions and 10 deletions
|
@ -3164,7 +3164,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
int? requestedMaxHeight)
|
int? requestedMaxHeight)
|
||||||
{
|
{
|
||||||
var isV4l2 = string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase);
|
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 scaleVal = isV4l2 ? 64 : 2;
|
||||||
|
var targetAr = isMjpeg ? "(a*sar)" : "a"; // manually calculate AR when using mjpeg encoder
|
||||||
|
|
||||||
// If fixed dimensions were supplied
|
// If fixed dimensions were supplied
|
||||||
if (requestedWidth.HasValue && requestedHeight.HasValue)
|
if (requestedWidth.HasValue && requestedHeight.HasValue)
|
||||||
|
@ -3193,10 +3195,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
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,
|
maxWidthParam,
|
||||||
maxHeightParam,
|
maxHeightParam,
|
||||||
scaleVal);
|
scaleVal,
|
||||||
|
targetAr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a fixed width was requested
|
// If a fixed width was requested
|
||||||
|
@ -3212,8 +3215,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"scale={0}:trunc(ow/a/2)*2",
|
"scale={0}:trunc(ow/{1}/2)*2",
|
||||||
widthParam);
|
widthParam,
|
||||||
|
targetAr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a fixed height was requested
|
// If a fixed height was requested
|
||||||
|
@ -3223,9 +3227,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"scale=trunc(oh*a/{1})*{1}:{0}",
|
"scale=trunc(oh*{2}/{1})*{1}:{0}",
|
||||||
heightParam,
|
heightParam,
|
||||||
scaleVal);
|
scaleVal,
|
||||||
|
targetAr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a max width was requested
|
// If a max width was requested
|
||||||
|
@ -3235,9 +3240,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
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,
|
maxWidthParam,
|
||||||
scaleVal);
|
scaleVal,
|
||||||
|
targetAr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a max height was requested
|
// If a max height was requested
|
||||||
|
@ -3247,9 +3253,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
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,
|
maxHeightParam,
|
||||||
scaleVal);
|
scaleVal,
|
||||||
|
targetAr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
|
@ -822,6 +822,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
options.EnableTonemapping = false;
|
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 baseRequest = new BaseEncodingJobOptions { MaxWidth = maxWidth, MaxFramerate = (float)(1.0 / interval.TotalSeconds) };
|
||||||
var jobState = new EncodingJobInfo(TranscodingJobType.Progressive)
|
var jobState = new EncodingJobInfo(TranscodingJobType.Progressive)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue