浏览代码

Merge branch 'master' into nullable2

Bond-009 5 年之前
父节点
当前提交
ba1ffbabd3
共有 100 个文件被更改,包括 762 次插入7485 次删除
  1. 96 0
      .ci/azure-pipelines-compat.yml
  2. 101 0
      .ci/azure-pipelines-main.yml
  3. 65 0
      .ci/azure-pipelines-test.yml
  4. 82 0
      .ci/azure-pipelines-windows.yml
  5. 25 346
      .ci/azure-pipelines.yml
  6. 0 46
      .ci/publish-nightly.yml
  7. 0 48
      .ci/publish-release.yml
  8. 4 2
      .github/ISSUE_TEMPLATE/media_playback.md
  9. 1 1
      .vscode/launch.json
  10. 0 17
      BDInfo/BDInfo.csproj
  11. 0 33
      BDInfo/BDInfoSettings.cs
  12. 0 449
      BDInfo/BDROM.cs
  13. 0 493
      BDInfo/LanguageCodes.cs
  14. 0 21
      BDInfo/Properties/AssemblyInfo.cs
  15. 0 5
      BDInfo/ReadMe.txt
  16. 0 309
      BDInfo/TSCodecAC3.cs
  17. 0 148
      BDInfo/TSCodecAVC.cs
  18. 0 159
      BDInfo/TSCodecDTS.cs
  19. 0 246
      BDInfo/TSCodecDTSHD.cs
  20. 0 123
      BDInfo/TSCodecLPCM.cs
  21. 0 208
      BDInfo/TSCodecMPEG2.cs
  22. 0 36
      BDInfo/TSCodecMVC.cs
  23. 0 186
      BDInfo/TSCodecTrueHD.cs
  24. 0 131
      BDInfo/TSCodecVC1.cs
  25. 0 37
      BDInfo/TSInterleavedFile.cs
  26. 0 1282
      BDInfo/TSPlaylistFile.cs
  27. 0 780
      BDInfo/TSStream.cs
  28. 0 130
      BDInfo/TSStreamBuffer.cs
  29. 0 107
      BDInfo/TSStreamClip.cs
  30. 0 244
      BDInfo/TSStreamClipFile.cs
  31. 0 1555
      BDInfo/TSStreamFile.cs
  32. 2 0
      CONTRIBUTORS.md
  33. 5 3
      Dockerfile
  34. 3 6
      Dockerfile.arm
  35. 3 6
      Dockerfile.arm64
  36. 1 1
      DvdLib/DvdLib.csproj
  37. 2 2
      DvdLib/Ifo/Dvd.cs
  38. 8 8
      Emby.Dlna/Api/DlnaServerService.cs
  39. 5 2
      Emby.Dlna/ConnectionManager/ConnectionManager.cs
  40. 5 2
      Emby.Dlna/ContentDirectory/ContentDirectory.cs
  41. 4 4
      Emby.Dlna/ContentDirectory/ControlHandler.cs
  42. 0 1
      Emby.Dlna/Didl/DidlBuilder.cs
  43. 1 1
      Emby.Dlna/Didl/Filter.cs
  44. 1 1
      Emby.Dlna/DlnaManager.cs
  45. 12 24
      Emby.Dlna/Eventing/EventManager.cs
  46. 3 1
      Emby.Dlna/IUpnpService.cs
  47. 5 2
      Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrar.cs
  48. 0 1
      Emby.Dlna/PlayTo/PlayToController.cs
  49. 0 1
      Emby.Dlna/PlayTo/PlaylistItemFactory.cs
  50. 0 1
      Emby.Dlna/Server/DescriptionXmlBuilder.cs
  51. 39 56
      Emby.Dlna/Service/BaseControlHandler.cs
  52. 2 2
      Emby.Dlna/Service/ControlErrorHandler.cs
  53. 1 2
      Emby.Drawing/ImageProcessor.cs
  54. 3 0
      Emby.Naming/Audio/AlbumParser.cs
  55. 3 0
      Emby.Naming/Audio/AudioFileParser.cs
  56. 3 0
      Emby.Naming/Audio/MultiPartResult.cs
  57. 3 0
      Emby.Naming/AudioBook/AudioBookFilePathParser.cs
  58. 3 0
      Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs
  59. 3 0
      Emby.Naming/AudioBook/AudioBookInfo.cs
  60. 3 0
      Emby.Naming/AudioBook/AudioBookListResolver.cs
  61. 3 0
      Emby.Naming/AudioBook/AudioBookResolver.cs
  62. 3 0
      Emby.Naming/Common/EpisodeExpression.cs
  63. 3 0
      Emby.Naming/Common/MediaType.cs
  64. 25 22
      Emby.Naming/Common/NamingOptions.cs
  65. 3 2
      Emby.Naming/Emby.Naming.csproj
  66. 3 0
      Emby.Naming/Subtitles/SubtitleInfo.cs
  67. 4 2
      Emby.Naming/Subtitles/SubtitleParser.cs
  68. 3 0
      Emby.Naming/TV/EpisodeInfo.cs
  69. 4 1
      Emby.Naming/TV/EpisodePathParser.cs
  70. 3 0
      Emby.Naming/TV/EpisodePathParserResult.cs
  71. 3 0
      Emby.Naming/TV/EpisodeResolver.cs
  72. 3 0
      Emby.Naming/TV/SeasonPathParser.cs
  73. 3 0
      Emby.Naming/TV/SeasonPathParserResult.cs
  74. 18 56
      Emby.Naming/Video/CleanDateTimeParser.cs
  75. 22 10
      Emby.Naming/Video/CleanDateTimeResult.cs
  76. 21 25
      Emby.Naming/Video/CleanStringParser.cs
  77. 0 16
      Emby.Naming/Video/CleanStringResult.cs
  78. 4 1
      Emby.Naming/Video/ExtraResolver.cs
  79. 7 1
      Emby.Naming/Video/ExtraResult.cs
  80. 9 2
      Emby.Naming/Video/ExtraRule.cs
  81. 5 0
      Emby.Naming/Video/ExtraRuleType.cs
  82. 9 4
      Emby.Naming/Video/FileStack.cs
  83. 3 0
      Emby.Naming/Video/FlagParser.cs
  84. 3 0
      Emby.Naming/Video/Format3DParser.cs
  85. 3 0
      Emby.Naming/Video/Format3DResult.cs
  86. 4 0
      Emby.Naming/Video/Format3DRule.cs
  87. 3 0
      Emby.Naming/Video/StackResolver.cs
  88. 3 0
      Emby.Naming/Video/StackResult.cs
  89. 5 2
      Emby.Naming/Video/StubResolver.cs
  90. 3 0
      Emby.Naming/Video/StubResult.cs
  91. 3 0
      Emby.Naming/Video/StubTypeRule.cs
  92. 5 2
      Emby.Naming/Video/VideoFileInfo.cs
  93. 10 7
      Emby.Naming/Video/VideoInfo.cs
  94. 8 4
      Emby.Naming/Video/VideoListResolver.cs
  95. 9 5
      Emby.Naming/Video/VideoResolver.cs
  96. 5 5
      Emby.Photos/Emby.Photos.csproj
  97. 1 0
      Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
  98. 1 1
      Emby.Server.Implementations/Activity/ActivityManager.cs
  99. 1 0
      Emby.Server.Implementations/Activity/ActivityRepository.cs
  100. 37 48
      Emby.Server.Implementations/ApplicationHost.cs

+ 96 - 0
.ci/azure-pipelines-compat.yml

@@ -0,0 +1,96 @@
+parameters:
+  - name: Packages
+    type: object
+    default: {}
+  - name: LinuxImage
+    type: string
+    default: "ubuntu-latest"
+  - name: DotNetSdkVersion
+    type: string
+    default: 3.1.100
+
+jobs:
+  - job: CompatibilityCheck
+    displayName: Compatibility Check
+    pool:
+      vmImage: "${{ parameters.LinuxImage }}"
+    # only execute for pull requests
+    condition: and(succeeded(), variables['System.PullRequest.PullRequestNumber'])
+    strategy:
+      matrix:
+        ${{ each Package in parameters.Packages }}:
+          ${{ Package.key }}:
+            NugetPackageName: ${{ Package.value.NugetPackageName }}
+            AssemblyFileName: ${{ Package.value.AssemblyFileName }}
+      maxParallel: 2
+    dependsOn: MainBuild
+    steps:
+      - checkout: none
+
+      - task: UseDotNet@2
+        displayName: "Update DotNet"
+        inputs:
+          packageType: sdk
+          version: ${{ parameters.DotNetSdkVersion }}
+
+      - task: DownloadPipelineArtifact@2
+        displayName: "Download New Assembly Build Artifact"
+        inputs:
+          source: "current"
+          artifact: "$(NugetPackageName)"
+          path: "$(System.ArtifactsDirectory)/new-artifacts"
+          runVersion: "latest"
+
+      - task: CopyFiles@2
+        displayName: "Copy New Assembly Build Artifact"
+        inputs:
+          sourceFolder: $(System.ArtifactsDirectory)/new-artifacts
+          contents: "**/*.dll"
+          targetFolder: $(System.ArtifactsDirectory)/new-release
+          cleanTargetFolder: true
+          overWrite: true
+          flattenFolders: true
+
+      - task: DownloadPipelineArtifact@2
+        displayName: "Download Reference Assembly Build Artifact"
+        inputs:
+          source: "specific"
+          artifact: "$(NugetPackageName)"
+          path: "$(System.ArtifactsDirectory)/current-artifacts"
+          project: "$(System.TeamProjectId)"
+          pipeline: "$(System.DefinitionId)"
+          runVersion: "latestFromBranch"
+          runBranch: "refs/heads/$(System.PullRequest.TargetBranch)"
+
+      - task: CopyFiles@2
+        displayName: "Copy Reference Assembly Build Artifact"
+        inputs:
+          sourceFolder: $(System.ArtifactsDirectory)/current-artifacts
+          contents: "**/*.dll"
+          targetFolder: $(System.ArtifactsDirectory)/current-release
+          cleanTargetFolder: true
+          overWrite: true
+          flattenFolders: true
+
+      - task: DownloadGitHubRelease@0
+        displayName: "Download ABI Compatibility Check Tool"
+        inputs:
+          connection: Jellyfin Release Download
+          userRepository: EraYaN/dotnet-compatibility
+          defaultVersionType: "latest"
+          itemPattern: "**-ci.zip"
+          downloadPath: "$(System.ArtifactsDirectory)"
+
+      - task: ExtractFiles@1
+        displayName: "Extract ABI Compatibility Check Tool"
+        inputs:
+          archiveFilePatterns: "$(System.ArtifactsDirectory)/*-ci.zip"
+          destinationFolder: $(System.ArtifactsDirectory)/tools
+          cleanDestinationFolder: true
+
+      # The `--warnings-only` switch will swallow the return code and not emit any errors.
+      - task: CmdLine@2
+        displayName: "Execute ABI Compatibility Check Tool"
+        inputs:
+          script: "dotnet tools/CompatibilityCheckerCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName) --azure-pipelines --warnings-only"
+          workingDirectory: $(System.ArtifactsDirectory)

+ 101 - 0
.ci/azure-pipelines-main.yml

@@ -0,0 +1,101 @@
+parameters:
+  LinuxImage: "ubuntu-latest"
+  RestoreBuildProjects: "Jellyfin.Server/Jellyfin.Server.csproj"
+  DotNetSdkVersion: 3.1.100
+
+jobs:
+  - job: MainBuild
+    displayName: Main Build
+    strategy:
+      matrix:
+        Release:
+          BuildConfiguration: Release
+        Debug:
+          BuildConfiguration: Debug
+      maxParallel: 2
+    pool:
+      vmImage: "${{ parameters.LinuxImage }}"
+    steps:
+      - checkout: self
+        clean: true
+        submodules: true
+        persistCredentials: true
+
+      - task: CmdLine@2
+        displayName: "Clone Web Client (Master, Release, or Tag)"
+        condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          script: "git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
+
+      - task: CmdLine@2
+        displayName: "Clone Web Client (PR)"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest'))
+        inputs:
+          script: "git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
+
+      - task: NodeTool@0
+        displayName: "Install Node"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          versionSpec: "10.x"
+
+      - task: CmdLine@2
+        displayName: "Build Web Client"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          script: yarn install
+          workingDirectory: $(Agent.TempDirectory)/jellyfin-web
+
+      - task: CopyFiles@2
+        displayName: "Copy Web Client"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist
+          contents: "**"
+          targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web
+          cleanTargetFolder: true
+          overWrite: true
+          flattenFolders: false
+
+      - task: UseDotNet@2
+        displayName: "Update DotNet"
+        inputs:
+          packageType: sdk
+          version: ${{ parameters.DotNetSdkVersion }}
+
+      - task: DotNetCoreCLI@2
+        displayName: "Publish Server"
+        inputs:
+          command: publish
+          publishWebProjects: false
+          projects: "${{ parameters.RestoreBuildProjects }}"
+          arguments: "--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)"
+          zipAfterPublish: false
+
+      - task: PublishPipelineArtifact@0
+        displayName: "Publish Artifact Naming"
+        condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
+        inputs:
+          targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/Emby.Naming.dll"
+          artifactName: "Jellyfin.Naming"
+
+      - task: PublishPipelineArtifact@0
+        displayName: "Publish Artifact Controller"
+        condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
+        inputs:
+          targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Controller.dll"
+          artifactName: "Jellyfin.Controller"
+
+      - task: PublishPipelineArtifact@0
+        displayName: "Publish Artifact Model"
+        condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
+        inputs:
+          targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Model.dll"
+          artifactName: "Jellyfin.Model"
+
+      - task: PublishPipelineArtifact@0
+        displayName: "Publish Artifact Common"
+        condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
+        inputs:
+          targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Common.dll"
+          artifactName: "Jellyfin.Common"

+ 65 - 0
.ci/azure-pipelines-test.yml

@@ -0,0 +1,65 @@
+parameters:
+  - name: ImageNames
+    type: object
+    default:
+      Linux: "ubuntu-latest"
+      Windows: "windows-latest"
+      macOS: "macos-latest"
+  - name: TestProjects
+    type: string
+    default: "tests/**/*Tests.csproj"
+  - name: DotNetSdkVersion
+    type: string
+    default: 3.1.100
+
+jobs:
+  - job: MainTest
+    displayName: Main Test
+    strategy:
+      matrix:
+        ${{ each imageName in parameters.ImageNames }}:
+          ${{ imageName.key }}:
+            ImageName: ${{ imageName.value }}
+      maxParallel: 3
+    pool:
+      vmImage: "$(ImageName)"
+    steps:
+      - checkout: self
+        clean: true
+        submodules: true
+        persistCredentials: false
+
+      - task: UseDotNet@2
+        displayName: "Update DotNet"
+        inputs:
+          packageType: sdk
+          version: ${{ parameters.DotNetSdkVersion }}
+
+      - task: DotNetCoreCLI@2
+        displayName: Run .NET Core CLI tests
+        inputs:
+          command: "test"
+          projects: ${{ parameters.TestProjects }}
+          arguments: '--configuration Release --collect:"XPlat Code Coverage" --settings tests/coverletArgs.runsettings --verbosity minimal "-p:GenerateDocumentationFile=False"'
+          publishTestResults: true
+          testRunTitle: $(Agent.JobName)
+          workingDirectory: "$(Build.SourcesDirectory)"
+
+      - task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4
+        condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging
+        displayName: ReportGenerator (merge)
+        inputs:
+          reports: "$(Agent.TempDirectory)/**/coverage.cobertura.xml"
+          targetdir: "$(Agent.TempDirectory)/merged/"
+          reporttypes: "Cobertura"
+
+      ## V2 is already in the repository but it does not work "wrong number of segments" YAML error.
+      - task: PublishCodeCoverageResults@1
+        condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging
+        displayName: Publish Code Coverage
+        inputs:
+          codeCoverageTool: "cobertura"
+          #summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' # !!THIS IS FOR V2
+          summaryFileLocation: "$(Agent.TempDirectory)/merged/**.xml"
+          pathToSources: $(Build.SourcesDirectory)
+          failIfCoverageEmpty: true

+ 82 - 0
.ci/azure-pipelines-windows.yml

@@ -0,0 +1,82 @@
+parameters:
+  WindowsImage: "windows-latest"
+  TestProjects: "tests/**/*Tests.csproj"
+  DotNetSdkVersion: 3.1.100
+
+jobs:
+  - job: PublishWindows
+    displayName: Publish Windows
+    pool:
+      vmImage: ${{ parameters.WindowsImage }}
+    steps:
+      - checkout: self
+        clean: true
+        submodules: true
+        persistCredentials: true
+
+      - task: CmdLine@2
+        displayName: "Clone Web Client (Master, Release, or Tag)"
+        condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master'), contains(variables['Build.SourceBranch'], 'tag')), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          script: "git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
+
+      - task: CmdLine@2
+        displayName: "Clone Web Client (PR)"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest'))
+        inputs:
+          script: "git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
+
+      - task: NodeTool@0
+        displayName: "Install Node"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          versionSpec: "10.x"
+
+      - task: CmdLine@2
+        displayName: "Build Web Client"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          script: yarn install
+          workingDirectory: $(Agent.TempDirectory)/jellyfin-web
+
+      - task: CopyFiles@2
+        displayName: "Copy Web Client"
+        condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
+        inputs:
+          sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist
+          contents: "**"
+          targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web
+          cleanTargetFolder: true
+          overWrite: true
+          flattenFolders: false
+
+      - task: CmdLine@2
+        displayName: "Clone UX Repository"
+        inputs:
+          script: git clone --depth=1 https://github.com/jellyfin/jellyfin-ux $(Agent.TempDirectory)\jellyfin-ux
+
+      - task: PowerShell@2
+        displayName: "Build NSIS Installer"
+        inputs:
+          targetType: "filePath"
+          filePath: ./deployment/windows/build-jellyfin.ps1
+          arguments: -InstallFFMPEG -InstallNSSM -MakeNSIS -InstallTrayApp -UXLocation $(Agent.TempDirectory)\jellyfin-ux -InstallLocation $(build.artifactstagingdirectory)
+          errorActionPreference: "stop"
+          workingDirectory: $(Build.SourcesDirectory)
+
+      - task: CopyFiles@2
+        displayName: "Copy NSIS Installer"
+        inputs:
+          sourceFolder: $(Build.SourcesDirectory)/deployment/windows/
+          contents: "jellyfin*.exe"
+          targetFolder: $(System.ArtifactsDirectory)/setup
+          cleanTargetFolder: true
+          overWrite: true
+          flattenFolders: true
+
+      - task: PublishPipelineArtifact@0
+        displayName: "Publish Artifact Setup"
+        condition: succeeded()
+        inputs:
+          targetPath: "$(build.artifactstagingdirectory)/setup"
+          artifactName: "Jellyfin Server Setup"

+ 25 - 346
.ci/azure-pipelines.yml

@@ -2,9 +2,11 @@ name: $(Date:yyyyMMdd)$(Rev:.r)
 
 variables:
   - name: TestProjects
-    value: 'tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj'
+    value: "tests/**/*Tests.csproj"
   - name: RestoreBuildProjects
-    value: 'Jellyfin.Server/Jellyfin.Server.csproj'
+    value: "Jellyfin.Server/Jellyfin.Server.csproj"
+  - name: DotNetSdkVersion
+    value: 3.1.100
 
 pr:
   autoCancel: true
@@ -13,271 +15,26 @@ trigger:
   batch: true
 
 jobs:
-  - job: main_build
-    displayName: Main Build
-    pool:
-      vmImage: ubuntu-latest
-    strategy:
-      matrix:
-        release:
-          BuildConfiguration: Release
-        debug:
-          BuildConfiguration: Debug
-      maxParallel: 2
-    steps:
-    - checkout: self
-      clean: true
-      submodules: true
-      persistCredentials: true
-
-    - task: CmdLine@2
-      displayName: "Check out web"
-      condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        script: 'git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web'
-
-    - task: CmdLine@2
-      displayName: "Check out web (PR)"
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest'))
-      inputs:
-        script: 'git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web'
-
-    - task: NodeTool@0
-      displayName: 'Install Node.js'
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        versionSpec: '10.x'
-
-    - task: CmdLine@2
-      displayName: "Build Web UI"
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        script: yarn install
-        workingDirectory: $(Agent.TempDirectory)/jellyfin-web
-
-    - task: CopyFiles@2
-      displayName: Copy the web UI
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist # Optional
-        contents: '**'
-        targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web
-        cleanTargetFolder: true # Optional
-        overWrite: true # Optional
-        flattenFolders: false # Optional
-
-    - task: DotNetCoreCLI@2
-      displayName: Publish
-      inputs:
-        command: publish
-        publishWebProjects: false
-        projects: '$(RestoreBuildProjects)'
-        arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)'
-        zipAfterPublish: false
-
-    - task: PublishPipelineArtifact@0
-      displayName: 'Publish Artifact Naming'
-      condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
-      inputs:
-        targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/Emby.Naming.dll'
-        artifactName: 'Jellyfin.Naming'
-
-    - task: PublishPipelineArtifact@0
-      displayName: 'Publish Artifact Controller'
-      condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
-      inputs:
-        targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Controller.dll'
-        artifactName: 'Jellyfin.Controller'
-
-    - task: PublishPipelineArtifact@0
-      displayName: 'Publish Artifact Model'
-      condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
-      inputs:
-        targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Model.dll'
-        artifactName: 'Jellyfin.Model'
-
-    - task: PublishPipelineArtifact@0
-      displayName: 'Publish Artifact Common'
-      condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
-      inputs:
-        targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Common.dll'
-        artifactName: 'Jellyfin.Common'
-
-  - job: main_test
-    displayName: Main Test
-    pool:
-      vmImage: windows-latest
-    steps:
-    - checkout: self
-      clean: true
-      submodules: true
-      persistCredentials: false
-
-    - task: DotNetCoreCLI@2
-      displayName: Build
-      inputs:
-        command: build
-        publishWebProjects: false
-        projects: '$(TestProjects)'
-        arguments: '--configuration $(BuildConfiguration)'
-        zipAfterPublish: false
-
-    - task: VisualStudioTestPlatformInstaller@1
-      inputs:
-        packageFeedSelector: 'nugetOrg' # Options: nugetOrg, customFeed, netShare
-        versionSelector: 'latestPreRelease' # Required when packageFeedSelector == NugetOrg || PackageFeedSelector == CustomFeed# Options: latestPreRelease, latestStable, specificVersion
-
-    - task: VSTest@2
-      inputs:
-        testSelector: 'testAssemblies' # Options: testAssemblies, testPlan, testRun
-        testAssemblyVer2: | # Required when testSelector == TestAssemblies
-          **\bin\$(BuildConfiguration)\**\*test*.dll
-          !**\obj\**
-          !**\xunit.runner.visualstudio.testadapter.dll
-          !**\xunit.runner.visualstudio.dotnetcore.testadapter.dll
-        #testPlan: # Required when testSelector == TestPlan
-        #testSuite: # Required when testSelector == TestPlan
-        #testConfiguration: # Required when testSelector == TestPlan
-        #tcmTestRun: '$(test.RunId)' # Optional
-        searchFolder: '$(System.DefaultWorkingDirectory)'
-        #testFiltercriteria: # Optional
-        #runOnlyImpactedTests: False # Optional
-        #runAllTestsAfterXBuilds: '50' # Optional
-        #uiTests: false # Optional
-        #vstestLocationMethod: 'version' # Optional. Options: version, location
-        #vsTestVersion: 'latest' # Optional. Options: latest, 16.0, 15.0, 14.0, toolsInstaller
-        #vstestLocation: # Optional
-        #runSettingsFile: # Optional
-        #overrideTestrunParameters: # Optional
-        #pathtoCustomTestAdapters: # Optional
-        runInParallel: True # Optional
-        runTestsInIsolation: True # Optional
-        codeCoverageEnabled: True # Optional
-        #otherConsoleOptions: # Optional
-        #distributionBatchType: 'basedOnTestCases' # Optional. Options: basedOnTestCases, basedOnExecutionTime, basedOnAssembly
-        #batchingBasedOnAgentsOption: 'autoBatchSize' # Optional. Options: autoBatchSize, customBatchSize
-        #customBatchSizeValue: '10' # Required when distributionBatchType == BasedOnTestCases && BatchingBasedOnAgentsOption == CustomBatchSize
-        #batchingBasedOnExecutionTimeOption: 'autoBatchSize' # Optional. Options: autoBatchSize, customTimeBatchSize
-        #customRunTimePerBatchValue: '60' # Required when distributionBatchType == BasedOnExecutionTime && BatchingBasedOnExecutionTimeOption == CustomTimeBatchSize
-        #dontDistribute: False # Optional
-        #testRunTitle: # Optional
-        #platform: # Optional
-        configuration: 'Debug' # Optional
-        publishRunAttachments: true # Optional
-        #diagnosticsEnabled: false # Optional
-        #collectDumpOn: 'onAbortOnly' # Optional. Options: onAbortOnly, always, never
-        #rerunFailedTests: False # Optional
-        #rerunType: 'basedOnTestFailurePercentage' # Optional. Options: basedOnTestFailurePercentage, basedOnTestFailureCount
-        #rerunFailedThreshold: '30' # Optional
-        #rerunFailedTestCasesMaxLimit: '5' # Optional
-        #rerunMaxAttempts: '3' # Optional
-
-    # - task: PublishTestResults@2
-    #   inputs:
-    #     testResultsFormat: 'VSTest' # Options: JUnit, NUnit, VSTest, xUnit, cTest
-    #     testResultsFiles: '**/*.trx'
-    #     #searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
-    #     mergeTestResults: true # Optional
-    #     #failTaskOnFailedTests: false # Optional
-    #     #testRunTitle: # Optional
-    #     #buildPlatform: # Optional
-    #     #buildConfiguration: # Optional
-    #     #publishRunAttachments: true # Optional
-
-  - job: main_build_win
-    displayName: Main Build Windows
-    pool:
-      vmImage: windows-latest
-    strategy:
-      matrix:
-        release:
-          BuildConfiguration: Release
-      maxParallel: 2
-    steps:
-    - checkout: self
-      clean: true
-      submodules: true
-      persistCredentials: true
-
-    - task: CmdLine@2
-      displayName: "Check out web (master, release or tag)"
-      condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master'), contains(variables['Build.SourceBranch'], 'tag')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        script: 'git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web'
-
-    - task: CmdLine@2
-      displayName: "Check out web (PR)"
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest'))
-      inputs:
-        script: 'git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web'
-
-    - task: NodeTool@0
-      displayName: 'Install Node.js'
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        versionSpec: '10.x'
-
-    - task: CmdLine@2
-      displayName: "Build Web UI"
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        script: yarn install
-        workingDirectory: $(Agent.TempDirectory)/jellyfin-web
-
-    - task: CopyFiles@2
-      displayName: Copy the web UI
-      condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
-      inputs:
-        sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist # Optional
-        contents: '**'
-        targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web
-        cleanTargetFolder: true # Optional
-        overWrite: true # Optional
-        flattenFolders: false # Optional
-
-    - task: CmdLine@2
-      displayName: Clone the UX repository
-      inputs:
-        script: git clone --depth=1 https://github.com/jellyfin/jellyfin-ux $(Agent.TempDirectory)\jellyfin-ux
-
-    - task: PowerShell@2
-      displayName: Build the NSIS Installer
-      inputs:
-        targetType: 'filePath' # Optional. Options: filePath, inline
-        filePath: ./deployment/windows/build-jellyfin.ps1 # Required when targetType == FilePath
-        arguments: -InstallFFMPEG -InstallNSSM -MakeNSIS -InstallTrayApp -UXLocation $(Agent.TempDirectory)\jellyfin-ux -InstallLocation $(build.artifactstagingdirectory)
-        #script: '# Write your PowerShell commands here.Write-Host Hello World' # Required when targetType == Inline
-        errorActionPreference: 'stop' # Optional. Options: stop, continue, silentlyContinue
-        #failOnStderr: false # Optional
-        #ignoreLASTEXITCODE: false # Optional
-        #pwsh: false # Optional
-        workingDirectory: $(Build.SourcesDirectory) # Optional
-
-    - task: CopyFiles@2
-      displayName: Copy the NSIS Installer to the artifact directory
-      inputs:
-        sourceFolder: $(Build.SourcesDirectory)/deployment/windows/ # Optional
-        contents: 'jellyfin*.exe'
-        targetFolder: $(System.ArtifactsDirectory)/setup
-        cleanTargetFolder: true # Optional
-        overWrite: true # Optional
-        flattenFolders: true # Optional
-
-    - task: PublishPipelineArtifact@0
-      displayName: 'Publish Setup Artifact'
-      condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded())
-      inputs:
-        targetPath: '$(build.artifactstagingdirectory)/setup'
-        artifactName: 'Jellyfin Server Setup'
-
-  - job: dotnet_compat
-    displayName: Compatibility Check
-    pool:
-      vmImage: ubuntu-latest
-    dependsOn: main_build
-    condition: and(succeeded(), variables['System.PullRequest.PullRequestNumber']) # Only execute if the pullrequest numer is defined. (So not for normal CI builds)
-    strategy:
-      matrix:
+  - template: azure-pipelines-main.yml
+    parameters:
+      LinuxImage: "ubuntu-latest"
+      RestoreBuildProjects: $(RestoreBuildProjects)
+
+  - template: azure-pipelines-test.yml
+    parameters:
+      ImageNames:
+        Linux: "ubuntu-latest"
+        Windows: "windows-latest"
+        macOS: "macos-latest"
+
+  - template: azure-pipelines-windows.yml
+    parameters:
+      WindowsImage: "windows-latest"
+      TestProjects: $(TestProjects)
+
+  - template: azure-pipelines-compat.yml
+    parameters:
+      Packages:
         Naming:
           NugetPackageName: Jellyfin.Naming
           AssemblyFileName: Emby.Naming.dll
@@ -290,82 +47,4 @@ jobs:
         Common:
           NugetPackageName: Jellyfin.Common
           AssemblyFileName: MediaBrowser.Common.dll
-      maxParallel: 2
-    steps:
-    - checkout: none
-
-    - task: DownloadPipelineArtifact@2
-      displayName: Download the New Assembly Build Artifact
-      inputs:
-        source: 'current' # Options: current, specific
-        #preferTriggeringPipeline: false # Optional
-        #tags: # Optional
-        artifact: '$(NugetPackageName)' # Optional
-        #patterns: '**' # Optional
-        path: '$(System.ArtifactsDirectory)/new-artifacts'
-        #project: # Required when source == Specific
-        #pipeline: # Required when source == Specific
-        runVersion: 'latest' # Required when source == Specific. Options: latest, latestFromBranch, specific
-        #runBranch: 'refs/heads/master' # Required when source == Specific && runVersion == LatestFromBranch
-        #runId: # Required when source == Specific && runVersion == Specific
-
-    - task: CopyFiles@2
-      displayName: Copy New Assembly to new-release folder
-      inputs:
-        sourceFolder: $(System.ArtifactsDirectory)/new-artifacts # Optional
-        contents: '**/*.dll'
-        targetFolder: $(System.ArtifactsDirectory)/new-release
-        cleanTargetFolder: true # Optional
-        overWrite: true # Optional
-        flattenFolders: true # Optional
-
-    - task: DownloadPipelineArtifact@2
-      displayName: Download the Reference Assembly Build Artifact
-      inputs:
-        source: 'specific' # Options: current, specific
-        #preferTriggeringPipeline: false # Optional
-        #tags: # Optional
-        artifact: '$(NugetPackageName)' # Optional
-        #patterns: '**' # Optional
-        path: '$(System.ArtifactsDirectory)/current-artifacts'
-        project: '$(System.TeamProjectId)' # Required when source == Specific
-        pipeline: '$(System.DefinitionId)' # Required when source == Specific
-        runVersion: 'latestFromBranch' # Required when source == Specific. Options: latest, latestFromBranch, specific
-        runBranch: 'refs/heads/$(System.PullRequest.TargetBranch)' # Required when source == Specific && runVersion == LatestFromBranch
-        #runId: # Required when source == Specific && runVersion == Specific
-
-    - task: CopyFiles@2
-      displayName: Copy Reference Assembly to current-release folder
-      inputs:
-        sourceFolder: $(System.ArtifactsDirectory)/current-artifacts # Optional
-        contents: '**/*.dll'
-        targetFolder: $(System.ArtifactsDirectory)/current-release
-        cleanTargetFolder: true # Optional
-        overWrite: true # Optional
-        flattenFolders: true # Optional
-
-    - task: DownloadGitHubRelease@0
-      displayName: Download ABI compatibility check tool from GitHub
-      inputs:
-        connection: Jellyfin Release Download
-        userRepository: EraYaN/dotnet-compatibility
-        defaultVersionType: 'latest' # Options: latest, specificVersion, specificTag
-        #version: # Required when defaultVersionType != Latest
-        itemPattern: '**-ci.zip' # Optional
-        downloadPath: '$(System.ArtifactsDirectory)'
-
-    - task: ExtractFiles@1
-      displayName: Extract ABI compatibility check tool
-      inputs:
-        archiveFilePatterns: '$(System.ArtifactsDirectory)/*-ci.zip'
-        destinationFolder: $(System.ArtifactsDirectory)/tools
-        cleanDestinationFolder: true
-
-    - task: CmdLine@2
-      displayName: Execute ABI compatibility check tool
-      inputs:
-        script: 'dotnet tools/CompatibilityCheckerCoreCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName) --azure-pipelines'
-        workingDirectory: $(System.ArtifactsDirectory) # Optional
-        #failOnStderr: false # Optional
-
-
+      LinuxImage: "ubuntu-latest"

+ 0 - 46
.ci/publish-nightly.yml

@@ -1,46 +0,0 @@
-name: Nightly-$(date:yyyyMMdd).$(rev:r)
-
-variables:
-  - name: Version
-    value: '1.0.0'
-
-trigger: none
-pr: none
-
-jobs:
-  - job: publish_artifacts_nightly
-    displayName: Publish Artifacts Nightly
-    pool:
-      vmImage: ubuntu-latest
-    steps:
-    - checkout: none
-    - task: DownloadPipelineArtifact@2
-      displayName: Download the Windows Setup Artifact
-      inputs:
-        source: 'specific' # Options: current, specific
-        artifact: 'Jellyfin Server Setup' # Optional
-        path: '$(System.ArtifactsDirectory)/win-installer'
-        project: '$(System.TeamProjectId)' # Required when source == Specific
-        pipelineId: 1 # Required when source == Specific
-        runVersion: 'latestFromBranch' # Required when source == Specific. Options: latest, latestFromBranch, specific
-        runBranch: 'refs/heads/master' # Required when source == Specific && runVersion == LatestFromBranch
-
-    - task: SSH@0
-      displayName: 'Create Drop directory'
-      inputs:
-        sshEndpoint: 'Jellyfin Build Server'
-        commands: 'mkdir -p /srv/incoming/jellyfin_$(Version)/win-installer && ln -s /srv/incoming/jellyfin_$(Version) /srv/incoming/jellyfin_nightly_azure_upload'
-
-    - task: CopyFilesOverSSH@0
-      displayName: 'Copy the Windows Setup to the Repo'
-      inputs:
-        sshEndpoint: 'Jellyfin Build Server'
-        sourceFolder: '$(System.ArtifactsDirectory)/win-installer'
-        contents: 'jellyfin_*.exe'
-        targetFolder: '/srv/incoming/jellyfin_nightly_azure_upload/win-installer'
-
-    - task: SSH@0
-      displayName: 'Clean up SCP symlink'
-      inputs:
-        sshEndpoint: 'Jellyfin Build Server'
-        commands: 'rm -f /srv/incoming/jellyfin_nightly_azure_upload'

+ 0 - 48
.ci/publish-release.yml

@@ -1,48 +0,0 @@
-name: Release-$(Version)-$(date:yyyyMMdd).$(rev:r)
-
-variables:
-  - name: Version
-    value: '1.0.0'
-  - name: UsedRunId
-    value: 0
-
-trigger: none
-pr: none
-
-jobs:
-  - job: publish_artifacts_release
-    displayName: Publish Artifacts Release
-    pool:
-      vmImage: ubuntu-latest
-    steps:
-    - checkout: none
-    - task: DownloadPipelineArtifact@2
-      displayName: Download the Windows Setup Artifact
-      inputs:
-        source: 'specific' # Options: current, specific
-        artifact: 'Jellyfin Server Setup' # Optional
-        path: '$(System.ArtifactsDirectory)/win-installer'
-        project: '$(System.TeamProjectId)' # Required when source == Specific
-        pipelineId: 1 # Required when source == Specific
-        runVersion: 'specific' # Required when source == Specific. Options: latest, latestFromBranch, specific
-        runId: $(UsedRunId)
-
-    - task: SSH@0
-      displayName: 'Create Drop directory'
-      inputs:
-        sshEndpoint: 'Jellyfin Build Server'
-        commands: 'mkdir -p /srv/incoming/jellyfin_$(Version)/win-installer && ln -s /srv/incoming/jellyfin_$(Version) /srv/incoming/jellyfin_release_azure_upload'
-
-    - task: CopyFilesOverSSH@0
-      displayName: 'Copy the Windows Setup to the Repo'
-      inputs:
-        sshEndpoint: 'Jellyfin Build Server'
-        sourceFolder: '$(System.ArtifactsDirectory)/win-installer'
-        contents: 'jellyfin_*.exe'
-        targetFolder: '/srv/incoming/jellyfin_release_azure_upload/win-installer'
-
-    - task: SSH@0
-      displayName: 'Clean up SCP symlink'
-      inputs:
-        sshEndpoint: 'Jellyfin Build Server'
-        commands: 'rm -f /srv/incoming/jellyfin_release_azure_upload'

+ 4 - 2
.github/ISSUE_TEMPLATE/media_playback.md

@@ -11,7 +11,10 @@ assignees: ''
 <!-- Use the Media Info tool (set to text format, download here: https://mediaarea.net/en/MediaInfo) or copy the info from the web ui for the file with the playback issue. -->
 
 **Logs**
-<!-- Please paste any log message from during the playback issue, for example the ffmpeg command line can be very useful. -->
+<!-- Please paste any log messages from during the playback issue. -->
+
+**FFmpeg Logs**
+<!-- Please paste any FFmpeg logs if remuxing or transcoding appears to be part of the issue. -->
 
 **Stats for Nerds Screenshots**
 <!-- If available, add screenshots of the stats for nerds screen to help show the issue problem. -->
@@ -29,4 +32,3 @@ assignees: ''
  - Client: [e.g. Web/Browser, webOS, Android, Android TV, Electron]
  - Browser (if Web client): [e.g. Firefox, Chrome, Safari]
  - Client and Browser Version: [e.g. 10.3.4 and 68.0]
-

+ 1 - 1
.vscode/launch.json

@@ -10,7 +10,7 @@
             "request": "launch",
             "preLaunchTask": "build",
             // If you have changed target frameworks, make sure to update the program path.
-            "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.0/jellyfin.dll",
+            "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.1/jellyfin.dll",
             "args": [],
             "cwd": "${workspaceFolder}/Jellyfin.Server",
             // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window

+ 0 - 17
BDInfo/BDInfo.csproj

@@ -1,17 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <ItemGroup>
-    <Compile Include="..\SharedVersion.cs" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
-  </ItemGroup>
-
-  <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-    <GenerateDocumentationFile>true</GenerateDocumentationFile>
-  </PropertyGroup>
-
-</Project>

+ 0 - 33
BDInfo/BDInfoSettings.cs

@@ -1,33 +0,0 @@
-
-namespace BDInfo
-{
-    class BDInfoSettings
-    {
-        public static bool GenerateStreamDiagnostics => true;
-
-        public static bool EnableSSIF => true;
-
-        public static bool AutosaveReport => false;
-
-        public static bool GenerateFrameDataFile => false;
-
-        public static bool FilterLoopingPlaylists => true;
-
-        public static bool FilterShortPlaylists => false;
-
-        public static int FilterShortPlaylistsValue => 0;
-
-        public static bool UseImagePrefix => false;
-
-        public static string UseImagePrefixValue => null;
-
-        /// <summary>
-        /// Setting this to false throws an IComparer error on some discs.
-        /// </summary>
-        public static bool KeepStreamOrder => true;
-
-        public static bool GenerateTextSummary => false;
-
-        public static string LastPath => string.Empty;
-    }
-}

+ 0 - 449
BDInfo/BDROM.cs

@@ -1,449 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using MediaBrowser.Model.IO;
-
-namespace BDInfo
-{
-    public class BDROM
-    {
-        public FileSystemMetadata DirectoryRoot = null;
-        public FileSystemMetadata DirectoryBDMV = null;
-        public FileSystemMetadata DirectoryBDJO = null;
-        public FileSystemMetadata DirectoryCLIPINF = null;
-        public FileSystemMetadata DirectoryPLAYLIST = null;
-        public FileSystemMetadata DirectorySNP = null;
-        public FileSystemMetadata DirectorySSIF = null;
-        public FileSystemMetadata DirectorySTREAM = null;
-
-        public string VolumeLabel = null;
-        public ulong Size = 0;
-        public bool IsBDPlus = false;
-        public bool IsBDJava = false;
-        public bool IsDBOX = false;
-        public bool IsPSP = false;
-        public bool Is3D = false;
-        public bool Is50Hz = false;
-
-        private readonly IFileSystem _fileSystem;
-
-        public Dictionary<string, TSPlaylistFile> PlaylistFiles =
-            new Dictionary<string, TSPlaylistFile>();
-        public Dictionary<string, TSStreamClipFile> StreamClipFiles =
-            new Dictionary<string, TSStreamClipFile>();
-        public Dictionary<string, TSStreamFile> StreamFiles =
-            new Dictionary<string, TSStreamFile>();
-        public Dictionary<string, TSInterleavedFile> InterleavedFiles =
-            new Dictionary<string, TSInterleavedFile>();
-
-        public delegate bool OnStreamClipFileScanError(
-            TSStreamClipFile streamClipFile, Exception ex);
-
-        public event OnStreamClipFileScanError StreamClipFileScanError;
-
-        public delegate bool OnStreamFileScanError(
-            TSStreamFile streamClipFile, Exception ex);
-
-        public event OnStreamFileScanError StreamFileScanError;
-
-        public delegate bool OnPlaylistFileScanError(
-            TSPlaylistFile playlistFile, Exception ex);
-
-        public event OnPlaylistFileScanError PlaylistFileScanError;
-
-        public BDROM(string path, IFileSystem fileSystem)
-        {
-            if (string.IsNullOrEmpty(path))
-            {
-                throw new ArgumentNullException(nameof(path));
-            }
-
-            _fileSystem = fileSystem;
-            //
-            // Locate BDMV directories.
-            //
-
-            DirectoryBDMV =
-                GetDirectoryBDMV(path);
-
-            if (DirectoryBDMV == null)
-            {
-                throw new Exception("Unable to locate BD structure.");
-            }
-
-            DirectoryRoot =
-                _fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName));
-            DirectoryBDJO =
-                GetDirectory("BDJO", DirectoryBDMV, 0);
-            DirectoryCLIPINF =
-                GetDirectory("CLIPINF", DirectoryBDMV, 0);
-            DirectoryPLAYLIST =
-                GetDirectory("PLAYLIST", DirectoryBDMV, 0);
-            DirectorySNP =
-                GetDirectory("SNP", DirectoryRoot, 0);
-            DirectorySTREAM =
-                GetDirectory("STREAM", DirectoryBDMV, 0);
-            DirectorySSIF =
-                GetDirectory("SSIF", DirectorySTREAM, 0);
-
-            if (DirectoryCLIPINF == null
-                || DirectoryPLAYLIST == null)
-            {
-                throw new Exception("Unable to locate BD structure.");
-            }
-
-            //
-            // Initialize basic disc properties.
-            //
-
-            VolumeLabel = GetVolumeLabel(DirectoryRoot);
-            Size = (ulong)GetDirectorySize(DirectoryRoot);
-
-            if (null != GetDirectory("BDSVM", DirectoryRoot, 0))
-            {
-                IsBDPlus = true;
-            }
-            if (null != GetDirectory("SLYVM", DirectoryRoot, 0))
-            {
-                IsBDPlus = true;
-            }
-            if (null != GetDirectory("ANYVM", DirectoryRoot, 0))
-            {
-                IsBDPlus = true;
-            }
-
-            if (DirectoryBDJO != null &&
-                _fileSystem.GetFilePaths(DirectoryBDJO.FullName).Any())
-            {
-                IsBDJava = true;
-            }
-
-            if (DirectorySNP != null &&
-                GetFilePaths(DirectorySNP.FullName, ".mnv").Any())
-            {
-                IsPSP = true;
-            }
-
-            if (DirectorySSIF != null &&
-                _fileSystem.GetFilePaths(DirectorySSIF.FullName).Any())
-            {
-                Is3D = true;
-            }
-
-            if (File.Exists(Path.Combine(DirectoryRoot.FullName, "FilmIndex.xml")))
-            {
-                IsDBOX = true;
-            }
-
-            //
-            // Initialize file lists.
-            //
-
-            if (DirectoryPLAYLIST != null)
-            {
-                FileSystemMetadata[] files = GetFiles(DirectoryPLAYLIST.FullName, ".mpls").ToArray();
-                foreach (var file in files)
-                {
-                    PlaylistFiles.Add(
-                        file.Name.ToUpper(), new TSPlaylistFile(this, file));
-                }
-            }
-
-            if (DirectorySTREAM != null)
-            {
-                FileSystemMetadata[] files = GetFiles(DirectorySTREAM.FullName, ".m2ts").ToArray();
-                foreach (var file in files)
-                {
-                    StreamFiles.Add(
-                        file.Name.ToUpper(), new TSStreamFile(file, _fileSystem));
-                }
-            }
-
-            if (DirectoryCLIPINF != null)
-            {
-                FileSystemMetadata[] files = GetFiles(DirectoryCLIPINF.FullName, ".clpi").ToArray();
-                foreach (var file in files)
-                {
-                    StreamClipFiles.Add(
-                        file.Name.ToUpper(), new TSStreamClipFile(file));
-                }
-            }
-
-            if (DirectorySSIF != null)
-            {
-                FileSystemMetadata[] files = GetFiles(DirectorySSIF.FullName, ".ssif").ToArray();
-                foreach (var file in files)
-                {
-                    InterleavedFiles.Add(
-                        file.Name.ToUpper(), new TSInterleavedFile(file));
-                }
-            }
-        }
-
-        private IEnumerable<FileSystemMetadata> GetFiles(string path, string extension)
-        {
-            return _fileSystem.GetFiles(path, new[] { extension }, false, false);
-        }
-
-        private IEnumerable<string> GetFilePaths(string path, string extension)
-        {
-            return _fileSystem.GetFilePaths(path, new[] { extension }, false, false);
-        }
-
-        public void Scan()
-        {
-            foreach (var streamClipFile in StreamClipFiles.Values)
-            {
-                try
-                {
-                    streamClipFile.Scan();
-                }
-                catch (Exception ex)
-                {
-                    if (StreamClipFileScanError != null)
-                    {
-                        if (StreamClipFileScanError(streamClipFile, ex))
-                        {
-                            continue;
-                        }
-                        else
-                        {
-                            break;
-                        }
-                    }
-                    else throw;
-                }
-            }
-
-            foreach (var streamFile in StreamFiles.Values)
-            {
-                string ssifName = Path.GetFileNameWithoutExtension(streamFile.Name) + ".SSIF";
-                if (InterleavedFiles.ContainsKey(ssifName))
-                {
-                    streamFile.InterleavedFile = InterleavedFiles[ssifName];
-                }
-            }
-
-            TSStreamFile[] streamFiles = new TSStreamFile[StreamFiles.Count];
-            StreamFiles.Values.CopyTo(streamFiles, 0);
-            Array.Sort(streamFiles, CompareStreamFiles);
-
-            foreach (var playlistFile in PlaylistFiles.Values)
-            {
-                try
-                {
-                    playlistFile.Scan(StreamFiles, StreamClipFiles);
-                }
-                catch (Exception ex)
-                {
-                    if (PlaylistFileScanError != null)
-                    {
-                        if (PlaylistFileScanError(playlistFile, ex))
-                        {
-                            continue;
-                        }
-                        else
-                        {
-                            break;
-                        }
-                    }
-                    else throw;
-                }
-            }
-
-            foreach (var streamFile in streamFiles)
-            {
-                try
-                {
-                    var playlists = new List<TSPlaylistFile>();
-                    foreach (var playlist in PlaylistFiles.Values)
-                    {
-                        foreach (var streamClip in playlist.StreamClips)
-                        {
-                            if (streamClip.Name == streamFile.Name)
-                            {
-                                playlists.Add(playlist);
-                                break;
-                            }
-                        }
-                    }
-                    streamFile.Scan(playlists, false);
-                }
-                catch (Exception ex)
-                {
-                    if (StreamFileScanError != null)
-                    {
-                        if (StreamFileScanError(streamFile, ex))
-                        {
-                            continue;
-                        }
-                        else
-                        {
-                            break;
-                        }
-                    }
-                    else throw;
-                }
-            }
-
-            foreach (var playlistFile in PlaylistFiles.Values)
-            {
-                playlistFile.Initialize();
-                if (!Is50Hz)
-                {
-                    foreach (var videoStream in playlistFile.VideoStreams)
-                    {
-                        if (videoStream.FrameRate == TSFrameRate.FRAMERATE_25 ||
-                            videoStream.FrameRate == TSFrameRate.FRAMERATE_50)
-                        {
-                            Is50Hz = true;
-                        }
-                    }
-                }
-            }
-        }
-
-        private FileSystemMetadata GetDirectoryBDMV(
-            string path)
-        {
-            if (string.IsNullOrEmpty(path))
-            {
-                throw new ArgumentNullException(nameof(path));
-            }
-
-            FileSystemMetadata dir = _fileSystem.GetDirectoryInfo(path);
-
-            while (dir != null)
-            {
-                if (string.Equals(dir.Name, "BDMV", StringComparison.OrdinalIgnoreCase))
-                {
-                    return dir;
-                }
-                var parentFolder = Path.GetDirectoryName(dir.FullName);
-                if (string.IsNullOrEmpty(parentFolder))
-                {
-                    dir = null;
-                }
-                else
-                {
-                    dir = _fileSystem.GetDirectoryInfo(parentFolder);
-                }
-            }
-
-            return GetDirectory("BDMV", _fileSystem.GetDirectoryInfo(path), 0);
-        }
-
-        private FileSystemMetadata GetDirectory(
-            string name,
-            FileSystemMetadata dir,
-            int searchDepth)
-        {
-            if (dir != null)
-            {
-                FileSystemMetadata[] children = _fileSystem.GetDirectories(dir.FullName).ToArray();
-                foreach (var child in children)
-                {
-                    if (string.Equals(child.Name, name, StringComparison.OrdinalIgnoreCase))
-                    {
-                        return child;
-                    }
-                }
-                if (searchDepth > 0)
-                {
-                    foreach (var child in children)
-                    {
-                        GetDirectory(
-                            name, child, searchDepth - 1);
-                    }
-                }
-            }
-            return null;
-        }
-
-        private long GetDirectorySize(FileSystemMetadata directoryInfo)
-        {
-            long size = 0;
-
-            //if (!ExcludeDirs.Contains(directoryInfo.Name.ToUpper()))  // TODO: Keep?
-            {
-                FileSystemMetadata[] pathFiles = _fileSystem.GetFiles(directoryInfo.FullName).ToArray();
-                foreach (var pathFile in pathFiles)
-                {
-                    if (pathFile.Extension.ToUpper() == ".SSIF")
-                    {
-                        continue;
-                    }
-                    size += pathFile.Length;
-                }
-
-                FileSystemMetadata[] pathChildren = _fileSystem.GetDirectories(directoryInfo.FullName).ToArray();
-                foreach (var pathChild in pathChildren)
-                {
-                    size += GetDirectorySize(pathChild);
-                }
-            }
-
-            return size;
-        }
-
-        private string GetVolumeLabel(FileSystemMetadata dir)
-        {
-            return dir.Name;
-        }
-
-        public int CompareStreamFiles(
-            TSStreamFile x,
-            TSStreamFile y)
-        {
-            // TODO: Use interleaved file sizes
-
-            if ((x == null || x.FileInfo == null) && (y == null || y.FileInfo == null))
-            {
-                return 0;
-            }
-            else if ((x == null || x.FileInfo == null) && (y != null && y.FileInfo != null))
-            {
-                return 1;
-            }
-            else if ((x != null && x.FileInfo != null) && (y == null || y.FileInfo == null))
-            {
-                return -1;
-            }
-            else
-            {
-                if (x.FileInfo.Length > y.FileInfo.Length)
-                {
-                    return 1;
-                }
-                else if (y.FileInfo.Length > x.FileInfo.Length)
-                {
-                    return -1;
-                }
-                else
-                {
-                    return 0;
-                }
-            }
-        }
-    }
-}

+ 0 - 493
BDInfo/LanguageCodes.cs

@@ -1,493 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class LanguageCodes
-    {
-        public static string GetName(string code)
-        {
-            switch (code)
-            {
-                case "abk": return "Abkhazian";
-                case "ace": return "Achinese";
-                case "ach": return "Acoli";
-                case "ada": return "Adangme";
-                case "aar": return "Afar";
-                case "afh": return "Afrihili";
-                case "afr": return "Afrikaans";
-                case "afa": return "Afro-Asiatic (Other)";
-                case "aka": return "Akan";
-                case "akk": return "Akkadian";
-                case "alb": return "Albanian";
-                case "sqi": return "Albanian";
-                case "ale": return "Aleut";
-                case "alg": return "Algonquian languages";
-                case "tut": return "Altaic (Other)";
-                case "amh": return "Amharic";
-                case "apa": return "Apache languages";
-                case "ara": return "Arabic";
-                case "arc": return "Aramaic";
-                case "arp": return "Arapaho";
-                case "arn": return "Araucanian";
-                case "arw": return "Arawak";
-                case "arm": return "Armenian";
-                case "hye": return "Armenian";
-                case "art": return "Artificial (Other)";
-                case "asm": return "Assamese";
-                case "ath": return "Athapascan languages";
-                case "aus": return "Australian languages";
-                case "map": return "Austronesian (Other)";
-                case "ava": return "Avaric";
-                case "ave": return "Avestan";
-                case "awa": return "Awadhi";
-                case "aym": return "Aymara";
-                case "aze": return "Azerbaijani";
-                case "ban": return "Balinese";
-                case "bat": return "Baltic (Other)";
-                case "bal": return "Baluchi";
-                case "bam": return "Bambara";
-                case "bai": return "Bamileke languages";
-                case "bad": return "Banda";
-                case "bnt": return "Bantu (Other)";
-                case "bas": return "Basa";
-                case "bak": return "Bashkir";
-                case "baq": return "Basque";
-                case "eus": return "Basque";
-                case "btk": return "Batak (Indonesia)";
-                case "bej": return "Beja";
-                case "bel": return "Belarusian";
-                case "bem": return "Bemba";
-                case "ben": return "Bengali";
-                case "ber": return "Berber (Other)";
-                case "bho": return "Bhojpuri";
-                case "bih": return "Bihari";
-                case "bik": return "Bikol";
-                case "bin": return "Bini";
-                case "bis": return "Bislama";
-                case "bos": return "Bosnian";
-                case "bra": return "Braj";
-                case "bre": return "Breton";
-                case "bug": return "Buginese";
-                case "bul": return "Bulgarian";
-                case "bua": return "Buriat";
-                case "bur": return "Burmese";
-                case "mya": return "Burmese";
-                case "cad": return "Caddo";
-                case "car": return "Carib";
-                case "cat": return "Catalan";
-                case "cau": return "Caucasian (Other)";
-                case "ceb": return "Cebuano";
-                case "cel": return "Celtic (Other)";
-                case "cai": return "Central American Indian (Other)";
-                case "chg": return "Chagatai";
-                case "cmc": return "Chamic languages";
-                case "cha": return "Chamorro";
-                case "che": return "Chechen";
-                case "chr": return "Cherokee";
-                case "chy": return "Cheyenne";
-                case "chb": return "Chibcha";
-                case "chi": return "Chinese";
-                case "zho": return "Chinese";
-                case "chn": return "Chinook jargon";
-                case "chp": return "Chipewyan";
-                case "cho": return "Choctaw";
-                case "chu": return "Church Slavic";
-                case "chk": return "Chuukese";
-                case "chv": return "Chuvash";
-                case "cop": return "Coptic";
-                case "cor": return "Cornish";
-                case "cos": return "Corsican";
-                case "cre": return "Cree";
-                case "mus": return "Creek";
-                case "crp": return "Creoles and pidgins (Other)";
-                case "cpe": return "Creoles and pidgins,";
-                case "cpf": return "Creoles and pidgins,";
-                case "cpp": return "Creoles and pidgins,";
-                case "scr": return "Croatian";
-                case "hrv": return "Croatian";
-                case "cus": return "Cushitic (Other)";
-                case "cze": return "Czech";
-                case "ces": return "Czech";
-                case "dak": return "Dakota";
-                case "dan": return "Danish";
-                case "day": return "Dayak";
-                case "del": return "Delaware";
-                case "din": return "Dinka";
-                case "div": return "Divehi";
-                case "doi": return "Dogri";
-                case "dgr": return "Dogrib";
-                case "dra": return "Dravidian (Other)";
-                case "dua": return "Duala";
-                case "dut": return "Dutch";
-                case "nld": return "Dutch";
-                case "dum": return "Dutch, Middle (ca. 1050-1350)";
-                case "dyu": return "Dyula";
-                case "dzo": return "Dzongkha";
-                case "efi": return "Efik";
-                case "egy": return "Egyptian (Ancient)";
-                case "eka": return "Ekajuk";
-                case "elx": return "Elamite";
-                case "eng": return "English";
-                case "enm": return "English, Middle (1100-1500)";
-                case "ang": return "English, Old (ca.450-1100)";
-                case "epo": return "Esperanto";
-                case "est": return "Estonian";
-                case "ewe": return "Ewe";
-                case "ewo": return "Ewondo";
-                case "fan": return "Fang";
-                case "fat": return "Fanti";
-                case "fao": return "Faroese";
-                case "fij": return "Fijian";
-                case "fin": return "Finnish";
-                case "fiu": return "Finno-Ugrian (Other)";
-                case "fon": return "Fon";
-                case "fre": return "French";
-                case "fra": return "French";
-                case "frm": return "French, Middle (ca.1400-1600)";
-                case "fro": return "French, Old (842-ca.1400)";
-                case "fry": return "Frisian";
-                case "fur": return "Friulian";
-                case "ful": return "Fulah";
-                case "gaa": return "Ga";
-                case "glg": return "Gallegan";
-                case "lug": return "Ganda";
-                case "gay": return "Gayo";
-                case "gba": return "Gbaya";
-                case "gez": return "Geez";
-                case "geo": return "Georgian";
-                case "kat": return "Georgian";
-                case "ger": return "German";
-                case "deu": return "German";
-                case "nds": return "Saxon";
-                case "gmh": return "German, Middle High (ca.1050-1500)";
-                case "goh": return "German, Old High (ca.750-1050)";
-                case "gem": return "Germanic (Other)";
-                case "gil": return "Gilbertese";
-                case "gon": return "Gondi";
-                case "gor": return "Gorontalo";
-                case "got": return "Gothic";
-                case "grb": return "Grebo";
-                case "grc": return "Greek, Ancient (to 1453)";
-                case "gre": return "Greek";
-                case "ell": return "Greek";
-                case "grn": return "Guarani";
-                case "guj": return "Gujarati";
-                case "gwi": return "Gwich´in";
-                case "hai": return "Haida";
-                case "hau": return "Hausa";
-                case "haw": return "Hawaiian";
-                case "heb": return "Hebrew";
-                case "her": return "Herero";
-                case "hil": return "Hiligaynon";
-                case "him": return "Himachali";
-                case "hin": return "Hindi";
-                case "hmo": return "Hiri Motu";
-                case "hit": return "Hittite";
-                case "hmn": return "Hmong";
-                case "hun": return "Hungarian";
-                case "hup": return "Hupa";
-                case "iba": return "Iban";
-                case "ice": return "Icelandic";
-                case "isl": return "Icelandic";
-                case "ibo": return "Igbo";
-                case "ijo": return "Ijo";
-                case "ilo": return "Iloko";
-                case "inc": return "Indic (Other)";
-                case "ine": return "Indo-European (Other)";
-                case "ind": return "Indonesian";
-                case "ina": return "Interlingua (International";
-                case "ile": return "Interlingue";
-                case "iku": return "Inuktitut";
-                case "ipk": return "Inupiaq";
-                case "ira": return "Iranian (Other)";
-                case "gle": return "Irish";
-                case "mga": return "Irish, Middle (900-1200)";
-                case "sga": return "Irish, Old (to 900)";
-                case "iro": return "Iroquoian languages";
-                case "ita": return "Italian";
-                case "jpn": return "Japanese";
-                case "jav": return "Javanese";
-                case "jrb": return "Judeo-Arabic";
-                case "jpr": return "Judeo-Persian";
-                case "kab": return "Kabyle";
-                case "kac": return "Kachin";
-                case "kal": return "Kalaallisut";
-                case "kam": return "Kamba";
-                case "kan": return "Kannada";
-                case "kau": return "Kanuri";
-                case "kaa": return "Kara-Kalpak";
-                case "kar": return "Karen";
-                case "kas": return "Kashmiri";
-                case "kaw": return "Kawi";
-                case "kaz": return "Kazakh";
-                case "kha": return "Khasi";
-                case "khm": return "Khmer";
-                case "khi": return "Khoisan (Other)";
-                case "kho": return "Khotanese";
-                case "kik": return "Kikuyu";
-                case "kmb": return "Kimbundu";
-                case "kin": return "Kinyarwanda";
-                case "kir": return "Kirghiz";
-                case "kom": return "Komi";
-                case "kon": return "Kongo";
-                case "kok": return "Konkani";
-                case "kor": return "Korean";
-                case "kos": return "Kosraean";
-                case "kpe": return "Kpelle";
-                case "kro": return "Kru";
-                case "kua": return "Kuanyama";
-                case "kum": return "Kumyk";
-                case "kur": return "Kurdish";
-                case "kru": return "Kurukh";
-                case "kut": return "Kutenai";
-                case "lad": return "Ladino";
-                case "lah": return "Lahnda";
-                case "lam": return "Lamba";
-                case "lao": return "Lao";
-                case "lat": return "Latin";
-                case "lav": return "Latvian";
-                case "ltz": return "Letzeburgesch";
-                case "lez": return "Lezghian";
-                case "lin": return "Lingala";
-                case "lit": return "Lithuanian";
-                case "loz": return "Lozi";
-                case "lub": return "Luba-Katanga";
-                case "lua": return "Luba-Lulua";
-                case "lui": return "Luiseno";
-                case "lun": return "Lunda";
-                case "luo": return "Luo (Kenya and Tanzania)";
-                case "lus": return "Lushai";
-                case "mac": return "Macedonian";
-                case "mkd": return "Macedonian";
-                case "mad": return "Madurese";
-                case "mag": return "Magahi";
-                case "mai": return "Maithili";
-                case "mak": return "Makasar";
-                case "mlg": return "Malagasy";
-                case "may": return "Malay";
-                case "msa": return "Malay";
-                case "mal": return "Malayalam";
-                case "mlt": return "Maltese";
-                case "mnc": return "Manchu";
-                case "mdr": return "Mandar";
-                case "man": return "Mandingo";
-                case "mni": return "Manipuri";
-                case "mno": return "Manobo languages";
-                case "glv": return "Manx";
-                case "mao": return "Maori";
-                case "mri": return "Maori";
-                case "mar": return "Marathi";
-                case "chm": return "Mari";
-                case "mah": return "Marshall";
-                case "mwr": return "Marwari";
-                case "mas": return "Masai";
-                case "myn": return "Mayan languages";
-                case "men": return "Mende";
-                case "mic": return "Micmac";
-                case "min": return "Minangkabau";
-                case "mis": return "Miscellaneous languages";
-                case "moh": return "Mohawk";
-                case "mol": return "Moldavian";
-                case "mkh": return "Mon-Khmer (Other)";
-                case "lol": return "Mongo";
-                case "mon": return "Mongolian";
-                case "mos": return "Mossi";
-                case "mul": return "Multiple languages";
-                case "mun": return "Munda languages";
-                case "nah": return "Nahuatl";
-                case "nau": return "Nauru";
-                case "nav": return "Navajo";
-                case "nde": return "Ndebele, North";
-                case "nbl": return "Ndebele, South";
-                case "ndo": return "Ndonga";
-                case "nep": return "Nepali";
-                case "new": return "Newari";
-                case "nia": return "Nias";
-                case "nic": return "Niger-Kordofanian (Other)";
-                case "ssa": return "Nilo-Saharan (Other)";
-                case "niu": return "Niuean";
-                case "non": return "Norse, Old";
-                case "nai": return "North American Indian (Other)";
-                case "sme": return "Northern Sami";
-                case "nor": return "Norwegian";
-                case "nob": return "Norwegian Bokmål";
-                case "nno": return "Norwegian Nynorsk";
-                case "nub": return "Nubian languages";
-                case "nym": return "Nyamwezi";
-                case "nya": return "Nyanja";
-                case "nyn": return "Nyankole";
-                case "nyo": return "Nyoro";
-                case "nzi": return "Nzima";
-                case "oci": return "Occitan";
-                case "oji": return "Ojibwa";
-                case "ori": return "Oriya";
-                case "orm": return "Oromo";
-                case "osa": return "Osage";
-                case "oss": return "Ossetian";
-                case "oto": return "Otomian languages";
-                case "pal": return "Pahlavi";
-                case "pau": return "Palauan";
-                case "pli": return "Pali";
-                case "pam": return "Pampanga";
-                case "pag": return "Pangasinan";
-                case "pan": return "Panjabi";
-                case "pap": return "Papiamento";
-                case "paa": return "Papuan (Other)";
-                case "per": return "Persian";
-                case "fas": return "Persian";
-                case "peo": return "Persian, Old (ca.600-400 B.C.)";
-                case "phi": return "Philippine (Other)";
-                case "phn": return "Phoenician";
-                case "pon": return "Pohnpeian";
-                case "pol": return "Polish";
-                case "por": return "Portuguese";
-                case "pra": return "Prakrit languages";
-                case "pro": return "Provençal";
-                case "pus": return "Pushto";
-                case "que": return "Quechua";
-                case "roh": return "Raeto-Romance";
-                case "raj": return "Rajasthani";
-                case "rap": return "Rapanui";
-                case "rar": return "Rarotongan";
-                case "roa": return "Romance (Other)";
-                case "rum": return "Romanian";
-                case "ron": return "Romanian";
-                case "rom": return "Romany";
-                case "run": return "Rundi";
-                case "rus": return "Russian";
-                case "sal": return "Salishan languages";
-                case "sam": return "Samaritan Aramaic";
-                case "smi": return "Sami languages (Other)";
-                case "smo": return "Samoan";
-                case "sad": return "Sandawe";
-                case "sag": return "Sango";
-                case "san": return "Sanskrit";
-                case "sat": return "Santali";
-                case "srd": return "Sardinian";
-                case "sas": return "Sasak";
-                case "sco": return "Scots";
-                case "gla": return "Gaelic";
-                case "sel": return "Selkup";
-                case "sem": return "Semitic (Other)";
-                case "scc": return "Serbian";
-                case "srp": return "Serbian";
-                case "srr": return "Serer";
-                case "shn": return "Shan";
-                case "sna": return "Shona";
-                case "sid": return "Sidamo";
-                case "sgn": return "Sign languages";
-                case "bla": return "Siksika";
-                case "snd": return "Sindhi";
-                case "sin": return "Sinhalese";
-                case "sit": return "Sino-Tibetan (Other)";
-                case "sio": return "Siouan languages";
-                case "den": return "Slave (Athapascan)";
-                case "sla": return "Slavic (Other)";
-                case "slo": return "Slovak";
-                case "slk": return "Slovak";
-                case "slv": return "Slovenian";
-                case "sog": return "Sogdian";
-                case "som": return "Somali";
-                case "son": return "Songhai";
-                case "snk": return "Soninke";
-                case "wen": return "Sorbian languages";
-                case "nso": return "Sotho, Northern";
-                case "sot": return "Sotho, Southern";
-                case "sai": return "South American Indian (Other)";
-                case "spa": return "Spanish";
-                case "suk": return "Sukuma";
-                case "sux": return "Sumerian";
-                case "sun": return "Sundanese";
-                case "sus": return "Susu";
-                case "swa": return "Swahili";
-                case "ssw": return "Swati";
-                case "swe": return "Swedish";
-                case "syr": return "Syriac";
-                case "tgl": return "Tagalog";
-                case "tah": return "Tahitian";
-                case "tai": return "Tai (Other)";
-                case "tgk": return "Tajik";
-                case "tmh": return "Tamashek";
-                case "tam": return "Tamil";
-                case "tat": return "Tatar";
-                case "tel": return "Telugu";
-                case "ter": return "Tereno";
-                case "tet": return "Tetum";
-                case "tha": return "Thai";
-                case "tib": return "Tibetan";
-                case "bod": return "Tibetan";
-                case "tig": return "Tigre";
-                case "tir": return "Tigrinya";
-                case "tem": return "Timne";
-                case "tiv": return "Tiv";
-                case "tli": return "Tlingit";
-                case "tpi": return "Tok Pisin";
-                case "tkl": return "Tokelau";
-                case "tog": return "Tonga (Nyasa)";
-                case "ton": return "Tonga (Tonga Islands)";
-                case "tsi": return "Tsimshian";
-                case "tso": return "Tsonga";
-                case "tsn": return "Tswana";
-                case "tum": return "Tumbuka";
-                case "tur": return "Turkish";
-                case "ota": return "Turkish, Ottoman (1500-1928)";
-                case "tuk": return "Turkmen";
-                case "tvl": return "Tuvalu";
-                case "tyv": return "Tuvinian";
-                case "twi": return "Twi";
-                case "uga": return "Ugaritic";
-                case "uig": return "Uighur";
-                case "ukr": return "Ukrainian";
-                case "umb": return "Umbundu";
-                case "und": return "Undetermined";
-                case "urd": return "Urdu";
-                case "uzb": return "Uzbek";
-                case "vai": return "Vai";
-                case "ven": return "Venda";
-                case "vie": return "Vietnamese";
-                case "vol": return "Volapük";
-                case "vot": return "Votic";
-                case "wak": return "Wakashan languages";
-                case "wal": return "Walamo";
-                case "war": return "Waray";
-                case "was": return "Washo";
-                case "wel": return "Welsh";
-                case "cym": return "Welsh";
-                case "wol": return "Wolof";
-                case "xho": return "Xhosa";
-                case "sah": return "Yakut";
-                case "yao": return "Yao";
-                case "yap": return "Yapese";
-                case "yid": return "Yiddish";
-                case "yor": return "Yoruba";
-                case "ypk": return "Yupik languages";
-                case "znd": return "Zande";
-                case "zap": return "Zapotec";
-                case "zen": return "Zenaga";
-                case "zha": return "Zhuang";
-                case "zul": return "Zulu";
-                case "zun": return "Zuni";
-
-                default: return code;
-            }
-        }
-    }
-}

