Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streaming/Byte-Wise usage #40

Open
kreditor0815 opened this issue Oct 29, 2021 · 0 comments
Open

Streaming/Byte-Wise usage #40

kreditor0815 opened this issue Oct 29, 2021 · 0 comments

Comments

@kreditor0815
Copy link

kreditor0815 commented Oct 29, 2021

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);
        }
      }
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants