MP-MediaInfo icon indicating copy to clipboard operation
MP-MediaInfo copied to clipboard

Streaming/Byte-Wise usage

Open kreditor0815 opened this issue 4 years ago • 0 comments

Hi there,

is it possible to use the wrapper on a streaming/byte-wise usage? On an older version of your wrapper, i made some modifications to be able to push byte-arrays of the file contents into a method and get the mediainfo after i have pushed all data from file to this method. But that was 1+ years ago and i'm not able to maintain this "private fork". So i wanted to know, if this is possible with the current version of your wrapper. Basically i was utilizing "OpenBufferContinue" with "Option("File_IsSeekable", "0");" and "OpenBufferInit(FileSize, 0L);".

Why have i done this? I have some larger files i need to get media info from. Beside this, i also calculate some other file hashes of these files. Because of that, i do read those files byte per byte and push those bytes to the "consumers" i need/want to have informations from.

My modified MediaInfoWrapper.cs: Methods of interest should be:

  • public MediaInfoWrapper(long FileSize, string pathToDll, ILogger logger = null)
  • public bool AddBytesToRead(byte[] bytesToRead, int offset, int length)
  • public bool FinalizeReadBytes()
  • private void ExtractInfo(Stream FileStream, string pathToDll, NumberFormatInfo providerNumber)
using MediaInfo.Builder;
using MediaInfo.Model;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;

namespace MediaInfo
{
  public class MediaInfoWrapper
  {
    private static readonly Dictionary<string, bool> SubTitleExtensions = new Dictionary<string, bool>()
    {
      {
        ".AQT",
        true
      },
      {
        ".ASC",
        true
      },
      {
        ".ASS",
        true
      },
      {
        ".DAT",
        true
      },
      {
        ".DKS",
        true
      },
      {
        ".IDX",
        true
      },
      {
        ".JS",
        true
      },
      {
        ".JSS",
        true
      },
      {
        ".LRC",
        true
      },
      {
        ".MPL",
        true
      },
      {
        ".OVR",
        true
      },
      {
        ".PAN",
        true
      },
      {
        ".PJS",
        true
      },
      {
        ".PSB",
        true
      },
      {
        ".RT",
        true
      },
      {
        ".RTF",
        true
      },
      {
        ".S2K",
        true
      },
      {
        ".SBT",
        true
      },
      {
        ".SCR",
        true
      },
      {
        ".SMI",
        true
      },
      {
        ".SON",
        true
      },
      {
        ".SRT",
        true
      },
      {
        ".SSA",
        true
      },
      {
        ".SST",
        true
      },
      {
        ".SSTS",
        true
      },
      {
        ".STL",
        true
      },
      {
        ".SUB",
        true
      },
      {
        ".TXT",
        true
      },
      {
        ".VKT",
        true
      },
      {
        ".VSF",
        true
      },
      {
        ".ZEG",
        true
      }
    };
    private readonly ILogger _logger;
    private readonly string _filePath;
    private readonly bool Is64BitProcess;
    private readonly string RealPathToDll;
    private readonly MediaInfo.MediaInfo _mi;

    public MediaInfoWrapper(string filePath, ILogger logger = null)
      : this(filePath, Environment.Is64BitProcess ? ".\\x64" : ".\\x86", logger)
    {
    }