+ 0 - 21
BDInfo/Properties/AssemblyInfo.cs

@@ -1,21 +0,0 @@
-using System.Reflection;
-using System.Resources;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("BDInfo")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Jellyfin Project")]
-[assembly: AssemblyProduct("Jellyfin Server")]
-[assembly: AssemblyCopyright("Copyright ©  2016 CinemaSquid. Copyright ©  2019 Jellyfin Contributors. Code released under the GNU General Public License")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components.  If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]

+ 0 - 5
BDInfo/ReadMe.txt

@@ -1,5 +0,0 @@
-The source is taken from the BDRom folder of this project:
-
-http://www.cinemasquid.com/blu-ray/tools/bdinfo
-
-BDInfoSettings was taken from the FormSettings class, and changed so that the settings all return defaults.

+ 0 - 309
BDInfo/TSCodecAC3.cs

@@ -1,309 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-#undef DEBUG
-using System.IO;
-
-namespace BDInfo
-{
-    public abstract class TSCodecAC3
-    {
-        private static byte[] eac3_blocks = new byte[] { 1, 2, 3, 6 };
-
-        public static void Scan(
-            TSAudioStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            if (stream.IsInitialized) return;
-
-            byte[] sync = buffer.ReadBytes(2);
-            if (sync == null ||
-                sync[0] != 0x0B ||
-                sync[1] != 0x77)
-            {
-                return;
-            }
-
-            int sr_code = 0;
-            int frame_size = 0;
-            int frame_size_code = 0;
-            int channel_mode = 0;
-            int lfe_on = 0;
-            int dial_norm = 0;
-            int num_blocks = 0;
-
-            byte[] hdr = buffer.ReadBytes(4);
-            int bsid = (hdr[3] & 0xF8) >> 3;
-            buffer.Seek(-4, SeekOrigin.Current);
-            if (bsid <= 10)
-            {
-                byte[] crc = buffer.ReadBytes(2);
-                sr_code = buffer.ReadBits(2);
-                frame_size_code = buffer.ReadBits(6);
-                bsid = buffer.ReadBits(5);
-                int bsmod = buffer.ReadBits(3);
-
-                channel_mode = buffer.ReadBits(3);
-                int cmixlev = 0;
-                if (((channel_mode & 0x1) > 0) && (channel_mode != 0x1))
-                {
-                    cmixlev = buffer.ReadBits(2);
-                }
-                int surmixlev = 0;
-                if ((channel_mode & 0x4) > 0)
-                {
-                    surmixlev = buffer.ReadBits(2);
-                }
-                int dsurmod = 0;
-                if (channel_mode == 0x2)
-                {
-                    dsurmod = buffer.ReadBits(2);
-                    if (dsurmod == 0x2)
-                    {
-                        stream.AudioMode = TSAudioMode.Surround;
-                    }
-                }
-                lfe_on = buffer.ReadBits(1);
-                dial_norm = buffer.ReadBits(5);
-                int compr = 0;
-                if (1 == buffer.ReadBits(1))
-                {
-                    compr = buffer.ReadBits(8);
-                }
-                int langcod = 0;
-                if (1 == buffer.ReadBits(1))
-                {
-                    langcod = buffer.ReadBits(8);
-                }
-                int mixlevel = 0;
-                int roomtyp = 0;
-                if (1 == buffer.ReadBits(1))
-                {
-                    mixlevel = buffer.ReadBits(5);
-                    roomtyp = buffer.ReadBits(2);
-                }
-                if (channel_mode == 0)
-                {
-                    int dialnorm2 = buffer.ReadBits(5);
-                    int compr2 = 0;
-                    if (1 == buffer.ReadBits(1))
-                    {
-                        compr2 = buffer.ReadBits(8);
-                    }
-                    int langcod2 = 0;
-                    if (1 == buffer.ReadBits(1))
-                    {
-                        langcod2 = buffer.ReadBits(8);
-                    }
-                    int mixlevel2 = 0;
-                    int roomtyp2 = 0;
-                    if (1 == buffer.ReadBits(1))
-                    {
-                        mixlevel2 = buffer.ReadBits(5);
-                        roomtyp2 = buffer.ReadBits(2);
-                    }
-                }
-                int copyrightb = buffer.ReadBits(1);
-                int origbs = buffer.ReadBits(1);
-                if (bsid == 6)
-                {
-                    if (1 == buffer.ReadBits(1))
-                    {
-                        int dmixmod = buffer.ReadBits(2);
-                        int ltrtcmixlev = buffer.ReadBits(3);
-                        int ltrtsurmixlev = buffer.ReadBits(3);
-                        int lorocmixlev = buffer.ReadBits(3);
-                        int lorosurmixlev = buffer.ReadBits(3);
-                    }
-                    if (1 == buffer.ReadBits(1))
-                    {
-                        int dsurexmod = buffer.ReadBits(2);
-                        int dheadphonmod = buffer.ReadBits(2);
-                        if (dheadphonmod == 0x2)
-                        {
-                            // TODO
-                        }
-                        int adconvtyp = buffer.ReadBits(1);
-                        int xbsi2 = buffer.ReadBits(8);
-                        int encinfo = buffer.ReadBits(1);
-                        if (dsurexmod == 2)
-                        {
-                            stream.AudioMode = TSAudioMode.Extended;
-                        }
-                    }
-                }
-            }
-            else
-            {
-                int frame_type = buffer.ReadBits(2);
-                int substreamid = buffer.ReadBits(3);
-                frame_size = (buffer.ReadBits(11) + 1) << 1;
-
-                sr_code = buffer.ReadBits(2);
-                if (sr_code == 3)
-                {
-                    sr_code = buffer.ReadBits(2);
-                }
-                else
-                {
-                    num_blocks = buffer.ReadBits(2);
-                }
-                channel_mode = buffer.ReadBits(3);
-                lfe_on = buffer.ReadBits(1);
-            }
-
-            switch (channel_mode)
-            {
-                case 0: // 1+1
-                    stream.ChannelCount = 2;
-                    if (stream.AudioMode == TSAudioMode.Unknown)
-                    {
-                        stream.AudioMode = TSAudioMode.DualMono;
-                    }
-                    break;
-                case 1: // 1/0
-                    stream.ChannelCount = 1;
-                    break;
-                case 2: // 2/0
-                    stream.ChannelCount = 2;
-                    if (stream.AudioMode == TSAudioMode.Unknown)
-                    {
-                        stream.AudioMode = TSAudioMode.Stereo;
-                    }
-                    break;
-                case 3: // 3/0
-                    stream.ChannelCount = 3;
-                    break;
-                case 4: // 2/1
-                    stream.ChannelCount = 3;
-                    break;
-                case 5: // 3/1
-                    stream.ChannelCount = 4;
-                    break;
-                case 6: // 2/2
-                    stream.ChannelCount = 4;
-                    break;
-                case 7: // 3/2
-                    stream.ChannelCount = 5;
-                    break;
-                default:
-                    stream.ChannelCount = 0;
-                    break;
-            }
-
-            switch (sr_code)
-            {
-                case 0:
-                    stream.SampleRate = 48000;
-                    break;
-                case 1:
-                    stream.SampleRate = 44100;
-                    break;
-                case 2:
-                    stream.SampleRate = 32000;
-                    break;
-                default:
-                    stream.SampleRate = 0;
-                    break;
-            }
-
-            if (bsid <= 10)
-            {
-                switch (frame_size_code >> 1)
-                {
-                    case 18:
-                        stream.BitRate = 640000;
-                        break;
-                    case 17:
-                        stream.BitRate = 576000;
-                        break;
-                    case 16:
-                        stream.BitRate = 512000;
-                        break;
-                    case 15:
-                        stream.BitRate = 448000;
-                        break;
-                    case 14:
-                        stream.BitRate = 384000;
-                        break;
-                    case 13:
-                        stream.BitRate = 320000;
-                        break;
-                    case 12:
-                        stream.BitRate = 256000;
-                        break;
-                    case 11:
-                        stream.BitRate = 224000;
-                        break;
-                    case 10:
-                        stream.BitRate = 192000;
-                        break;
-                    case 9:
-                        stream.BitRate = 160000;
-                        break;
-                    case 8:
-                        stream.BitRate = 128000;
-                        break;
-                    case 7:
-                        stream.BitRate = 112000;
-                        break;
-                    case 6:
-                        stream.BitRate = 96000;
-                        break;
-                    case 5:
-                        stream.BitRate = 80000;
-                        break;
-                    case 4:
-                        stream.BitRate = 64000;
-                        break;
-                    case 3:
-                        stream.BitRate = 56000;
-                        break;
-                    case 2:
-                        stream.BitRate = 48000;
-                        break;
-                    case 1:
-                        stream.BitRate = 40000;
-                        break;
-                    case 0:
-                        stream.BitRate = 32000;
-                        break;
-                    default:
-                        stream.BitRate = 0;
-                        break;
-                }
-            }
-            else
-            {
-                stream.BitRate = (long)
-                    (4.0 * frame_size * stream.SampleRate / (num_blocks * 256));
-            }
-
-            stream.LFE = lfe_on;
-            if (stream.StreamType != TSStreamType.AC3_PLUS_AUDIO &&
-                stream.StreamType != TSStreamType.AC3_PLUS_SECONDARY_AUDIO)
-            {
-                stream.DialNorm = dial_norm - 31;
-            }
-            stream.IsVBR = false;
-            stream.IsInitialized = true;
-        }
-    }
-}

+ 0 - 148
BDInfo/TSCodecAVC.cs

@@ -1,148 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecAVC
-    {
-        public static void Scan(
-            TSVideoStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            uint parse = 0;
-            byte accessUnitDelimiterParse = 0;
-            byte sequenceParameterSetParse = 0;
-            string profile = null;
-            string level = null;
-            byte constraintSet0Flag = 0;
-            byte constraintSet1Flag = 0;
-            byte constraintSet2Flag = 0;
-            byte constraintSet3Flag = 0;
-
-            for (int i = 0; i < buffer.Length; i++)
-            {
-                parse = (parse << 8) + buffer.ReadByte();
-
-                if (parse == 0x00000109)
-                {
-                    accessUnitDelimiterParse = 1;
-                }
-                else if (accessUnitDelimiterParse > 0)
-                {
-                    --accessUnitDelimiterParse;
-                    if (accessUnitDelimiterParse == 0)
-                    {
-                        switch ((parse & 0xFF) >> 5)
-                        {
-                            case 0: // I
-                            case 3: // SI
-                            case 5: // I, SI
-                                tag = "I";
-                                break;
-
-                            case 1: // I, P
-                            case 4: // SI, SP
-                            case 6: // I, SI, P, SP
-                                tag = "P";
-                                break;
-
-                            case 2: // I, P, B
-                            case 7: // I, SI, P, SP, B
-                                tag = "B";
-                                break;
-                        }
-                        if (stream.IsInitialized) return;
-                    }
-                }
-                else if (parse == 0x00000127 || parse == 0x00000167)
-                {
-                    sequenceParameterSetParse = 3;
-                }
-                else if (sequenceParameterSetParse > 0)
-                {
-                    --sequenceParameterSetParse;
-                    switch (sequenceParameterSetParse)
-                    {
-                        case 2:
-                            switch (parse & 0xFF)
-                            {
-                                case 66:
-                                    profile = "Baseline Profile";
-                                    break;
-                                case 77:
-                                    profile = "Main Profile";
-                                    break;
-                                case 88:
-                                    profile = "Extended Profile";
-                                    break;
-                                case 100:
-                                    profile = "High Profile";
-                                    break;
-                                case 110:
-                                    profile = "High 10 Profile";
-                                    break;
-                                case 122:
-                                    profile = "High 4:2:2 Profile";
-                                    break;
-                                case 144:
-                                    profile = "High 4:4:4 Profile";
-                                    break;
-                                default:
-                                    profile = "Unknown Profile";
-                                    break;
-                            }
-                            break;
-
-                        case 1:
-                            constraintSet0Flag = (byte)
-                                ((parse & 0x80) >> 7);
-                            constraintSet1Flag = (byte)
-                                ((parse & 0x40) >> 6);
-                            constraintSet2Flag = (byte)
-                                ((parse & 0x20) >> 5);
-                            constraintSet3Flag = (byte)
-                                ((parse & 0x10) >> 4);
-                            break;
-
-                        case 0:
-                            byte b = (byte)(parse & 0xFF);
-                            if (b == 11 && constraintSet3Flag == 1)
-                            {
-                                level = "1b";
-                            }
-                            else
-                            {
-                                level = string.Format(
-                                    "{0:D}.{1:D}",
-                                    b / 10, (b - ((b / 10) * 10)));
-                            }
-                            stream.EncodingProfile = string.Format(
-                                "{0} {1}", profile, level);
-                            stream.IsVBR = true;
-                            stream.IsInitialized = true;
-                            break;
-                    }
-                }
-            }
-            return;
-        }
-    }
-}

+ 0 - 159
BDInfo/TSCodecDTS.cs

@@ -1,159 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecDTS
-    {
-        private static int[] dca_sample_rates =
-        {
-            0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
-            12000, 24000, 48000, 96000, 192000
-        };
-
-        private static int[] dca_bit_rates =
-        {
-            32000, 56000, 64000, 96000, 112000, 128000,
-            192000, 224000, 256000, 320000, 384000,
-            448000, 512000, 576000, 640000, 768000,
-            896000, 1024000, 1152000, 1280000, 1344000,
-            1408000, 1411200, 1472000, 1509000, 1920000,
-            2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
-        };
-
-        private static int[] dca_channels =
-        {
-            1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8
-        };
-
-        private static int[] dca_bits_per_sample =
-        {
-            16, 16, 20, 20, 0, 24, 24
-        };
-
-        public static void Scan(
-            TSAudioStream stream,
-            TSStreamBuffer buffer,
-            long bitrate,
-            ref string tag)
-        {
-            if (stream.IsInitialized) return;
-
-            bool syncFound = false;
-            uint sync = 0;
-            for (int i = 0; i < buffer.Length; i++)
-            {
-                sync = (sync << 8) + buffer.ReadByte();
-                if (sync == 0x7FFE8001)
-                {
-                    syncFound = true;
-                    break;
-                }
-            }
-            if (!syncFound) return;
-
-            int frame_type = buffer.ReadBits(1);
-            int samples_deficit = buffer.ReadBits(5);
-            int crc_present = buffer.ReadBits(1);
-            int sample_blocks = buffer.ReadBits(7);
-            int frame_size = buffer.ReadBits(14);
-            if (frame_size < 95)
-            {
-                return;
-            }
-            int amode = buffer.ReadBits(6);
-            int sample_rate = buffer.ReadBits(4);
-            if (sample_rate < 0 || sample_rate >= dca_sample_rates.Length)
-            {
-                return;
-            }
-            int bit_rate = buffer.ReadBits(5);
-            if (bit_rate < 0 || bit_rate >= dca_bit_rates.Length)
-            {
-                return;
-            }
-            int downmix = buffer.ReadBits(1);
-            int dynrange = buffer.ReadBits(1);
-            int timestamp = buffer.ReadBits(1);
-            int aux_data = buffer.ReadBits(1);
-            int hdcd = buffer.ReadBits(1);
-            int ext_descr = buffer.ReadBits(3);
-            int ext_coding = buffer.ReadBits(1);
-            int aspf = buffer.ReadBits(1);
-            int lfe = buffer.ReadBits(2);
-            int predictor_history = buffer.ReadBits(1);
-            if (crc_present == 1)
-            {
-                int crc = buffer.ReadBits(16);
-            }
-            int multirate_inter = buffer.ReadBits(1);
-            int version = buffer.ReadBits(4);
-            int copy_history = buffer.ReadBits(2);
-            int source_pcm_res = buffer.ReadBits(3);
-            int front_sum = buffer.ReadBits(1);
-            int surround_sum = buffer.ReadBits(1);
-            int dialog_norm = buffer.ReadBits(4);
-            if (source_pcm_res < 0 || source_pcm_res >= dca_bits_per_sample.Length)
-            {
-                return;
-            }
-            int subframes = buffer.ReadBits(4);
-            int total_channels = buffer.ReadBits(3) + 1 + ext_coding;
-
-            stream.SampleRate = dca_sample_rates[sample_rate];
-            stream.ChannelCount = total_channels;
-            stream.LFE = (lfe > 0 ? 1 : 0);
-            stream.BitDepth = dca_bits_per_sample[source_pcm_res];
-            stream.DialNorm = -dialog_norm;
-            if ((source_pcm_res & 0x1) == 0x1)
-            {
-                stream.AudioMode = TSAudioMode.Extended;
-            }
-
-            stream.BitRate = (uint)dca_bit_rates[bit_rate];
-            switch (stream.BitRate)
-            {
-                case 1:
-                    if (bitrate > 0)
-                    {
-                        stream.BitRate = bitrate;
-                        stream.IsVBR = false;
-                        stream.IsInitialized = true;
-                    }
-                    else
-                    {
-                        stream.BitRate = 0;
-                    }
-                    break;
-
-                case 2:
-                case 3:
-                    stream.IsVBR = true;
-                    stream.IsInitialized = true;
-                    break;
-
-                default:
-                    stream.IsVBR = false;
-                    stream.IsInitialized = true;
-                    break;
-            }
-        }
-    }
-}

+ 0 - 246
BDInfo/TSCodecDTSHD.cs

@@ -1,246 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecDTSHD
-    {
-        private static int[] SampleRates = new int[]
-        { 0x1F40, 0x3E80, 0x7D00, 0x0FA00, 0x1F400, 0x5622, 0x0AC44, 0x15888, 0x2B110, 0x56220, 0x2EE0, 0x5DC0, 0x0BB80, 0x17700, 0x2EE00, 0x5DC00 };
-
-        public static void Scan(
-            TSAudioStream stream,
-            TSStreamBuffer buffer,
-            long bitrate,
-            ref string tag)
-        {
-            if (stream.IsInitialized &&
-                (stream.StreamType == TSStreamType.DTS_HD_SECONDARY_AUDIO ||
-                (stream.CoreStream != null &&
-                 stream.CoreStream.IsInitialized))) return;
-
-            bool syncFound = false;
-            uint sync = 0;
-            for (int i = 0; i < buffer.Length; i++)
-            {
-                sync = (sync << 8) + buffer.ReadByte();
-                if (sync == 0x64582025)
-                {
-                    syncFound = true;
-                    break;
-                }
-            }
-
-            if (!syncFound)
-            {
-                tag = "CORE";
-                if (stream.CoreStream == null)
-                {
-                    stream.CoreStream = new TSAudioStream();
-                    stream.CoreStream.StreamType = TSStreamType.DTS_AUDIO;
-                }
-                if (!stream.CoreStream.IsInitialized)
-                {
-                    buffer.BeginRead();
-                    TSCodecDTS.Scan(stream.CoreStream, buffer, bitrate, ref tag);
-                }
-                return;
-            }
-
-            tag = "HD";
-            int temp1 = buffer.ReadBits(8);
-            int nuSubStreamIndex = buffer.ReadBits(2);
-            int nuExtSSHeaderSize = 0;
-            int nuExtSSFSize = 0;
-            int bBlownUpHeader = buffer.ReadBits(1);
-            if (1 == bBlownUpHeader)
-            {
-                nuExtSSHeaderSize = buffer.ReadBits(12) + 1;
-                nuExtSSFSize = buffer.ReadBits(20) + 1;
-            }
-            else
-            {
-                nuExtSSHeaderSize = buffer.ReadBits(8) + 1;
-                nuExtSSFSize = buffer.ReadBits(16) + 1;
-            }
-            int nuNumAudioPresent = 1;
-            int nuNumAssets = 1;
-            int bStaticFieldsPresent = buffer.ReadBits(1);
-            if (1 == bStaticFieldsPresent)
-            {
-                int nuRefClockCode = buffer.ReadBits(2);
-                int nuExSSFrameDurationCode = buffer.ReadBits(3) + 1;
-                long nuTimeStamp = 0;
-                if (1 == buffer.ReadBits(1))
-                {
-                    nuTimeStamp = (buffer.ReadBits(18) << 18) + buffer.ReadBits(18);
-                }
-                nuNumAudioPresent = buffer.ReadBits(3) + 1;
-                nuNumAssets = buffer.ReadBits(3) + 1;
-                int[] nuActiveExSSMask = new int[nuNumAudioPresent];
-                for (int i = 0; i < nuNumAudioPresent; i++)
-                {
-                    nuActiveExSSMask[i] = buffer.ReadBits(nuSubStreamIndex + 1); //?
-                }
-                for (int i = 0; i < nuNumAudioPresent; i++)
-                {
-                    for (int j = 0; j < nuSubStreamIndex + 1; j++)
-                    {
-                        if (((j + 1) % 2) == 1)
-                        {
-                            int mask = buffer.ReadBits(8);
-                        }
-                    }
-                }
-                if (1 == buffer.ReadBits(1))
-                {
-                    int nuMixMetadataAdjLevel = buffer.ReadBits(2);
-                    int nuBits4MixOutMask = buffer.ReadBits(2) * 4 + 4;
-                    int nuNumMixOutConfigs = buffer.ReadBits(2) + 1;
-                    int[] nuMixOutChMask = new int[nuNumMixOutConfigs];
-                    for (int i = 0; i < nuNumMixOutConfigs; i++)
-                    {
-                        nuMixOutChMask[i] = buffer.ReadBits(nuBits4MixOutMask);
-                    }
-                }
-            }
-            int[] AssetSizes = new int[nuNumAssets];
-            for (int i = 0; i < nuNumAssets; i++)
-            {
-                if (1 == bBlownUpHeader)
-                {
-                    AssetSizes[i] = buffer.ReadBits(20) + 1;
-                }
-                else
-                {
-                    AssetSizes[i] = buffer.ReadBits(16) + 1;
-                }
-            }
-            for (int i = 0; i < nuNumAssets; i++)
-            {
-                long bufferPosition = buffer.Position;
-                int nuAssetDescriptorFSIZE = buffer.ReadBits(9) + 1;
-                int DescriptorDataForAssetIndex = buffer.ReadBits(3);
-                if (1 == bStaticFieldsPresent)
-                {
-                    int AssetTypeDescrPresent = buffer.ReadBits(1);
-                    if (1 == AssetTypeDescrPresent)
-                    {
-                        int AssetTypeDescriptor = buffer.ReadBits(4);
-                    }
-                    int LanguageDescrPresent = buffer.ReadBits(1);
-                    if (1 == LanguageDescrPresent)
-                    {
-                        int LanguageDescriptor = buffer.ReadBits(24);
-                    }
-                    int bInfoTextPresent = buffer.ReadBits(1);
-                    if (1 == bInfoTextPresent)
-                    {
-                        int nuInfoTextByteSize = buffer.ReadBits(10) + 1;
-                        int[] InfoText = new int[nuInfoTextByteSize];
-                        for (int j = 0; j < nuInfoTextByteSize; j++)
-                        {
-                            InfoText[j] = buffer.ReadBits(8);
-                        }
-                    }
-                    int nuBitResolution = buffer.ReadBits(5) + 1;
-                    int nuMaxSampleRate = buffer.ReadBits(4);
-                    int nuTotalNumChs = buffer.ReadBits(8) + 1;
-                    int bOne2OneMapChannels2Speakers = buffer.ReadBits(1);
-                    int nuSpkrActivityMask = 0;
-                    if (1 == bOne2OneMapChannels2Speakers)
-                    {
-                        int bEmbeddedStereoFlag = 0;
-                        if (nuTotalNumChs > 2)
-                        {
-                            bEmbeddedStereoFlag = buffer.ReadBits(1);
-                        }
-                        int bEmbeddedSixChFlag = 0;
-                        if (nuTotalNumChs > 6)
-                        {
-                            bEmbeddedSixChFlag = buffer.ReadBits(1);
-                        }
-                        int bSpkrMaskEnabled = buffer.ReadBits(1);
-                        int nuNumBits4SAMask = 0;
-                        if (1 == bSpkrMaskEnabled)
-                        {
-                            nuNumBits4SAMask = buffer.ReadBits(2);
-                            nuNumBits4SAMask = nuNumBits4SAMask * 4 + 4;
-                            nuSpkrActivityMask = buffer.ReadBits(nuNumBits4SAMask);
-                        }
-                        // TODO...
-                    }
-                    stream.SampleRate = SampleRates[nuMaxSampleRate];
-                    stream.BitDepth = nuBitResolution;
-
-                    stream.LFE = 0;
-                    if ((nuSpkrActivityMask & 0x8) == 0x8)
-                    {
-                        ++stream.LFE;
-                    }
-                    if ((nuSpkrActivityMask & 0x1000) == 0x1000)
-                    {
-                        ++stream.LFE;
-                    }
-                    stream.ChannelCount = nuTotalNumChs - stream.LFE;
-                }
-                if (nuNumAssets > 1)
-                {
-                    // TODO...
-                    break;
-                }
-            }
-
-            // TODO
-            if (stream.CoreStream != null)
-            {
-                var coreStream = (TSAudioStream)stream.CoreStream;
-                if (coreStream.AudioMode == TSAudioMode.Extended &&
-                    stream.ChannelCount == 5)
-                {
-                    stream.AudioMode = TSAudioMode.Extended;
-                }
-                /*
-                if (coreStream.DialNorm != 0)
-                {
-                    stream.DialNorm = coreStream.DialNorm;
-                }
-                */
-            }
-
-            if (stream.StreamType == TSStreamType.DTS_HD_MASTER_AUDIO)
-            {
-                stream.IsVBR = true;
-                stream.IsInitialized = true;
-            }
-            else if (bitrate > 0)
-            {
-                stream.IsVBR = false;
-                stream.BitRate = bitrate;
-                if (stream.CoreStream != null)
-                {
-                    stream.BitRate += stream.CoreStream.BitRate;
-                    stream.IsInitialized = true;
-                }
-                stream.IsInitialized = (stream.BitRate > 0 ? true : false);
-            }
-        }
-    }
-}

+ 0 - 123
BDInfo/TSCodecLPCM.cs

@@ -1,123 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecLPCM
-    {
-        public static void Scan(
-            TSAudioStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            if (stream.IsInitialized) return;
-
-            byte[] header = buffer.ReadBytes(4);
-            int flags = (header[2] << 8) + header[3];
-
-            switch ((flags & 0xF000) >> 12)
-            {
-                case 1: // 1/0/0
-                    stream.ChannelCount = 1;
-                    stream.LFE = 0;
-                    break;
-                case 3: // 2/0/0
-                    stream.ChannelCount = 2;
-                    stream.LFE = 0;
-                    break;
-                case 4: // 3/0/0
-                    stream.ChannelCount = 3;
-                    stream.LFE = 0;
-                    break;
-                case 5: // 2/1/0
-                    stream.ChannelCount = 3;
-                    stream.LFE = 0;
-                    break;
-                case 6: // 3/1/0
-                    stream.ChannelCount = 4;
-                    stream.LFE = 0;
-                    break;
-                case 7: // 2/2/0
-                    stream.ChannelCount = 4;
-                    stream.LFE = 0;
-                    break;
-                case 8: // 3/2/0
-                    stream.ChannelCount = 5;
-                    stream.LFE = 0;
-                    break;
-                case 9: // 3/2/1
-                    stream.ChannelCount = 5;
-                    stream.LFE = 1;
-                    break;
-                case 10: // 3/4/0
-                    stream.ChannelCount = 7;
-                    stream.LFE = 0;
-                    break;
-                case 11: // 3/4/1
-                    stream.ChannelCount = 7;
-                    stream.LFE = 1;
-                    break;
-                default:
-                    stream.ChannelCount = 0;
-                    stream.LFE = 0;
-                    break;
-            }
-
-            switch ((flags & 0xC0) >> 6)
-            {
-                case 1:
-                    stream.BitDepth = 16;
-                    break;
-                case 2:
-                    stream.BitDepth = 20;
-                    break;
-                case 3:
-                    stream.BitDepth = 24;
-                    break;
-                default:
-                    stream.BitDepth = 0;
-                    break;
-            }
-
-            switch ((flags & 0xF00) >> 8)
-            {
-                case 1:
-                    stream.SampleRate = 48000;
-                    break;
-                case 4:
-                    stream.SampleRate = 96000;
-                    break;
-                case 5:
-                    stream.SampleRate = 192000;
-                    break;
-                default:
-                    stream.SampleRate = 0;
-                    break;
-            }
-
-            stream.BitRate = (uint)
-                (stream.SampleRate * stream.BitDepth *
-                 (stream.ChannelCount + stream.LFE));
-
-            stream.IsVBR = false;
-            stream.IsInitialized = true;
-        }
-    }
-}

+ 0 - 208
BDInfo/TSCodecMPEG2.cs

@@ -1,208 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-#undef DEBUG
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecMPEG2
-    {
-        public static void Scan(
-            TSVideoStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            int parse = 0;
-            int pictureParse = 0;
-            int sequenceHeaderParse = 0;
-            int extensionParse = 0;
-            int sequenceExtensionParse = 0;
-
-            for (int i = 0; i < buffer.Length; i++)
-            {
-                parse = (parse << 8) + buffer.ReadByte();
-
-                if (parse == 0x00000100)
-                {
-                    pictureParse = 2;
-                }
-                else if (parse == 0x000001B3)
-                {
-                    sequenceHeaderParse = 7;
-                }
-                else if (sequenceHeaderParse > 0)
-                {
-                    --sequenceHeaderParse;
-                    switch (sequenceHeaderParse)
-                    {
-#if DEBUG
-                        case 6:
-                            break;
-
-                        case 5:
-                            break;
-
-                        case 4:
-                            stream.Width =
-                                (int)((parse & 0xFFF000) >> 12);
-                            stream.Height =
-                                (int)(parse & 0xFFF);
-                            break;
-
-                        case 3:
-                            stream.AspectRatio =
-                                (TSAspectRatio)((parse & 0xF0) >> 4);
-
-                            switch ((parse & 0xF0) >> 4)
-                            {
-                                case 0: // Forbidden
-                                    break;
-                                case 1: // Square
-                                    break;
-                                case 2: // 4:3
-                                    break;
-                                case 3: // 16:9
-                                    break;
-                                case 4: // 2.21:1
-                                    break;
-                                default: // Reserved
-                                    break;
-                            }
-
-                            switch (parse & 0xF)
-                            {
-                                case 0: // Forbidden
-                                    break;
-                                case 1: // 23.976
-                                    stream.FrameRateEnumerator = 24000;
-                                    stream.FrameRateDenominator = 1001;
-                                    break;
-                                case 2: // 24
-                                    stream.FrameRateEnumerator = 24000;
-                                    stream.FrameRateDenominator = 1000;
-                                    break;
-                                case 3: // 25
-                                    stream.FrameRateEnumerator = 25000;
-                                    stream.FrameRateDenominator = 1000;
-                                    break;
-                                case 4: // 29.97
-                                    stream.FrameRateEnumerator = 30000;
-                                    stream.FrameRateDenominator = 1001;
-                                    break;
-                                case 5: // 30
-                                    stream.FrameRateEnumerator = 30000;
-                                    stream.FrameRateDenominator = 1000;
-                                    break;
-                                case 6: // 50
-                                    stream.FrameRateEnumerator = 50000;
-                                    stream.FrameRateDenominator = 1000;
-                                    break;
-                                case 7: // 59.94
-                                    stream.FrameRateEnumerator = 60000;
-                                    stream.FrameRateDenominator = 1001;
-                                    break;
-                                case 8: // 60
-                                    stream.FrameRateEnumerator = 60000;
-                                    stream.FrameRateDenominator = 1000;
-                                    break;
-                                default: // Reserved
-                                    stream.FrameRateEnumerator = 0;
-                                    stream.FrameRateDenominator = 0;
-                                    break;
-                            }
-                            break;
-
-                        case 2:
-                            break;
-
-                        case 1:
-                            break;
-#endif
-
-                        case 0:
-#if DEBUG
-                            stream.BitRate =
-                                (((parse & 0xFFFFC0) >> 6) * 200);
-#endif
-                            stream.IsVBR = true;
-                            stream.IsInitialized = true;
-                            break;
-                    }
-                }
-                else if (pictureParse > 0)
-                {
-                    --pictureParse;
-                    if (pictureParse == 0)
-                    {
-                        switch ((parse & 0x38) >> 3)
-                        {
-                            case 1:
-                                tag = "I";
-                                break;
-                            case 2:
-                                tag = "P";
-                                break;
-                            case 3:
-                                tag = "B";
-                                break;
-                            default:
-                                break;
-                        }
-                        if (stream.IsInitialized) return;
-                    }
-                }
-                else if (parse == 0x000001B5)
-                {
-                    extensionParse = 1;
-                }
-                else if (extensionParse > 0)
-                {
-                    --extensionParse;
-                    if (extensionParse == 0)
-                    {
-                        if ((parse & 0xF0) == 0x10)
-                        {
-                            sequenceExtensionParse = 1;
-                        }
-                    }
-                }
-                else if (sequenceExtensionParse > 0)
-                {
-                    --sequenceExtensionParse;
-#if DEBUG
-                    if (sequenceExtensionParse == 0)
-                    {
-                        uint sequenceExtension =
-                            ((parse & 0x8) >> 3);
-                        if (sequenceExtension == 0)
-                        {
-                            stream.IsInterlaced = true;
-                        }
-                        else
-                        {
-                            stream.IsInterlaced = false;
-                        }
-                    }
-#endif
-                }
-            }
-        }
-    }
-}

