MediaStreamRepository.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Immutable;
  4. using System.Linq;
  5. using System.Threading;
  6. using Jellyfin.Data.Entities;
  7. using MediaBrowser.Controller;
  8. using MediaBrowser.Controller.Persistence;
  9. using MediaBrowser.Model.Entities;
  10. using MediaBrowser.Model.Globalization;
  11. using Microsoft.EntityFrameworkCore;
  12. namespace Jellyfin.Server.Implementations.Item;
  13. /// <summary>
  14. /// Initializes a new instance of the <see cref="MediaStreamRepository"/> class.
  15. /// </summary>
  16. /// <param name="dbProvider">The EFCore db factory.</param>
  17. /// <param name="serverApplicationHost">The Application host.</param>
  18. /// <param name="localization">The Localisation Provider.</param>
  19. public class MediaStreamRepository(IDbContextFactory<JellyfinDbContext> dbProvider, IServerApplicationHost serverApplicationHost, ILocalizationManager localization) : IMediaStreamRepository
  20. {
  21. /// <inheritdoc />
  22. public void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken)
  23. {
  24. using var context = dbProvider.CreateDbContext();
  25. using var transaction = context.Database.BeginTransaction();
  26. context.MediaStreamInfos.Where(e => e.ItemId.Equals(id)).ExecuteDelete();
  27. context.MediaStreamInfos.AddRange(streams.Select(f => Map(f, id)));
  28. context.SaveChanges();
  29. transaction.Commit();
  30. }
  31. /// <inheritdoc />
  32. public IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery filter)
  33. {
  34. using var context = dbProvider.CreateDbContext();
  35. return TranslateQuery(context.MediaStreamInfos.AsNoTracking(), filter).AsEnumerable().Select(Map).ToImmutableArray();
  36. }
  37. private string? GetPathToSave(string? path)
  38. {
  39. if (path is null)
  40. {
  41. return null;
  42. }
  43. return serverApplicationHost.ReverseVirtualPath(path);
  44. }
  45. private string? RestorePath(string? path)
  46. {
  47. if (path is null)
  48. {
  49. return null;
  50. }
  51. return serverApplicationHost.ExpandVirtualPath(path);
  52. }
  53. private IQueryable<MediaStreamInfo> TranslateQuery(IQueryable<MediaStreamInfo> query, MediaStreamQuery filter)
  54. {
  55. query = query.Where(e => e.ItemId.Equals(filter.ItemId));
  56. if (filter.Index.HasValue)
  57. {
  58. query = query.Where(e => e.StreamIndex == filter.Index);
  59. }
  60. if (filter.Type.HasValue)
  61. {
  62. var typeValue = (MediaStreamTypeEntity)filter.Type.Value;
  63. query = query.Where(e => e.StreamType!.Value == typeValue);
  64. }
  65. return query;
  66. }
  67. private MediaStream Map(MediaStreamInfo entity)
  68. {
  69. var dto = new MediaStream();
  70. dto.Index = entity.StreamIndex;
  71. if (entity.StreamType != null)
  72. {
  73. dto.Type = (MediaStreamType)entity.StreamType;
  74. }
  75. dto.IsAVC = entity.IsAvc;
  76. dto.Codec = entity.Codec;
  77. dto.Language = entity.Language;
  78. dto.ChannelLayout = entity.ChannelLayout;
  79. dto.Profile = entity.Profile;
  80. dto.AspectRatio = entity.AspectRatio;
  81. dto.Path = RestorePath(entity.Path);
  82. dto.IsInterlaced = entity.IsInterlaced;
  83. dto.BitRate = entity.BitRate;
  84. dto.Channels = entity.Channels;
  85. dto.SampleRate = entity.SampleRate;
  86. dto.IsDefault = entity.IsDefault;
  87. dto.IsForced = entity.IsForced;
  88. dto.IsExternal = entity.IsExternal;
  89. dto.Height = entity.Height;
  90. dto.Width = entity.Width;
  91. dto.AverageFrameRate = entity.AverageFrameRate;
  92. dto.RealFrameRate = entity.RealFrameRate;
  93. dto.Level = entity.Level;
  94. dto.PixelFormat = entity.PixelFormat;
  95. dto.BitDepth = entity.BitDepth;
  96. dto.IsAnamorphic = entity.IsAnamorphic;
  97. dto.RefFrames = entity.RefFrames;
  98. dto.CodecTag = entity.CodecTag;
  99. dto.Comment = entity.Comment;
  100. dto.NalLengthSize = entity.NalLengthSize;
  101. dto.Title = entity.Title;
  102. dto.TimeBase = entity.TimeBase;
  103. dto.CodecTimeBase = entity.CodecTimeBase;
  104. dto.ColorPrimaries = entity.ColorPrimaries;
  105. dto.ColorSpace = entity.ColorSpace;
  106. dto.ColorTransfer = entity.ColorTransfer;
  107. dto.DvVersionMajor = entity.DvVersionMajor;
  108. dto.DvVersionMinor = entity.DvVersionMinor;
  109. dto.DvProfile = entity.DvProfile;
  110. dto.DvLevel = entity.DvLevel;
  111. dto.RpuPresentFlag = entity.RpuPresentFlag;
  112. dto.ElPresentFlag = entity.ElPresentFlag;
  113. dto.BlPresentFlag = entity.BlPresentFlag;
  114. dto.DvBlSignalCompatibilityId = entity.DvBlSignalCompatibilityId;
  115. dto.IsHearingImpaired = entity.IsHearingImpaired;
  116. dto.Rotation = entity.Rotation;
  117. if (dto.Type is MediaStreamType.Audio or MediaStreamType.Subtitle)
  118. {
  119. dto.LocalizedDefault = localization.GetLocalizedString("Default");
  120. dto.LocalizedExternal = localization.GetLocalizedString("External");
  121. if (dto.Type is MediaStreamType.Subtitle)
  122. {
  123. dto.LocalizedUndefined = localization.GetLocalizedString("Undefined");
  124. dto.LocalizedForced = localization.GetLocalizedString("Forced");
  125. dto.LocalizedHearingImpaired = localization.GetLocalizedString("HearingImpaired");
  126. }
  127. }
  128. return dto;
  129. }
  130. private MediaStreamInfo Map(MediaStream dto, Guid itemId)
  131. {
  132. var entity = new MediaStreamInfo
  133. {
  134. Item = null!,
  135. ItemId = itemId,
  136. StreamIndex = dto.Index,
  137. StreamType = (MediaStreamTypeEntity)dto.Type,
  138. IsAvc = dto.IsAVC.GetValueOrDefault(),
  139. Codec = dto.Codec,
  140. Language = dto.Language,
  141. ChannelLayout = dto.ChannelLayout,
  142. Profile = dto.Profile,
  143. AspectRatio = dto.AspectRatio,
  144. Path = GetPathToSave(dto.Path),
  145. IsInterlaced = dto.IsInterlaced,
  146. BitRate = dto.BitRate.GetValueOrDefault(0),
  147. Channels = dto.Channels.GetValueOrDefault(0),
  148. SampleRate = dto.SampleRate.GetValueOrDefault(0),
  149. IsDefault = dto.IsDefault,
  150. IsForced = dto.IsForced,
  151. IsExternal = dto.IsExternal,
  152. Height = dto.Height.GetValueOrDefault(0),
  153. Width = dto.Width.GetValueOrDefault(0),
  154. AverageFrameRate = dto.AverageFrameRate.GetValueOrDefault(0),
  155. RealFrameRate = dto.RealFrameRate.GetValueOrDefault(0),
  156. Level = (float)dto.Level.GetValueOrDefault(),
  157. PixelFormat = dto.PixelFormat,
  158. BitDepth = dto.BitDepth.GetValueOrDefault(0),
  159. IsAnamorphic = dto.IsAnamorphic.GetValueOrDefault(),
  160. RefFrames = dto.RefFrames.GetValueOrDefault(0),
  161. CodecTag = dto.CodecTag,
  162. Comment = dto.Comment,
  163. NalLengthSize = dto.NalLengthSize,
  164. Title = dto.Title,
  165. TimeBase = dto.TimeBase,
  166. CodecTimeBase = dto.CodecTimeBase,
  167. ColorPrimaries = dto.ColorPrimaries,
  168. ColorSpace = dto.ColorSpace,
  169. ColorTransfer = dto.ColorTransfer,
  170. DvVersionMajor = dto.DvVersionMajor.GetValueOrDefault(0),
  171. DvVersionMinor = dto.DvVersionMinor.GetValueOrDefault(0),
  172. DvProfile = dto.DvProfile.GetValueOrDefault(0),
  173. DvLevel = dto.DvLevel.GetValueOrDefault(0),
  174. RpuPresentFlag = dto.RpuPresentFlag.GetValueOrDefault(0),
  175. ElPresentFlag = dto.ElPresentFlag.GetValueOrDefault(0),
  176. BlPresentFlag = dto.BlPresentFlag.GetValueOrDefault(0),
  177. DvBlSignalCompatibilityId = dto.DvBlSignalCompatibilityId.GetValueOrDefault(0),
  178. IsHearingImpaired = dto.IsHearingImpaired,
  179. Rotation = dto.Rotation.GetValueOrDefault(0)
  180. };
  181. return entity;
  182. }
  183. }