    public MediaInfoWrapper(string filePath, string pathToDll, ILogger logger)
    {
      this._filePath = filePath;
      this._logger = logger;
      logger.LogDebug("Analyzing media {0}.", (object) filePath);
      this.VideoStreams = (IList<VideoStream>) new List<VideoStream>();
      this.AudioStreams = (IList<AudioStream>) new List<AudioStream>();
      this.Subtitles = (IList<SubtitleStream>) new List<SubtitleStream>();
      this.Chapters = (IList<ChapterStream>) new List<ChapterStream>();
      this.MenuStreams = (IList<MenuStream>) new List<MenuStream>();
      if (string.IsNullOrEmpty(filePath))
      {
        this.MediaInfoNotloaded = true;
        logger.LogError("Media file name to processing is null or empty");
      }
      else
      {
        string pathToDll1 = ((string) null).IfExistsPath("./", logger).IfExistsPath(pathToDll, logger).IfExistsPath(Path.GetDirectoryName(typeof (MediaInfoWrapper).Assembly.Location), logger).IfExistsPath(Path.IsPathRooted(pathToDll) ? (string) null : Path.Combine(Path.GetDirectoryName(typeof (MediaInfoWrapper).Assembly.Location), pathToDll), logger);
        if (string.IsNullOrEmpty(pathToDll1))
        {
          logger.LogError("MediaInfo.dll was not found");
          this.MediaInfoNotloaded = true;
        }
        else
        {
          bool flag1 = filePath.IsLiveTv();
          bool flag2 = filePath.IsLiveTv();
          bool flag3 = filePath.IsRtsp();
          bool flag4 = filePath.IsAvStream();
          if (flag3)
          {
            this.MediaInfoNotloaded = true;
            logger.LogInformation("Media file is RTSP");
          }
          else
          {
            if (flag2 | flag1)
            {
              string[] files = Directory.GetFiles(Path.GetDirectoryName(filePath), Path.GetFileName(filePath) + "*.ts");
              if ((uint) files.Length > 0U)
              {
                filePath = files[0];
              }
              else
              {
                this.MediaInfoNotloaded = true;
                logger.LogInformation("Media file is " + (flag1 ? "TV" : (flag2 ? "radio" : (flag3 ? "RTSP" : string.Empty))));
                return;
              }
            }
            NumberFormatInfo providerNumber = new NumberFormatInfo()
            {
              NumberDecimalSeparator = "."
            };
            try
            {
              if (!flag4)
              {
                if (filePath.EndsWith(".ifo", StringComparison.OrdinalIgnoreCase))
                {
                  this._logger.LogDebug("Detects DVD. Processing DVD information");
                  filePath = this.ProcessDvd(filePath, pathToDll1, providerNumber);
                }
                else if (filePath.EndsWith(".bdmv", StringComparison.OrdinalIgnoreCase))
                {
                  this._logger.LogDebug("Detects BD.");
                  this.IsBluRay = true;
                  filePath = Path.GetDirectoryName(filePath);
                  this.Size = MediaInfoWrapper.GetDirectorySize(filePath);
                }
                else
                  this.Size = new FileInfo(filePath).Length;
                this.HasExternalSubtitles = !string.IsNullOrEmpty(filePath) && MediaInfoWrapper.CheckHasExternalSubtitles(filePath);
                if (this.HasExternalSubtitles)
                  this._logger.LogDebug("Found external subtitles");
              }
              this.ExtractInfo(filePath, pathToDll1, providerNumber);
              logger.LogDebug(string.Format("Process file {0} was completed successfully. Video={1}, Audio={2}, Subtitle={3}", (object) filePath, (object) this.VideoStreams.Count, (object) this.AudioStreams.Count, (object) this.Subtitles.Count));
            }
            catch (Exception ex)
            {
              logger.LogError(ex, "Error processing media file");
            }
          }
        }
      }
    }