+ 0 - 36
BDInfo/TSCodecMVC.cs

@@ -1,36 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    // TODO: Do something more interesting here...
-
-    public abstract class TSCodecMVC
-    {
-        public static void Scan(
-            TSVideoStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            stream.IsVBR = true;
-            stream.IsInitialized = true;
-        }
-    }
-}

+ 0 - 186
BDInfo/TSCodecTrueHD.cs

@@ -1,186 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecTrueHD
-    {
-        public static void Scan(
-            TSAudioStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            if (stream.IsInitialized &&
-                stream.CoreStream != null &&
-                stream.CoreStream.IsInitialized) return;
-
-            bool syncFound = false;
-            uint sync = 0;
-            for (int i = 0; i < buffer.Length; i++)
-            {
-                sync = (sync << 8) + buffer.ReadByte();
-                if (sync == 0xF8726FBA)
-                {
-                    syncFound = true;
-                    break;
-                }
-            }
-
-            if (!syncFound)
-            {
-                tag = "CORE";
-                if (stream.CoreStream == null)
-                {
-                    stream.CoreStream = new TSAudioStream();
-                    stream.CoreStream.StreamType = TSStreamType.AC3_AUDIO;
-                }
-                if (!stream.CoreStream.IsInitialized)
-                {
-                    buffer.BeginRead();
-                    TSCodecAC3.Scan(stream.CoreStream, buffer, ref tag);
-                }
-                return;
-            }
-
-            tag = "HD";
-            int ratebits = buffer.ReadBits(4);
-            if (ratebits != 0xF)
-            {
-                stream.SampleRate =
-                    (((ratebits & 8) > 0 ? 44100 : 48000) << (ratebits & 7));
-            }
-            int temp1 = buffer.ReadBits(8);
-            int channels_thd_stream1 = buffer.ReadBits(5);
-            int temp2 = buffer.ReadBits(2);
-
-            stream.ChannelCount = 0;
-            stream.LFE = 0;
-            int c_LFE2 = buffer.ReadBits(1);
-            if (c_LFE2 == 1)
-            {
-                stream.LFE += 1;
-            }
-            int c_Cvh = buffer.ReadBits(1);
-            if (c_Cvh == 1)
-            {
-                stream.ChannelCount += 1;
-            }
-            int c_LRw = buffer.ReadBits(1);
-            if (c_LRw == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-            int c_LRsd = buffer.ReadBits(1);
-            if (c_LRsd == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-            int c_Ts = buffer.ReadBits(1);
-            if (c_Ts == 1)
-            {
-                stream.ChannelCount += 1;
-            }
-            int c_Cs = buffer.ReadBits(1);
-            if (c_Cs == 1)
-            {
-                stream.ChannelCount += 1;
-            }
-            int c_LRrs = buffer.ReadBits(1);
-            if (c_LRrs == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-            int c_LRc = buffer.ReadBits(1);
-            if (c_LRc == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-            int c_LRvh = buffer.ReadBits(1);
-            if (c_LRvh == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-            int c_LRs = buffer.ReadBits(1);
-            if (c_LRs == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-            int c_LFE = buffer.ReadBits(1);
-            if (c_LFE == 1)
-            {
-                stream.LFE += 1;
-            }
-            int c_C = buffer.ReadBits(1);
-            if (c_C == 1)
-            {
-                stream.ChannelCount += 1;
-            }
-            int c_LR = buffer.ReadBits(1);
-            if (c_LR == 1)
-            {
-                stream.ChannelCount += 2;
-            }
-
-            int access_unit_size = 40 << (ratebits & 7);
-            int access_unit_size_pow2 = 64 << (ratebits & 7);
-
-            int a1 = buffer.ReadBits(16);
-            int a2 = buffer.ReadBits(16);
-            int a3 = buffer.ReadBits(16);
-
-            int is_vbr = buffer.ReadBits(1);
-            int peak_bitrate = buffer.ReadBits(15);
-            peak_bitrate = (peak_bitrate * stream.SampleRate) >> 4;
-
-            double peak_bitdepth =
-                (double)peak_bitrate /
-                (stream.ChannelCount + stream.LFE) /
-                stream.SampleRate;
-            if (peak_bitdepth > 14)
-            {
-                stream.BitDepth = 24;
-            }
-            else
-            {
-                stream.BitDepth = 16;
-            }
-
-#if DEBUG
-            System.Diagnostics.Debug.WriteLine(string.Format(
-                "{0}\t{1}\t{2:F2}",
-                stream.PID, peak_bitrate, peak_bitdepth));
-#endif
-            /*
-            // TODO: Get THD dialnorm from metadata
-            if (stream.CoreStream != null)
-            {
-                TSAudioStream coreStream = (TSAudioStream)stream.CoreStream;
-                if (coreStream.DialNorm != 0)
-                {
-                    stream.DialNorm = coreStream.DialNorm;
-                }
-            }
-            */
-
-            stream.IsVBR = true;
-            stream.IsInitialized = true;
-        }
-    }
-}

+ 0 - 131
BDInfo/TSCodecVC1.cs

@@ -1,131 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-
-namespace BDInfo
-{
-    public abstract class TSCodecVC1
-    {
-        public static void Scan(
-            TSVideoStream stream,
-            TSStreamBuffer buffer,
-            ref string tag)
-        {
-            int parse = 0;
-            byte frameHeaderParse = 0;
-            byte sequenceHeaderParse = 0;
-            bool isInterlaced = false;
-
-            for (int i = 0; i < buffer.Length; i++)
-            {
-                parse = (parse << 8) + buffer.ReadByte();
-
-                if (parse == 0x0000010D)
-                {
-                    frameHeaderParse = 4;
-                }
-                else if (frameHeaderParse > 0)
-                {
-                    --frameHeaderParse;
-                    if (frameHeaderParse == 0)
-                    {
-                        uint pictureType = 0;
-                        if (isInterlaced)
-                        {
-                            if ((parse & 0x80000000) == 0)
-                            {
-                                pictureType =
-                                    (uint)((parse & 0x78000000) >> 13);
-                            }
-                            else
-                            {
-                                pictureType =
-                                    (uint)((parse & 0x3c000000) >> 12);
-                            }
-                        }
-                        else
-                        {
-                            pictureType =
-                                (uint)((parse & 0xf0000000) >> 14);
-                        }
-
-                        if ((pictureType & 0x20000) == 0)
-                        {
-                            tag = "P";
-                        }
-                        else if ((pictureType & 0x10000) == 0)
-                        {
-                            tag = "B";
-                        }
-                        else if ((pictureType & 0x8000) == 0)
-                        {
-                            tag = "I";
-                        }
-                        else if ((pictureType & 0x4000) == 0)
-                        {
-                            tag = "BI";
-                        }
-                        else
-                        {
-                            tag = null;
-                        }
-                        if (stream.IsInitialized) return;
-                    }
-                }
-                else if (parse == 0x0000010F)
-                {
-                    sequenceHeaderParse = 6;
-                }
-                else if (sequenceHeaderParse > 0)
-                {
-                    --sequenceHeaderParse;
-                    switch (sequenceHeaderParse)
-                    {
-                        case 5:
-                            int profileLevel = ((parse & 0x38) >> 3);
-                            if (((parse & 0xC0) >> 6) == 3)
-                            {
-                                stream.EncodingProfile = string.Format(
-                                    "Advanced Profile {0}", profileLevel);
-                            }
-                            else
-                            {
-                                stream.EncodingProfile = string.Format(
-                                    "Main Profile {0}", profileLevel);
-                            }
-                            break;
-
-                        case 0:
-                            if (((parse & 0x40) >> 6) > 0)
-                            {
-                                isInterlaced = true;
-                            }
-                            else
-                            {
-                                isInterlaced = false;
-                            }
-                            break;
-                    }
-                    stream.IsVBR = true;
-                    stream.IsInitialized = true;
-                }
-            }
-        }
-    }
-}

+ 0 - 37
BDInfo/TSInterleavedFile.cs

@@ -1,37 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-using MediaBrowser.Model.IO;
-
-// TODO: Do more interesting things here...
-
-namespace BDInfo
-{
-    public class TSInterleavedFile
-    {
-        public FileSystemMetadata FileInfo = null;
-        public string Name = null;
-
-        public TSInterleavedFile(FileSystemMetadata fileInfo)
-        {
-            FileInfo = fileInfo;
-            Name = fileInfo.Name.ToUpper();
-        }
-    }
-}

+ 0 - 1282
BDInfo/TSPlaylistFile.cs

@@ -1,1282 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-#undef DEBUG
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using MediaBrowser.Model.IO;
-
-namespace BDInfo
-{
-    public class TSPlaylistFile
-    {
-        private FileSystemMetadata FileInfo = null;
-        public string FileType = null;
-        public bool IsInitialized = false;
-        public string Name = null;
-        public BDROM BDROM = null;
-        public bool HasHiddenTracks = false;
-        public bool HasLoops = false;
-        public bool IsCustom = false;
-
-        public List<double> Chapters = new List<double>();
-
-        public Dictionary<ushort, TSStream> Streams =
-            new Dictionary<ushort, TSStream>();
-        public Dictionary<ushort, TSStream> PlaylistStreams =
-            new Dictionary<ushort, TSStream>();
-        public List<TSStreamClip> StreamClips =
-            new List<TSStreamClip>();
-        public List<Dictionary<ushort, TSStream>> AngleStreams =
-            new List<Dictionary<ushort, TSStream>>();
-        public List<Dictionary<double, TSStreamClip>> AngleClips =
-            new List<Dictionary<double, TSStreamClip>>();
-        public int AngleCount = 0;
-
-        public List<TSStream> SortedStreams =
-            new List<TSStream>();
-        public List<TSVideoStream> VideoStreams =
-            new List<TSVideoStream>();
-        public List<TSAudioStream> AudioStreams =
-            new List<TSAudioStream>();
-        public List<TSTextStream> TextStreams =
-            new List<TSTextStream>();
-        public List<TSGraphicsStream> GraphicsStreams =
-            new List<TSGraphicsStream>();
-
-        public TSPlaylistFile(BDROM bdrom,
-            FileSystemMetadata fileInfo)
-        {
-            BDROM = bdrom;
-            FileInfo = fileInfo;
-            Name = fileInfo.Name.ToUpper();
-        }
-
-        public TSPlaylistFile(BDROM bdrom,
-            string name,
-            List<TSStreamClip> clips)
-        {
-            BDROM = bdrom;
-            Name = name;
-            IsCustom = true;
-            foreach (var clip in clips)
-            {
-                var newClip = new TSStreamClip(
-                    clip.StreamFile, clip.StreamClipFile);
-
-                newClip.Name = clip.Name;
-                newClip.TimeIn = clip.TimeIn;
-                newClip.TimeOut = clip.TimeOut;
-                newClip.Length = newClip.TimeOut - newClip.TimeIn;
-                newClip.RelativeTimeIn = TotalLength;
-                newClip.RelativeTimeOut = newClip.RelativeTimeIn + newClip.Length;
-                newClip.AngleIndex = clip.AngleIndex;
-                newClip.Chapters.Add(clip.TimeIn);
-                StreamClips.Add(newClip);
-
-                if (newClip.AngleIndex > AngleCount)
-                {
-                    AngleCount = newClip.AngleIndex;
-                }
-                if (newClip.AngleIndex == 0)
-                {
-                    Chapters.Add(newClip.RelativeTimeIn);
-                }
-            }
-            LoadStreamClips();
-            IsInitialized = true;
-        }
-
-        public override string ToString()
-        {
-            return Name;
-        }
-
-        public ulong InterleavedFileSize
-        {
-            get
-            {
-                ulong size = 0;
-                foreach (var clip in StreamClips)
-                {
-                    size += clip.InterleavedFileSize;
-                }
-                return size;
-            }
-        }
-        public ulong FileSize
-        {
-            get
-            {
-                ulong size = 0;
-                foreach (var clip in StreamClips)
-                {
-                    size += clip.FileSize;
-                }
-                return size;
-            }
-        }
-        public double TotalLength
-        {
-            get
-            {
-                double length = 0;
-                foreach (var clip in StreamClips)
-                {
-                    if (clip.AngleIndex == 0)
-                    {
-                        length += clip.Length;
-                    }
-                }
-                return length;
-            }
-        }
-
-        public double TotalAngleLength
-        {
-            get
-            {
-                double length = 0;
-                foreach (var clip in StreamClips)
-                {
-                    length += clip.Length;
-                }
-                return length;
-            }
-        }
-
-        public ulong TotalSize
-        {
-            get
-            {
-                ulong size = 0;
-                foreach (var clip in StreamClips)
-                {
-                    if (clip.AngleIndex == 0)
-                    {
-                        size += clip.PacketSize;
-                    }
-                }
-                return size;
-            }
-        }
-
-        public ulong TotalAngleSize
-        {
-            get
-            {
-                ulong size = 0;
-                foreach (var clip in StreamClips)
-                {
-                    size += clip.PacketSize;
-                }
-                return size;
-            }
-        }
-
-        public ulong TotalBitRate
-        {
-            get
-            {
-                if (TotalLength > 0)
-                {
-                    return (ulong)Math.Round(((TotalSize * 8.0) / TotalLength));
-                }
-                return 0;
-            }
-        }
-
-        public ulong TotalAngleBitRate
-        {
-            get
-            {
-                if (TotalAngleLength > 0)
-                {
-                    return (ulong)Math.Round(((TotalAngleSize * 8.0) / TotalAngleLength));
-                }
-                return 0;
-            }
-        }
-
-        public void Scan(
-            Dictionary<string, TSStreamFile> streamFiles,
-            Dictionary<string, TSStreamClipFile> streamClipFiles)
-        {
-            Stream fileStream = null;
-            BinaryReader fileReader = null;
-
-            try
-            {
-                Streams.Clear();
-                StreamClips.Clear();
-
-                fileStream = File.OpenRead(FileInfo.FullName);
-                fileReader = new BinaryReader(fileStream);
-
-                byte[] data = new byte[fileStream.Length];
-                int dataLength = fileReader.Read(data, 0, data.Length);
-
-                int pos = 0;
-
-                FileType = ReadString(data, 8, ref pos);
-                if (FileType != "MPLS0100" && FileType != "MPLS0200")
-                {
-                    throw new Exception(string.Format(
-                        "Playlist {0} has an unknown file type {1}.",
-                        FileInfo.Name, FileType));
-                }
-
-                int playlistOffset = ReadInt32(data, ref pos);
-                int chaptersOffset = ReadInt32(data, ref pos);
-                int extensionsOffset = ReadInt32(data, ref pos);
-
-                pos = playlistOffset;
-
-                int playlistLength = ReadInt32(data, ref pos);
-                int playlistReserved = ReadInt16(data, ref pos);
-                int itemCount = ReadInt16(data, ref pos);
-                int subitemCount = ReadInt16(data, ref pos);
-
-                var chapterClips = new List<TSStreamClip>();
-                for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
-                {
-                    int itemStart = pos;
-                    int itemLength = ReadInt16(data, ref pos);
-                    string itemName = ReadString(data, 5, ref pos);
-                    string itemType = ReadString(data, 4, ref pos);
-
-                    TSStreamFile streamFile = null;
-                    string streamFileName = string.Format(
-                        "{0}.M2TS", itemName);
-                    if (streamFiles.ContainsKey(streamFileName))
-                    {
-                        streamFile = streamFiles[streamFileName];
-                    }
-                    if (streamFile == null)
-                    {
-                        // Error condition
-                    }
-
-                    TSStreamClipFile streamClipFile = null;
-                    string streamClipFileName = string.Format(
-                        "{0}.CLPI", itemName);
-                    if (streamClipFiles.ContainsKey(streamClipFileName))
-                    {
-                        streamClipFile = streamClipFiles[streamClipFileName];
-                    }
-                    if (streamClipFile == null)
-                    {
-                        throw new Exception(string.Format(
-                            "Playlist {0} referenced missing file {1}.",
-                            FileInfo.Name, streamFileName));
-                    }
-
-                    pos += 1;
-                    int multiangle = (data[pos] >> 4) & 0x01;
-                    int condition = data[pos] & 0x0F;
-                    pos += 2;
-
-                    int inTime = ReadInt32(data, ref pos);
-                    if (inTime < 0) inTime &= 0x7FFFFFFF;
-                    double timeIn = (double)inTime / 45000;
-
-                    int outTime = ReadInt32(data, ref pos);
-                    if (outTime < 0) outTime &= 0x7FFFFFFF;
-                    double timeOut = (double)outTime / 45000;
-
-                    var streamClip = new TSStreamClip(
-                        streamFile, streamClipFile);
-
-                    streamClip.Name = streamFileName; //TODO
-                    streamClip.TimeIn = timeIn;
-                    streamClip.TimeOut = timeOut;
-                    streamClip.Length = streamClip.TimeOut - streamClip.TimeIn;
-                    streamClip.RelativeTimeIn = TotalLength;
-                    streamClip.RelativeTimeOut = streamClip.RelativeTimeIn + streamClip.Length;
-                    StreamClips.Add(streamClip);
-                    chapterClips.Add(streamClip);
-
-                    pos += 12;
-                    if (multiangle > 0)
-                    {
-                        int angles = data[pos];
-                        pos += 2;
-                        for (int angle = 0; angle < angles - 1; angle++)
-                        {
-                            string angleName = ReadString(data, 5, ref pos);
-                            string angleType = ReadString(data, 4, ref pos);
-                            pos += 1;
-
-                            TSStreamFile angleFile = null;
-                            string angleFileName = string.Format(
-                                "{0}.M2TS", angleName);
-                            if (streamFiles.ContainsKey(angleFileName))
-                            {
-                                angleFile = streamFiles[angleFileName];
-                            }
-                            if (angleFile == null)
-                            {
-                                throw new Exception(string.Format(
-                                    "Playlist {0} referenced missing angle file {1}.",
-                                    FileInfo.Name, angleFileName));
-                            }
-
-                            TSStreamClipFile angleClipFile = null;
-                            string angleClipFileName = string.Format(
-                                "{0}.CLPI", angleName);
-                            if (streamClipFiles.ContainsKey(angleClipFileName))
-                            {
-                                angleClipFile = streamClipFiles[angleClipFileName];
-                            }
-                            if (angleClipFile == null)
-                            {
-                                throw new Exception(string.Format(
-                                    "Playlist {0} referenced missing angle file {1}.",
-                                    FileInfo.Name, angleClipFileName));
-                            }
-
-                            var angleClip =
-                                new TSStreamClip(angleFile, angleClipFile);
-                            angleClip.AngleIndex = angle + 1;
-                            angleClip.TimeIn = streamClip.TimeIn;
-                            angleClip.TimeOut = streamClip.TimeOut;
-                            angleClip.RelativeTimeIn = streamClip.RelativeTimeIn;
-                            angleClip.RelativeTimeOut = streamClip.RelativeTimeOut;
-                            angleClip.Length = streamClip.Length;
-                            StreamClips.Add(angleClip);
-                        }
-                        if (angles - 1 > AngleCount) AngleCount = angles - 1;
-                    }
-
-                    int streamInfoLength = ReadInt16(data, ref pos);
-                    pos += 2;
-                    int streamCountVideo = data[pos++];
-                    int streamCountAudio = data[pos++];
-                    int streamCountPG = data[pos++];
-                    int streamCountIG = data[pos++];
-                    int streamCountSecondaryAudio = data[pos++];
-                    int streamCountSecondaryVideo = data[pos++];
-                    int streamCountPIP = data[pos++];
-                    pos += 5;
-
-#if DEBUG
-                    Debug.WriteLine(string.Format(
-                        "{0} : {1} -> V:{2} A:{3} PG:{4} IG:{5} 2A:{6} 2V:{7} PIP:{8}",
-                        Name, streamFileName, streamCountVideo, streamCountAudio, streamCountPG, streamCountIG,
-                        streamCountSecondaryAudio, streamCountSecondaryVideo, streamCountPIP));
-#endif
-
-                    for (int i = 0; i < streamCountVideo; i++)
-                    {
-                        var stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                    }
-                    for (int i = 0; i < streamCountAudio; i++)
-                    {
-                        var stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                    }
-                    for (int i = 0; i < streamCountPG; i++)
-                    {
-                        var stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                    }
-                    for (int i = 0; i < streamCountIG; i++)
-                    {
-                        var stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                    }
-                    for (int i = 0; i < streamCountSecondaryAudio; i++)
-                    {
-                        var stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                        pos += 2;
-                    }
-                    for (int i = 0; i < streamCountSecondaryVideo; i++)
-                    {
-                        var stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                        pos += 6;
-                    }
-                    /*
-                     * TODO
-                     *
-                    for (int i = 0; i < streamCountPIP; i++)
-                    {
-                        TSStream stream = CreatePlaylistStream(data, ref pos);
-                        if (stream != null) PlaylistStreams[stream.PID] = stream;
-                    }
-                    */
-
-                    pos += itemLength - (pos - itemStart) + 2;
-                }
-
-                pos = chaptersOffset + 4;
-
-                int chapterCount = ReadInt16(data, ref pos);
-
-                for (int chapterIndex = 0;
-                    chapterIndex < chapterCount;
-                    chapterIndex++)
-                {
-                    int chapterType = data[pos + 1];
-
-                    if (chapterType == 1)
-                    {
-                        int streamFileIndex =
-                            ((int)data[pos + 2] << 8) + data[pos + 3];
-
-                        long chapterTime =
-                            ((long)data[pos + 4] << 24) +
-                            ((long)data[pos + 5] << 16) +
-                            ((long)data[pos + 6] << 8) +
-                            ((long)data[pos + 7]);
-
-                        var streamClip = chapterClips[streamFileIndex];
-
-                        double chapterSeconds = (double)chapterTime / 45000;
-
-                        double relativeSeconds =
-                            chapterSeconds -
-                            streamClip.TimeIn +
-                            streamClip.RelativeTimeIn;
-
-                        // TODO: Ignore short last chapter?
-                        if (TotalLength - relativeSeconds > 1.0)
-                        {
-                            streamClip.Chapters.Add(chapterSeconds);
-                            this.Chapters.Add(relativeSeconds);
-                        }
-                    }
-                    else
-                    {
-                        // TODO: Handle other chapter types?
-                    }
-                    pos += 14;
-                }
-            }
-            finally
-            {
-                if (fileReader != null)
-                {
-                    fileReader.Dispose();
-                }
-                if (fileStream != null)
-                {
-                    fileStream.Dispose();
-                }
-            }
-        }
-
-        public void Initialize()
-        {
-            LoadStreamClips();
-
-            var clipTimes = new Dictionary<string, List<double>>();
-            foreach (var clip in StreamClips)
-            {
-                if (clip.AngleIndex == 0)
-                {
-                    if (clipTimes.ContainsKey(clip.Name))
-                    {
-                        if (clipTimes[clip.Name].Contains(clip.TimeIn))
-                        {
-                            HasLoops = true;
-                            break;
-                        }
-                        else
-                        {
-                            clipTimes[clip.Name].Add(clip.TimeIn);
-                        }
-                    }
-                    else
-                    {
-                        clipTimes[clip.Name] = new List<double> { clip.TimeIn };
-                    }
-                }
-            }
-            ClearBitrates();
-            IsInitialized = true;
-        }
-
-        protected TSStream CreatePlaylistStream(byte[] data, ref int pos)
-        {
-            TSStream stream = null;
-
-            int start = pos;
-
-            int headerLength = data[pos++];
-            int headerPos = pos;
-            int headerType = data[pos++];
-
-            int pid = 0;
-            int subpathid = 0;
-            int subclipid = 0;
-
-            switch (headerType)
-            {
-                case 1:
-                    pid = ReadInt16(data, ref pos);
-                    break;
-                case 2:
-                    subpathid = data[pos++];
-                    subclipid = data[pos++];
-                    pid = ReadInt16(data, ref pos);
-                    break;
-                case 3:
-                    subpathid = data[pos++];
-                    pid = ReadInt16(data, ref pos);
-                    break;
-                case 4:
-                    subpathid = data[pos++];
-                    subclipid = data[pos++];
-                    pid = ReadInt16(data, ref pos);
-                    break;
-                default:
-                    break;
-            }
-
-            pos = headerPos + headerLength;
-
-            int streamLength = data[pos++];
-            int streamPos = pos;
-
-            var streamType = (TSStreamType)data[pos++];
-            switch (streamType)
-            {
-                case TSStreamType.MVC_VIDEO:
-                    // TODO
-                    break;
-
-                case TSStreamType.AVC_VIDEO:
-                case TSStreamType.MPEG1_VIDEO:
-                case TSStreamType.MPEG2_VIDEO:
-                case TSStreamType.VC1_VIDEO:
-
-                    var videoFormat = (TSVideoFormat)
-                        (data[pos] >> 4);
-                    var frameRate = (TSFrameRate)
-                        (data[pos] & 0xF);
-                    var aspectRatio = (TSAspectRatio)
-                        (data[pos + 1] >> 4);
-
-                    stream = new TSVideoStream();
-                    ((TSVideoStream)stream).VideoFormat = videoFormat;
-                    ((TSVideoStream)stream).AspectRatio = aspectRatio;
-                    ((TSVideoStream)stream).FrameRate = frameRate;
-
-#if DEBUG
-                            Debug.WriteLine(string.Format(
-                                "\t{0} {1} {2} {3} {4}",
-                                pid,
-                                streamType,
-                                videoFormat,
-                                frameRate,
-                                aspectRatio));
-#endif
-
-                    break;
-
-                case TSStreamType.AC3_AUDIO:
-                case TSStreamType.AC3_PLUS_AUDIO:
-                case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                case TSStreamType.AC3_TRUE_HD_AUDIO:
-                case TSStreamType.DTS_AUDIO:
-                case TSStreamType.DTS_HD_AUDIO:
-                case TSStreamType.DTS_HD_MASTER_AUDIO:
-                case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                case TSStreamType.LPCM_AUDIO:
-                case TSStreamType.MPEG1_AUDIO:
-                case TSStreamType.MPEG2_AUDIO:
-
-                    int audioFormat = ReadByte(data, ref pos);
-
-                    var channelLayout = (TSChannelLayout)
-                        (audioFormat >> 4);
-                    var sampleRate = (TSSampleRate)
-                        (audioFormat & 0xF);
-
-                    string audioLanguage = ReadString(data, 3, ref pos);
-
-                    stream = new TSAudioStream();
-                    ((TSAudioStream)stream).ChannelLayout = channelLayout;
-                    ((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate);
-                    ((TSAudioStream)stream).LanguageCode = audioLanguage;
-
-#if DEBUG
-                    Debug.WriteLine(string.Format(
-                        "\t{0} {1} {2} {3} {4}",
-                        pid,
-                        streamType,
-                        audioLanguage,
-                        channelLayout,
-                        sampleRate));
-#endif
-
-                    break;
-
-                case TSStreamType.INTERACTIVE_GRAPHICS:
-                case TSStreamType.PRESENTATION_GRAPHICS:
-
-                    string graphicsLanguage = ReadString(data, 3, ref pos);
-
-                    stream = new TSGraphicsStream();
-                    ((TSGraphicsStream)stream).LanguageCode = graphicsLanguage;
-
-                    if (data[pos] != 0)
-                    {
-                    }
-
-#if DEBUG
-                    Debug.WriteLine(string.Format(
-                        "\t{0} {1} {2}",
-                        pid,
-                        streamType,
-                        graphicsLanguage));
-#endif
-
-                    break;
-
-                case TSStreamType.SUBTITLE:
-
-                    int code = ReadByte(data, ref pos); // TODO
-                    string textLanguage = ReadString(data, 3, ref pos);
-
-                    stream = new TSTextStream();
-                    ((TSTextStream)stream).LanguageCode = textLanguage;
-
-#if DEBUG
-                    Debug.WriteLine(string.Format(
-                        "\t{0} {1} {2}",
-                        pid,
-                        streamType,
-                        textLanguage));
-#endif
-
-                    break;
-
-                default:
-                    break;
-            }
-
-            pos = streamPos + streamLength;
-
-            if (stream != null)
-            {
-                stream.PID = (ushort)pid;
-                stream.StreamType = streamType;
-            }
-
-            return stream;
-        }
-
-        private void LoadStreamClips()
-        {
-            AngleClips.Clear();
-            if (AngleCount > 0)
-            {
-                for (int angleIndex = 0; angleIndex < AngleCount; angleIndex++)
-                {
-                    AngleClips.Add(new Dictionary<double, TSStreamClip>());
-                }
-            }
-
-            TSStreamClip referenceClip = null;
-            if (StreamClips.Count > 0)
-            {
-                referenceClip = StreamClips[0];
-            }
-            foreach (var clip in StreamClips)
-            {
-                if (clip.StreamClipFile.Streams.Count > referenceClip.StreamClipFile.Streams.Count)
-                {
-                    referenceClip = clip;
-                }
-                else if (clip.Length > referenceClip.Length)
-                {
-                    referenceClip = clip;
-                }
-                if (AngleCount > 0)
-                {
-                    if (clip.AngleIndex == 0)
-                    {
-                        for (int angleIndex = 0; angleIndex < AngleCount; angleIndex++)
-                        {
-                            AngleClips[angleIndex][clip.RelativeTimeIn] = clip;
-                        }
-                    }
-                    else
-                    {
-                        AngleClips[clip.AngleIndex - 1][clip.RelativeTimeIn] = clip;
-                    }
-                }
-            }
-
-            foreach (var clipStream
-                in referenceClip.StreamClipFile.Streams.Values)
-            {
-                if (!Streams.ContainsKey(clipStream.PID))
-                {
-                    var stream = clipStream.Clone();
-                    Streams[clipStream.PID] = stream;
-
-                    if (!IsCustom && !PlaylistStreams.ContainsKey(stream.PID))
-                    {
-                        stream.IsHidden = true;
-                        HasHiddenTracks = true;
-                    }
-
-                    if (stream.IsVideoStream)
-                    {
-                        VideoStreams.Add((TSVideoStream)stream);
-                    }
-                    else if (stream.IsAudioStream)
-                    {
-                        AudioStreams.Add((TSAudioStream)stream);
-                    }
-                    else if (stream.IsGraphicsStream)
-                    {
-                        GraphicsStreams.Add((TSGraphicsStream)stream);
-                    }
-                    else if (stream.IsTextStream)
-                    {
-                        TextStreams.Add((TSTextStream)stream);
-                    }
-                }
-            }
-
-            if (referenceClip.StreamFile != null)
-            {
-                // TODO: Better way to add this in?
-                if (BDInfoSettings.EnableSSIF &&
-                    referenceClip.StreamFile.InterleavedFile != null &&
-                    referenceClip.StreamFile.Streams.ContainsKey(4114) &&
-                    !Streams.ContainsKey(4114))
-                {
-                    var stream = referenceClip.StreamFile.Streams[4114].Clone();
-                    Streams[4114] = stream;
-                    if (stream.IsVideoStream)
-                    {
-                        VideoStreams.Add((TSVideoStream)stream);
-                    }
-                }
-
-                foreach (var clipStream
-                    in referenceClip.StreamFile.Streams.Values)
-                {
-                    if (Streams.ContainsKey(clipStream.PID))
-                    {
-                        var stream = Streams[clipStream.PID];
-
-                        if (stream.StreamType != clipStream.StreamType) continue;
-
-                        if (clipStream.BitRate > stream.BitRate)
-                        {
-                            stream.BitRate = clipStream.BitRate;
-                        }
-                        stream.IsVBR = clipStream.IsVBR;
-
-                        if (stream.IsVideoStream &&
-                            clipStream.IsVideoStream)
-                        {
-                            ((TSVideoStream)stream).EncodingProfile =
-                                ((TSVideoStream)clipStream).EncodingProfile;
-                        }
-                        else if (stream.IsAudioStream &&
-                            clipStream.IsAudioStream)
-                        {
-                            var audioStream = (TSAudioStream)stream;
-                            var clipAudioStream = (TSAudioStream)clipStream;
-
-                            if (clipAudioStream.ChannelCount > audioStream.ChannelCount)
-                            {
-                                audioStream.ChannelCount = clipAudioStream.ChannelCount;
-                            }
-                            if (clipAudioStream.LFE > audioStream.LFE)
-                            {
-                                audioStream.LFE = clipAudioStream.LFE;
-                            }
-                            if (clipAudioStream.SampleRate > audioStream.SampleRate)
-                            {
-                                audioStream.SampleRate = clipAudioStream.SampleRate;
-                            }
-                            if (clipAudioStream.BitDepth > audioStream.BitDepth)
-                            {
-                                audioStream.BitDepth = clipAudioStream.BitDepth;
-                            }
-                            if (clipAudioStream.DialNorm < audioStream.DialNorm)
-                            {
-                                audioStream.DialNorm = clipAudioStream.DialNorm;
-                            }
-                            if (clipAudioStream.AudioMode != TSAudioMode.Unknown)
-                            {
-                                audioStream.AudioMode = clipAudioStream.AudioMode;
-                            }
-                            if (clipAudioStream.CoreStream != null &&
-                                audioStream.CoreStream == null)
-                            {
-                                audioStream.CoreStream = (TSAudioStream)
-                                    clipAudioStream.CoreStream.Clone();
-                            }
-                        }
-                    }
-                }
-            }
-
-            for (int i = 0; i < AngleCount; i++)
-            {
-                AngleStreams.Add(new Dictionary<ushort, TSStream>());
-            }
-
-            if (!BDInfoSettings.KeepStreamOrder)
-            {
-                VideoStreams.Sort(CompareVideoStreams);
-            }
-            foreach (TSStream stream in VideoStreams)
-            {
-                SortedStreams.Add(stream);
-                for (int i = 0; i < AngleCount; i++)
-                {
-                    var angleStream = stream.Clone();
-                    angleStream.AngleIndex = i + 1;
-                    AngleStreams[i][angleStream.PID] = angleStream;
-                    SortedStreams.Add(angleStream);
-                }
-            }
-
-            if (!BDInfoSettings.KeepStreamOrder)
-            {
-                AudioStreams.Sort(CompareAudioStreams);
-            }
-            foreach (TSStream stream in AudioStreams)
-            {
-                SortedStreams.Add(stream);
-            }
-
-            if (!BDInfoSettings.KeepStreamOrder)
-            {
-                GraphicsStreams.Sort(CompareGraphicsStreams);
-            }
-            foreach (TSStream stream in GraphicsStreams)
-            {
-                SortedStreams.Add(stream);
-            }
-
-            if (!BDInfoSettings.KeepStreamOrder)
-            {
-                TextStreams.Sort(CompareTextStreams);
-            }
-            foreach (TSStream stream in TextStreams)
-            {
-                SortedStreams.Add(stream);
-            }
-        }
-
-        public void ClearBitrates()
-        {
-            foreach (var clip in StreamClips)
-            {
-                clip.PayloadBytes = 0;
-                clip.PacketCount = 0;
-                clip.PacketSeconds = 0;
-
-                if (clip.StreamFile != null)
-                {
-                    foreach (var stream in clip.StreamFile.Streams.Values)
-                    {
-                        stream.PayloadBytes = 0;
-                        stream.PacketCount = 0;
-                        stream.PacketSeconds = 0;
-                    }
-
-                    if (clip.StreamFile != null &&
-                        clip.StreamFile.StreamDiagnostics != null)
-                    {
-                        clip.StreamFile.StreamDiagnostics.Clear();
-                    }
-                }
-            }
-
-            foreach (var stream in SortedStreams)
-            {
-                stream.PayloadBytes = 0;
-                stream.PacketCount = 0;
-                stream.PacketSeconds = 0;
-            }
-        }
-
-        public bool IsValid
-        {
-            get
-            {
-                if (!IsInitialized) return false;
-
-                if (BDInfoSettings.FilterShortPlaylists &&
-                    TotalLength < BDInfoSettings.FilterShortPlaylistsValue)
-                {
-                    return false;
-                }
-
-                if (HasLoops &&
-                    BDInfoSettings.FilterLoopingPlaylists)
-                {
-                    return false;
-                }
-
-                return true;
-            }
-        }
-
-        public int CompareVideoStreams(
-            TSVideoStream x,
-            TSVideoStream y)
-        {
-            if (x == null && y == null)
-            {
-                return 0;
-            }
-            else if (x == null && y != null)
-            {
-                return 1;
-            }
-            else if (x != null && y == null)
-            {
-                return -1;
-            }
-            else
-            {
-                if (x.Height > y.Height)
-                {
-                    return -1;
-                }
-                else if (y.Height > x.Height)
-                {
-                    return 1;
-                }
-                else if (x.PID > y.PID)
-                {
-                    return 1;
-                }
-                else if (y.PID > x.PID)
-                {
-                    return -1;
-                }
-                else
-                {
-                    return 0;
-                }
-            }
-        }
-
-        public int CompareAudioStreams(
-            TSAudioStream x,
-            TSAudioStream y)
-        {
-            if (x == y)
-            {
-                return 0;
-            }
-            else if (x == null && y == null)
-            {
-                return 0;
-            }
-            else if (x == null && y != null)
-            {
-                return -1;
-            }
-            else if (x != null && y == null)
-            {
-                return 1;
-            }
-            else
-            {
-                if (x.ChannelCount > y.ChannelCount)
-                {
-                    return -1;
-                }
-                else if (y.ChannelCount > x.ChannelCount)
-                {
-                    return 1;
-                }
-                else
-                {
-                    int sortX = GetStreamTypeSortIndex(x.StreamType);
-                    int sortY = GetStreamTypeSortIndex(y.StreamType);
-
-                    if (sortX > sortY)
-                    {
-                        return -1;
-                    }
-                    else if (sortY > sortX)
-                    {
-                        return 1;
-                    }
-                    else
-                    {
-                        if (x.LanguageCode == "eng")
-                        {
-                            return -1;
-                        }
-                        else if (y.LanguageCode == "eng")
-                        {
-                            return 1;
-                        }
-                        else if (x.LanguageCode != y.LanguageCode)
-                        {
-                            return string.Compare(
-                                x.LanguageName, y.LanguageName);
-                        }
-                        else if (x.PID < y.PID)
-                        {
-                            return -1;
-                        }
-                        else if (y.PID < x.PID)
-                        {
-                            return 1;
-                        }
-                        return 0;
-                    }
-                }
-            }
-        }
-
-        public int CompareTextStreams(
-            TSTextStream x,
-            TSTextStream y)
-        {
-            if (x == y)
-            {
-                return 0;
-            }
-            else if (x == null && y == null)
-            {
-                return 0;
-            }
-            else if (x == null && y != null)
-            {
-                return -1;
-            }
-            else if (x != null && y == null)
-            {
-                return 1;
-            }
-            else
-            {
-                if (x.LanguageCode == "eng")
-                {
-                    return -1;
-                }
-                else if (y.LanguageCode == "eng")
-                {
-                    return 1;
-                }
-                else
-                {
-                    if (x.LanguageCode == y.LanguageCode)
-                    {
-                        if (x.PID > y.PID)
-                        {
-                            return 1;
-                        }
-                        else if (y.PID > x.PID)
-                        {
-                            return -1;
-                        }
-                        else
-                        {
-                            return 0;
-                        }
-                    }
-                    else
-                    {
-                        return string.Compare(
-                            x.LanguageName, y.LanguageName);
-                    }
-                }
-            }
-        }
-
-        private int CompareGraphicsStreams(
-            TSGraphicsStream x,
-            TSGraphicsStream y)
-        {
-            if (x == y)
-            {
-                return 0;
-            }
-            else if (x == null && y == null)
-            {
-                return 0;
-            }
-            else if (x == null && y != null)
-            {
-                return -1;
-            }
-            else if (x != null && y == null)
-            {
-                return 1;
-            }
-            else
-            {
-                int sortX = GetStreamTypeSortIndex(x.StreamType);
-                int sortY = GetStreamTypeSortIndex(y.StreamType);
-
-                if (sortX > sortY)
-                {
-                    return -1;
-                }
-                else if (sortY > sortX)
-                {
-                    return 1;
-                }
-                else if (x.LanguageCode == "eng")
-                {
-                    return -1;
-                }
-                else if (y.LanguageCode == "eng")
-                {
-                    return 1;
-                }
-                else
-                {
-                    if (x.LanguageCode == y.LanguageCode)
-                    {
-                        if (x.PID > y.PID)
-                        {
-                            return 1;
-                        }
-                        else if (y.PID > x.PID)
-                        {
-                            return -1;
-                        }
-                        else
-                        {
-                            return 0;
-                        }
-                    }
-                    else
-                    {
-                        return string.Compare(x.LanguageName, y.LanguageName);
-                    }
-                }
-            }
-        }
-
-        private int GetStreamTypeSortIndex(TSStreamType streamType)
-        {
-            switch (streamType)
-            {
-                case TSStreamType.Unknown:
-                    return 0;
-                case TSStreamType.MPEG1_VIDEO:
-                    return 1;
-                case TSStreamType.MPEG2_VIDEO:
-                    return 2;
-                case TSStreamType.AVC_VIDEO:
-                    return 3;
-                case TSStreamType.VC1_VIDEO:
-                    return 4;
-                case TSStreamType.MVC_VIDEO:
-                    return 5;
-
-                case TSStreamType.MPEG1_AUDIO:
-                    return 1;
-                case TSStreamType.MPEG2_AUDIO:
-                    return 2;
-                case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                    return 3;
-                case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                    return 4;
-                case TSStreamType.AC3_AUDIO:
-                    return 5;
-                case TSStreamType.DTS_AUDIO:
-                    return 6;
-                case TSStreamType.AC3_PLUS_AUDIO:
-                    return 7;
-                case TSStreamType.DTS_HD_AUDIO:
-                    return 8;
-                case TSStreamType.AC3_TRUE_HD_AUDIO:
-                    return 9;
-                case TSStreamType.DTS_HD_MASTER_AUDIO:
-                    return 10;
-                case TSStreamType.LPCM_AUDIO:
-                    return 11;
-
-                case TSStreamType.SUBTITLE:
-                    return 1;
-                case TSStreamType.INTERACTIVE_GRAPHICS:
-                    return 2;
-                case TSStreamType.PRESENTATION_GRAPHICS:
-                    return 3;
-
-                default:
-                    return 0;
-            }
-        }
-
-        protected string ReadString(
-            byte[] data,
-            int count,
-            ref int pos)
-        {
-            string val = Encoding.ASCII.GetString(data, pos, count);
-
-            pos += count;
-
-            return val;
-        }
-
-        protected int ReadInt32(
-            byte[] data,
-            ref int pos)
-        {
-            int val =
-                ((int)data[pos] << 24) +
-                ((int)data[pos + 1] << 16) +
-                ((int)data[pos + 2] << 8) +
-                ((int)data[pos + 3]);
-
-            pos += 4;
-
-            return val;
-        }
-
-        protected int ReadInt16(
-            byte[] data,
-            ref int pos)
-        {
-            int val =
-                ((int)data[pos] << 8) +
-                ((int)data[pos + 1]);
-
-            pos += 2;
-
-            return val;
-        }
-
-        protected byte ReadByte(
-            byte[] data,
-            ref int pos)
-        {
-            return data[pos++];
-        }
-    }
-}

+ 0 - 780
BDInfo/TSStream.cs

@@ -1,780 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-using System;
-using System.Collections.Generic;
-
-namespace BDInfo
-{
-    public enum TSStreamType : byte
-    {
-        Unknown = 0,
-        MPEG1_VIDEO = 0x01,
-        MPEG2_VIDEO = 0x02,
-        AVC_VIDEO = 0x1b,
-        MVC_VIDEO = 0x20,
-        VC1_VIDEO = 0xea,
-        MPEG1_AUDIO = 0x03,
-        MPEG2_AUDIO = 0x04,
-        LPCM_AUDIO = 0x80,
-        AC3_AUDIO = 0x81,
-        AC3_PLUS_AUDIO = 0x84,
-        AC3_PLUS_SECONDARY_AUDIO = 0xA1,
-        AC3_TRUE_HD_AUDIO = 0x83,
-        DTS_AUDIO = 0x82,
-        DTS_HD_AUDIO = 0x85,
-        DTS_HD_SECONDARY_AUDIO = 0xA2,
-        DTS_HD_MASTER_AUDIO = 0x86,
-        PRESENTATION_GRAPHICS = 0x90,
-        INTERACTIVE_GRAPHICS = 0x91,
-        SUBTITLE = 0x92
-    }
-
-    public enum TSVideoFormat : byte
-    {
-        Unknown = 0,
-        VIDEOFORMAT_480i = 1,
-        VIDEOFORMAT_576i = 2,
-        VIDEOFORMAT_480p = 3,
-        VIDEOFORMAT_1080i = 4,
-        VIDEOFORMAT_720p = 5,
-        VIDEOFORMAT_1080p = 6,
-        VIDEOFORMAT_576p = 7,
-    }
-
-    public enum TSFrameRate : byte
-    {
-        Unknown = 0,
-        FRAMERATE_23_976 = 1,
-        FRAMERATE_24 = 2,
-        FRAMERATE_25 = 3,
-        FRAMERATE_29_97 = 4,
-        FRAMERATE_50 = 6,
-        FRAMERATE_59_94 = 7
-    }
-
-    public enum TSChannelLayout : byte
-    {
-        Unknown = 0,
-        CHANNELLAYOUT_MONO = 1,
-        CHANNELLAYOUT_STEREO = 3,
-        CHANNELLAYOUT_MULTI = 6,
-        CHANNELLAYOUT_COMBO = 12
-    }
-
-    public enum TSSampleRate : byte
-    {
-        Unknown = 0,
-        SAMPLERATE_48 = 1,
-        SAMPLERATE_96 = 4,
-        SAMPLERATE_192 = 5,
-        SAMPLERATE_48_192 = 12,
-        SAMPLERATE_48_96 = 14
-    }
-
-    public enum TSAspectRatio
-    {
-        Unknown = 0,
-        ASPECT_4_3 = 2,
-        ASPECT_16_9 = 3,
-        ASPECT_2_21 = 4
-    }
-
-    public class TSDescriptor
-    {
-        public byte Name;
-        public byte[] Value;
-
-        public TSDescriptor(byte name, byte length)
-        {
-            Name = name;
-            Value = new byte[length];
-        }
-
-        public TSDescriptor Clone()
-        {
-            var descriptor =
-                new TSDescriptor(Name, (byte)Value.Length);
-            Value.CopyTo(descriptor.Value, 0);
-            return descriptor;
-        }
-    }
-
-    public abstract class TSStream
-    {
-        public TSStream()
-        {
-        }
-
-        public override string ToString()
-        {
-            return string.Format("{0} ({1})", CodecShortName, PID);
-        }
-
-        public ushort PID;
-        public TSStreamType StreamType;
-        public List<TSDescriptor> Descriptors = null;
-        public long BitRate = 0;
-        public long ActiveBitRate = 0;
-        public bool IsVBR = false;
-        public bool IsInitialized = false;
-        public string LanguageName;
-        public bool IsHidden = false;
-
-        public ulong PayloadBytes = 0;
-        public ulong PacketCount = 0;
-        public double PacketSeconds = 0;
-        public int AngleIndex = 0;
-
-        public ulong PacketSize => PacketCount * 192;
-
-        private string _LanguageCode;
-        public string LanguageCode
-        {
-            get => _LanguageCode;
-            set
-            {
-                _LanguageCode = value;
-                LanguageName = LanguageCodes.GetName(value);
-            }
-        }
-
-        public bool IsVideoStream
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.MPEG1_VIDEO:
-                    case TSStreamType.MPEG2_VIDEO:
-                    case TSStreamType.AVC_VIDEO:
-                    case TSStreamType.MVC_VIDEO:
-                    case TSStreamType.VC1_VIDEO:
-                        return true;
-
-                    default:
-                        return false;
-                }
-            }
-        }
-
-        public bool IsAudioStream
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.MPEG1_AUDIO:
-                    case TSStreamType.MPEG2_AUDIO:
-                    case TSStreamType.LPCM_AUDIO:
-                    case TSStreamType.AC3_AUDIO:
-                    case TSStreamType.AC3_PLUS_AUDIO:
-                    case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                    case TSStreamType.AC3_TRUE_HD_AUDIO:
-                    case TSStreamType.DTS_AUDIO:
-                    case TSStreamType.DTS_HD_AUDIO:
-                    case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                    case TSStreamType.DTS_HD_MASTER_AUDIO:
-                        return true;
-
-                    default:
-                        return false;
-                }
-            }
-        }
-
-        public bool IsGraphicsStream
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.PRESENTATION_GRAPHICS:
-                    case TSStreamType.INTERACTIVE_GRAPHICS:
-                        return true;
-
-                    default:
-                        return false;
-                }
-            }
-        }
-
-        public bool IsTextStream
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.SUBTITLE:
-                        return true;
-
-                    default:
-                        return false;
-                }
-            }
-        }
-
-        public string CodecName
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.MPEG1_VIDEO:
-                        return "MPEG-1 Video";
-                    case TSStreamType.MPEG2_VIDEO:
-                        return "MPEG-2 Video";
-                    case TSStreamType.AVC_VIDEO:
-                        return "MPEG-4 AVC Video";
-                    case TSStreamType.MVC_VIDEO:
-                        return "MPEG-4 MVC Video";
-                    case TSStreamType.VC1_VIDEO:
-                        return "VC-1 Video";
-                    case TSStreamType.MPEG1_AUDIO:
-                        return "MP1 Audio";
-                    case TSStreamType.MPEG2_AUDIO:
-                        return "MP2 Audio";
-                    case TSStreamType.LPCM_AUDIO:
-                        return "LPCM Audio";
-                    case TSStreamType.AC3_AUDIO:
-                        if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
-                            return "Dolby Digital EX Audio";
-                        else
-                            return "Dolby Digital Audio";
-                    case TSStreamType.AC3_PLUS_AUDIO:
-                    case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                        return "Dolby Digital Plus Audio";
-                    case TSStreamType.AC3_TRUE_HD_AUDIO:
-                        return "Dolby TrueHD Audio";
-                    case TSStreamType.DTS_AUDIO:
-                        if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
-                            return "DTS-ES Audio";
-                        else
-                            return "DTS Audio";
-                    case TSStreamType.DTS_HD_AUDIO:
-                        return "DTS-HD High-Res Audio";
-                    case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                        return "DTS Express";
-                    case TSStreamType.DTS_HD_MASTER_AUDIO:
-                        return "DTS-HD Master Audio";
-                    case TSStreamType.PRESENTATION_GRAPHICS:
-                        return "Presentation Graphics";
-                    case TSStreamType.INTERACTIVE_GRAPHICS:
-                        return "Interactive Graphics";
-                    case TSStreamType.SUBTITLE:
-                        return "Subtitle";
-                    default:
-                        return "UNKNOWN";
-                }
-            }
-        }
-
-        public string CodecAltName
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.MPEG1_VIDEO:
-                        return "MPEG-1";
-                    case TSStreamType.MPEG2_VIDEO:
-                        return "MPEG-2";
-                    case TSStreamType.AVC_VIDEO:
-                        return "AVC";
-                    case TSStreamType.MVC_VIDEO:
-                        return "MVC";
-                    case TSStreamType.VC1_VIDEO:
-                        return "VC-1";
-                    case TSStreamType.MPEG1_AUDIO:
-                        return "MP1";
-                    case TSStreamType.MPEG2_AUDIO:
-                        return "MP2";
-                    case TSStreamType.LPCM_AUDIO:
-                        return "LPCM";
-                    case TSStreamType.AC3_AUDIO:
-                        return "DD AC3";
-                    case TSStreamType.AC3_PLUS_AUDIO:
-                    case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                        return "DD AC3+";
-                    case TSStreamType.AC3_TRUE_HD_AUDIO:
-                        return "Dolby TrueHD";
-                    case TSStreamType.DTS_AUDIO:
-                        return "DTS";
-                    case TSStreamType.DTS_HD_AUDIO:
-                        return "DTS-HD Hi-Res";
-                    case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                        return "DTS Express";
-                    case TSStreamType.DTS_HD_MASTER_AUDIO:
-                        return "DTS-HD Master";
-                    case TSStreamType.PRESENTATION_GRAPHICS:
-                        return "PGS";
-                    case TSStreamType.INTERACTIVE_GRAPHICS:
-                        return "IGS";
-                    case TSStreamType.SUBTITLE:
-                        return "SUB";
-                    default:
-                        return "UNKNOWN";
-                }
-            }
-        }
-
-        public string CodecShortName
-        {
-            get
-            {
-                switch (StreamType)
-                {
-                    case TSStreamType.MPEG1_VIDEO:
-                        return "MPEG-1";
-                    case TSStreamType.MPEG2_VIDEO:
-                        return "MPEG-2";
-                    case TSStreamType.AVC_VIDEO:
-                        return "AVC";
-                    case TSStreamType.MVC_VIDEO:
-                        return "MVC";
-                    case TSStreamType.VC1_VIDEO:
-                        return "VC-1";
-                    case TSStreamType.MPEG1_AUDIO:
-                        return "MP1";
-                    case TSStreamType.MPEG2_AUDIO:
-                        return "MP2";
-                    case TSStreamType.LPCM_AUDIO:
-                        return "LPCM";
-                    case TSStreamType.AC3_AUDIO:
-                        if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
-                            return "AC3-EX";
-                        else
-                            return "AC3";
-                    case TSStreamType.AC3_PLUS_AUDIO:
-                    case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                        return "AC3+";
-                    case TSStreamType.AC3_TRUE_HD_AUDIO:
-                        return "TrueHD";
-                    case TSStreamType.DTS_AUDIO:
-                        if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
-                            return "DTS-ES";
-                        else
-                            return "DTS";
-                    case TSStreamType.DTS_HD_AUDIO:
-                        return "DTS-HD HR";
-                    case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                        return "DTS Express";
-                    case TSStreamType.DTS_HD_MASTER_AUDIO:
-                        return "DTS-HD MA";
-                    case TSStreamType.PRESENTATION_GRAPHICS:
-                        return "PGS";
-                    case TSStreamType.INTERACTIVE_GRAPHICS:
-                        return "IGS";
-                    case TSStreamType.SUBTITLE:
-                        return "SUB";
-                    default:
-                        return "UNKNOWN";
-                }
-            }
-        }
-
-        public virtual string Description => "";
-
-        public abstract TSStream Clone();
-
-        protected void CopyTo(TSStream stream)
-        {
-            stream.PID = PID;
-            stream.StreamType = StreamType;
-            stream.IsVBR = IsVBR;
-            stream.BitRate = BitRate;
-            stream.IsInitialized = IsInitialized;
-            stream.LanguageCode = _LanguageCode;
-            if (Descriptors != null)
-            {
-                stream.Descriptors = new List<TSDescriptor>();
-                foreach (var descriptor in Descriptors)
-                {
-                    stream.Descriptors.Add(descriptor.Clone());
-                }
-            }
-        }
-    }
-
-    public class TSVideoStream : TSStream
-    {
-        public TSVideoStream()
-        {
-        }
-
-        public int Width;
-        public int Height;
-        public bool IsInterlaced;
-        public int FrameRateEnumerator;
-        public int FrameRateDenominator;
-        public TSAspectRatio AspectRatio;
-        public string EncodingProfile;
-
-        private TSVideoFormat _VideoFormat;
-        public TSVideoFormat VideoFormat
-        {
-            get => _VideoFormat;
-            set
-            {
-                _VideoFormat = value;
-                switch (value)
-                {
-                    case TSVideoFormat.VIDEOFORMAT_480i:
-                        Height = 480;
-                        IsInterlaced = true;
-                        break;
-                    case TSVideoFormat.VIDEOFORMAT_480p:
-                        Height = 480;
-                        IsInterlaced = false;
-                        break;
-                    case TSVideoFormat.VIDEOFORMAT_576i:
-                        Height = 576;
-                        IsInterlaced = true;
-                        break;
-                    case TSVideoFormat.VIDEOFORMAT_576p:
-                        Height = 576;
-                        IsInterlaced = false;
-                        break;
-                    case TSVideoFormat.VIDEOFORMAT_720p:
-                        Height = 720;
-                        IsInterlaced = false;
-                        break;
-                    case TSVideoFormat.VIDEOFORMAT_1080i:
-                        Height = 1080;
-                        IsInterlaced = true;
-                        break;
-                    case TSVideoFormat.VIDEOFORMAT_1080p:
-                        Height = 1080;
-                        IsInterlaced = false;
-                        break;
-                }
-            }
-        }
-
-        private TSFrameRate _FrameRate;
-        public TSFrameRate FrameRate
-        {
-            get => _FrameRate;
-            set
-            {
-                _FrameRate = value;
-                switch (value)
-                {
-                    case TSFrameRate.FRAMERATE_23_976:
-                        FrameRateEnumerator = 24000;
-                        FrameRateDenominator = 1001;
-                        break;
-                    case TSFrameRate.FRAMERATE_24:
-                        FrameRateEnumerator = 24000;
-                        FrameRateDenominator = 1000;
-                        break;
-                    case TSFrameRate.FRAMERATE_25:
-                        FrameRateEnumerator = 25000;
-                        FrameRateDenominator = 1000;
-                        break;
-                    case TSFrameRate.FRAMERATE_29_97:
-                        FrameRateEnumerator = 30000;
-                        FrameRateDenominator = 1001;
-                        break;
-                    case TSFrameRate.FRAMERATE_50:
-                        FrameRateEnumerator = 50000;
-                        FrameRateDenominator = 1000;
-                        break;
-                    case TSFrameRate.FRAMERATE_59_94:
-                        FrameRateEnumerator = 60000;
-                        FrameRateDenominator = 1001;
-                        break;
-                }
-            }
-        }
-
-        public override string Description
-        {
-            get
-            {
-                string description = "";
-
-                if (Height > 0)
-                {
-                    description += string.Format("{0:D}{1} / ",
-                        Height,
-                        IsInterlaced ? "i" : "p");
-                }
-                if (FrameRateEnumerator > 0 &&
-                    FrameRateDenominator > 0)
-                {
-                    if (FrameRateEnumerator % FrameRateDenominator == 0)
-                    {
-                        description += string.Format("{0:D} fps / ",
-                            FrameRateEnumerator / FrameRateDenominator);
-                    }
-                    else
-                    {
-                        description += string.Format("{0:F3} fps / ",
-                            (double)FrameRateEnumerator / FrameRateDenominator);
-                    }
-
-                }
-                if (AspectRatio == TSAspectRatio.ASPECT_4_3)
-                {
-                    description += "4:3 / ";
-                }
-                else if (AspectRatio == TSAspectRatio.ASPECT_16_9)
-                {
-                    description += "16:9 / ";
-                }
-                if (EncodingProfile != null)
-                {
-                    description += EncodingProfile + " / ";
-                }
-                if (description.EndsWith(" / "))
-                {
-                    description = description.Substring(0, description.Length - 3);
-                }
-                return description;
-            }
-        }
-
-        public override TSStream Clone()
-        {
-            var stream = new TSVideoStream();
-            CopyTo(stream);
-
-            stream.VideoFormat = _VideoFormat;
-            stream.FrameRate = _FrameRate;
-            stream.Width = Width;
-            stream.Height = Height;
-            stream.IsInterlaced = IsInterlaced;
-            stream.FrameRateEnumerator = FrameRateEnumerator;
-            stream.FrameRateDenominator = FrameRateDenominator;
-            stream.AspectRatio = AspectRatio;
-            stream.EncodingProfile = EncodingProfile;
-
-            return stream;
-        }
-    }
-
-    public enum TSAudioMode
-    {
-        Unknown,
-        DualMono,
-        Stereo,
-        Surround,
-        Extended
-    }
-
-    public class TSAudioStream : TSStream
-    {
-        public TSAudioStream()
-        {
-        }
-
-        public int SampleRate;
-        public int ChannelCount;
-        public int BitDepth;
-        public int LFE;
-        public int DialNorm;
-        public TSAudioMode AudioMode;
-        public TSAudioStream CoreStream;
-        public TSChannelLayout ChannelLayout;
-
-        public static int ConvertSampleRate(
-            TSSampleRate sampleRate)
-        {
-            switch (sampleRate)
-            {
-                case TSSampleRate.SAMPLERATE_48:
-                    return 48000;
-
-                case TSSampleRate.SAMPLERATE_96:
-                case TSSampleRate.SAMPLERATE_48_96:
-                    return 96000;
-
-                case TSSampleRate.SAMPLERATE_192:
-                case TSSampleRate.SAMPLERATE_48_192:
-                    return 192000;
-            }
-            return 0;
-        }
-
-        public string ChannelDescription
-        {
-            get
-            {
-                if (ChannelLayout == TSChannelLayout.CHANNELLAYOUT_MONO &&
-                    ChannelCount == 2)
-                {
-                }
-
-                string description = "";
-                if (ChannelCount > 0)
-                {
-                    description += string.Format(
-                        "{0:D}.{1:D}",
-                        ChannelCount, LFE);
-                }
-                else
-                {
-                    switch (ChannelLayout)
-                    {
-                        case TSChannelLayout.CHANNELLAYOUT_MONO:
-                            description += "1.0";
-                            break;
-                        case TSChannelLayout.CHANNELLAYOUT_STEREO:
-                            description += "2.0";
-                            break;
-                        case TSChannelLayout.CHANNELLAYOUT_MULTI:
-                            description += "5.1";
-                            break;
-                    }
-                }
-                if (AudioMode == TSAudioMode.Extended)
-                {
-                    if (StreamType == TSStreamType.AC3_AUDIO)
-                    {
-                        description += "-EX";
-                    }
-                    if (StreamType == TSStreamType.DTS_AUDIO ||
-                        StreamType == TSStreamType.DTS_HD_AUDIO ||
-                        StreamType == TSStreamType.DTS_HD_MASTER_AUDIO)
-                    {
-                        description += "-ES";
-                    }
-                }
-                return description;
-            }
-        }
-
-        public override string Description
-        {
-            get
-            {
-                string description = ChannelDescription;
-
-                if (SampleRate > 0)
-                {
-                    description += string.Format(
-                        " / {0:D} kHz", SampleRate / 1000);
-                }
-                if (BitRate > 0)
-                {
-                    description += string.Format(
-                        " / {0:D} kbps", (uint)Math.Round((double)BitRate / 1000));
-                }
-                if (BitDepth > 0)
-                {
-                    description += string.Format(
-                        " / {0:D}-bit", BitDepth);
-                }
-                if (DialNorm != 0)
-                {
-                    description += string.Format(
-                        " / DN {0}dB", DialNorm);
-                }
-                if (ChannelCount == 2)
-                {
-                    switch (AudioMode)
-                    {
-                        case TSAudioMode.DualMono:
-                            description += " / Dual Mono";
-                            break;
-
-                        case TSAudioMode.Surround:
-                            description += " / Dolby Surround";
-                            break;
-                    }
-                }
-                if (description.EndsWith(" / "))
-                {
-                    description = description.Substring(0, description.Length - 3);
-                }
-                if (CoreStream != null)
-                {
-                    string codec = "";
-                    switch (CoreStream.StreamType)
-                    {
-                        case TSStreamType.AC3_AUDIO:
-                            codec = "AC3 Embedded";
-                            break;
-                        case TSStreamType.DTS_AUDIO:
-                            codec = "DTS Core";
-                            break;
-                    }
-                    description += string.Format(
-                        " ({0}: {1})",
-                        codec,
-                        CoreStream.Description);
-                }
-                return description;
-            }
-        }
-
-        public override TSStream Clone()
-        {
-            var stream = new TSAudioStream();
-            CopyTo(stream);
-
-            stream.SampleRate = SampleRate;
-            stream.ChannelLayout = ChannelLayout;
-            stream.ChannelCount = ChannelCount;
-            stream.BitDepth = BitDepth;
-            stream.LFE = LFE;
-            stream.DialNorm = DialNorm;
-            stream.AudioMode = AudioMode;
-            if (CoreStream != null)
-            {
-                stream.CoreStream = (TSAudioStream)CoreStream.Clone();
-            }
-
-            return stream;
-        }
-    }
-
-    public class TSGraphicsStream : TSStream
-    {
-        public TSGraphicsStream()
-        {
-            IsVBR = true;
-            IsInitialized = true;
-        }
-
-        public override TSStream Clone()
-        {
-            var stream = new TSGraphicsStream();
-            CopyTo(stream);
-            return stream;
-        }
-    }
-
-    public class TSTextStream : TSStream
-    {
-        public TSTextStream()
-        {
-            IsVBR = true;
-            IsInitialized = true;
-        }
-
-        public override TSStream Clone()
-        {
-            var stream = new TSTextStream();
-            CopyTo(stream);
-            return stream;
-        }
-    }
-}

