MediaStreamRepository.cs 7.9 KB

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