    public void WriteInfo()
    {
      this._logger.LogInformation("Inspecting media    : " + this._filePath);
      if (this.MediaInfoNotloaded)
      {
        this._logger.LogWarning("MediaInfo.dll was not loaded!");
      }
      else
      {
        this._logger.LogDebug("DLL version         : " + this.Version);
        this._logger.LogDebug(string.Format("Media duration      : {0}", (object) TimeSpan.FromMilliseconds((double) this.Duration)));
        ILogger logger1 = this._logger;
        IList<AudioStream> audioStreams1 = this.AudioStreams;
        string message1 = string.Format("Has audio           : {0}", (object) ((audioStreams1 != null ? audioStreams1.Count : 0) > 0));
        object[] objArray1 = new object[0];
        logger1.LogDebug(message1, objArray1);
        this._logger.LogDebug(string.Format("Has video           : {0}", (object) this.HasVideo));
        this._logger.LogDebug(string.Format("Has subtitles       : {0}", (object) this.HasSubtitles));
        this._logger.LogDebug(string.Format("Has chapters        : {0}", (object) this.HasChapters));
        this._logger.LogDebug(string.Format("Is DVD              : {0}", (object) this.IsDvd));
        this._logger.LogDebug(string.Format("Is Blu-Ray disk     : {0}", (object) this.IsBluRay));
        if (this.HasVideo)
        {
          ILogger logger2 = this._logger;
          VideoStream bestVideoStream1 = this.BestVideoStream;
          string message2 = string.Format("Video duration      : {0}", (object) (bestVideoStream1 != null ? bestVideoStream1.Duration : TimeSpan.MinValue));
          object[] objArray2 = new object[0];
          logger2.LogDebug(message2, objArray2);
          this._logger.LogDebug(string.Format("Video frame rate    : {0}", (object) this.Framerate));
          this._logger.LogDebug(string.Format("Video width         : {0}", (object) this.Width));
          this._logger.LogDebug(string.Format("Video height        : {0}", (object) this.Height));
          this._logger.LogDebug("Video aspect ratio  : " + this.AspectRatio);
          this._logger.LogDebug("Video codec         : " + this.VideoCodec);
          this._logger.LogDebug("Video scan type     : " + this.ScanType);
          this._logger.LogDebug(string.Format("Is video interlaced : {0}", (object) this.IsInterlaced));
          this._logger.LogDebug("Video resolution    : " + this.VideoResolution);
          ILogger logger3 = this._logger;
          VideoStream bestVideoStream2 = this.BestVideoStream;
          string message3 = string.Format("Video 3D mode       : {0}", (object) (StereoMode) (bestVideoStream2 != null ? (int) bestVideoStream2.Stereoscopic : 0));
          object[] objArray3 = new object[0];
          logger3.LogDebug(message3, objArray3);
          ILogger logger4 = this._logger;
          VideoStream bestVideoStream3 = this.BestVideoStream;
          string message4 = string.Format("Video HDR standard  : {0}", (object) (Hdr) (bestVideoStream3 != null ? (int) bestVideoStream3.Hdr : 0));
          object[] objArray4 = new object[0];
          logger4.LogDebug(message4, objArray4);
        }
        IList<AudioStream> audioStreams2 = this.AudioStreams;
        if ((audioStreams2 != null ? audioStreams2.Count : 0) > 0)
        {
          ILogger logger5 = this._logger;
          AudioStream bestAudioStream1 = this.BestAudioStream;
          string message5 = string.Format("Audio duration      : {0}", (object) (bestAudioStream1 != null ? bestAudioStream1.Duration : TimeSpan.MinValue));
          object[] objArray5 = new object[0];
          logger5.LogDebug(message5, objArray5);
          this._logger.LogDebug(string.Format("Audio rate          : {0}", (object) this.AudioRate));
          this._logger.LogDebug("Audio channels      : " + this.AudioChannelsFriendly);
          this._logger.LogDebug("Audio codec         : " + this.AudioCodec);
          ILogger logger6 = this._logger;
          AudioStream bestAudioStream2 = this.BestAudioStream;
          string message6 = string.Format("Audio bit depth     : {0}", (object) (bestAudioStream2 != null ? bestAudioStream2.BitDepth : 0));
          object[] objArray6 = new object[0];
          logger6.LogDebug(message6, objArray6);
        }
        if (this.HasSubtitles)
        {
          ILogger logger7 = this._logger;
          IList<SubtitleStream> subtitles = this.Subtitles;
          string message7 = string.Format("Subtitles count     : {0}", (object) (subtitles != null ? subtitles.Count : 0));
          object[] objArray7 = new object[0];
          logger7.LogDebug(message7, objArray7);
        }
        if (this.HasChapters)
        {
          ILogger logger8 = this._logger;
          IList<ChapterStream> chapters = this.Chapters;
          string message8 = string.Format("Chapters count      : {0}", (object) (chapters != null ? chapters.Count : 0));
          object[] objArray8 = new object[0];
          logger8.LogDebug(message8, objArray8);
        }
      }
    }

    private static long GetDirectorySize(string folderName) => !Directory.Exists(folderName) ? 0L : ((IEnumerable<string>) Directory.GetFiles(folderName)).Sum<string>((Func<string, long>) (x => new FileInfo(x).Length)) + ((IEnumerable<string>) Directory.GetDirectories(folderName)).Sum<string>((Func<string, long>) (x => MediaInfoWrapper.GetDirectorySize(x)));

