EmbeddedImageProviderTests.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Entities.Movies;
  7. using MediaBrowser.Controller.Entities.TV;
  8. using MediaBrowser.Controller.MediaEncoding;
  9. using MediaBrowser.Model.Drawing;
  10. using MediaBrowser.Model.Dto;
  11. using MediaBrowser.Model.Entities;
  12. using MediaBrowser.Providers.MediaInfo;
  13. using Moq;
  14. using Xunit;
  15. namespace Jellyfin.Providers.Tests.MediaInfo
  16. {
  17. public class EmbeddedImageProviderTests
  18. {
  19. public static TheoryData<BaseItem> GetSupportedImages_Empty_TestData =>
  20. new ()
  21. {
  22. new AudioBook(),
  23. new BoxSet(),
  24. new Series(),
  25. new Season(),
  26. };
  27. public static TheoryData<BaseItem, IEnumerable<ImageType>> GetSupportedImages_Populated_TestData =>
  28. new TheoryData<BaseItem, IEnumerable<ImageType>>
  29. {
  30. { new Episode(), new List<ImageType> { ImageType.Primary } },
  31. { new Movie(), new List<ImageType> { ImageType.Logo, ImageType.Backdrop, ImageType.Primary } },
  32. };
  33. private EmbeddedImageProvider GetEmbeddedImageProvider(IMediaEncoder? mediaEncoder)
  34. {
  35. return new EmbeddedImageProvider(mediaEncoder);
  36. }
  37. [Theory]
  38. [MemberData(nameof(GetSupportedImages_Empty_TestData))]
  39. public void GetSupportedImages_Empty(BaseItem item)
  40. {
  41. var embeddedImageProvider = GetEmbeddedImageProvider(null);
  42. Assert.False(embeddedImageProvider.GetSupportedImages(item).Any());
  43. }
  44. [Theory]
  45. [MemberData(nameof(GetSupportedImages_Populated_TestData))]
  46. public void GetSupportedImages_Populated(BaseItem item, IEnumerable<ImageType> expected)
  47. {
  48. var embeddedImageProvider = GetEmbeddedImageProvider(null);
  49. var actual = embeddedImageProvider.GetSupportedImages(item);
  50. Assert.Equal(expected.OrderBy(i => i.ToString()), actual.OrderBy(i => i.ToString()));
  51. }
  52. [Fact]
  53. public async void GetImage_Empty_NoStreams()
  54. {
  55. var embeddedImageProvider = GetEmbeddedImageProvider(null);
  56. var input = new Mock<Movie>();
  57. input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>()))
  58. .Returns(new List<MediaSourceInfo>());
  59. input.Setup(movie => movie.GetMediaStreams())
  60. .Returns(new List<MediaStream>());
  61. var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None);
  62. Assert.NotNull(actual);
  63. Assert.False(actual.HasImage);
  64. }
  65. [Fact]
  66. public async void GetImage_Empty_NoLabeledAttachments()
  67. {
  68. var embeddedImageProvider = GetEmbeddedImageProvider(null);
  69. var input = new Mock<Movie>();
  70. // add an attachment without a filename - has a list to look through but finds nothing
  71. input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>()))
  72. .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = new List<MediaAttachment> { new () } } });
  73. input.Setup(movie => movie.GetMediaStreams())
  74. .Returns(new List<MediaStream>());
  75. var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None);
  76. Assert.NotNull(actual);
  77. Assert.False(actual.HasImage);
  78. }
  79. [Fact]
  80. public async void GetImage_Empty_NoEmbeddedLabeledBackdrop()
  81. {
  82. var embeddedImageProvider = GetEmbeddedImageProvider(null);
  83. var input = new Mock<Movie>();
  84. input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>()))
  85. .Returns(new List<MediaSourceInfo>());
  86. input.Setup(movie => movie.GetMediaStreams())
  87. .Returns(new List<MediaStream> { new () { Type = MediaStreamType.EmbeddedImage } });
  88. var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None);
  89. Assert.NotNull(actual);
  90. Assert.False(actual.HasImage);
  91. }
  92. [Fact]
  93. public async void GetImage_Attached()
  94. {
  95. // first tests file extension detection, second uses mimetype, third defaults to jpg
  96. MediaAttachment sampleAttachment1 = new () { FileName = "clearlogo.png", Index = 1 };
  97. MediaAttachment sampleAttachment2 = new () { FileName = "backdrop", MimeType = "image/bmp", Index = 2 };
  98. MediaAttachment sampleAttachment3 = new () { FileName = "poster", Index = 3 };
  99. string targetPath1 = "path1.png";
  100. string targetPath2 = "path2.bmp";
  101. string targetPath3 = "path2.jpg";
  102. var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict);
  103. mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), 1, ".png", CancellationToken.None))
  104. .Returns(Task.FromResult(targetPath1));
  105. mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), 2, ".bmp", CancellationToken.None))
  106. .Returns(Task.FromResult(targetPath2));
  107. mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), 3, ".jpg", CancellationToken.None))
  108. .Returns(Task.FromResult(targetPath3));
  109. var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object);
  110. var input = new Mock<Movie>();
  111. input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>()))
  112. .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = new List<MediaAttachment> { sampleAttachment1, sampleAttachment2, sampleAttachment3 } } });
  113. input.Setup(movie => movie.GetMediaStreams())
  114. .Returns(new List<MediaStream>());
  115. var actualLogo = await embeddedImageProvider.GetImage(input.Object, ImageType.Logo, CancellationToken.None);
  116. Assert.NotNull(actualLogo);
  117. Assert.True(actualLogo.HasImage);
  118. Assert.Equal(targetPath1, actualLogo.Path);
  119. Assert.Equal(ImageFormat.Png, actualLogo.Format);
  120. var actualBackdrop = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None);
  121. Assert.NotNull(actualBackdrop);
  122. Assert.True(actualBackdrop.HasImage);
  123. Assert.Equal(targetPath2, actualBackdrop.Path);
  124. Assert.Equal(ImageFormat.Bmp, actualBackdrop.Format);
  125. var actualPrimary = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None);
  126. Assert.NotNull(actualPrimary);
  127. Assert.True(actualPrimary.HasImage);
  128. Assert.Equal(targetPath3, actualPrimary.Path);
  129. Assert.Equal(ImageFormat.Jpg, actualPrimary.Format);
  130. }
  131. [Fact]
  132. public async void GetImage_EmbeddedDefault()
  133. {
  134. MediaStream sampleStream = new () { Type = MediaStreamType.EmbeddedImage, Index = 1 };
  135. string targetPath = "path";
  136. var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict);
  137. mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream, 1, "jpg", CancellationToken.None))
  138. .Returns(Task.FromResult(targetPath));
  139. var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object);
  140. var input = new Mock<Movie>();
  141. input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>()))
  142. .Returns(new List<MediaSourceInfo>());
  143. input.Setup(movie => movie.GetMediaStreams())
  144. .Returns(new List<MediaStream>() { sampleStream });
  145. var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None);
  146. Assert.NotNull(actual);
  147. Assert.True(actual.HasImage);
  148. Assert.Equal(targetPath, actual.Path);
  149. Assert.Equal(ImageFormat.Jpg, actual.Format);
  150. }
  151. [Fact]
  152. public async void GetImage_EmbeddedSelection()
  153. {
  154. // primary is second stream to ensure it's not defaulting, backdrop is first
  155. MediaStream sampleStream1 = new () { Type = MediaStreamType.EmbeddedImage, Index = 1, Comment = "backdrop" };
  156. MediaStream sampleStream2 = new () { Type = MediaStreamType.EmbeddedImage, Index = 2, Comment = "cover" };
  157. string targetPath1 = "path1.jpg";
  158. string targetPath2 = "path2.jpg";
  159. var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict);
  160. mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream1, 1, "jpg", CancellationToken.None))
  161. .Returns(Task.FromResult(targetPath1));
  162. mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream2, 2, "jpg", CancellationToken.None))
  163. .Returns(Task.FromResult(targetPath2));
  164. var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object);
  165. var input = new Mock<Movie>();
  166. input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>()))
  167. .Returns(new List<MediaSourceInfo>());
  168. input.Setup(movie => movie.GetMediaStreams())
  169. .Returns(new List<MediaStream> { sampleStream1, sampleStream2 });
  170. var actualPrimary = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None);
  171. Assert.NotNull(actualPrimary);
  172. Assert.True(actualPrimary.HasImage);
  173. Assert.Equal(targetPath2, actualPrimary.Path);
  174. Assert.Equal(ImageFormat.Jpg, actualPrimary.Format);
  175. var actualBackdrop = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None);
  176. Assert.NotNull(actualBackdrop);
  177. Assert.True(actualBackdrop.HasImage);
  178. Assert.Equal(targetPath1, actualBackdrop.Path);
  179. Assert.Equal(ImageFormat.Jpg, actualBackdrop.Format);
  180. }
  181. }
  182. }