+ 0 - 130
BDInfo/TSStreamBuffer.cs

@@ -1,130 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-using System;
-using System.Collections.Specialized;
-using System.IO;
-
-namespace BDInfo
-{
-    public class TSStreamBuffer
-    {
-        private MemoryStream Stream = new MemoryStream();
-        private int SkipBits = 0;
-        private byte[] Buffer;
-        private int BufferLength = 0;
-        public int TransferLength = 0;
-
-        public TSStreamBuffer()
-        {
-            Buffer = new byte[4096];
-            Stream = new MemoryStream(Buffer);
-        }
-
-        public long Length => (long)BufferLength;
-
-        public long Position => Stream.Position;
-
-        public void Add(
-            byte[] buffer,
-            int offset,
-            int length)
-        {
-            TransferLength += length;
-
-            if (BufferLength + length >= Buffer.Length)
-            {
-                length = Buffer.Length - BufferLength;
-            }
-            if (length > 0)
-            {
-                Array.Copy(buffer, offset, Buffer, BufferLength, length);
-                BufferLength += length;
-            }
-        }
-
-        public void Seek(
-            long offset,
-            SeekOrigin loc)
-        {
-            Stream.Seek(offset, loc);
-        }
-
-        public void Reset()
-        {
-            BufferLength = 0;
-            TransferLength = 0;
-        }
-
-        public void BeginRead()
-        {
-            SkipBits = 0;
-            Stream.Seek(0, SeekOrigin.Begin);
-        }
-
-        public void EndRead()
-        {
-        }
-
-        public byte[] ReadBytes(int bytes)
-        {
-            if (Stream.Position + bytes >= BufferLength)
-            {
-                return null;
-            }
-
-            byte[] value = new byte[bytes];
-            Stream.Read(value, 0, bytes);
-            return value;
-        }
-
-        public byte ReadByte()
-        {
-            return (byte)Stream.ReadByte();
-        }
-
-        public int ReadBits(int bits)
-        {
-            long pos = Stream.Position;
-
-            int shift = 24;
-            int data = 0;
-            for (int i = 0; i < 4; i++)
-            {
-                if (pos + i >= BufferLength) break;
-                data += (Stream.ReadByte() << shift);
-                shift -= 8;
-            }
-            var vector = new BitVector32(data);
-
-            int value = 0;
-            for (int i = SkipBits; i < SkipBits + bits; i++)
-            {
-                value <<= 1;
-                value += (vector[1 << (32 - i - 1)] ? 1 : 0);
-            }
-
-            SkipBits += bits;
-            Stream.Seek(pos + (SkipBits >> 3), SeekOrigin.Begin);
-            SkipBits = SkipBits % 8;
-
-            return value;
-        }
-    }
-}

+ 0 - 107
BDInfo/TSStreamClip.cs