    private string ProcessDvd(string filePath, string pathToDll, NumberFormatInfo providerNumber)
    {
      this.IsDvd = true;
      string str = Path.GetDirectoryName(filePath) ?? string.Empty;
      this.Size = MediaInfoWrapper.GetDirectorySize(str);
      string[] files = Directory.GetFiles(str, "*.BUP", SearchOption.TopDirectoryOnly);
      List<Tuple<string, int>> source = new List<Tuple<string, int>>();
      foreach (string fileName in files)
      {
        using (MediaInfo.MediaInfo mediaInfo = new MediaInfo.MediaInfo(pathToDll))
        {
          this.Version = mediaInfo.Option("Info_Version");
          mediaInfo.Open(fileName);
          if (mediaInfo.Get(StreamKind.General, 0, "Format_Profile") == "Program")
          {
            double result;
            double.TryParse(mediaInfo.Get(StreamKind.Video, 0, "Duration"), NumberStyles.AllowDecimalPoint, (IFormatProvider) providerNumber, out result);
            source.Add(new Tuple<string, int>(fileName, (int) result));
          }
        }
      }
      if (source.Any<Tuple<string, int>>())
      {
        this.Duration = source.Max<Tuple<string, int>>((Func<Tuple<string, int>, int>) (x => x.Item2));
        filePath = source.First<Tuple<string, int>>((Func<Tuple<string, int>, bool>) (x => x.Item2 == this.Duration)).Item1;
      }
      return filePath;
    }

    private void ExtractInfo(string filePath, string pathToDll, NumberFormatInfo providerNumber)
    {
      using (MediaInfo.MediaInfo mediaInfo = new MediaInfo.MediaInfo(pathToDll))
      {
        if (mediaInfo.Handle == IntPtr.Zero)
        {
          this.MediaInfoNotloaded = true;
          this._logger.LogWarning("MediaInfo library was not loaded!");
        }
        else
        {
          this.Version = mediaInfo.Option("Info_Version");
          this._logger.LogDebug(string.Format("MediaInfo library was loaded. Handle={0} Version is {1}", (object) mediaInfo.Handle, (object) this.Version));
          IntPtr num1 = mediaInfo.Open(filePath);
          if (num1 == IntPtr.Zero)
          {
            this.MediaInfoNotloaded = true;
            this._logger.LogWarning("MediaInfo library has not been opened media " + filePath);
          }
          else
          {
            this._logger.LogDebug(string.Format("MediaInfo library successfully opened {0}. Handle={1}", (object) filePath, (object) num1));
            this.Format = mediaInfo.Get(StreamKind.General, 0, "Format");
            this.Profile = mediaInfo.Get(StreamKind.General, 0, "Format_Profile");
            this.FormatVersion = mediaInfo.Get(StreamKind.General, 0, "Format_Version");
            this.Codec = mediaInfo.Get(StreamKind.General, 0, "CodecID");
            int num2 = 0;
            this.Tags = new AudioTagBuilder(mediaInfo, 0).Build();
            this._logger.LogDebug(string.Format("Found {0} video streams.", (object) mediaInfo.CountGet(StreamKind.Video)));
            for (int position = 0; position < mediaInfo.CountGet(StreamKind.Video); ++position)
              this.VideoStreams.Add(new VideoStreamBuilder(mediaInfo, num2++, position).Build());
            if (this.Duration == 0)
            {
              double result;
              double.TryParse(mediaInfo.Get(StreamKind.Video, 0, 88), NumberStyles.AllowDecimalPoint, (IFormatProvider) providerNumber, out result);
              this.Duration = (int) result;
            }
            object obj1;
            if (this.VideoStreams.Count == 1 && this.Tags.GeneralTags.TryGetValue((NativeMethods.General) 1000, out obj1))
            {
              object obj2;
              this.VideoStreams[0].Stereoscopic = !this.Tags.GeneralTags.TryGetValue((NativeMethods.General) 1001, out obj2) ? ((bool) obj1 ? StereoMode.Stereo : StereoMode.Mono) : (StereoMode) obj2;
            }
            this._logger.LogDebug(string.Format("Found {0} audio streams.", (object) mediaInfo.CountGet(StreamKind.Audio)));
            for (int position = 0; position < mediaInfo.CountGet(StreamKind.Audio); ++position)
              this.AudioStreams.Add(new AudioStreamBuilder(mediaInfo, num2++, position).Build());
            if (this.Duration == 0)
            {
              double result;
              double.TryParse(mediaInfo.Get(StreamKind.Audio, 0, 70), NumberStyles.AllowDecimalPoint, (IFormatProvider) providerNumber, out result);
              this.Duration = (int) result;
            }
            this._logger.LogDebug(string.Format("Found {0} subtitle streams.", (object) mediaInfo.CountGet(StreamKind.Text)));
            for (int position = 0; position < mediaInfo.CountGet(StreamKind.Text); ++position)
              this.Subtitles.Add(new SubtitleStreamBuilder(mediaInfo, num2++, position).Build());
            this._logger.LogDebug(string.Format("Found {0} chapters.", (object) mediaInfo.CountGet(StreamKind.Other)));
            for (int position = 0; position < mediaInfo.CountGet(StreamKind.Other); ++position)
              this.Chapters.Add(new ChapterStreamBuilder(mediaInfo, num2++, position).Build());
            this._logger.LogDebug(string.Format("Found {0} menu items.", (object) mediaInfo.CountGet(StreamKind.Menu)));
            for (int position = 0; position < mediaInfo.CountGet(StreamKind.Menu); ++position)
              this.MenuStreams.Add(new MenuStreamBuilder(mediaInfo, num2++, position).Build());
            this.MediaInfoNotloaded = this.VideoStreams.Count == 0 && this.AudioStreams.Count == 0 && this.Subtitles.Count == 0;
            if (this.MediaInfoNotloaded)
              this.SetPropertiesDefault();
            else
              this.SetupProperties(mediaInfo);
          }
        }
      }
    }

