aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
authornicknsy <20588554+nicknsy@users.noreply.github.com>2023-02-22 00:08:35 -0800
committerNick <20588554+nicknsy@users.noreply.github.com>2023-06-22 16:19:59 -0700
commitca7d1a13000ad948eebbfdeb40542312f3e37d3e (patch)
tree6ff31f7f318410c62ba3278aeac71f26e9626603 /Emby.Server.Implementations
parenta1eb2f6ea8cd78d527f1ae395378419f016208ab (diff)
Trickplay generation, manager, storage
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs3
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs123
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs5
3 files changed, 131 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 7969577bc..1e0bb0cd6 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -78,6 +78,7 @@ using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller.SyncPlay;
+using MediaBrowser.Controller.Trickplay;
using MediaBrowser.Controller.TV;
using MediaBrowser.LocalMetadata.Savers;
using MediaBrowser.MediaEncoding.BdInfo;
@@ -96,6 +97,7 @@ using MediaBrowser.Providers.Lyric;
using MediaBrowser.Providers.Manager;
using MediaBrowser.Providers.Plugins.Tmdb;
using MediaBrowser.Providers.Subtitles;
+using MediaBrowser.Providers.Trickplay;
using MediaBrowser.XbmcMetadata.Providers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -591,6 +593,7 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IDeviceDiscovery, DeviceDiscovery>();
serviceCollection.AddSingleton<IChapterManager, ChapterManager>();
+ serviceCollection.AddSingleton<ITrickplayManager, TrickplayManager>();
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index ca8f605a0..8ec24522b 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -48,6 +48,7 @@ namespace Emby.Server.Implementations.Data
{
private const string FromText = " from TypedBaseItems A";
private const string ChaptersTableName = "Chapters2";
+ private const string TrickplayTableName = "Trickplay";
private const string SaveItemCommandText =
@"replace into TypedBaseItems
@@ -383,6 +384,8 @@ namespace Emby.Server.Implementations.Data
"create table if not exists " + ChaptersTableName + " (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
+ "create table if not exists " + TrickplayTableName + " (ItemId GUID, Width INT NOT NULL, Height INT NOT NULL, TileWidth INT NOT NULL, TileHeight INT NOT NULL, TileCount INT NOT NULL, Interval INT NOT NULL, Bandwidth INT NOT NULL, PRIMARY KEY (ItemId, Width))",
+
CreateMediaStreamsTableCommand,
CreateMediaAttachmentsTableCommand,
@@ -2135,6 +2138,126 @@ namespace Emby.Server.Implementations.Data
}
}
+ /// <inheritdoc />
+ public Dictionary<int, TrickplayTilesInfo> GetTilesResolutions(Guid itemId)
+ {
+ CheckDisposed();
+
+ var tilesResolutions = new Dictionary<int, TrickplayTilesInfo>();
+ using (var connection = GetConnection(true))
+ {
+ using (var statement = PrepareStatement(connection, "select Width,Height,TileWidth,TileHeight,TileCount,Interval,Bandwidth from " + TrickplayTableName + " where ItemId = @ItemId order by Width asc"))
+ {
+ statement.TryBind("@ItemId", itemId);
+
+ foreach (var row in statement.ExecuteQuery())
+ {
+ TrickplayTilesInfo tilesInfo = GetTrickplayTilesInfo(row);
+ tilesResolutions[tilesInfo.Width] = tilesInfo;
+ }
+ }
+ }
+
+ return tilesResolutions;
+ }
+
+ /// <inheritdoc />
+ public void SaveTilesInfo(Guid itemId, TrickplayTilesInfo tilesInfo)
+ {
+ CheckDisposed();
+
+ ArgumentNullException.ThrowIfNull(tilesInfo);
+
+ var idBlob = itemId.ToByteArray();
+ using (var connection = GetConnection(false))
+ {
+ connection.RunInTransaction(
+ db =>
+ {
+ // Delete old tiles info
+ db.Execute("delete from " + TrickplayTableName + " where ItemId=@ItemId and Width=@Width", idBlob, tilesInfo.Width);
+ db.Execute(
+ "insert into " + TrickplayTableName + " values (@ItemId, @Width, @Height, @TileWidth, @TileHeight, @TileCount, @Interval, @Bandwidth)",
+ idBlob,
+ tilesInfo.Width,
+ tilesInfo.Height,
+ tilesInfo.TileWidth,
+ tilesInfo.TileHeight,
+ tilesInfo.TileCount,
+ tilesInfo.Interval,
+ tilesInfo.Bandwidth);
+ },
+ TransactionMode);
+ }
+ }
+
+ /// <inheritdoc />
+ public Dictionary<Guid, Dictionary<int, TrickplayTilesInfo>> GetTrickplayManifest(BaseItem item)
+ {
+ CheckDisposed();
+
+ var trickplayManifest = new Dictionary<Guid, Dictionary<int, TrickplayTilesInfo>>();
+ foreach (var mediaSource in item.GetMediaSources(false))
+ {
+ var mediaSourceId = Guid.Parse(mediaSource.Id);
+ var tilesResolutions = GetTilesResolutions(mediaSourceId);
+
+ if (tilesResolutions.Count > 0)
+ {
+ trickplayManifest[mediaSourceId] = tilesResolutions;
+ }
+ }
+
+ return trickplayManifest;
+ }
+
+ /// <summary>
+ /// Gets the trickplay tiles info.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>TrickplayTilesInfo.</returns>
+ private TrickplayTilesInfo GetTrickplayTilesInfo(IReadOnlyList<ResultSetValue> reader)
+ {
+ var tilesInfo = new TrickplayTilesInfo();
+
+ if (reader.TryGetInt32(0, out var width))
+ {
+ tilesInfo.Width = width;
+ }
+
+ if (reader.TryGetInt32(1, out var height))
+ {
+ tilesInfo.Height = height;
+ }
+
+ if (reader.TryGetInt32(2, out var tileWidth))
+ {
+ tilesInfo.TileWidth = tileWidth;
+ }
+
+ if (reader.TryGetInt32(3, out var tileHeight))
+ {
+ tilesInfo.TileHeight = tileHeight;
+ }
+
+ if (reader.TryGetInt32(4, out var tileCount))
+ {
+ tilesInfo.TileCount = tileCount;
+ }
+
+ if (reader.TryGetInt32(5, out var interval))
+ {
+ tilesInfo.Interval = interval;
+ }
+
+ if (reader.TryGetInt32(6, out var bandwidth))
+ {
+ tilesInfo.Bandwidth = bandwidth;
+ }
+
+ return tilesInfo;
+ }
+
private static bool EnableJoinUserData(InternalItemsQuery query)
{
if (query.User is null)
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 7a6ed2cb8..10352b6ff 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -1058,6 +1058,11 @@ namespace Emby.Server.Implementations.Dto
dto.Chapters = _itemRepo.GetChapters(item);
}
+ if (options.ContainsField(ItemFields.Trickplay))
+ {
+ dto.Trickplay = _itemRepo.GetTrickplayManifest(item);
+ }
+
if (video.ExtraType.HasValue)
{
dto.ExtraType = video.ExtraType.Value.ToString();