MediaStreamRepository.cs 7.8 KB

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