    private void SetPropertiesDefault()
    {
      this.VideoCodec = string.Empty;
      this.VideoResolution = string.Empty;
      this.ScanType = string.Empty;
      this.AspectRatio = string.Empty;
      this.AudioCodec = string.Empty;
      this.AudioChannelsFriendly = string.Empty;
    }

    private void SetupProperties(MediaInfo.MediaInfo mediaInfo)
    {
      this.BestVideoStream = this.VideoStreams.OrderByDescending<VideoStream, double>((Func<VideoStream, double>) (x => (double) ((long) x.Width * (long) x.Height * (long) x.BitDepth * (x.Stereoscopic == StereoMode.Mono ? 1L : 2L)) * x.FrameRate * (x.Bitrate <= 1E-07 ? 1.0 : x.Bitrate))).FirstOrDefault<VideoStream>();
      this.VideoCodec = this.BestVideoStream?.CodecName ?? string.Empty;
      double? nullable1 = this.BestVideoStream?.Bitrate;
      int? nullable2 = nullable1.HasValue ? new int?((int) nullable1.GetValueOrDefault()) : new int?();
      this.VideoRate = nullable2.GetValueOrDefault();
      this.VideoResolution = this.BestVideoStream?.Resolution ?? string.Empty;
      VideoStream bestVideoStream1 = this.BestVideoStream;
      this.Width = bestVideoStream1 != null ? bestVideoStream1.Width : 0;
      VideoStream bestVideoStream2 = this.BestVideoStream;
      this.Height = bestVideoStream2 != null ? bestVideoStream2.Height : 0;
      VideoStream bestVideoStream3 = this.BestVideoStream;
      this.IsInterlaced = bestVideoStream3 != null && bestVideoStream3.Interlaced;
      VideoStream bestVideoStream4 = this.BestVideoStream;
      this.Framerate = bestVideoStream4 != null ? bestVideoStream4.FrameRate : 0.0;
      this.ScanType = this.BestVideoStream != null ? mediaInfo.Get(StreamKind.Video, this.BestVideoStream.StreamPosition, "ScanType").ToLower() : string.Empty;
      this.AspectRatio = this.BestVideoStream != null ? mediaInfo.Get(StreamKind.Video, this.BestVideoStream.StreamPosition, "DisplayAspectRatio") : string.Empty;
      this.AspectRatio = this.BestVideoStream != null ? (this.AspectRatio == "4:3" || this.AspectRatio == "1.333" ? "fullscreen" : "widescreen") : string.Empty;
      this.BestAudioStream = this.AudioStreams.OrderByDescending<AudioStream, double>((Func<AudioStream, double>) (x => (double) (x.Channel * 10000000) + x.Bitrate)).FirstOrDefault<AudioStream>();
      this.AudioCodec = this.BestAudioStream?.CodecName ?? string.Empty;
      nullable1 = this.BestAudioStream?.Bitrate;
      int? nullable3;
      if (!nullable1.HasValue)
      {
        nullable2 = new int?();
        nullable3 = nullable2;
      }
      else
        nullable3 = new int?((int) nullable1.GetValueOrDefault());
      nullable2 = nullable3;
      this.AudioRate = nullable2.GetValueOrDefault();
      nullable1 = this.BestAudioStream?.SamplingRate;
      int? nullable4;
      if (!nullable1.HasValue)
      {
        nullable2 = new int?();
        nullable4 = nullable2;
      }
      else
        nullable4 = new int?((int) nullable1.GetValueOrDefault());
      nullable2 = nullable4;
      this.AudioSampleRate = nullable2.GetValueOrDefault();
      AudioStream bestAudioStream = this.BestAudioStream;
      this.AudioChannels = bestAudioStream != null ? bestAudioStream.Channel : 0;
      this.AudioChannelsFriendly = this.BestAudioStream?.AudioChannelsFriendly ?? string.Empty;
    }