@@ -1,107 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-using System;
-using System.Collections.Generic;
-
-namespace BDInfo
-{
-    public class TSStreamClip
-    {
-        public int AngleIndex = 0;
-        public string Name;
-        public double TimeIn;
-        public double TimeOut;
-        public double RelativeTimeIn;
-        public double RelativeTimeOut;
-        public double Length;
-
-        public ulong FileSize = 0;
-        public ulong InterleavedFileSize = 0;
-        public ulong PayloadBytes = 0;
-        public ulong PacketCount = 0;
-        public double PacketSeconds = 0;
-
-        public List<double> Chapters = new List<double>();
-
-        public TSStreamFile StreamFile = null;
-        public TSStreamClipFile StreamClipFile = null;
-
-        public TSStreamClip(
-            TSStreamFile streamFile,
-            TSStreamClipFile streamClipFile)
-        {
-            if (streamFile != null)
-            {
-                Name = streamFile.Name;
-                StreamFile = streamFile;
-                FileSize = (ulong)StreamFile.FileInfo.Length;
-                if (StreamFile.InterleavedFile != null)
-                {
-                    InterleavedFileSize = (ulong)StreamFile.InterleavedFile.FileInfo.Length;
-                }
-            }
-            StreamClipFile = streamClipFile;
-        }
-
-        public string DisplayName
-        {
-            get
-            {
-                if (StreamFile != null &&
-                    StreamFile.InterleavedFile != null &&
-                    BDInfoSettings.EnableSSIF)
-                {
-                    return StreamFile.InterleavedFile.Name;
-                }
-                return Name;
-            }
-        }
-
-        public ulong PacketSize => PacketCount * 192;
-
-        public ulong PacketBitRate
-        {
-            get
-            {
-                if (PacketSeconds > 0)
-                {
-                    return (ulong)Math.Round(((PacketSize * 8.0) / PacketSeconds));
-                }
-                return 0;
-            }
-        }
-
-        public bool IsCompatible(TSStreamClip clip)
-        {
-            foreach (var stream1 in StreamFile.Streams.Values)
-            {
-                if (clip.StreamFile.Streams.ContainsKey(stream1.PID))
-                {
-                    var stream2 = clip.StreamFile.Streams[stream1.PID];
-                    if (stream1.StreamType != stream2.StreamType)
-                    {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
-    }
-}

+ 0 - 244
BDInfo/TSStreamClipFile.cs

@@ -1,244 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-#undef DEBUG
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using MediaBrowser.Model.IO;
-
-namespace BDInfo
-{
-    public class TSStreamClipFile
-    {
-        public FileSystemMetadata FileInfo = null;
-        public string FileType = null;
-        public bool IsValid = false;
-        public string Name = null;
-
-        public Dictionary<ushort, TSStream> Streams =
-            new Dictionary<ushort, TSStream>();
-
-        public TSStreamClipFile(FileSystemMetadata fileInfo)
-        {
-            FileInfo = fileInfo;
-            Name = fileInfo.Name.ToUpper();
-        }
-
-        public void Scan()
-        {
-            Stream fileStream = null;
-            BinaryReader fileReader = null;
-
-            try
-            {
-#if DEBUG
-                Debug.WriteLine(string.Format(
-                    "Scanning {0}...", Name));
-#endif
-                Streams.Clear();
-
-                fileStream = File.OpenRead(FileInfo.FullName);
-                fileReader = new BinaryReader(fileStream);
-
-                byte[] data = new byte[fileStream.Length];
-                fileReader.Read(data, 0, data.Length);
-
-                byte[] fileType = new byte[8];
-                Array.Copy(data, 0, fileType, 0, fileType.Length);
-
-                FileType = Encoding.ASCII.GetString(fileType, 0, fileType.Length);
-                if (FileType != "HDMV0100" &&
-                    FileType != "HDMV0200")
-                {
-                    throw new Exception(string.Format(
-                        "Clip info file {0} has an unknown file type {1}.",
-                        FileInfo.Name, FileType));
-                }
-#if DEBUG
-                Debug.WriteLine(string.Format(
-                    "\tFileType: {0}", FileType));
-#endif
-                int clipIndex =
-                    ((int)data[12] << 24) +
-                    ((int)data[13] << 16) +
-                    ((int)data[14] << 8) +
-                    ((int)data[15]);
-
-                int clipLength =
-                    ((int)data[clipIndex] << 24) +
-                    ((int)data[clipIndex + 1] << 16) +
-                    ((int)data[clipIndex + 2] << 8) +
-                    ((int)data[clipIndex + 3]);
-
-                byte[] clipData = new byte[clipLength];
-                Array.Copy(data, clipIndex + 4, clipData, 0, clipData.Length);
-
-                int streamCount = clipData[8];
-#if DEBUG
-                Debug.WriteLine(string.Format(
-                    "\tStreamCount: {0}", streamCount));
-#endif
-                int streamOffset = 10;
-                for (int streamIndex = 0;
-                    streamIndex < streamCount;
-                    streamIndex++)
-                {
-                    TSStream stream = null;
-
-                    ushort PID = (ushort)
-                        ((clipData[streamOffset] << 8) +
-                          clipData[streamOffset + 1]);
-
-                    streamOffset += 2;
-
-                    var streamType = (TSStreamType)
-                        clipData[streamOffset + 1];
-                    switch (streamType)
-                    {
-                        case TSStreamType.MVC_VIDEO:
-                            // TODO
-                            break;
-
-                        case TSStreamType.AVC_VIDEO:
-                        case TSStreamType.MPEG1_VIDEO:
-                        case TSStreamType.MPEG2_VIDEO:
-                        case TSStreamType.VC1_VIDEO:
-                            {
-                                var videoFormat = (TSVideoFormat)
-                                    (clipData[streamOffset + 2] >> 4);
-                                var frameRate = (TSFrameRate)
-                                    (clipData[streamOffset + 2] & 0xF);
-                                var aspectRatio = (TSAspectRatio)
-                                    (clipData[streamOffset + 3] >> 4);
-
-                                stream = new TSVideoStream();
-                                ((TSVideoStream)stream).VideoFormat = videoFormat;
-                                ((TSVideoStream)stream).AspectRatio = aspectRatio;
-                                ((TSVideoStream)stream).FrameRate = frameRate;
-#if DEBUG
-                            Debug.WriteLine(string.Format(
-                                "\t{0} {1} {2} {3} {4}",
-                                PID,
-                                streamType,
-                                videoFormat,
-                                frameRate,
-                                aspectRatio));
-#endif
-                            }
-                            break;
-
-                        case TSStreamType.AC3_AUDIO:
-                        case TSStreamType.AC3_PLUS_AUDIO:
-                        case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                        case TSStreamType.AC3_TRUE_HD_AUDIO:
-                        case TSStreamType.DTS_AUDIO:
-                        case TSStreamType.DTS_HD_AUDIO:
-                        case TSStreamType.DTS_HD_MASTER_AUDIO:
-                        case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                        case TSStreamType.LPCM_AUDIO:
-                        case TSStreamType.MPEG1_AUDIO:
-                        case TSStreamType.MPEG2_AUDIO:
-                            {
-                                byte[] languageBytes = new byte[3];
-                                Array.Copy(clipData, streamOffset + 3,
-                                    languageBytes, 0, languageBytes.Length);
-                                string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length);
-
-                                var channelLayout = (TSChannelLayout)
-                                    (clipData[streamOffset + 2] >> 4);
-                                var sampleRate = (TSSampleRate)
-                                    (clipData[streamOffset + 2] & 0xF);
-
-                                stream = new TSAudioStream();
-                                ((TSAudioStream)stream).LanguageCode = languageCode;
-                                ((TSAudioStream)stream).ChannelLayout = channelLayout;
-                                ((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate);
-                                ((TSAudioStream)stream).LanguageCode = languageCode;
-#if DEBUG
-                            Debug.WriteLine(string.Format(
-                                "\t{0} {1} {2} {3} {4}",
-                                PID,
-                                streamType,
-                                languageCode,
-                                channelLayout,
-                                sampleRate));
-#endif
-                            }
-                            break;
-
-                        case TSStreamType.INTERACTIVE_GRAPHICS:
-                        case TSStreamType.PRESENTATION_GRAPHICS:
-                            {
-                                byte[] languageBytes = new byte[3];
-                                Array.Copy(clipData, streamOffset + 2,
-                                    languageBytes, 0, languageBytes.Length);
-                                string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length);
-
-                                stream = new TSGraphicsStream();
-                                stream.LanguageCode = languageCode;
-#if DEBUG
-                            Debug.WriteLine(string.Format(
-                                "\t{0} {1} {2}",
-                                PID,
-                                streamType,
-                                languageCode));
-#endif
-                            }
-                            break;
-
-                        case TSStreamType.SUBTITLE:
-                            {
-                                byte[] languageBytes = new byte[3];
-                                Array.Copy(clipData, streamOffset + 3,
-                                    languageBytes, 0, languageBytes.Length);
-                                string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length);
-#if DEBUG
-                            Debug.WriteLine(string.Format(
-                                "\t{0} {1} {2}",
-                                PID,
-                                streamType,
-                                languageCode));
-#endif
-                                stream = new TSTextStream();
-                                stream.LanguageCode = languageCode;
-                            }
-                            break;
-                    }
-
-                    if (stream != null)
-                    {
-                        stream.PID = PID;
-                        stream.StreamType = streamType;
-                        Streams.Add(PID, stream);
-                    }
-
-                    streamOffset += clipData[streamOffset] + 1;
-                }
-                IsValid = true;
-            }
-            finally
-            {
-                if (fileReader != null) fileReader.Dispose();
-                if (fileStream != null) fileStream.Dispose();
-            }
-        }
-    }
-}

+ 0 - 1555
BDInfo/TSStreamFile.cs

@@ -1,1555 +0,0 @@
-//============================================================================
-// BDInfo - Blu-ray Video and Audio Analysis Tool
-// Copyright © 2010 Cinema Squid
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//=============================================================================
-
-#undef DEBUG
-using System;
-using System.Collections.Generic;
-using System.IO;
-using MediaBrowser.Model.IO;
-
-namespace BDInfo
-{
-    public class TSStreamState
-    {
-        public ulong TransferCount = 0;
-
-        public string StreamTag = null;
-
-        public ulong TotalPackets = 0;
-        public ulong WindowPackets = 0;
-
-        public ulong TotalBytes = 0;
-        public ulong WindowBytes = 0;
-
-        public long PeakTransferLength = 0;
-        public long PeakTransferRate = 0;
-
-        public double TransferMarker = 0;
-        public double TransferInterval = 0;
-
-        public TSStreamBuffer StreamBuffer = new TSStreamBuffer();
-
-        public uint Parse = 0;
-        public bool TransferState = false;
-        public int TransferLength = 0;
-        public int PacketLength = 0;
-        public byte PacketLengthParse = 0;
-        public byte PacketParse = 0;
-
-        public byte PTSParse = 0;
-        public ulong PTS = 0;
-        public ulong PTSTemp = 0;
-        public ulong PTSLast = 0;
-        public ulong PTSPrev = 0;
-        public ulong PTSDiff = 0;
-        public ulong PTSCount = 0;
-        public ulong PTSTransfer = 0;
-
-        public byte DTSParse = 0;
-        public ulong DTSTemp = 0;
-        public ulong DTSPrev = 0;
-
-        public byte PESHeaderLength = 0;
-        public byte PESHeaderFlags = 0;
-#if DEBUG
-        public byte PESHeaderIndex = 0;
-        public byte[] PESHeader = new byte[256 + 9];
-#endif
-    }
-
-    public class TSPacketParser
-    {
-        public bool SyncState = false;
-        public byte TimeCodeParse = 4;
-        public byte PacketLength = 0;
-        public byte HeaderParse = 0;
-
-        public uint TimeCode;
-        public byte TransportErrorIndicator;
-        public byte PayloadUnitStartIndicator;
-        public byte TransportPriority;
-        public ushort PID;
-        public byte TransportScramblingControl;
-        public byte AdaptionFieldControl;
-
-        public bool AdaptionFieldState = false;
-        public byte AdaptionFieldParse = 0;
-        public byte AdaptionFieldLength = 0;
-
-        public ushort PCRPID = 0xFFFF;
-        public byte PCRParse = 0;
-        public ulong PreviousPCR = 0;
-        public ulong PCR = 0;
-        public ulong PCRCount = 0;
-        public ulong PTSFirst = ulong.MaxValue;
-        public ulong PTSLast = ulong.MinValue;
-        public ulong PTSDiff = 0;
-
-        public byte[] PAT = new byte[1024];
-        public bool PATSectionStart = false;
-        public byte PATPointerField = 0;
-        public uint PATOffset = 0;
-        public byte PATSectionLengthParse = 0;
-        public ushort PATSectionLength = 0;
-        public uint PATSectionParse = 0;
-        public bool PATTransferState = false;
-        public byte PATSectionNumber = 0;
-        public byte PATLastSectionNumber = 0;
-
-        public ushort TransportStreamId = 0xFFFF;
-
-        public List<TSDescriptor> PMTProgramDescriptors = new List<TSDescriptor>();
-        public ushort PMTPID = 0xFFFF;
-        public Dictionary<ushort, byte[]> PMT = new Dictionary<ushort, byte[]>();
-        public bool PMTSectionStart = false;
-        public ushort PMTProgramInfoLength = 0;
-        public byte PMTProgramDescriptor = 0;
-        public byte PMTProgramDescriptorLengthParse = 0;
-        public byte PMTProgramDescriptorLength = 0;
-        public ushort PMTStreamInfoLength = 0;
-        public uint PMTStreamDescriptorLengthParse = 0;
-        public uint PMTStreamDescriptorLength = 0;
-        public byte PMTPointerField = 0;
-        public uint PMTOffset = 0;
-        public uint PMTSectionLengthParse = 0;
-        public ushort PMTSectionLength = 0;
-        public uint PMTSectionParse = 0;
-        public bool PMTTransferState = false;
-        public byte PMTSectionNumber = 0;
-        public byte PMTLastSectionNumber = 0;
-
-        public byte PMTTemp = 0;
-
-        public TSStream Stream = null;
-        public TSStreamState StreamState = null;
-
-        public ulong TotalPackets = 0;
-    }
-
-    public class TSStreamDiagnostics
-    {
-        public ulong Bytes = 0;
-        public ulong Packets = 0;
-        public double Marker = 0;
-        public double Interval = 0;
-        public string Tag = null;
-    }
-
-    public class TSStreamFile
-    {
-        public FileSystemMetadata FileInfo = null;
-        public string Name = null;
-        public long Size = 0;
-        public double Length = 0;
-
-        public TSInterleavedFile InterleavedFile = null;
-
-        private Dictionary<ushort, TSStreamState> StreamStates =
-            new Dictionary<ushort, TSStreamState>();
-
-        public Dictionary<ushort, TSStream> Streams =
-            new Dictionary<ushort, TSStream>();
-
-        public Dictionary<ushort, List<TSStreamDiagnostics>> StreamDiagnostics =
-            new Dictionary<ushort, List<TSStreamDiagnostics>>();
-
-        private List<TSPlaylistFile> Playlists = null;
-
-        private readonly IFileSystem _fileSystem;
-
-        public TSStreamFile(FileSystemMetadata fileInfo, IFileSystem fileSystem)
-        {
-            FileInfo = fileInfo;
-            _fileSystem = fileSystem;
-            Name = fileInfo.Name.ToUpper();
-        }
-
-        public string DisplayName
-        {
-            get
-            {
-                if (BDInfoSettings.EnableSSIF &&
-                    InterleavedFile != null)
-                {
-                    return InterleavedFile.Name;
-                }
-                return Name;
-            }
-        }
-
-        private bool ScanStream(
-            TSStream stream,
-            TSStreamState streamState,
-            TSStreamBuffer buffer)
-        {
-            streamState.StreamTag = null;
-
-            long bitrate = 0;
-            if (stream.IsAudioStream &&
-                streamState.PTSTransfer > 0)
-            {
-                bitrate = (long)Math.Round(
-                    (buffer.TransferLength * 8.0) /
-                    ((double)streamState.PTSTransfer / 90000));
-
-                if (bitrate > streamState.PeakTransferRate)
-                {
-                    streamState.PeakTransferRate = bitrate;
-                }
-            }
-            if (buffer.TransferLength > streamState.PeakTransferLength)
-            {
-                streamState.PeakTransferLength = buffer.TransferLength;
-            }
-
-            buffer.BeginRead();
-            switch (stream.StreamType)
-            {
-                case TSStreamType.MPEG2_VIDEO:
-                    TSCodecMPEG2.Scan(
-                        (TSVideoStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.AVC_VIDEO:
-                    TSCodecAVC.Scan(
-                        (TSVideoStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.MVC_VIDEO:
-                    TSCodecMVC.Scan(
-                        (TSVideoStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.VC1_VIDEO:
-                    TSCodecVC1.Scan(
-                        (TSVideoStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.AC3_AUDIO:
-                    TSCodecAC3.Scan(
-                        (TSAudioStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.AC3_PLUS_AUDIO:
-                case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                    TSCodecAC3.Scan(
-                        (TSAudioStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.AC3_TRUE_HD_AUDIO:
-                    TSCodecTrueHD.Scan(
-                        (TSAudioStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.LPCM_AUDIO:
-                    TSCodecLPCM.Scan(
-                        (TSAudioStream)stream, buffer, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.DTS_AUDIO:
-                    TSCodecDTS.Scan(
-                        (TSAudioStream)stream, buffer, bitrate, ref streamState.StreamTag);
-                    break;
-
-                case TSStreamType.DTS_HD_AUDIO:
-                case TSStreamType.DTS_HD_MASTER_AUDIO:
-                case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                    TSCodecDTSHD.Scan(
-                        (TSAudioStream)stream, buffer, bitrate, ref streamState.StreamTag);
-                    break;
-
-                default:
-                    stream.IsInitialized = true;
-                    break;
-            }
-            buffer.EndRead();
-            streamState.StreamBuffer.Reset();
-
-            bool isAVC = false;
-            bool isMVC = false;
-            foreach (var finishedStream in Streams.Values)
-            {
-                if (!finishedStream.IsInitialized)
-                {
-                    return false;
-                }
-                if (finishedStream.StreamType == TSStreamType.AVC_VIDEO)
-                {
-                    isAVC = true;
-                }
-                if (finishedStream.StreamType == TSStreamType.MVC_VIDEO)
-                {
-                    isMVC = true;
-                }
-            }
-            if (isMVC && !isAVC)
-            {
-                return false;
-            }
-            return true;
-        }
-
-        private void UpdateStreamBitrates(
-            ushort PTSPID,
-            ulong PTS,
-            ulong PTSDiff)
-        {
-            if (Playlists == null) return;
-
-            foreach (ushort PID in StreamStates.Keys)
-            {
-                if (Streams.ContainsKey(PID) &&
-                    Streams[PID].IsVideoStream &&
-                    PID != PTSPID)
-                {
-                    continue;
-                }
-                if (StreamStates[PID].WindowPackets == 0)
-                {
-                    continue;
-                }
-                UpdateStreamBitrate(PID, PTSPID, PTS, PTSDiff);
-            }
-
-            foreach (var playlist in Playlists)
-            {
-                double packetSeconds = 0;
-                foreach (var clip in playlist.StreamClips)
-                {
-                    if (clip.AngleIndex == 0)
-                    {
-                        packetSeconds += clip.PacketSeconds;
-                    }
-                }
-                if (packetSeconds > 0)
-                {
-                    foreach (var playlistStream in playlist.SortedStreams)
-                    {
-                        if (playlistStream.IsVBR)
-                        {
-                            playlistStream.BitRate = (long)Math.Round(
-                                ((playlistStream.PayloadBytes * 8.0) / packetSeconds));
-
-                            if (playlistStream.StreamType == TSStreamType.AC3_TRUE_HD_AUDIO &&
-                                ((TSAudioStream)playlistStream).CoreStream != null)
-                            {
-                                playlistStream.BitRate -=
-                                    ((TSAudioStream)playlistStream).CoreStream.BitRate;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private void UpdateStreamBitrate(
-            ushort PID,
-            ushort PTSPID,
-            ulong PTS,
-            ulong PTSDiff)
-        {
-            if (Playlists == null) return;
-
-            var streamState = StreamStates[PID];
-            double streamTime = (double)PTS / 90000;
-            double streamInterval = (double)PTSDiff / 90000;
-            double streamOffset = streamTime + streamInterval;
-
-            foreach (var playlist in Playlists)
-            {
-                foreach (var clip in playlist.StreamClips)
-                {
-                    if (clip.Name != this.Name) continue;
-
-                    if (streamTime == 0 ||
-                        (streamTime >= clip.TimeIn &&
-                         streamTime <= clip.TimeOut))
-                    {
-                        clip.PayloadBytes += streamState.WindowBytes;
-                        clip.PacketCount += streamState.WindowPackets;
-
-                        if (streamOffset > clip.TimeIn &&
-                            streamOffset - clip.TimeIn > clip.PacketSeconds)
-                        {
-                            clip.PacketSeconds = streamOffset - clip.TimeIn;
-                        }
-
-                        var playlistStreams = playlist.Streams;
-                        if (clip.AngleIndex > 0 &&
-                            clip.AngleIndex < playlist.AngleStreams.Count + 1)
-                        {
-                            playlistStreams = playlist.AngleStreams[clip.AngleIndex - 1];
-                        }
-                        if (playlistStreams.ContainsKey(PID))
-                        {
-                            var stream = playlistStreams[PID];
-
-                            stream.PayloadBytes += streamState.WindowBytes;
-                            stream.PacketCount += streamState.WindowPackets;
-
-                            if (stream.IsVideoStream)
-                            {
-                                stream.PacketSeconds += streamInterval;
-
-                                stream.ActiveBitRate = (long)Math.Round(
-                                    ((stream.PayloadBytes * 8.0) /
-                                    stream.PacketSeconds));
-                            }
-
-                            if (stream.StreamType == TSStreamType.AC3_TRUE_HD_AUDIO &&
-                                ((TSAudioStream)stream).CoreStream != null)
-                            {
-                                stream.ActiveBitRate -=
-                                    ((TSAudioStream)stream).CoreStream.BitRate;
-                            }
-                        }
-                    }
-                }
-            }
-
-            if (Streams.ContainsKey(PID))
-            {
-                var stream = Streams[PID];
-                stream.PayloadBytes += streamState.WindowBytes;
-                stream.PacketCount += streamState.WindowPackets;
-
-                if (stream.IsVideoStream)
-                {
-                    var diag = new TSStreamDiagnostics();
-                    diag.Marker = (double)PTS / 90000;
-                    diag.Interval = (double)PTSDiff / 90000;
-                    diag.Bytes = streamState.WindowBytes;
-                    diag.Packets = streamState.WindowPackets;
-                    diag.Tag = streamState.StreamTag;
-                    StreamDiagnostics[PID].Add(diag);
-
-                    stream.PacketSeconds += streamInterval;
-                }
-            }
-            streamState.WindowPackets = 0;
-            streamState.WindowBytes = 0;
-        }
-
-        public void Scan(List<TSPlaylistFile> playlists, bool isFullScan)
-        {
-            if (playlists == null || playlists.Count == 0)
-            {
-                return;
-            }
-
-            Playlists = playlists;
-            int dataSize = 16384;
-            Stream fileStream = null;
-            try
-            {
-                string fileName;
-                if (BDInfoSettings.EnableSSIF &&
-                    InterleavedFile != null)
-                {
-                    fileName = InterleavedFile.FileInfo.FullName;
-                }
-                else
-                {
-                    fileName = FileInfo.FullName;
-                }
-                fileStream = _fileSystem.GetFileStream(
-                    fileName,
-                    FileOpenMode.Open,
-                    FileAccessMode.Read,
-                    FileShareMode.Read,
-                    false);
-
-                Size = 0;
-                Length = 0;
-
-                Streams.Clear();
-                StreamStates.Clear();
-                StreamDiagnostics.Clear();
-
-                var parser =
-                    new TSPacketParser();
-
-                long fileLength = (uint)fileStream.Length;
-                byte[] buffer = new byte[dataSize];
-                int bufferLength = 0;
-                while ((bufferLength =
-                    fileStream.Read(buffer, 0, buffer.Length)) > 0)
-                {
-                    int offset = 0;
-                    for (int i = 0; i < bufferLength; i++)
-                    {
-                        if (parser.SyncState == false)
-                        {
-                            if (parser.TimeCodeParse > 0)
-                            {
-                                parser.TimeCodeParse--;
-                                switch (parser.TimeCodeParse)
-                                {
-                                    case 3:
-                                        parser.TimeCode = 0;
-                                        parser.TimeCode |=
-                                            ((uint)buffer[i] & 0x3F) << 24;
-                                        break;
-                                    case 2:
-                                        parser.TimeCode |=
-                                            ((uint)buffer[i] & 0xFF) << 16;
-                                        break;
-                                    case 1:
-                                        parser.TimeCode |=
-                                            ((uint)buffer[i] & 0xFF) << 8;
-                                        break;
-                                    case 0:
-                                        parser.TimeCode |=
-                                            ((uint)buffer[i] & 0xFF);
-                                        break;
-                                }
-                            }
-                            else if (buffer[i] == 0x47)
-                            {
-                                parser.SyncState = true;
-                                parser.PacketLength = 187;
-                                parser.TimeCodeParse = 4;
-                                parser.HeaderParse = 3;
-                            }
-                        }
-                        else if (parser.HeaderParse > 0)
-                        {
-                            parser.PacketLength--;
-                            parser.HeaderParse--;
-
-                            switch (parser.HeaderParse)
-                            {
-                                case 2:
-                                    {
-                                        parser.TransportErrorIndicator =
-                                            (byte)((buffer[i] >> 7) & 0x1);
-                                        parser.PayloadUnitStartIndicator =
-                                            (byte)((buffer[i] >> 6) & 0x1);
-                                        parser.TransportPriority =
-                                            (byte)((buffer[i] >> 5) & 0x1);
-                                        parser.PID =
-                                            (ushort)((buffer[i] & 0x1f) << 8);
-                                    }
-                                    break;
-
-                                case 1:
-                                    {
-                                        parser.PID |= (ushort)buffer[i];
-                                        if (Streams.ContainsKey(parser.PID))
-                                        {
-                                            parser.Stream = Streams[parser.PID];
-                                        }
-                                        else
-                                        {
-                                            parser.Stream = null;
-                                        }
-                                        if (!StreamStates.ContainsKey(parser.PID))
-                                        {
-                                            StreamStates[parser.PID] = new TSStreamState();
-                                        }
-                                        parser.StreamState = StreamStates[parser.PID];
-                                        parser.StreamState.TotalPackets++;
-                                        parser.StreamState.WindowPackets++;
-                                        parser.TotalPackets++;
-                                    }
-                                    break;
-
-                                case 0:
-                                    {
-                                        parser.TransportScramblingControl =
-                                            (byte)((buffer[i] >> 6) & 0x3);
-                                        parser.AdaptionFieldControl =
-                                            (byte)((buffer[i] >> 4) & 0x3);
-
-                                        if ((parser.AdaptionFieldControl & 0x2) == 0x2)
-                                        {
-                                            parser.AdaptionFieldState = true;
-                                        }
-                                        if (parser.PayloadUnitStartIndicator == 1)
-                                        {
-                                            if (parser.PID == 0)
-                                            {
-                                                parser.PATSectionStart = true;
-                                            }
-                                            else if (parser.PID == parser.PMTPID)
-                                            {
-                                                parser.PMTSectionStart = true;
-                                            }
-                                            else if (parser.StreamState != null &&
-                                                parser.StreamState.TransferState)
-                                            {
-                                                parser.StreamState.TransferState = false;
-                                                parser.StreamState.TransferCount++;
-
-                                                bool isFinished = ScanStream(
-                                                    parser.Stream,
-                                                    parser.StreamState,
-                                                    parser.StreamState.StreamBuffer);
-
-                                                if (!isFullScan && isFinished)
-                                                {
-                                                    return;
-                                                }
-                                            }
-                                        }
-                                    }
-                                    break;
-                            }
-                        }
-                        else if (parser.AdaptionFieldState)
-                        {
-                            parser.PacketLength--;
-                            parser.AdaptionFieldParse = buffer[i];
-                            parser.AdaptionFieldLength = buffer[i];
-                            parser.AdaptionFieldState = false;
-                        }
-                        else if (parser.AdaptionFieldParse > 0)
-                        {
-                            parser.PacketLength--;
-                            parser.AdaptionFieldParse--;
-                            if ((parser.AdaptionFieldLength - parser.AdaptionFieldParse) == 1)
-                            {
-                                if ((buffer[i] & 0x10) == 0x10)
-                                {
-                                    parser.PCRParse = 6;
-                                    parser.PCR = 0;
-                                }
-                            }
-                            else if (parser.PCRParse > 0)
-                            {
-                                parser.PCRParse--;
-                                parser.PCR = (parser.PCR << 8) + (ulong)buffer[i];
-                                if (parser.PCRParse == 0)
-                                {
-                                    parser.PreviousPCR = parser.PCR;
-                                    parser.PCR = (parser.PCR & 0x1FF) +
-                                        ((parser.PCR >> 15) * 300);
-                                }
-                                parser.PCRCount++;
-                            }
-                            if (parser.PacketLength == 0)
-                            {
-                                parser.SyncState = false;
-                            }
-                        }
-                        else if (parser.PID == 0)
-                        {
-                            if (parser.PATTransferState)
-                            {
-                                if ((bufferLength - i) > parser.PATSectionLength)
-                                {
-                                    offset = parser.PATSectionLength;
-                                }
-                                else
-                                {
-                                    offset = (bufferLength - i);
-                                }
-                                if (parser.PacketLength <= offset)
-                                {
-                                    offset = parser.PacketLength;
-                                }
-
-                                for (int k = 0; k < offset; k++)
-                                {
-                                    parser.PAT[parser.PATOffset++] = buffer[i++];
-                                    parser.PATSectionLength--;
-                                    parser.PacketLength--;
-                                }
-                                --i;
-
-                                if (parser.PATSectionLength == 0)
-                                {
-                                    parser.PATTransferState = false;
-                                    if (parser.PATSectionNumber == parser.PATLastSectionNumber)
-                                    {
-                                        for (int k = 0; k < (parser.PATOffset - 4); k += 4)
-                                        {
-                                            uint programNumber = (uint)
-                                                ((parser.PAT[k] << 8) +
-                                                  parser.PAT[k + 1]);
-
-                                            ushort programPID = (ushort)
-                                                (((parser.PAT[k + 2] & 0x1F) << 8) +
-                                                   parser.PAT[k + 3]);
-
-                                            if (programNumber == 1)
-                                            {
-                                                parser.PMTPID = programPID;
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                --parser.PacketLength;
-                                if (parser.PATSectionStart)
-                                {
-                                    parser.PATPointerField = buffer[i];
-                                    if (parser.PATPointerField == 0)
-                                    {
-                                        parser.PATSectionLengthParse = 3;
-                                    }
-                                    parser.PATSectionStart = false;
-                                }
-                                else if (parser.PATPointerField > 0)
-                                {
-                                    --parser.PATPointerField;
-                                    if (parser.PATPointerField == 0)
-                                    {
-                                        parser.PATSectionLengthParse = 3;
-                                    }
-                                }
-                                else if (parser.PATSectionLengthParse > 0)
-                                {
-                                    --parser.PATSectionLengthParse;
-                                    switch (parser.PATSectionLengthParse)
-                                    {
-                                        case 2:
-                                            break;
-                                        case 1:
-                                            parser.PATSectionLength = (ushort)
-                                                ((buffer[i] & 0xF) << 8);
-                                            break;
-                                        case 0:
-                                            parser.PATSectionLength |= buffer[i];
-                                            if (parser.PATSectionLength > 1021)
-                                            {
-                                                parser.PATSectionLength = 0;
-                                            }
-                                            else
-                                            {
-                                                parser.PATSectionParse = 5;
-                                            }
-                                            break;
-                                    }
-                                }
-                                else if (parser.PATSectionParse > 0)
-                                {
-                                    --parser.PATSectionLength;
-                                    --parser.PATSectionParse;
-
-                                    switch (parser.PATSectionParse)
-                                    {
-                                        case 4:
-                                            parser.TransportStreamId = (ushort)
-                                                (buffer[i] << 8);
-                                            break;
-                                        case 3:
-                                            parser.TransportStreamId |= buffer[i];
-                                            break;
-                                        case 2:
-                                            break;
-                                        case 1:
-                                            parser.PATSectionNumber = buffer[i];
-                                            if (parser.PATSectionNumber == 0)
-                                            {
-                                                parser.PATOffset = 0;
-                                            }
-                                            break;
-                                        case 0:
-                                            parser.PATLastSectionNumber = buffer[i];
-                                            parser.PATTransferState = true;
-                                            break;
-                                    }
-                                }
-                            }
-                            if (parser.PacketLength == 0)
-                            {
-                                parser.SyncState = false;
-                            }
-                        }
-                        else if (parser.PID == parser.PMTPID)
-                        {
-                            if (parser.PMTTransferState)
-                            {
-                                if ((bufferLength - i) >= parser.PMTSectionLength)
-                                {
-                                    offset = parser.PMTSectionLength;
-                                }
-                                else
-                                {
-                                    offset = (bufferLength - i);
-                                }
-                                if (parser.PacketLength <= offset)
-                                {
-                                    offset = parser.PacketLength;
-                                }
-                                if (!parser.PMT.ContainsKey(parser.PID))
-                                {
-                                    parser.PMT[parser.PID] = new byte[1024];
-                                }
-
-                                byte[] PMT = parser.PMT[parser.PID];
-                                for (int k = 0; k < offset; k++)
-                                {
-                                    PMT[parser.PMTOffset++] = buffer[i++];
-                                    --parser.PMTSectionLength;
-                                    --parser.PacketLength;
-                                }
-                                --i;
-
-                                if (parser.PMTSectionLength == 0)
-                                {
-                                    parser.PMTTransferState = false;
-                                    if (parser.PMTSectionNumber == parser.PMTLastSectionNumber)
-                                    {
-                                        //Console.WriteLine("PMT Start: " + parser.PMTTemp);
-                                        try
-                                        {
-                                            for (int k = 0; k < (parser.PMTOffset - 4); k += 5)
-                                            {
-                                                byte streamType = PMT[k];
-
-                                                ushort streamPID = (ushort)
-                                                    (((PMT[k + 1] & 0x1F) << 8) +
-                                                       PMT[k + 2]);
-
-                                                ushort streamInfoLength = (ushort)
-                                                    (((PMT[k + 3] & 0xF) << 8) +
-                                                       PMT[k + 4]);
-
-                                                /*
-                                                if (streamInfoLength == 2)
-                                                {
-                                                    // TODO: Cleanup
-                                                    //streamInfoLength = 0;
-                                                }
-
-                                                Console.WriteLine(string.Format(
-                                                    "Type: {0} PID: {1} Length: {2}",
-                                                    streamType, streamPID, streamInfoLength));
-                                                 */
-
-                                                if (!Streams.ContainsKey(streamPID))
-                                                {
-                                                    var streamDescriptors =
-                                                        new List<TSDescriptor>();
-
-                                                    /*
-                                                     * TODO: Getting bad streamInfoLength
-                                                    if (streamInfoLength > 0)
-                                                    {
-                                                        for (int d = 0; d < streamInfoLength; d++)
-                                                        {
-                                                            byte name = PMT[k + d + 5];
-                                                            byte length = PMT[k + d + 6];
-                                                            TSDescriptor descriptor =
-                                                                new TSDescriptor(name, length);
-                                                            for (int v = 0; v < length; v++)
-                                                            {
-                                                                descriptor.Value[v] =
-                                                                    PMT[k + d + v + 7];
-                                                            }
-                                                            streamDescriptors.Add(descriptor);
-                                                            d += (length + 1);
-                                                        }
-                                                    }
-                                                    */
-                                                    CreateStream(streamPID, streamType, streamDescriptors);
-                                                }
-                                                k += streamInfoLength;
-                                            }
-                                        }
-                                        catch
-                                        {
-                                            // TODO
-                                            //Console.WriteLine(ex.Message);
-                                        }
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                --parser.PacketLength;
-                                if (parser.PMTSectionStart)
-                                {
-                                    parser.PMTPointerField = buffer[i];
-                                    if (parser.PMTPointerField == 0)
-                                    {
-                                        parser.PMTSectionLengthParse = 3;
-                                    }
-                                    parser.PMTSectionStart = false;
-                                }
-                                else if (parser.PMTPointerField > 0)
-                                {
-                                    --parser.PMTPointerField;
-                                    if (parser.PMTPointerField == 0)
-                                    {
-                                        parser.PMTSectionLengthParse = 3;
-                                    }
-                                }
-                                else if (parser.PMTSectionLengthParse > 0)
-                                {
-                                    --parser.PMTSectionLengthParse;
-                                    switch (parser.PMTSectionLengthParse)
-                                    {
-                                        case 2:
-                                            if (buffer[i] != 0x2)
-                                            {
-                                                parser.PMTSectionLengthParse = 0;
-                                            }
-                                            break;
-                                        case 1:
-                                            parser.PMTSectionLength = (ushort)
-                                                ((buffer[i] & 0xF) << 8);
-                                            break;
-                                        case 0:
-                                            parser.PMTSectionLength |= buffer[i];
-                                            if (parser.PMTSectionLength > 1021)
-                                            {
-                                                parser.PMTSectionLength = 0;
-                                            }
-                                            else
-                                            {
-                                                parser.PMTSectionParse = 9;
-                                            }
-                                            break;
-                                    }
-                                }
-                                else if (parser.PMTSectionParse > 0)
-                                {
-                                    --parser.PMTSectionLength;
-                                    --parser.PMTSectionParse;
-
-                                    switch (parser.PMTSectionParse)
-                                    {
-                                        case 8:
-                                        case 7:
-                                            break;
-                                        case 6:
-                                            parser.PMTTemp = buffer[i];
-                                            break;
-                                        case 5:
-                                            parser.PMTSectionNumber = buffer[i];
-                                            if (parser.PMTSectionNumber == 0)
-                                            {
-                                                parser.PMTOffset = 0;
-                                            }
-                                            break;
-                                        case 4:
-                                            parser.PMTLastSectionNumber = buffer[i];
-                                            break;
-                                        case 3:
-                                            parser.PCRPID = (ushort)
-                                                ((buffer[i] & 0x1F) << 8);
-                                            break;
-                                        case 2:
-                                            parser.PCRPID |= buffer[i];
-                                            break;
-                                        case 1:
-                                            parser.PMTProgramInfoLength = (ushort)
-                                                ((buffer[i] & 0xF) << 8);
-                                            break;
-                                        case 0:
-                                            parser.PMTProgramInfoLength |= buffer[i];
-                                            if (parser.PMTProgramInfoLength == 0)
-                                            {
-                                                parser.PMTTransferState = true;
-                                            }
-                                            else
-                                            {
-                                                parser.PMTProgramDescriptorLengthParse = 2;
-                                            }
-                                            break;
-                                    }
-                                }
-                                else if (parser.PMTProgramInfoLength > 0)
-                                {
-                                    --parser.PMTSectionLength;
-                                    --parser.PMTProgramInfoLength;
-
-                                    if (parser.PMTProgramDescriptorLengthParse > 0)
-                                    {
-                                        --parser.PMTProgramDescriptorLengthParse;
-                                        switch (parser.PMTProgramDescriptorLengthParse)
-                                        {
-                                            case 1:
-                                                parser.PMTProgramDescriptor = buffer[i];
-                                                break;
-                                            case 0:
-                                                parser.PMTProgramDescriptorLength = buffer[i];
-                                                parser.PMTProgramDescriptors.Add(
-                                                    new TSDescriptor(
-                                                        parser.PMTProgramDescriptor,
-                                                        parser.PMTProgramDescriptorLength));
-                                                break;
-                                        }
-                                    }
-                                    else if (parser.PMTProgramDescriptorLength > 0)
-                                    {
-                                        --parser.PMTProgramDescriptorLength;
-
-                                        var descriptor = parser.PMTProgramDescriptors[
-                                            parser.PMTProgramDescriptors.Count - 1];
-
-                                        int valueIndex =
-                                            descriptor.Value.Length -
-                                            parser.PMTProgramDescriptorLength - 1;
-
-                                        descriptor.Value[valueIndex] = buffer[i];
-
-                                        if (parser.PMTProgramDescriptorLength == 0 &&
-                                            parser.PMTProgramInfoLength > 0)
-                                        {
-                                            parser.PMTProgramDescriptorLengthParse = 2;
-                                        }
-                                    }
-                                    if (parser.PMTProgramInfoLength == 0)
-                                    {
-                                        parser.PMTTransferState = true;
-                                    }
-                                }
-                            }
-                            if (parser.PacketLength == 0)
-                            {
-                                parser.SyncState = false;
-                            }
-                        }
-                        else if (parser.Stream != null &&
-                            parser.StreamState != null &&
-                            parser.TransportScramblingControl == 0)
-                        {
-                            var stream = parser.Stream;
-                            var streamState = parser.StreamState;
-
-                            streamState.Parse =
-                                (streamState.Parse << 8) + buffer[i];
-
-                            if (streamState.TransferState)
-                            {
-                                if ((bufferLength - i) >= streamState.PacketLength &&
-                                    streamState.PacketLength > 0)
-                                {
-                                    offset = streamState.PacketLength;
-                                }
-                                else
-                                {
-                                    offset = (bufferLength - i);
-                                }
-                                if (parser.PacketLength <= offset)
-                                {
-                                    offset = parser.PacketLength;
-                                }
-                                streamState.TransferLength = offset;
-
-                                if (!stream.IsInitialized ||
-                                    stream.IsVideoStream)
-                                {
-                                    streamState.StreamBuffer.Add(
-                                        buffer, i, offset);
-                                }
-                                else
-                                {
-                                    streamState.StreamBuffer.TransferLength += offset;
-                                }
-
-                                i += (int)(streamState.TransferLength - 1);
-                                streamState.PacketLength -= streamState.TransferLength;
-                                parser.PacketLength -= (byte)streamState.TransferLength;
-
-                                streamState.TotalBytes += (ulong)streamState.TransferLength;
-                                streamState.WindowBytes += (ulong)streamState.TransferLength;
-
-                                if (streamState.PacketLength == 0)
-                                {
-                                    streamState.TransferState = false;
-                                    streamState.TransferCount++;
-                                    bool isFinished = ScanStream(
-                                        stream,
-                                        streamState,
-                                        streamState.StreamBuffer);
-
-                                    if (!isFullScan && isFinished)
-                                    {
-                                        return;
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                --parser.PacketLength;
-
-                                bool headerFound = false;
-                                if (stream.IsVideoStream &&
-                                    streamState.Parse == 0x000001FD)
-                                {
-                                    headerFound = true;
-                                }
-                                if (stream.IsVideoStream &&
-                                    streamState.Parse >= 0x000001E0 &&
-                                    streamState.Parse <= 0x000001EF)
-                                {
-                                    headerFound = true;
-                                }
-                                if (stream.IsAudioStream &&
-                                    streamState.Parse == 0x000001BD)
-                                {
-                                    headerFound = true;
-                                }
-                                if (stream.IsAudioStream &&
-                                    (streamState.Parse == 0x000001FA ||
-                                     streamState.Parse == 0x000001FD))
-                                {
-                                    headerFound = true;
-                                }
-
-                                if (!stream.IsVideoStream &&
-                                    !stream.IsAudioStream &&
-                                    (streamState.Parse == 0x000001FA ||
-                                     streamState.Parse == 0x000001FD ||
-                                     streamState.Parse == 0x000001BD ||
-                                     (streamState.Parse >= 0x000001E0 &&
-                                      streamState.Parse <= 0x000001EF)))
-                                {
-                                    headerFound = true;
-                                }
-
-                                if (headerFound)
-                                {
-                                    streamState.PacketLengthParse = 2;
-#if DEBUG
-                                    streamState.PESHeaderIndex = 0;
-                                    streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                        (byte)((streamState.Parse >> 24) & 0xFF);
-                                    streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                        (byte)((streamState.Parse >> 16) & 0xFF);
-                                    streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                        (byte)((streamState.Parse >> 8) & 0xFF);
-                                    streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                        (byte)(streamState.Parse & 0xFF);
-#endif
-                                }
-                                else if (streamState.PacketLengthParse > 0)
-                                {
-                                    --streamState.PacketLengthParse;
-                                    switch (streamState.PacketLengthParse)
-                                    {
-                                        case 1:
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 0:
-                                            streamState.PacketLength =
-                                                (int)(streamState.Parse & 0xFFFF);
-                                            streamState.PacketParse = 3;
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-                                    }
-                                }
-                                else if (streamState.PacketParse > 0)
-                                {
-                                    --streamState.PacketLength;
-                                    --streamState.PacketParse;
-
-                                    switch (streamState.PacketParse)
-                                    {
-                                        case 2:
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 1:
-                                            streamState.PESHeaderFlags =
-                                                (byte)(streamState.Parse & 0xFF);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 0:
-                                            streamState.PESHeaderLength =
-                                                (byte)(streamState.Parse & 0xFF);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            if ((streamState.PESHeaderFlags & 0xC0) == 0x80)
-                                            {
-                                                streamState.PTSParse = 5;
-                                            }
-                                            else if ((streamState.PESHeaderFlags & 0xC0) == 0xC0)
-                                            {
-                                                streamState.DTSParse = 10;
-                                            }
-                                            if (streamState.PESHeaderLength == 0)
-                                            {
-                                                streamState.TransferState = true;
-                                            }
-                                            break;
-                                    }
-                                }
-                                else if (streamState.PTSParse > 0)
-                                {
-                                    --streamState.PacketLength;
-                                    --streamState.PESHeaderLength;
-                                    --streamState.PTSParse;
-
-                                    switch (streamState.PTSParse)
-                                    {
-                                        case 4:
-                                            streamState.PTSTemp =
-                                                ((streamState.Parse & 0xE) << 29);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            break;
-
-                                        case 3:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFF) << 22);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 2:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFE) << 14);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 1:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFF) << 7);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 0:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFE) >> 1);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            streamState.PTS = streamState.PTSTemp;
-
-                                            if (streamState.PTS > streamState.PTSLast)
-                                            {
-                                                if (streamState.PTSLast > 0)
-                                                {
-                                                    streamState.PTSTransfer = (streamState.PTS - streamState.PTSLast);
-                                                }
-                                                streamState.PTSLast = streamState.PTS;
-                                            }
-
-                                            streamState.PTSDiff = streamState.PTS - streamState.DTSPrev;
-
-                                            if (streamState.PTSCount > 0 &&
-                                                stream.IsVideoStream)
-                                            {
-                                                UpdateStreamBitrates(stream.PID, streamState.PTS, streamState.PTSDiff);
-                                                if (streamState.DTSTemp < parser.PTSFirst)
-                                                {
-                                                    parser.PTSFirst = streamState.DTSTemp;
-                                                }
-                                                if (streamState.DTSTemp > parser.PTSLast)
-                                                {
-                                                    parser.PTSLast = streamState.DTSTemp;
-                                                }
-                                                Length = (double)(parser.PTSLast - parser.PTSFirst) / 90000;
-                                            }
-
-                                            streamState.DTSPrev = streamState.PTS;
-                                            streamState.PTSCount++;
-                                            if (streamState.PESHeaderLength == 0)
-                                            {
-                                                streamState.TransferState = true;
-                                            }
-                                            break;
-                                    }
-                                }
-                                else if (streamState.DTSParse > 0)
-                                {
-                                    --streamState.PacketLength;
-                                    --streamState.PESHeaderLength;
-                                    --streamState.DTSParse;
-
-                                    switch (streamState.DTSParse)
-                                    {
-                                        case 9:
-                                            streamState.PTSTemp =
-                                                ((streamState.Parse & 0xE) << 29);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 8:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFF) << 22);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 7:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFE) << 14);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            break;
-
-                                        case 6:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFF) << 7);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 5:
-                                            streamState.PTSTemp |=
-                                                ((streamState.Parse & 0xFE) >> 1);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            streamState.PTS = streamState.PTSTemp;
-                                            if (streamState.PTS > streamState.PTSLast)
-                                            {
-                                                streamState.PTSLast = streamState.PTS;
-                                            }
-                                            break;
-
-                                        case 4:
-                                            streamState.DTSTemp =
-                                                ((streamState.Parse & 0xE) << 29);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            break;
-
-                                        case 3:
-                                            streamState.DTSTemp |=
-                                                ((streamState.Parse & 0xFF) << 22);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            break;
-
-                                        case 2:
-                                            streamState.DTSTemp |=
-                                                ((streamState.Parse & 0xFE) << 14);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            break;
-
-                                        case 1:
-                                            streamState.DTSTemp |=
-                                                ((streamState.Parse & 0xFF) << 7);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xFF);
-#endif
-                                            break;
-
-                                        case 0:
-                                            streamState.DTSTemp |=
-                                                ((streamState.Parse & 0xFE) >> 1);
-#if DEBUG
-                                            streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                                (byte)(streamState.Parse & 0xff);
-#endif
-                                            streamState.PTSDiff = streamState.DTSTemp - streamState.DTSPrev;
-
-                                            if (streamState.PTSCount > 0 &&
-                                                stream.IsVideoStream)
-                                            {
-                                                UpdateStreamBitrates(stream.PID, streamState.DTSTemp, streamState.PTSDiff);
-                                                if (streamState.DTSTemp < parser.PTSFirst)
-                                                {
-                                                    parser.PTSFirst = streamState.DTSTemp;
-                                                }
-                                                if (streamState.DTSTemp > parser.PTSLast)
-                                                {
-                                                    parser.PTSLast = streamState.DTSTemp;
-                                                }
-                                                Length = (double)(parser.PTSLast - parser.PTSFirst) / 90000;
-                                            }
-                                            streamState.DTSPrev = streamState.DTSTemp;
-                                            streamState.PTSCount++;
-                                            if (streamState.PESHeaderLength == 0)
-                                            {
-                                                streamState.TransferState = true;
-                                            }
-                                            break;
-                                    }
-                                }
-                                else if (streamState.PESHeaderLength > 0)
-                                {
-                                    --streamState.PacketLength;
-                                    --streamState.PESHeaderLength;
-#if DEBUG
-                                    streamState.PESHeader[streamState.PESHeaderIndex++] =
-                                        (byte)(streamState.Parse & 0xFF);
-#endif
-                                    if (streamState.PESHeaderLength == 0)
-                                    {
-                                        streamState.TransferState = true;
-                                    }
-                                }
-                            }
-                            if (parser.PacketLength == 0)
-                            {
-                                parser.SyncState = false;
-                            }
-                        }
-                        else
-                        {
-                            parser.PacketLength--;
-                            if ((bufferLength - i) >= parser.PacketLength)
-                            {
-                                i = i + parser.PacketLength;
-                                parser.PacketLength = 0;
-                            }
-                            else
-                            {
-                                parser.PacketLength -= (byte)((bufferLength - i) + 1);
-                                i = bufferLength;
-                            }
-                            if (parser.PacketLength == 0)
-                            {
-                                parser.SyncState = false;
-                            }
-                        }
-                    }
-                    Size += bufferLength;
-                }
-
-                ulong PTSLast = 0;
-                ulong PTSDiff = 0;
-                foreach (var stream in Streams.Values)
-                {
-                    if (!stream.IsVideoStream) continue;
-
-                    if (StreamStates.ContainsKey(stream.PID) &&
-                        StreamStates[stream.PID].PTSLast > PTSLast)
-                    {
-                        PTSLast = StreamStates[stream.PID].PTSLast;
-                        PTSDiff = PTSLast - StreamStates[stream.PID].DTSPrev;
-                    }
-                    UpdateStreamBitrates(stream.PID, PTSLast, PTSDiff);
-                }
-            }
-            finally
-            {
-                if (fileStream != null)
-                {
-                    fileStream.Dispose();
-                }
-            }
-        }
-
-        private TSStream CreateStream(
-            ushort streamPID,
-            byte streamType,
-            List<TSDescriptor> streamDescriptors)
-        {
-            TSStream stream = null;
-
-            switch ((TSStreamType)streamType)
-            {
-                case TSStreamType.MVC_VIDEO:
-                case TSStreamType.AVC_VIDEO:
-                case TSStreamType.MPEG1_VIDEO:
-                case TSStreamType.MPEG2_VIDEO:
-                case TSStreamType.VC1_VIDEO:
-                    {
-                        stream = new TSVideoStream();
-                    }
-                    break;
-
-                case TSStreamType.AC3_AUDIO:
-                case TSStreamType.AC3_PLUS_AUDIO:
-                case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
-                case TSStreamType.AC3_TRUE_HD_AUDIO:
-                case TSStreamType.DTS_AUDIO:
-                case TSStreamType.DTS_HD_AUDIO:
-                case TSStreamType.DTS_HD_MASTER_AUDIO:
-                case TSStreamType.DTS_HD_SECONDARY_AUDIO:
-                case TSStreamType.LPCM_AUDIO:
-                case TSStreamType.MPEG1_AUDIO:
-                case TSStreamType.MPEG2_AUDIO:
-                    {
-                        stream = new TSAudioStream();
-                    }
-                    break;
-
-                case TSStreamType.INTERACTIVE_GRAPHICS:
-                case TSStreamType.PRESENTATION_GRAPHICS:
-                    {
-                        stream = new TSGraphicsStream();
-                    }
-                    break;
-
-                case TSStreamType.SUBTITLE:
-                    {
-                        stream = new TSTextStream();
-                    }
-                    break;
-
-                default:
-                    break;
-            }
-
-            if (stream != null &&
-                !Streams.ContainsKey(streamPID))
-            {
-                stream.PID = streamPID;
-                stream.StreamType = (TSStreamType)streamType;
-                stream.Descriptors = streamDescriptors;
-                Streams[stream.PID] = stream;
-            }
-            if (!StreamDiagnostics.ContainsKey(streamPID))
-            {
-                StreamDiagnostics[streamPID] =
-                    new List<TSStreamDiagnostics>();
-            }
-
-            return stream;
-        }
-    }
-}

+ 2 - 0
CONTRIBUTORS.md

@@ -31,6 +31,8 @@
  - [fhriley](https://github.com/fhriley)
  - [nevado](https://github.com/nevado)
  - [mark-monteiro](https://github.com/mark-monteiro)
+ - [ullmie02](https://github.com/ullmie02)
+ - [pR0Ps](https://github.com/pR0Ps)
 
 # Emby Contributors
 

+ 5 - 3
Dockerfile

@@ -1,4 +1,4 @@
-ARG DOTNET_VERSION=3.0
+ARG DOTNET_VERSION=3.1
 ARG FFMPEG_VERSION=latest
 
 FROM node:alpine as web-builder
@@ -14,7 +14,9 @@ FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION}-buster as builder
 WORKDIR /repo
 COPY . .
 ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
-RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:GenerateDocumentationFile=false;DebugSymbols=false;DebugType=none"
+# because of changes in docker and systemd we need to not build in parallel at the moment
+# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
+RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:GenerateDocumentationFile=false;DebugSymbols=false;DebugType=none"
 
 FROM jellyfin/ffmpeg:${FFMPEG_VERSION} as ffmpeg
 FROM debian:buster-slim
@@ -29,7 +31,7 @@ COPY --from=web-builder /dist /jellyfin/jellyfin-web
 #   mesa-va-drivers: needed for VAAPI
 RUN apt-get update \
  && apt-get install --no-install-recommends --no-install-suggests -y \
-   libfontconfig1 libgomp1 libva-drm2 mesa-va-drivers openssl \
+   libfontconfig1 libgomp1 libva-drm2 mesa-va-drivers openssl ca-certificates \
  && apt-get clean autoclean \
  && apt-get autoremove \
  && rm -rf /var/lib/apt/lists/* \

+ 3 - 6
Dockerfile.arm

@@ -1,6 +1,4 @@
-# Requires binfm_misc registration
-# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
-ARG DOTNET_VERSION=3.0
+ARG DOTNET_VERSION=3.1
 
 
 FROM node:alpine as web-builder
@@ -23,11 +21,10 @@ RUN find . -type d -name obj | xargs -r rm -r
 RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:GenerateDocumentationFile=false;DebugSymbols=false;DebugType=none"
 
 
-FROM multiarch/qemu-user-static:x86_64-arm as qemu
-FROM debian:stretch-slim-arm32v7
-COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
+FROM debian:buster-slim
 RUN apt-get update \
  && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
+ libssl-dev ca-certificates \
  && rm -rf /var/lib/apt/lists/* \
  && mkdir -p /cache /config /media \
  && chmod 777 /cache /config /media

+ 3 - 6
Dockerfile.arm64

@@ -1,6 +1,4 @@
-# Requires binfm_misc registration
-# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
-ARG DOTNET_VERSION=3.0
+ARG DOTNET_VERSION=3.1
 
 
 FROM node:alpine as web-builder
@@ -23,11 +21,10 @@ RUN find . -type d -name obj | xargs -r rm -r
 RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:GenerateDocumentationFile=false;DebugSymbols=false;DebugType=none"
 
 
-FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
-FROM debian:stretch-slim-arm64v8
-COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
+FROM debian:buster-slim
 RUN apt-get update \
  && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
+ libssl-dev ca-certificates \
  && rm -rf /var/lib/apt/lists/* \
  && mkdir -p /cache /config /media \
  && chmod 777 /cache /config /media

+ 1 - 1
DvdLib/DvdLib.csproj

@@ -9,7 +9,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
+    <TargetFramework>netstandard2.1</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 2 - 2
DvdLib/Ifo/Dvd.cs

@@ -42,7 +42,7 @@ namespace DvdLib.Ifo
             }
             else
             {
-                using (var vmgFs = _fileSystem.GetFileStream(vmgPath.FullName, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
+                using (var vmgFs = new FileStream(vmgPath.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                 {
                     using (var vmgRead = new BigEndianBinaryReader(vmgFs))
                     {
@@ -95,7 +95,7 @@ namespace DvdLib.Ifo
         {
             VTSPaths[vtsNum] = vtsPath;
 
-            using (var vtsFs = _fileSystem.GetFileStream(vtsPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
+            using (var vtsFs = new FileStream(vtsPath, FileMode.Open, FileAccess.Read, FileShare.Read))
             {
                 using (var vtsRead = new BigEndianBinaryReader(vtsFs))
                 {

+ 8 - 8
Emby.Dlna/Api/DlnaServerService.cs

@@ -170,32 +170,32 @@ namespace Emby.Dlna.Api
             return _resultFactory.GetResult(Request, xml, XMLContentType);
         }
 
-        public object Post(ProcessMediaReceiverRegistrarControlRequest request)
+        public async Task<object> Post(ProcessMediaReceiverRegistrarControlRequest request)
         {
-            var response = PostAsync(request.RequestStream, MediaReceiverRegistrar);
+            var response = await PostAsync(request.RequestStream, MediaReceiverRegistrar).ConfigureAwait(false);
 
             return _resultFactory.GetResult(Request, response.Xml, XMLContentType);
         }
 
-        public object Post(ProcessContentDirectoryControlRequest request)
+        public async Task<object> Post(ProcessContentDirectoryControlRequest request)
         {
-            var response = PostAsync(request.RequestStream, ContentDirectory);
+            var response = await PostAsync(request.RequestStream, ContentDirectory).ConfigureAwait(false);
 
             return _resultFactory.GetResult(Request, response.Xml, XMLContentType);
         }
 
-        public object Post(ProcessConnectionManagerControlRequest request)
+        public async Task<object> Post(ProcessConnectionManagerControlRequest request)
         {
-            var response = PostAsync(request.RequestStream, ConnectionManager);
+            var response = await PostAsync(request.RequestStream, ConnectionManager).ConfigureAwait(false);
 
             return _resultFactory.GetResult(Request, response.Xml, XMLContentType);
         }
 
-        private ControlResponse PostAsync(Stream requestStream, IUpnpService service)
+        private Task<ControlResponse> PostAsync(Stream requestStream, IUpnpService service)
         {
             var id = GetPathValue(2).ToString();
 
-            return service.ProcessControlRequest(new ControlRequest
+            return service.ProcessControlRequestAsync(new ControlRequest
             {
                 Headers = Request.Headers,
                 InputXml = requestStream,

+ 5 - 2
Emby.Dlna/ConnectionManager/ConnectionManager.cs

@@ -1,3 +1,4 @@
+using System.Threading.Tasks;
 using Emby.Dlna.Service;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
@@ -20,17 +21,19 @@ namespace Emby.Dlna.ConnectionManager
             _logger = logger;
         }
 
+        /// <inheritdoc />
         public string GetServiceXml()
         {
             return new ConnectionManagerXmlBuilder().GetXml();
         }
 
-        public ControlResponse ProcessControlRequest(ControlRequest request)
+        /// <inheritdoc />
+        public Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
         {
             var profile = _dlna.GetProfile(request.Headers) ??
                          _dlna.GetDefaultProfile();
 
-            return new ControlHandler(_config, _logger, profile).ProcessControlRequest(request);
+            return new ControlHandler(_config, _logger, profile).ProcessControlRequestAsync(request);
         }
     }
 }

+ 5 - 2
Emby.Dlna/ContentDirectory/ContentDirectory.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Threading.Tasks;
 using Emby.Dlna.Service;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
@@ -66,12 +67,14 @@ namespace Emby.Dlna.ContentDirectory
             }
         }
 
+        /// <inheritdoc />
         public string GetServiceXml()
         {
             return new ContentDirectoryXmlBuilder().GetXml();
         }
 
-        public ControlResponse ProcessControlRequest(ControlRequest request)
+        /// <inheritdoc />
+        public Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
         {
             var profile = _dlna.GetProfile(request.Headers) ??
                           _dlna.GetDefaultProfile();
@@ -96,7 +99,7 @@ namespace Emby.Dlna.ContentDirectory
                 _userViewManager,
                 _mediaEncoder,
                 _tvSeriesManager)
-                .ProcessControlRequest(request);
+                .ProcessControlRequestAsync(request);
         }
 
         private User GetUser(DeviceProfile profile)

+ 4 - 4
Emby.Dlna/ContentDirectory/ControlHandler.cs

@@ -76,7 +76,7 @@ namespace Emby.Dlna.ContentDirectory
             _profile = profile;
             _config = config;
 
-            _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, _logger, mediaEncoder);
+            _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, mediaEncoder);
         }
 
         protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, IDictionary<string, string> methodParams)
@@ -771,11 +771,11 @@ namespace Emby.Dlna.ContentDirectory
                 })
                 .ToArray();
 
-            return new QueryResult<ServerItem>
+            return ApplyPaging(new QueryResult<ServerItem>
             {
                 Items = folders,
                 TotalRecordCount = folders.Length
-            };
+            }, startIndex, limit);
         }
 
         private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
@@ -1336,7 +1336,7 @@ namespace Emby.Dlna.ContentDirectory
                 };
             }
 
-            _logger.LogError("Error parsing item Id: {id}. Returning user root folder.", id);
+            Logger.LogError("Error parsing item Id: {id}. Returning user root folder.", id);
 
             return new ServerItem(_libraryManager.GetUserRootFolder());
         }

+ 0 - 1
Emby.Dlna/Didl/DidlBuilder.cs

@@ -18,7 +18,6 @@ using MediaBrowser.Controller.Playlists;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Net;
 using Microsoft.Extensions.Logging;

+ 1 - 1
Emby.Dlna/Didl/Filter.cs

@@ -16,7 +16,7 @@ namespace Emby.Dlna.Didl
 
         public Filter(string filter)
         {
-            _all = StringHelper.EqualsIgnoreCase(filter, "*");
+            _all = string.Equals(filter, "*", StringComparison.OrdinalIgnoreCase);
 
             _fields = (filter ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
         }

+ 1 - 1
Emby.Dlna/DlnaManager.cs

@@ -385,7 +385,7 @@ namespace Emby.Dlna
                     {
                         Directory.CreateDirectory(systemProfilesPath);
 
-                        using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
+                        using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
                         {
                             await stream.CopyToAsync(fileStream);
                         }

+ 12 - 24
Emby.Dlna/Eventing/EventManager.cs

@@ -29,25 +29,15 @@ namespace Emby.Dlna.Eventing
         {
             var subscription = GetSubscription(subscriptionId, false);
 
-            int timeoutSeconds;
+            subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300;
+            int timeoutSeconds = subscription.TimeoutSeconds;
+            subscription.SubscriptionTime = DateTime.UtcNow;
 
-            // Remove logging for now because some devices are sending this very frequently
-            // TODO re-enable with dlna debug logging setting
-            //_logger.LogDebug("Renewing event subscription for {0} with timeout of {1} to {2}",
-            //    subscription.NotificationType,
-            //    timeout,
-            //    subscription.CallbackUrl);
-
-            if (subscription != null)
-            {
-                subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300;
-                timeoutSeconds = subscription.TimeoutSeconds;
-                subscription.SubscriptionTime = DateTime.UtcNow;
-            }
-            else
-            {
-                timeoutSeconds = 300;
-            }
+            _logger.LogDebug(
+                "Renewing event subscription for {0} with timeout of {1} to {2}",
+                subscription.NotificationType,
+                timeoutSeconds,
+                subscription.CallbackUrl);
 
             return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds);
         }
@@ -57,12 +47,10 @@ namespace Emby.Dlna.Eventing
             var timeout = ParseTimeout(requestedTimeoutString) ?? 300;
             var id = "uuid:" + Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
 
-            // Remove logging for now because some devices are sending this very frequently
-            // TODO re-enable with dlna debug logging setting
-            //_logger.LogDebug("Creating event subscription for {0} with timeout of {1} to {2}",
-            //    notificationType,
-            //    timeout,
-            //    callbackUrl);
+            _logger.LogDebug("Creating event subscription for {0} with timeout of {1} to {2}",
+                notificationType,
+                timeout,
+                callbackUrl);
 
             _subscriptions.TryAdd(id, new EventSubscription
             {

+ 3 - 1
Emby.Dlna/IUpnpService.cs

@@ -1,3 +1,5 @@
+using System.Threading.Tasks;
+
 namespace Emby.Dlna
 {
     public interface IUpnpService
@@ -13,6 +15,6 @@ namespace Emby.Dlna
         /// </summary>
         /// <param name="request">The request.</param>
         /// <returns>ControlResponse.</returns>
-        ControlResponse ProcessControlRequest(ControlRequest request);
+        Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request);
     }
 }

+ 5 - 2
Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrar.cs

@@ -1,3 +1,4 @@
+using System.Threading.Tasks;
 using Emby.Dlna.Service;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
@@ -15,17 +16,19 @@ namespace Emby.Dlna.MediaReceiverRegistrar
             _config = config;
         }
 
+        /// <inheritdoc />
         public string GetServiceXml()
         {
             return new MediaReceiverRegistrarXmlBuilder().GetXml();
         }
 
-        public ControlResponse ProcessControlRequest(ControlRequest request)
+        /// <inheritdoc />
+        public Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
         {
             return new ControlHandler(
                 _config,
                 Logger)
-                .ProcessControlRequest(request);
+                .ProcessControlRequestAsync(request);
         }
     }
 }

+ 0 - 1
Emby.Dlna/PlayTo/PlayToController.cs

@@ -6,7 +6,6 @@ using System.Threading;
 using System.Threading.Tasks;
 using Emby.Dlna.Didl;
 using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Entities;

+ 0 - 1
Emby.Dlna/PlayTo/PlaylistItemFactory.cs

@@ -1,4 +1,3 @@
-using System.Globalization;
 using System.IO;
 using System.Linq;
 using MediaBrowser.Controller.Entities;

+ 0 - 1
Emby.Dlna/Server/DescriptionXmlBuilder.cs

@@ -5,7 +5,6 @@ using System.Linq;
 using System.Text;
 using Emby.Dlna.Common;
 using MediaBrowser.Model.Dlna;
-using MediaBrowser.Model.Extensions;
 
 namespace Emby.Dlna.Server
 {

+ 39 - 56
Emby.Dlna/Service/BaseControlHandler.cs

@@ -1,8 +1,8 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
 using System.Text;
+using System.Threading.Tasks;
 using System.Xml;
 using Emby.Dlna.Didl;
 using MediaBrowser.Controller.Configuration;
@@ -15,44 +15,34 @@ namespace Emby.Dlna.Service
     {
         private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
 
-        protected readonly IServerConfigurationManager Config;
-        protected readonly ILogger _logger;
+        protected IServerConfigurationManager Config { get; }
+        protected ILogger Logger { get; }
 
         protected BaseControlHandler(IServerConfigurationManager config, ILogger logger)
         {
             Config = config;
-            _logger = logger;
+            Logger = logger;
         }
 
-        public ControlResponse ProcessControlRequest(ControlRequest request)
+        public async Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
         {
             try
             {
-                var enableDebugLogging = Config.GetDlnaConfiguration().EnableDebugLog;
-
-                if (enableDebugLogging)
-                {
-                    LogRequest(request);
-                }
-
-                var response = ProcessControlRequestInternal(request);
-
-                if (enableDebugLogging)
-                {
-                    LogResponse(response);
-                }
+                LogRequest(request);
 
+                var response = await ProcessControlRequestInternalAsync(request).ConfigureAwait(false);
+                LogResponse(response);
                 return response;
             }
             catch (Exception ex)
             {
-                _logger.LogError(ex, "Error processing control request");
+                Logger.LogError(ex, "Error processing control request");
 
-                return new ControlErrorHandler().GetResponse(ex);
+                return ControlErrorHandler.GetResponse(ex);
             }
         }
 
-        private ControlResponse ProcessControlRequestInternal(ControlRequest request)
+        private async Task<ControlResponse> ProcessControlRequestInternalAsync(ControlRequest request)
         {
             ControlRequestInfo requestInfo = null;
 
@@ -63,16 +53,17 @@ namespace Emby.Dlna.Service
                     ValidationType = ValidationType.None,
                     CheckCharacters = false,
                     IgnoreProcessingInstructions = true,
-                    IgnoreComments = true
+                    IgnoreComments = true,
+                    Async = true
                 };
 
                 using (var reader = XmlReader.Create(streamReader, readerSettings))
                 {
-                    requestInfo = ParseRequest(reader);
+                    requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false);
                 }
             }
 
-            _logger.LogDebug("Received control request {0}", requestInfo.LocalName);
+            Logger.LogDebug("Received control request {0}", requestInfo.LocalName);
 
             var result = GetResult(requestInfo.LocalName, requestInfo.Headers);
 
@@ -114,17 +105,15 @@ namespace Emby.Dlna.Service
                 IsSuccessful = true
             };
 
-            //logger.LogDebug(xml);
-
             controlResponse.Headers.Add("EXT", string.Empty);
 
             return controlResponse;
         }
 
-        private ControlRequestInfo ParseRequest(XmlReader reader)
+        private async Task<ControlRequestInfo> ParseRequestAsync(XmlReader reader)
         {
-            reader.MoveToContent();
-            reader.Read();
+            await reader.MoveToContentAsync().ConfigureAwait(false);
+            await reader.ReadAsync().ConfigureAwait(false);
 
             // Loop through each element
             while (!reader.EOF && reader.ReadState == ReadState.Interactive)
@@ -139,37 +128,38 @@ namespace Emby.Dlna.Service
                                 {
                                     using (var subReader = reader.ReadSubtree())
                                     {
-                                        return ParseBodyTag(subReader);
+                                        return await ParseBodyTagAsync(subReader).ConfigureAwait(false);
                                     }
                                 }
                                 else
                                 {
-                                    reader.Read();
+                                    await reader.ReadAsync().ConfigureAwait(false);
                                 }
+
                                 break;
                             }
                         default:
                             {
-                                reader.Skip();
+                                await reader.SkipAsync().ConfigureAwait(false);
                                 break;
                             }
                     }
                 }
                 else
                 {
-                    reader.Read();
+                    await reader.ReadAsync().ConfigureAwait(false);
                 }
             }
 
             return new ControlRequestInfo();
         }
 
-        private ControlRequestInfo ParseBodyTag(XmlReader reader)
+        private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
         {
             var result = new ControlRequestInfo();
 
-            reader.MoveToContent();
-            reader.Read();
+            await reader.MoveToContentAsync().ConfigureAwait(false);
+            await reader.ReadAsync().ConfigureAwait(false);
 
             // Loop through each element
             while (!reader.EOF && reader.ReadState == ReadState.Interactive)
@@ -183,28 +173,28 @@ namespace Emby.Dlna.Service
                     {
                         using (var subReader = reader.ReadSubtree())
                         {
-                            ParseFirstBodyChild(subReader, result.Headers);
+                            await ParseFirstBodyChildAsync(subReader, result.Headers).ConfigureAwait(false);
                             return result;
                         }
                     }
                     else
                     {
-                        reader.Read();
+                        await reader.ReadAsync().ConfigureAwait(false);
                     }
                 }
                 else
                 {
-                    reader.Read();
+                    await reader.ReadAsync().ConfigureAwait(false);
                 }
             }
 
             return result;
         }
 
-        private void ParseFirstBodyChild(XmlReader reader, IDictionary<string, string> headers)
+        private async Task ParseFirstBodyChildAsync(XmlReader reader, IDictionary<string, string> headers)
         {
-            reader.MoveToContent();
-            reader.Read();
+            await reader.MoveToContentAsync().ConfigureAwait(false);
+            await reader.ReadAsync().ConfigureAwait(false);
 
             // Loop through each element
             while (!reader.EOF && reader.ReadState == ReadState.Interactive)
@@ -212,20 +202,20 @@ namespace Emby.Dlna.Service
                 if (reader.NodeType == XmlNodeType.Element)
                 {
                     // TODO: Should we be doing this here, or should it be handled earlier when decoding the request?
-                    headers[reader.LocalName.RemoveDiacritics()] = reader.ReadElementContentAsString();
+                    headers[reader.LocalName.RemoveDiacritics()] = await reader.ReadElementContentAsStringAsync().ConfigureAwait(false);
                 }
                 else
                 {
-                    reader.Read();
+                    await reader.ReadAsync().ConfigureAwait(false);
                 }
             }
         }
 
         private class ControlRequestInfo
         {
-            public string LocalName;
-            public string NamespaceURI;
-            public IDictionary<string, string> Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+            public string LocalName { get; set; }
+            public string NamespaceURI { get; set; }
+            public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         }
 
         protected abstract IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, IDictionary<string, string> methodParams);
@@ -237,10 +227,7 @@ namespace Emby.Dlna.Service
                 return;
             }
 
-            var originalHeaders = request.Headers;
-            var headers = string.Join(", ", originalHeaders.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray());
-
-            _logger.LogDebug("Control request. Headers: {0}", headers);
+            Logger.LogDebug("Control request. Headers: {@Headers}", request.Headers);
         }
 
         private void LogResponse(ControlResponse response)
@@ -250,11 +237,7 @@ namespace Emby.Dlna.Service
                 return;
             }
 
-            var originalHeaders = response.Headers;
-            var headers = string.Join(", ", originalHeaders.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray());
-            //builder.Append(response.Xml);
-
-            _logger.LogDebug("Control response. Headers: {0}", headers);
+            Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml);
         }
     }
 }

+ 2 - 2
Emby.Dlna/Service/ControlErrorHandler.cs

@@ -6,11 +6,11 @@ using Emby.Dlna.Didl;
 
 namespace Emby.Dlna.Service
 {
-    public class ControlErrorHandler
+    public static class ControlErrorHandler
     {
         private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
 
-        public ControlResponse GetResponse(Exception ex)
+        public static ControlResponse GetResponse(Exception ex)
         {
             var settings = new XmlWriterSettings
             {

+ 1 - 2
Emby.Drawing/ImageProcessor.cs

@@ -14,7 +14,6 @@ using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Net;
 using Microsoft.Extensions.Logging;
@@ -129,7 +128,7 @@ namespace Emby.Drawing
         {
             var file = await ProcessImage(options).ConfigureAwait(false);
 
-            using (var fileStream = _fileSystem.GetFileStream(file.Item1, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true))
+            using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true))
             {
                 await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
             }

+ 3 - 0
Emby.Naming/Audio/AlbumParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Globalization;
 using System.IO;

+ 3 - 0
Emby.Naming/Audio/AudioFileParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;

+ 3 - 0
Emby.Naming/Audio/MultiPartResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Audio
 {
     public class MultiPartResult

+ 3 - 0
Emby.Naming/AudioBook/AudioBookFilePathParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Globalization;
 using System.IO;

+ 3 - 0
Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.AudioBook
 {
     public class AudioBookFilePathParserResult

+ 3 - 0
Emby.Naming/AudioBook/AudioBookInfo.cs

@@ -7,6 +7,9 @@ namespace Emby.Naming.AudioBook
     /// </summary>
     public class AudioBookInfo
     {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AudioBookInfo" /> class.
+        /// </summary>
         public AudioBookInfo()
         {
             Files = new List<AudioBookFileInfo>();

+ 3 - 0
Emby.Naming/AudioBook/AudioBookListResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System.Collections.Generic;
 using System.Linq;
 using Emby.Naming.Common;

+ 3 - 0
Emby.Naming/AudioBook/AudioBookResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;

+ 3 - 0
Emby.Naming/Common/EpisodeExpression.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Text.RegularExpressions;
 

+ 3 - 0
Emby.Naming/Common/MediaType.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Common
 {
     public enum MediaType

+ 25 - 22
Emby.Naming/Common/NamingOptions.cs

@@ -1,7 +1,11 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Linq;
 using System.Text.RegularExpressions;
 using Emby.Naming.Video;
+using MediaBrowser.Model.Entities;
 
 namespace Emby.Naming.Common
 {
@@ -173,13 +177,12 @@ namespace Emby.Naming.Common
 
             CleanDateTimes = new[]
             {
-                @"(.+[^ _\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9][0-9]|20[0-1][0-9])([ _\,\.\(\)\[\]\-][^0-9]|$)"
+                @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19\d{2}|20\d{2})([ _\,\.\(\)\[\]\-][^0-9]|).*(19\d{2}|20\d{2})*"
             };
 
             CleanStrings = new[]
             {
-                @"[ _\,\.\(\)\[\]\-](ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
-                @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
+                @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
                 @"(\[.*\])"
             };
 
@@ -336,7 +339,7 @@ namespace Emby.Naming.Common
 
                 // *** End Kodi Standard Naming
 
-                // [bar] Foo - 1 [baz]
+                // [bar] Foo - 1 [baz]
                 new EpisodeExpression(@".*?(\[.*?\])+.*?(?<seriesname>[\w\s]+?)[-\s_]+(?<epnumber>\d+).*$")
                 {
                     IsNamed = true
@@ -420,126 +423,126 @@ namespace Emby.Naming.Common
             {
                 new ExtraRule
                 {
-                    ExtraType = "trailer",
+                    ExtraType = ExtraType.Trailer,
                     RuleType = ExtraRuleType.Filename,
                     Token = "trailer",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "trailer",
+                    ExtraType = ExtraType.Trailer,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-trailer",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "trailer",
+                    ExtraType = ExtraType.Trailer,
                     RuleType = ExtraRuleType.Suffix,
                     Token = ".trailer",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "trailer",
+                    ExtraType = ExtraType.Trailer,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "_trailer",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "trailer",
+                    ExtraType = ExtraType.Trailer,
                     RuleType = ExtraRuleType.Suffix,
                     Token = " trailer",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "sample",
+                    ExtraType = ExtraType.Sample,
                     RuleType = ExtraRuleType.Filename,
                     Token = "sample",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "sample",
+                    ExtraType = ExtraType.Sample,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-sample",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "sample",
+                    ExtraType = ExtraType.Sample,
                     RuleType = ExtraRuleType.Suffix,
                     Token = ".sample",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "sample",
+                    ExtraType = ExtraType.Sample,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "_sample",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "sample",
+                    ExtraType = ExtraType.Sample,
                     RuleType = ExtraRuleType.Suffix,
                     Token = " sample",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "themesong",
+                    ExtraType = ExtraType.ThemeSong,
                     RuleType = ExtraRuleType.Filename,
                     Token = "theme",
                     MediaType = MediaType.Audio
                 },
                 new ExtraRule
                 {
-                    ExtraType = "scene",
+                    ExtraType = ExtraType.Scene,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-scene",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "clip",
+                    ExtraType = ExtraType.Clip,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-clip",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "interview",
+                    ExtraType = ExtraType.Interview,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-interview",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "behindthescenes",
+                    ExtraType = ExtraType.BehindTheScenes,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-behindthescenes",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "deletedscene",
+                    ExtraType = ExtraType.DeletedScene,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-deleted",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "featurette",
+                    ExtraType = ExtraType.Clip,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-featurette",
                     MediaType = MediaType.Video
                 },
                 new ExtraRule
                 {
-                    ExtraType = "short",
+                    ExtraType = ExtraType.Clip,
                     RuleType = ExtraRuleType.Suffix,
                     Token = "-short",
                     MediaType = MediaType.Video

+ 3 - 2
Emby.Naming/Emby.Naming.csproj

@@ -4,6 +4,7 @@
     <TargetFramework>netstandard2.1</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' " >true</TreatWarningsAsErrors>
   </PropertyGroup>
 
   <ItemGroup>
@@ -21,9 +22,9 @@
     <RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
   </PropertyGroup>
 
-  <!-- Code analysers-->
+  <!-- Code Analyzers-->
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" PrivateAssets="All" />
+    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />

+ 3 - 0
Emby.Naming/Subtitles/SubtitleInfo.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Subtitles
 {
     public class SubtitleInfo

+ 4 - 2
Emby.Naming/Subtitles/SubtitleParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;
@@ -28,7 +31,6 @@ namespace Emby.Naming.Subtitles
             }
 
             var flags = GetFlags(path);
-
             var info = new SubtitleInfo
             {
                 Path = path,
@@ -42,7 +44,7 @@ namespace Emby.Naming.Subtitles
             // Should have a name, language and file extension
             if (parts.Count >= 3)
             {
-                info.Language = parts[parts.Count - 2];
+                info.Language = parts[^2];
             }
 
             return info;

+ 3 - 0
Emby.Naming/TV/EpisodeInfo.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.TV
 {
     public class EpisodeInfo

+ 4 - 1
Emby.Naming/TV/EpisodePathParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -128,7 +131,7 @@ namespace Emby.Naming.TV
                     var endingNumberGroup = match.Groups["endingepnumber"];
                     if (endingNumberGroup.Success)
                     {
-                        // Will only set EndingEpsiodeNumber if the captured number is not followed by additional numbers
+                        // Will only set EndingEpisodeNumber if the captured number is not followed by additional numbers
                         // or a 'p' or 'i' as what you would get with a pixel resolution specification.
                         // It avoids erroneous parsing of something like "series-s09e14-1080p.mkv" as a multi-episode from E14 to E108
                         int nextIndex = endingNumberGroup.Index + endingNumberGroup.Length;

+ 3 - 0
Emby.Naming/TV/EpisodePathParserResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.TV
 {
     public class EpisodePathParserResult

+ 3 - 0
Emby.Naming/TV/EpisodeResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;

+ 3 - 0
Emby.Naming/TV/SeasonPathParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Globalization;
 using System.IO;

+ 3 - 0
Emby.Naming/TV/SeasonPathParserResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.TV
 {
     public class SeasonPathParserResult

+ 18 - 56
Emby.Naming/Video/CleanDateTimeParser.cs

@@ -1,86 +1,48 @@
-using System;
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+#nullable enable
+
+using System.Collections.Generic;
 using System.Globalization;
-using System.IO;
-using System.Linq;
 using System.Text.RegularExpressions;
-using Emby.Naming.Common;
 
 namespace Emby.Naming.Video
 {
     /// <summary>
     /// <see href="http://kodi.wiki/view/Advancedsettings.xml#video" />.
     /// </summary>
-    public class CleanDateTimeParser
+    public static class CleanDateTimeParser
     {
-        private readonly NamingOptions _options;
-
-        public CleanDateTimeParser(NamingOptions options)
-        {
-            _options = options;
-        }
-
-        public CleanDateTimeResult Clean(string name)
+        public static CleanDateTimeResult Clean(string name, IReadOnlyList<Regex> cleanDateTimeRegexes)
         {
-            var originalName = name;
-
-            try
+            CleanDateTimeResult result = new CleanDateTimeResult(name);
+            var len = cleanDateTimeRegexes.Count;
+            for (int i = 0; i < len; i++)
             {
-                var extension = Path.GetExtension(name) ?? string.Empty;
-                // Check supported extensions
-                if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)
-                    && !_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
+                if (TryClean(name, cleanDateTimeRegexes[i], ref result))
                 {
-                    // Dummy up a file extension because the expressions will fail without one
-                    // This is tricky because we can't just check Path.GetExtension for empty
-                    // If the input is "St. Vincent (2014)", it will produce ". Vincent (2014)" as the extension
-                    name += ".mkv";
+                    return result;
                 }
             }
-            catch (ArgumentException)
-            {
-            }
 
-            var result = _options.CleanDateTimeRegexes.Select(i => Clean(name, i))
-                .FirstOrDefault(i => i.HasChanged) ??
-                new CleanDateTimeResult { Name = originalName };
-
-            if (result.HasChanged)
-            {
-                return result;
-            }
-
-            // Make a second pass, running clean string first
-            var cleanStringResult = new CleanStringParser().Clean(name, _options.CleanStringRegexes);
-
-            if (!cleanStringResult.HasChanged)
-            {
-                return result;
-            }
-
-            return _options.CleanDateTimeRegexes.Select(i => Clean(cleanStringResult.Name, i))
-                .FirstOrDefault(i => i.HasChanged) ??
-                result;
+            return result;
         }
 
-        private static CleanDateTimeResult Clean(string name, Regex expression)
+        private static bool TryClean(string name, Regex expression, ref CleanDateTimeResult result)
         {
-            var result = new CleanDateTimeResult();
-
             var match = expression.Match(name);
 
             if (match.Success
-                && match.Groups.Count == 4
+                && match.Groups.Count == 5
                 && match.Groups[1].Success
                 && match.Groups[2].Success
                 && int.TryParse(match.Groups[2].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year))
             {
-                name = match.Groups[1].Value;
-                result.Year = year;
-                result.HasChanged = true;
+                result = new CleanDateTimeResult(match.Groups[1].Value.TrimEnd(), year);
+                return true;
             }
 
-            result.Name = name;
-            return result;
+            return false;
         }
     }
 }

+ 22 - 10
Emby.Naming/Video/CleanDateTimeResult.cs

@@ -1,21 +1,33 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+#nullable enable
+
 namespace Emby.Naming.Video
 {
-    public class CleanDateTimeResult
+    public readonly struct CleanDateTimeResult
     {
+        public CleanDateTimeResult(string name, int? year)
+        {
+            Name = name;
+            Year = year;
+        }
+
+        public CleanDateTimeResult(string name)
+        {
+            Name = name;
+            Year = null;
+        }
+
         /// <summary>
-        /// Gets or sets the name.
+        /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name { get; set; }
+        public string Name { get; }
+
         /// <summary>
-        /// Gets or sets the year.
+        /// Gets the year.
         /// </summary>
         /// <value>The year.</value>
-        public int? Year { get; set; }
-        /// <summary>
-        /// Gets or sets a value indicating whether this instance has changed.
-        /// </summary>
-        /// <value><c>true</c> if this instance has changed; otherwise, <c>false</c>.</value>
-        public bool HasChanged { get; set; }
+        public int? Year { get; }
     }
 }

+ 21 - 25
Emby.Naming/Video/CleanStringParser.cs

@@ -1,49 +1,45 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+#nullable enable
+
+using System;
 using System.Collections.Generic;
 using System.Text.RegularExpressions;
 
 namespace Emby.Naming.Video
 {
     /// <summary>
-    /// http://kodi.wiki/view/Advancedsettings.xml#video
+    /// <see href="http://kodi.wiki/view/Advancedsettings.xml#video" />.
     /// </summary>
-    public class CleanStringParser
+    public static class CleanStringParser
     {
-        public CleanStringResult Clean(string name, IEnumerable<Regex> expressions)
+        public static bool TryClean(string name, IReadOnlyList<Regex> expressions, out ReadOnlySpan<char> newName)
         {
-            var hasChanged = false;
-
-            foreach (var exp in expressions)
+            var len = expressions.Count;
+            for (int i = 0; i < len; i++)
             {
-                var result = Clean(name, exp);
-
-                if (!string.IsNullOrEmpty(result.Name))
+                if (TryClean(name, expressions[i], out newName))
                 {
-                    name = result.Name;
-                    hasChanged = hasChanged || result.HasChanged;
+                    return true;
                 }
             }
 
-            return new CleanStringResult
-            {
-                Name = name,
-                HasChanged = hasChanged
-            };
+            newName = ReadOnlySpan<char>.Empty;
+            return false;
         }
 
-        private static CleanStringResult Clean(string name, Regex expression)
+        private static bool TryClean(string name, Regex expression, out ReadOnlySpan<char> newName)
         {
-            var result = new CleanStringResult();
-
             var match = expression.Match(name);
-
-            if (match.Success)
+            int index = match.Index;
+            if (match.Success && index != 0)
             {
-                result.HasChanged = true;
-                name = name.Substring(0, match.Index);
+                newName = name.AsSpan().Slice(0, match.Index);
+                return true;
             }
 
-            result.Name = name;
-            return result;
+            newName = string.Empty;
+            return false;
         }
     }
 }

+ 0 - 16
Emby.Naming/Video/CleanStringResult.cs

@@ -1,16 +0,0 @@
-namespace Emby.Naming.Video
-{
-    public class CleanStringResult
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-        /// <summary>
-        /// Gets or sets a value indicating whether this instance has changed.
-        /// </summary>
-        /// <value><c>true</c> if this instance has changed; otherwise, <c>false</c>.</value>
-        public bool HasChanged { get; set; }
-    }
-}

+ 4 - 1
Emby.Naming/Video/ExtraResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;
@@ -20,7 +23,7 @@ namespace Emby.Naming.Video
         {
             return _options.VideoExtraRules
                 .Select(i => GetExtraInfo(path, i))
-                .FirstOrDefault(i => !string.IsNullOrEmpty(i.ExtraType)) ?? new ExtraResult();
+                .FirstOrDefault(i => i.ExtraType != null) ?? new ExtraResult();
         }
 
         private ExtraResult GetExtraInfo(string path, ExtraRule rule)

+ 7 - 1
Emby.Naming/Video/ExtraResult.cs

@@ -1,3 +1,8 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
+using MediaBrowser.Model.Entities;
+
 namespace Emby.Naming.Video
 {
     public class ExtraResult
@@ -6,7 +11,8 @@ namespace Emby.Naming.Video
         /// Gets or sets the type of the extra.
         /// </summary>
         /// <value>The type of the extra.</value>
-        public string ExtraType { get; set; }
+        public ExtraType? ExtraType { get; set; }
+
         /// <summary>
         /// Gets or sets the rule.
         /// </summary>

+ 9 - 2
Emby.Naming/Video/ExtraRule.cs

@@ -1,4 +1,8 @@
-using Emby.Naming.Common;
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
+using MediaBrowser.Model.Entities;
+using MediaType = Emby.Naming.Common.MediaType;
 
 namespace Emby.Naming.Video
 {
@@ -9,16 +13,19 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value>The token.</value>
         public string Token { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the extra.
         /// </summary>
         /// <value>The type of the extra.</value>
-        public string ExtraType { get; set; }
+        public ExtraType ExtraType { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the rule.
         /// </summary>
         /// <value>The type of the rule.</value>
         public ExtraRuleType RuleType { get; set; }
+
         /// <summary>
         /// Gets or sets the type of the media.
         /// </summary>

+ 5 - 0
Emby.Naming/Video/ExtraRuleType.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Video
 {
     public enum ExtraRuleType
@@ -6,10 +9,12 @@ namespace Emby.Naming.Video
         /// The suffix
         /// </summary>
         Suffix = 0,
+
         /// <summary>
         /// The filename
         /// </summary>
         Filename = 1,
+
         /// <summary>
         /// The regex
         /// </summary>

+ 9 - 4
Emby.Naming/Video/FileStack.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -6,15 +9,17 @@ namespace Emby.Naming.Video
 {
     public class FileStack
     {
-        public string Name { get; set; }
-        public List<string> Files { get; set; }
-        public bool IsDirectoryStack { get; set; }
-
         public FileStack()
         {
             Files = new List<string>();
         }
 
+        public string Name { get; set; }
+
+        public List<string> Files { get; set; }
+
+        public bool IsDirectoryStack { get; set; }
+
         public bool ContainsFile(string file, bool isDirectory)
         {
             if (IsDirectoryStack == isDirectory)

+ 3 - 0
Emby.Naming/Video/FlagParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using Emby.Naming.Common;

+ 3 - 0
Emby.Naming/Video/Format3DParser.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Linq;
 using Emby.Naming.Common;

+ 3 - 0
Emby.Naming/Video/Format3DResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System.Collections.Generic;
 
 namespace Emby.Naming.Video

+ 4 - 0
Emby.Naming/Video/Format3DRule.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Video
 {
     public class Format3DRule
@@ -7,6 +10,7 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value>The token.</value>
         public string Token { get; set; }
+
         /// <summary>
         /// Gets or sets the preceeding token.
         /// </summary>

+ 3 - 0
Emby.Naming/Video/StackResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Collections.Generic;
 using System.IO;

+ 3 - 0
Emby.Naming/Video/StackResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System.Collections.Generic;
 
 namespace Emby.Naming.Video

+ 5 - 2
Emby.Naming/Video/StubResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;
@@ -11,14 +14,14 @@ namespace Emby.Naming.Video
         {
             if (path == null)
             {
-                return default(StubResult);
+                return default;
             }
 
             var extension = Path.GetExtension(path);
 
             if (!options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
             {
-                return default(StubResult);
+                return default;
             }
 
             var result = new StubResult()

+ 3 - 0
Emby.Naming/Video/StubResult.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Video
 {
     public struct StubResult

+ 3 - 0
Emby.Naming/Video/StubTypeRule.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 namespace Emby.Naming.Video
 {
     public class StubTypeRule

+ 5 - 2
Emby.Naming/Video/VideoFileInfo.cs

@@ -1,3 +1,5 @@
+using MediaBrowser.Model.Entities;
+
 namespace Emby.Naming.Video
 {
     /// <summary>
@@ -30,10 +32,10 @@ namespace Emby.Naming.Video
         public int? Year { get; set; }
 
         /// <summary>
-        /// Gets or sets the type of the extra, e.g. trailer, theme song, behing the scenes, etc.
+        /// Gets or sets the type of the extra, e.g. trailer, theme song, behind the scenes, etc.
         /// </summary>
         /// <value>The type of the extra.</value>
-        public string ExtraType { get; set; }
+        public ExtraType? ExtraType { get; set; }
 
         /// <summary>
         /// Gets or sets the extra rule.
@@ -77,6 +79,7 @@ namespace Emby.Naming.Video
         /// <value>The file name without extension.</value>
         public string FileNameWithoutExtension => !IsDirectory ? System.IO.Path.GetFileNameWithoutExtension(Path) : System.IO.Path.GetFileName(Path);
 
+        /// <inheritdoc />
         public override string ToString()
         {
             // Makes debugging easier

+ 10 - 7
Emby.Naming/Video/VideoInfo.cs

@@ -7,6 +7,16 @@ namespace Emby.Naming.Video
     /// </summary>
     public class VideoInfo
     {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="VideoInfo" /> class.
+        /// </summary>
+        public VideoInfo()
+        {
+            Files = new List<VideoFileInfo>();
+            Extras = new List<VideoFileInfo>();
+            AlternateVersions = new List<VideoFileInfo>();
+        }
+
         /// <summary>
         /// Gets or sets the name.
         /// </summary>
@@ -36,12 +46,5 @@ namespace Emby.Naming.Video
         /// </summary>
         /// <value>The alternate versions.</value>
         public List<VideoFileInfo> AlternateVersions { get; set; }
-
-        public VideoInfo()
-        {
-            Files = new List<VideoFileInfo>();
-            Extras = new List<VideoFileInfo>();
-            AlternateVersions = new List<VideoFileInfo>();
-        }
     }
 }

+ 8 - 4
Emby.Naming/Video/VideoListResolver.cs

@@ -1,9 +1,13 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Text.RegularExpressions;
 using Emby.Naming.Common;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 
 namespace Emby.Naming.Video
@@ -29,7 +33,7 @@ namespace Emby.Naming.Video
             // Filter out all extras, otherwise they could cause stacks to not be resolved
             // See the unit test TestStackedWithTrailer
             var nonExtras = videoInfos
-                .Where(i => string.IsNullOrEmpty(i.ExtraType))
+                .Where(i => i.ExtraType == null)
                 .Select(i => new FileSystemMetadata
                 {
                     FullName = i.Path,
@@ -76,7 +80,7 @@ namespace Emby.Naming.Video
             }
 
             var standaloneMedia = remainingFiles
-                .Where(i => string.IsNullOrEmpty(i.ExtraType))
+                .Where(i => i.ExtraType == null)
                 .ToList();
 
             foreach (var media in standaloneMedia)
@@ -145,7 +149,7 @@ namespace Emby.Naming.Video
             if (list.Count == 1)
             {
                 var trailers = remainingFiles
-                    .Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase))
+                    .Where(i => i.ExtraType == ExtraType.Trailer)
                     .ToList();
 
                 list[0].Extras.AddRange(trailers);
@@ -226,7 +230,7 @@ namespace Emby.Naming.Video
             }
 
             return remainingFiles
-                .Where(i => !string.IsNullOrEmpty(i.ExtraType))
+                .Where(i => i.ExtraType == null)
                 .Where(i => baseNames.Any(b => i.FileNameWithoutExtension.StartsWith(b, StringComparison.OrdinalIgnoreCase)))
                 .ToList();
         }

+ 9 - 5
Emby.Naming/Video/VideoResolver.cs

@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
 using System;
 using System.IO;
 using System.Linq;
@@ -91,9 +94,10 @@ namespace Emby.Naming.Video
             {
                 var cleanDateTimeResult = CleanDateTime(name);
 
-                if (string.IsNullOrEmpty(extraResult.ExtraType))
+                if (extraResult.ExtraType == null
+                    && TryCleanString(cleanDateTimeResult.Name, out ReadOnlySpan<char> newName))
                 {
-                    name = CleanString(cleanDateTimeResult.Name).Name;
+                    name = newName.ToString();
                 }
 
                 year = cleanDateTimeResult.Year;
@@ -127,14 +131,14 @@ namespace Emby.Naming.Video
             return _options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
         }
 
-        public CleanStringResult CleanString(string name)
+        public bool TryCleanString(string name, out ReadOnlySpan<char> newName)
         {
-            return new CleanStringParser().Clean(name, _options.CleanStringRegexes);
+            return CleanStringParser.TryClean(name, _options.CleanStringRegexes, out newName);
         }
 
         public CleanDateTimeResult CleanDateTime(string name)
         {
-            return new CleanDateTimeParser(_options).Clean(name);
+            return CleanDateTimeParser.Clean(name, _options.CleanDateTimeRegexes);
         }
     }
 }

+ 5 - 5
Emby.Photos/Emby.Photos.csproj

@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk">
-
   <ItemGroup>
     <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
@@ -21,11 +20,12 @@
     <Nullable>enable</Nullable>
   </PropertyGroup>
 
-  <!-- Code analysers-->
+  <!-- Code Analyzers-->
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
-    <PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
+    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+    <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+    <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
 
   <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

+ 1 - 0
Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs

@@ -1,4 +1,5 @@
 #pragma warning disable CS1591
+#pragma warning disable SA1600
 
 using System;
 using System.Collections.Generic;

+ 1 - 1
Emby.Server.Implementations/Activity/ActivityManager.cs

@@ -1,7 +1,7 @@
 #pragma warning disable CS1591
+#pragma warning disable SA1600
 
 using System;
-using System.Linq;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Activity;
 using MediaBrowser.Model.Events;

+ 1 - 0
Emby.Server.Implementations/Activity/ActivityRepository.cs

@@ -1,4 +1,5 @@
 #pragma warning disable CS1591
+#pragma warning disable SA1600
 
 using System;
 using System.Collections.Generic;

+ 37 - 48
Emby.Server.Implementations/ApplicationHost.cs

@@ -1,4 +1,5 @@
 #pragma warning disable CS1591
+#pragma warning disable SA1600
 
 using System;
 using System.Collections.Concurrent;
@@ -103,14 +104,11 @@ using MediaBrowser.Providers.Subtitles;
 using MediaBrowser.Providers.TV.TheTVDB;
 using MediaBrowser.WebDashboard.Api;
 using MediaBrowser.XbmcMetadata.Providers;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
-using Microsoft.OpenApi.Models;
 using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
 
 namespace Emby.Server.Implementations
@@ -180,11 +178,7 @@ namespace Emby.Server.Implementations
         /// Gets the plugins.
         /// </summary>
         /// <value>The plugins.</value>
-        public IPlugin[] Plugins
-        {
-            get => _plugins;
-            protected set => _plugins = value;
-        }
+        public IReadOnlyList<IPlugin> Plugins => _plugins;
 
         /// <summary>
         /// Gets or sets the logger factory.
@@ -605,7 +599,7 @@ namespace Emby.Server.Implementations
                 HttpsPort = ServerConfiguration.DefaultHttpsPort;
             }
 
-            JsonSerializer = new JsonSerializer(FileSystemManager);
+            JsonSerializer = new JsonSerializer();
 
             if (Plugins != null)
             {
@@ -764,9 +758,8 @@ namespace Emby.Server.Implementations
             LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
             serviceCollection.AddSingleton(LibraryManager);
 
-            // TODO wtaylor: investigate use of second music manager
             var musicManager = new MusicManager(LibraryManager);
-            serviceCollection.AddSingleton<IMusicManager>(new MusicManager(LibraryManager));
+            serviceCollection.AddSingleton<IMusicManager>(musicManager);
 
             LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager);
             serviceCollection.AddSingleton(LibraryMonitor);
@@ -879,6 +872,8 @@ namespace Emby.Server.Implementations
             serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager));
             serviceCollection.AddSingleton<EncodingHelper>();
 
+            serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor));
+
             _displayPreferencesRepository.Initialize();
 
             var userDataRepo = new SqliteUserDataRepository(LoggerFactory.CreateLogger<SqliteUserDataRepository>(), ApplicationPaths);
@@ -1012,7 +1007,7 @@ namespace Emby.Server.Implementations
         {
             string dir = Path.Combine(ApplicationPaths.PluginsPath, args.Argument.name);
             var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories)
-                        .Select(x => Assembly.LoadFrom(x))
+                        .Select(Assembly.LoadFrom)
                         .SelectMany(x => x.ExportedTypes)
                         .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType)
                         .ToArray();
@@ -1058,7 +1053,7 @@ namespace Emby.Server.Implementations
             }
 
             ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
-            Plugins = GetExports<IPlugin>()
+            _plugins = GetExports<IPlugin>()
                         .Select(LoadPlugin)
                         .Where(i => i != null)
                         .ToArray();
@@ -1479,7 +1474,7 @@ namespace Emby.Server.Implementations
         /// </summary>
         /// <param name="address">The IPv6 address.</param>
         /// <returns>The IPv6 address without the scope id.</returns>
-        private string RemoveScopeId(string address)
+        private ReadOnlySpan<char> RemoveScopeId(ReadOnlySpan<char> address)
         {
             var index = address.IndexOf('%');
             if (index == -1)
@@ -1487,33 +1482,50 @@ namespace Emby.Server.Implementations
                 return address;
             }
 
-            return address.Substring(0, index);
+            return address.Slice(0, index);
         }
 
+        /// <inheritdoc />
         public string GetLocalApiUrl(IPAddress ipAddress)
         {
             if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
             {
                 var str = RemoveScopeId(ipAddress.ToString());
+                Span<char> span = new char[str.Length + 2];
+                span[0] = '[';
+                str.CopyTo(span.Slice(1));
+                span[^1] = ']';
 
-                return GetLocalApiUrl("[" + str + "]");
+                return GetLocalApiUrl(span);
             }
 
             return GetLocalApiUrl(ipAddress.ToString());
         }
 
-        public string GetLocalApiUrl(string host)
+        /// <inheritdoc />
+        public string GetLocalApiUrl(ReadOnlySpan<char> host)
         {
+            var url = new StringBuilder(64);
             if (EnableHttps)
             {
-                return string.Format("https://{0}:{1}",
-                    host,
-                    HttpsPort.ToString(CultureInfo.InvariantCulture));
+                url.Append("https://");
+            }
+            else
+            {
+                url.Append("http://");
+            }
+
+            url.Append(host)
+                .Append(':')
+                .Append(HttpPort);
+
+            string baseUrl = ServerConfigurationManager.Configuration.BaseUrl;
+            if (baseUrl.Length != 0)
+            {
+                url.Append('/').Append(baseUrl);
             }
 
-            return string.Format("http://{0}:{1}",
-                    host,
-                    HttpPort.ToString(CultureInfo.InvariantCulture));
+            return url.ToString();
         }
 
         public Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken)
@@ -1690,32 +1702,9 @@ namespace Emby.Server.Implementations
         /// <param name="plugin">The plugin.</param>
         public void RemovePlugin(IPlugin plugin)
         {
-            var list = Plugins.ToList();
+            var list = _plugins.ToList();
             list.Remove(plugin);
-            Plugins = list.ToArray();
-        }
-
-        /// <summary>
-        /// This returns localhost in the case of no external dns, and the hostname if the
-        /// dns is prefixed with a valid Uri prefix.
-        /// </summary>
-        /// <param name="externalDns">The external dns prefix to get the hostname of.</param>
-        /// <returns>The hostname in <paramref name="externalDns"/>.</returns>
-        private static string GetHostnameFromExternalDns(string externalDns)
-        {
-            if (string.IsNullOrEmpty(externalDns))
-            {
-                return "localhost";
-            }
-
-            try
-            {
-                return new Uri(externalDns).Host;
-            }
-            catch
-            {
-                return externalDns;
-            }
+            _plugins = list.ToArray();
         }
 
         public virtual void LaunchUrl(string url)

部分文件因为文件数量过多而无法显示