VideoPlay.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using DirectShow;
  2. using Sonic;
  3. using System;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6. using VideoPlayLib.KnownGuid;
  7. namespace VideoPlayLib
  8. {
  9. public class VideoPlay: IDisposable
  10. {
  11. //---- fields
  12. private readonly Graph _gWrap;
  13. private readonly DSFilter _audioRender;
  14. private readonly DSPin[] _arrAudioPins;
  15. private DSPin _currentAudioOutPin;
  16. private VideoInControl[] _vics;
  17. //---- ctor
  18. public VideoPlay(string mediaFile, params Control[] videoContainers)
  19. {
  20. _gWrap = new Graph();
  21. _audioRender = new DSFilter(AudioRender.DirectSound);
  22. _gWrap.AddFilter(_audioRender, "audio");
  23. var dsfSrc = _gWrap.AddSourceFilter(mediaFile, "src");
  24. if (dsfSrc.Output.Count == 0)
  25. {
  26. throw new Exception("Not found any output pin from source!");
  27. }
  28. if (dsfSrc.Output.Count == 1 && dsfSrc.OutputPin.MediaTypes.Any(p => p.majorType == MediaType.Stream))
  29. {
  30. //we got a Stream, should find a spliter
  31. var pinSource = dsfSrc.OutputPin;
  32. var guid = pinSource.MediaTypes.Where(p => p.subType != Guid.Empty).Select(p => p.subType).FirstOrDefault();
  33. DSFilter dsfSplit;
  34. if (guid == MediaSubType.Avi)
  35. dsfSplit = new DSFilter(Spliter.Avi);
  36. else if (guid == MediaSubTypeGuids.Mp4)
  37. dsfSplit = new DSFilter(Spliter.Mp4);
  38. else if (guid == MediaSubTypeGuids.Mpg)
  39. dsfSplit = new DSFilter(Spliter.Mpeg);
  40. else if (guid == MediaSubTypeGuids.Flv)
  41. dsfSplit = new DSFilter(Spliter.Flv);
  42. else
  43. {
  44. throw new Exception("Not found any support MediaSubType!");
  45. }
  46. _gWrap.AddFilter(dsfSplit, "spliter");
  47. _gWrap.Connect(pinSource, dsfSplit.InputPin);
  48. dsfSrc = dsfSplit;
  49. }
  50. _arrAudioPins = dsfSrc.Output.Where(p => p.MediaTypes.Any(q => q.majorType == MediaType.Audio)).ToArray();
  51. var arrVideoPins = dsfSrc.Output.Where(p => p.MediaTypes.Any(q => q.majorType == MediaType.Video)).ToArray();
  52. if (_arrAudioPins.Any())
  53. {
  54. _gWrap.Connect(_currentAudioOutPin = _arrAudioPins.First(), _audioRender.InputPin);
  55. }
  56. if (!arrVideoPins.Any() || !videoContainers.Any())
  57. return;
  58. if (videoContainers.Length == 1)
  59. {
  60. var videoRender = new DSFilter(VideoRender.MadVr);
  61. _gWrap.AddFilter(videoRender, "video");
  62. _gWrap.Connect(arrVideoPins.First(), videoRender.InputPin);
  63. _vics = new[]
  64. {
  65. new VideoInControl(videoRender, videoContainers.First(), false)
  66. };
  67. }
  68. else //use tee
  69. {
  70. _vics = new VideoInControl[videoContainers.Length];
  71. //define a tee
  72. var dsfInfTee = new DSFilter(Misc.InfTee);
  73. _gWrap.AddFilter(dsfInfTee, "infTee");
  74. //connect input pin of tee , from source
  75. _gWrap.Connect(arrVideoPins.First(), dsfInfTee.InputPin);
  76. //connect output pin of tee , to evety render
  77. for (var i = 0; i < videoContainers.Length; i++)
  78. {
  79. var videoRender = new DSFilter(VideoRender.MadVr);
  80. _gWrap.AddFilter(videoRender, "video" + i);
  81. //FIXME: 某些情况会出错 TODO: 让tee在解码滤镜之后
  82. _gWrap.Connect(dsfInfTee.Output[i], videoRender.InputPin);
  83. _vics[i] = new VideoInControl(videoRender, videoContainers[i], false);
  84. }
  85. }
  86. }
  87. //--- members
  88. public string[] Audios { get { return _arrAudioPins.Select(p => p.Name).ToArray(); } }
  89. public void SetAudio(int index)
  90. {
  91. var s = _gWrap.GetState();
  92. if (s == FilterState.Running)
  93. _gWrap.Stop();
  94. if (_audioRender.InputPin.ConnectedTo.Filter.Value != _currentAudioOutPin.Filter.Value)
  95. {
  96. _gWrap.RemoveFilter(_audioRender.InputPin.ConnectedTo.Filter);
  97. }
  98. else
  99. {
  100. _gWrap.Disconnect(_audioRender.InputPin);
  101. _gWrap.Disconnect(_currentAudioOutPin);
  102. }
  103. _gWrap.Connect(_arrAudioPins[index], _audioRender.InputPin);
  104. if (s == FilterState.Running)
  105. _gWrap.Run();
  106. _currentAudioOutPin = _arrAudioPins[index];
  107. }
  108. public void Play()
  109. {
  110. _gWrap.Run();
  111. }
  112. public void Pause()
  113. {
  114. _gWrap.Pause();
  115. }
  116. public void Dispose()
  117. {
  118. _gWrap.Abort();
  119. }
  120. public double Duration { get { return _gWrap.Duration; } }
  121. public double CurrentPosition
  122. {
  123. get { return _gWrap.CurrentPosition; }
  124. set { _gWrap.CurrentPosition = value; }
  125. }
  126. }
  127. }