    private static bool CheckHasExternalSubtitles(string strFile)
    {
      if (string.IsNullOrEmpty(strFile))
        return false;
      string withoutExtension = Path.GetFileNameWithoutExtension(strFile);
      try
      {
        return ((IEnumerable<string>) Directory.GetFiles(Path.GetDirectoryName(strFile) ?? string.Empty, withoutExtension + "*")).Select<string, FileInfo>((Func<string, FileInfo>) (file => new FileInfo(file))).Any<FileInfo>((Func<FileInfo, bool>) (fi => MediaInfoWrapper.SubTitleExtensions.ContainsKey(fi.Extension.ToUpper())));
      }
      catch
      {
        return false;
      }
    }

    public bool HasVideo => this.VideoStreams.Count > 0;

    public bool Is3D => this.VideoStreams.Any<VideoStream>((Func<VideoStream, bool>) (x => (uint) x.Stereoscopic > 0U));

    public bool IsHdr => this.VideoStreams.Any<VideoStream>((Func<VideoStream, bool>) (x => (uint) x.Hdr > 0U));

    public IList<VideoStream> VideoStreams { get; }

    public VideoStream BestVideoStream { get; private set; }

    public string VideoCodec { get; private set; }

    public double Framerate { get; private set; }

    public int Width { get; private set; }

    public int Height { get; private set; }

    public string AspectRatio { get; private set; }

    public string ScanType { get; private set; }

    public bool IsInterlaced { get; private set; }

    public string VideoResolution { get; private set; }

    public int VideoRate { get; private set; }

    public IList<AudioStream> AudioStreams { get; }

    public AudioStream BestAudioStream { get; private set; }

    public string AudioCodec { get; private set; }

    public int AudioRate { get; private set; }

    public int AudioSampleRate { get; private set; }

    public int AudioChannels { get; private set; }

    public string AudioChannelsFriendly { get; private set; }

    public IList<SubtitleStream> Subtitles { get; }

    public bool HasSubtitles => this.HasExternalSubtitles || this.Subtitles.Count > 0;

    public bool HasExternalSubtitles { get; }

    public IList<ChapterStream> Chapters { get; }

    public bool HasChapters => this.Chapters.Count > 0;

    public IList<MenuStream> MenuStreams { get; }

    public bool HasMenu => this.MenuStreams.Count > 0;

    public bool IsDvd { get; private set; }

    public string Format { get; private set; }

    public string FormatVersion { get; private set; }

    public string Profile { get; private set; }

    public string Codec { get; private set; }

    public bool IsBluRay { get; }

    public bool MediaInfoNotloaded { get; private set; }

    public int Duration { get; private set; }

    public string Version { get; private set; }

    public long Size { get; private set; }

    public AudioTags Tags { get; private set; }

    public MediaInfoWrapper(long FileSize, ILogger logger = null)
      : this(FileSize, Environment.Is64BitProcess ? ".\\x64" : ".\\x86", logger)
    {
    }

