Grabbelés és a MediaDetector II.

Na akkor folytassuk, mert nem fért ki, még a hozzá kapcsolódó tulajdonságok (de majd rövidesen az egészet felteszem mindenki számára elérhetően), addig is lehet nézegetni miről is van szó, kikommenteztem mindent, ugyanis én szeretem, különösen ezeket az XML kommenteket, amik rengeteget tudnak segíteni a kód írásakor:
 
     public class MediaDetector : IDisposable
    
{
          #region Tulajdonságok

          /// <summary>
          
/// Létezik e média detektor
          
/// </summary>
          
public bool Active
          
{
               
get { return MediaDet != null; }
          
}

          /// <summary>
          
/// A jelenleg kiválasztott stream médiatúpusa
          
/// </summary>
          
public Guid? CurrentStream
          
{
               
get
               
{
                    
Reset();

                    if (Active)
                    
{
                         
int CurrentStream;

                         if (MediaDet.get_CurrentStream(out CurrentStream) == 0)
                         
{
                              
AMMediaType MdType = new AMMediaType();
                              
if (MediaDet.get_StreamMediaType(MdType) == 0)
                              
{
                                   
Guid GuidMT = MdType.majorType;
                                   
DsUtils.FreeAMMediaType(MdType);
                                   
return GuidMT;
                              
}
                         
}
                    
}

                    return null;
               
}

               set
               
{
                    
Reset();

                    if (Active && value != null)
                    
{
                         
EnumMediaTypes(
                              
delegate(int CurrentStream, AMMediaType MediaType)
                              
{
                                   
if (MediaType.majorType == value)
                                   
{
                                        
MediaDet.put_CurrentStream(CurrentStream);
                                        
return true;
                                   
}
                                   
                                   
return false;
                              
}
                         );
                    }
               
}
          
}

          private string FFileName;
          
/// <summary>
          
/// Médiafájl neve
          
/// </summary>
          
public string FileName
          
{
               
get { return FFileName; }

               set
               
{
                    
FFileName = value;
                    
                    
// az előző detektort a süllyesztőbe küldjük 🙂
                    
Destroy();

                    if (FFileName != null)
                    
{
                         
// minden egyes alkalommal (minden fájlra) külön példányt kell létrehozni,
                         
// ugyanis a put_FileName() nem hívható meg egy példányon, csak egyszer
                         
MediaDet = new DirectShowLib.DES.MediaDet() as IMediaDet;
                         
if (Active)
                         
{
                              
int HResult = MediaDet.put_Filename(FFileName);
                              
if (HResult < 0) 
                              
{
                                   
Destroy();
                                   
DsError.ThrowExceptionForHR(HResult);
                              

                         
}
                    

               
}
          
}

          /// <summary>
          
/// A forrás-szűrő, amit a médiadetektor éppen használ
          
/// </summary>
          
public BaseFilter SourceFilter
          
{
               
get
               
{
                    
Reset();

                    if (Active)
                    
{
                         
object Filter;

                         if (MediaDet.get_Filter(out Filter) == 0)
                              
return new BaseFilter((IBaseFilter)Filter);
                    
}
                    
                    
return null;
               
}

               set
               
{
                    
Reset();

                    if (Active && value != null)
                         
DsError.ThrowExceptionForHR(MediaDet.put_Filter(value.Filter));
               
}
          
}

          /// <summary>
          
/// Képkockasebesség (fps)
          
/// </summary>
          
public double? FrameRate
          
{
               
get
               
{
                    
Reset();

                    if (Active)
                    
{
                         
double Value;
                         
if (MediaDet.get_FrameRate(out Value) == 0)
                              
return Value;
                    
}

                    return null;
               
}
          
}

          /// <summary>
          
/// Stream hossza
          
/// </summary>
          
public double? StreamLength
          
{
               
get
               
{
                    
Reset();

                    if (Active)
                    
{
                         
double Value;
                         
if (MediaDet.get_StreamLength(out Value) == 0)
                              
return Value;
                    
}
                    
                    
return null;
               
}
          
}

          /// <summary>
          
/// A fájl médiatípusa
          
/// </summary>
          
public MediaTypeEnum MediaType
          
{
               
get
               
{
                    
Reset();

                    bool AudioStream = false;
                    
bool VideoStream = false;

                    // médiatípusok  átnézése
                    
EnumMediaTypes(
                         
delegate (int CurrentStream, AMMediaType MediaType)
                         {
                              
if (MediaType.majorType == DirectShowLib.MediaType.Video)
                                   
VideoStream = true;
                              e
lse if (MediaType.majorType == DirectShowLib.MediaType.Audio)
                                   
AudioStream = true;
                              
                              
return false;
                         
}
                    
);

                    if (VideoStream && AudioStream)
                         
return MediaTypeEnum.mtAudioVideo;
                    
else if (VideoStream)
                         
return MediaTypeEnum.mtVideo;
                    
else if (AudioStream)
                         
return MediaTypeEnum.mtAudio;
                    
else
                         
return MediaTypeEnum.mtOther;
               
}
          
}

          /// <summary>
          
/// Videóinformációk
          
/// Ha nem nyerhető ki, pl. nincs videó stream, akkor null értéket ad vissza
          /// </summary>
          
public VideoInfoHeader VideoInfo
          
{
               
get
               
{
                    
Reset();

                    if (Active)
                    
{
                         
CurrentStream = DirectShowLib.MediaType.Video;
                         
// ha sikerült a videóstreamet beállítani (azaz van neki olyan)
                         
if (CurrentStream == DirectShowLib.MediaType.Video)
                         
{
                              
AMMediaType MdType = new AMMediaType();
                              
if (MediaDet.get_StreamMediaType(MdType) == 0)
                              
{
                                   
VideoInfoHeader VideoInf = (VideoInfoHeader)Marshal.PtrToStructure(MdType.formatPtr, typeof(VideoInfoHeader));
                                   
DsUtils.FreeAMMediaType(MdType);
                                   
return VideoInf;
                              
}
                         
}
                    
}

                    return null;
               
}
          
}

          /// <summary>
          
/// Audio információk
          
/// Ha nem nyerhető ki, pl. nincs audio stream, akkor null értéket ad vissza
          
/// </summary>
          
public WaveFormatEx AudioInfo
          
{
               
get
               
{
                    
Reset();

                    if (Active)
                    
{
                         
CurrentStream = DirectShowLib.MediaType.Audio;
                         
// ha sikerült az audiostreamet beállítani (azaz van neki olyan)
                         
if (CurrentStream == DirectShowLib.MediaType.Audio)
                         

                              
AMMediaType MdType = new AMMediaType();
                              
if (MediaDet.get_StreamMediaType(MdType) == 0)
                              
{
                                   
WaveFormatEx AudioInf = (WaveFormatEx)Marshal.PtrToStructure(MdType.formatPtr, typeof(WaveFormatEx));
                                   
DsUtils.FreeAMMediaType(MdType);
                                   
return AudioInf;
                              
}
                         
}
                    
}

                    return null;
               
}
          }

          #endregion

 
      }

A referenciaszámláló szépen számolgatja a grabbeléssel kapcsolatos tagfüggvények hívását, s bármilyen más tevékenység esetén előtte ellenőrzi, hogy el lehet e érni e még az adott dolgokat, azaz nem váltottunk e át grabbelési üzemmódba. Igaz ez az EnumMediaTypes()-ra is, ezért van mindenhol ott a Reset() minden előtt. Viszont ennek köszönhetően nem kell ezt írni például, hogy:

MediaDetector Detector = new MediaDetector();
Detector.FileName = MPlayer.FileName;
pbVideoBitmap1.Image = Detector.GetBitmap(10);
Detector.FileName = MPlayer.FileName;
pbVideoBitmap2.Image = Detector.GetBitmap(20);
Detector.FileName = MPlayer.FileName;
pbVideoBitmap3.Image = Detector.GetBitmap(30);

Elég csak ennyi (ami amúgy is a normális lenne):

MediaDetector Detector = new MediaDetector(MPlayer.FileName);
pbVideoBitmap1.Image = Detector.GetBitmap(10);
pbVideoBitmap2.Image = Detector.GetBitmap(20);
pbVideoBitmap3.Image = Detector.GetBitmap(30);

Minden további nélkül elérhetők a médiatípussal kapcsolatos, illetve videó és audió adatokkal kapcsolatos információk is, pl.:

Detector.EnumMediaTypes(
    

delegate(int CurrentStream, AMMediaType MediaType)
    

         
MessageBox.Show(MediaType.majorType.ToString());
         
return false;
    
}
);

