< Summary - Jellyfin

Information
Class: Jellyfin.MediaEncoding.Keyframes.Matroska.MatroskaKeyframeExtractor
Assembly: Jellyfin.MediaEncoding.Keyframes
File(s): /srv/git/jellyfin/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 45
Coverable lines: 45
Total lines: 87
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetKeyframeData(...)0%7280%
ScaleToTicks(...)100%210%
ScaleToTicks(...)100%210%

File(s)

/srv/git/jellyfin/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using Jellyfin.MediaEncoding.Keyframes.Matroska.Extensions;
 5using Jellyfin.MediaEncoding.Keyframes.Matroska.Models;
 6using NEbml.Core;
 7
 8namespace Jellyfin.MediaEncoding.Keyframes.Matroska;
 9
 10/// <summary>
 11/// The keyframe extractor for the matroska container.
 12/// </summary>
 13public static class MatroskaKeyframeExtractor
 14{
 15    /// <summary>
 16    /// Extracts the keyframes in ticks (scaled using the container timestamp scale) from the matroska container.
 17    /// </summary>
 18    /// <param name="filePath">The file path.</param>
 19    /// <returns>An instance of <see cref="KeyframeData"/>.</returns>
 20    public static KeyframeData GetKeyframeData(string filePath)
 021    {
 022        using var stream = File.OpenRead(filePath);
 023        using var reader = new EbmlReader(stream);
 24
 025        var seekHead = reader.ReadSeekHead();
 26        // External lib does not support seeking backwards (yet)
 27        Info info;
 28        ulong videoTrackNumber;
 029        if (seekHead.InfoPosition < seekHead.TracksPosition)
 030        {
 031            info = reader.ReadInfo(seekHead.InfoPosition);
 032            videoTrackNumber = reader.FindFirstTrackNumberByType(seekHead.TracksPosition, MatroskaConstants.TrackTypeVid
 033        }
 34        else
 035        {
 036            videoTrackNumber = reader.FindFirstTrackNumberByType(seekHead.TracksPosition, MatroskaConstants.TrackTypeVid
 037            info = reader.ReadInfo(seekHead.InfoPosition);
 038        }
 39
 040        var keyframes = new List<long>();
 041        reader.ReadAt(seekHead.CuesPosition);
 042        reader.EnterContainer();
 43
 044        while (reader.FindElement(MatroskaConstants.CuePoint))
 045        {
 046            reader.EnterContainer();
 047            ulong? trackNumber = null;
 48            // Mandatory element
 049            reader.FindElement(MatroskaConstants.CueTime);
 050            var cueTime = reader.ReadUInt();
 51
 52            // Mandatory element
 053            reader.FindElement(MatroskaConstants.CueTrackPositions);
 054            reader.EnterContainer();
 055            if (reader.FindElement(MatroskaConstants.CuePointTrackNumber))
 056            {
 057                trackNumber = reader.ReadUInt();
 058            }
 59
 060            reader.LeaveContainer();
 61
 062            if (trackNumber == videoTrackNumber)
 063            {
 064                keyframes.Add(ScaleToTicks(cueTime, info.TimestampScale));
 065            }
 66
 067            reader.LeaveContainer();
 068        }
 69
 070        reader.LeaveContainer();
 71
 072        var result = new KeyframeData(ScaleToTicks(info.Duration ?? 0, info.TimestampScale), keyframes);
 073        return result;
 074    }
 75
 76    private static long ScaleToTicks(ulong unscaledValue, long timestampScale)
 077    {
 78        // TimestampScale is in nanoseconds, scale it to get the value in ticks, 1 tick == 100 ns
 079        return (long)unscaledValue * timestampScale / 100;
 080    }
 81
 82    private static long ScaleToTicks(double unscaledValue, long timestampScale)
 083    {
 84        // TimestampScale is in nanoseconds, scale it to get the value in ticks, 1 tick == 100 ns
 085        return Convert.ToInt64(unscaledValue * timestampScale / 100);
 086    }
 87}