    public MediaInfoWrapper(long FileSize, string pathToDll, ILogger logger = null)
    {
      this.Is64BitProcess = Environment.Is64BitProcess;
      if (string.IsNullOrEmpty(pathToDll))
        pathToDll = Environment.Is64BitProcess ? ".\\x64" : ".\\x86";
      this._logger = logger;
      logger.LogDebug("Initializing media for stream.");
      this.VideoStreams = (IList<VideoStream>) new List<VideoStream>();
      this.AudioStreams = (IList<AudioStream>) new List<AudioStream>();
      this.Subtitles = (IList<SubtitleStream>) new List<SubtitleStream>();
      this.Chapters = (IList<ChapterStream>) new List<ChapterStream>();
      this.RealPathToDll = ((string) null).IfExistsPath("./", logger).IfExistsPath(pathToDll, logger).IfExistsPath(Path.GetDirectoryName(typeof (MediaInfoWrapper).Assembly.Location), logger).IfExistsPath(Path.IsPathRooted(pathToDll) ? (string) null : Path.Combine(Path.GetDirectoryName(typeof (MediaInfoWrapper).Assembly.Location), pathToDll), logger);
      this.MenuStreams = (IList<MenuStream>) new List<MenuStream>();
      if (string.IsNullOrEmpty(this.RealPathToDll))
      {
        logger.LogError("MediaInfo.dll was not found");
        this.MediaInfoNotloaded = true;
      }
      else
      {
        this._mi = new MediaInfo.MediaInfo(this.RealPathToDll);
        this._mi = new MediaInfo.MediaInfo(pathToDll);
        this.Size = FileSize;
        this._mi.Option("File_IsSeekable", "0");
        this._mi.OpenBufferInit(FileSize, 0L);
      }
    }

    public MediaInfoWrapper(Stream inputStream, ILogger logger = null)
      : this(inputStream, Environment.Is64BitProcess ? ".\\x64" : ".\\x86", logger)
    {
    }

    public MediaInfoWrapper(Stream inputStream, string pathToDll, ILogger logger)
      : this(inputStream.Length, pathToDll, logger)
    {
      NumberFormatInfo providerNumber = new NumberFormatInfo()
      {
        NumberDecimalSeparator = "."
      };
      try
      {
        this.ExtractInfo(inputStream, this.RealPathToDll, providerNumber);
        logger.LogDebug(string.Format("Process file {0} was completed successfully. Video={1}, Audio={2}, Subtitle={3}", (object) inputStream, (object) this.VideoStreams.Count, (object) this.AudioStreams.Count, (object) this.Subtitles.Count));
      }
      catch (Exception ex)
      {
        logger.LogError(ex, "Error processing media file");
      }
    }

    public bool AddBytesToRead(byte[] bytesToRead, int offset, int length)
    {
      if (offset > 0)
      {
        byte[] numArray = new byte[length];
        Array.Copy((Array) bytesToRead, offset, (Array) numArray, 0, length);
        bytesToRead = numArray;
      }
      GCHandle gcHandle = GCHandle.Alloc((object) bytesToRead, GCHandleType.Pinned);
      IntPtr num = this._mi.OpenBufferContinue(gcHandle.AddrOfPinnedObject(), (IntPtr) length);
      gcHandle.Free();
      return ((int) num & 8) != 8;
    }

    public bool FinalizeReadBytes()
    {
      NumberFormatInfo providerNumber = new NumberFormatInfo()
      {
        NumberDecimalSeparator = "."
      };
      bool flag;
      try
      {
        this._mi.OpenBufferFinalize();
        this.ExtractData(this._mi, providerNumber);
        flag = true;
      }
      catch (Exception ex)
      {
        flag = false;
      }
      return flag;
    }