WaveFormatEx W = Detector.AudioInfo;
if (W != null)
    
MessageBox.Show(W.nChannels.ToString());

Továbbá az EnumMediaTypes()-t úgy írtam meg, hogy megszakítható legyen (return true), nem mintha nagyon számítana, mivel úgy se sok van, de ha megvan amit keresünk, akkor felesleges átszánkózni a többin is. A keresett típus és a stream azonosítóját is átadja, hasonló módon, mint Win32 alatt a CALLBACK függvények voltak.

Most már a médiadetektorunk megvan, még jöhet egy videólejátszó extra kiegészítés a VMR-el, egy DVD lejátszó menükezelővel, illetve egy felvételrögzítő control és ezzel a DirectShow általános szolgáltatásait már elérhetővé is sikerült tenni .NET alatt. Persze most Adobe Premiert nem fogok írni, de ahhoz is a DirectShow-ban kellene hozzáfogni.

Még néhány apró dolog azoknak, akik Delphi-t használtak csak eddig, s nem ismerik még a Visual Studio kódszerkesztő lehetőségeit, például tulajdonságok gyors létrehozásához elég beírni, hogy prop és tab. A konstruktor ugyanígy ctor és tab. Van rengeteg ilyen Delphiben automatikus kódsablonoknak elnevezett szerűség a C#-ban is.

Ami még tervbe szerepelt, hogy most ugyan nem használtam, de majd szükségünk lesz a generikus típusokra is. Ez egy olyan szép dolog, amiért már jónéhány Delphi fejlesztő az első kiadás óta rimánkodik. Majd később részletesen beszélünk ezekről is, addig is aki nézegeti elárulom, hogy a Delphi Highlander (.NET 2.0) megvalósítása hogy festett volna, ha kiadták volna:

type
  GenericType<T: MyClass, IMyInterface, constructor> = class(List<T>)

Ez ekvivalens ezzel a C# kóddal:

public

class GenericType<T> : List<T> where T : MyClass, IMyInterface, new()

Ez egy olyan generikus listát reprezentál, ahol T jelöli a típust, amire különböző megszorítások vannak, mégpedig, hogy a MyClass-ból kell származnia és implementálnia kell az IMyInterface-t, továbbá rendelkeznie kell egy paraméter nélküli konstruktorral. Ez az egyik nagy újítása a .NET 2.0-nak.

Hozzászólás