    private void ExtractData(MediaInfo.MediaInfo MI, NumberFormatInfo providerNumber)
    {
      this.Format = MI.Get(StreamKind.General, 0, "Format");
      this.Profile = MI.Get(StreamKind.General, 0, "Format_Profile");
      this.FormatVersion = MI.Get(StreamKind.General, 0, "Format_Version");
      this.Codec = MI.Get(StreamKind.General, 0, "CodecID");
      int num = 0;
      this.Tags = new AudioTagBuilder(MI, 0).Build();
      this._logger.LogDebug(string.Format("Found {0} video streams.", (object) MI.CountGet(StreamKind.Video)));
      for (int position = 0; position < MI.CountGet(StreamKind.Video); ++position)
        this.VideoStreams.Add(new VideoStreamBuilder(MI, num++, position).Build());
      if (this.Duration == 0)
      {
        double result;
        double.TryParse(MI.Get(StreamKind.Video, 0, 88), NumberStyles.AllowDecimalPoint, (IFormatProvider) providerNumber, out result);
        this.Duration = (int) result;
      }
      object obj1;
      if (this.VideoStreams.Count == 1 && this.Tags.GeneralTags.TryGetValue((NativeMethods.General) 1000, out obj1))
      {
        object obj2;
        this.VideoStreams[0].Stereoscopic = !this.Tags.GeneralTags.TryGetValue((NativeMethods.General) 1001, out obj2) ? ((bool) obj1 ? StereoMode.Stereo : StereoMode.Mono) : (StereoMode) obj2;
      }
      this._logger.LogDebug(string.Format("Found {0} audio streams.", (object) MI.CountGet(StreamKind.Audio)));
      for (int position = 0; position < MI.CountGet(StreamKind.Audio); ++position)
        this.AudioStreams.Add(new AudioStreamBuilder(MI, num++, position).Build());
      if (this.Duration == 0)
      {
        double result;
        double.TryParse(MI.Get(StreamKind.Audio, 0, 70), NumberStyles.AllowDecimalPoint, (IFormatProvider) providerNumber, out result);
        this.Duration = (int) result;
      }
      this._logger.LogDebug(string.Format("Found {0} subtitle streams.", (object) MI.CountGet(StreamKind.Text)));
      for (int position = 0; position < MI.CountGet(StreamKind.Text); ++position)
        this.Subtitles.Add(new SubtitleStreamBuilder(MI, num++, position).Build());
      this._logger.LogDebug(string.Format("Found {0} chapters.", (object) MI.CountGet(StreamKind.Other)));
      for (int position = 0; position < MI.CountGet(StreamKind.Other); ++position)
        this.Chapters.Add(new ChapterStreamBuilder(MI, num++, position).Build());
      this._logger.LogDebug(string.Format("Found {0} menu items.", (object) MI.CountGet(StreamKind.Menu)));
      for (int position = 0; position < MI.CountGet(StreamKind.Menu); ++position)
        this.MenuStreams.Add(new MenuStreamBuilder(MI, num++, position).Build());
      this.MediaInfoNotloaded = this.VideoStreams.Count == 0 && this.AudioStreams.Count == 0 && this.Subtitles.Count == 0;
      if (this.MediaInfoNotloaded)
        this.SetPropertiesDefault();
      else
        this.SetupProperties(MI);
    }

    private void ExtractInfo(Stream FileStream, string pathToDll, NumberFormatInfo providerNumber)
    {
      using (MediaInfo.MediaInfo MI = new MediaInfo.MediaInfo(pathToDll))
      {
        if (MI.Handle == IntPtr.Zero)
        {
          this.MediaInfoNotloaded = true;
          this._logger.LogWarning("MediaInfo library was not loaded!");
        }
        else
        {
          this.Version = MI.Option("Info_Version");
          this._logger.LogDebug(string.Format("MediaInfo library was loaded. Handle={0} Version is {1}", (object) MI.Handle, (object) this.Version));
          if (!FileStream.CanSeek)
          {
            MI.Option("File_IsSeekable", "0");
            MI.OpenBufferInit(FileStream.Length, 0L);
            int num1;
            IntPtr num2;
            do
            {
              byte[] buffer1 = new byte[65536];
              num1 = FileStream.Read(buffer1, 0, buffer1.Length);
              GCHandle gcHandle = GCHandle.Alloc((object) buffer1, GCHandleType.Pinned);
              IntPtr buffer2 = gcHandle.AddrOfPinnedObject();
              num2 = MI.OpenBufferContinue(buffer2, (IntPtr) num1);
              gcHandle.Free();
            }
            while ((int) num2 != 0 && FileStream.CanRead && num1 > 0);
          }
          else
          {
            MI.OpenBufferInit(FileStream.Length, 0L);
            int num3;
            do
            {
              byte[] buffer3 = new byte[65536];
              num3 = FileStream.Read(buffer3, 0, buffer3.Length);
              GCHandle gcHandle = GCHandle.Alloc((object) buffer3, GCHandleType.Pinned);
              IntPtr buffer4 = gcHandle.AddrOfPinnedObject();
              IntPtr num4 = MI.OpenBufferContinue(buffer4, (IntPtr) num3);
              gcHandle.Free();
              if (((int) num4 & 8) != 8)
              {
                long get = MI.OpenBufferContinueGoToGet();
                if (get != -1L)
                {
                  long fileOffset = FileStream.Seek(get, SeekOrigin.Begin);
                  MI.OpenBufferInit(FileStream.Length, fileOffset);
                }
              }
              else
                break;
            }
            while (FileStream.CanRead && num3 > 0);
          }
          MI.OpenBufferFinalize();
          this.ExtractData(MI, providerNumber);
        }
      }
    }
  }
}

kreditor0815 avatar Oct 29 '21 23:10 kreditor0815