2012-11-27 2 views
0

J'utilise un contrôle tiers pour la capture vidéo qui utilise des fichiers .prx pour certains attributs de sortie, à savoir la taille de sortie. J'essaie de définir la hauteur et la largeur de sortie les plus grandes possibles tout en conservant le ratio de la taille réelle de l'écran de l'utilisateur.Modifier le fichier Windows Media Profile (.prx) dans le code

Je crois que le fichier .prx est juste un fichier XML, mais quand je l'ouvre comme XMLDocument puis l'enregistre, je reçois un message indiquant "Le profil est invalide. (0xC00D0BC6)" en essayant d'ouvrir avec Windows Media Encoder. J'ai été en mesure d'ouvrir le même fichier sans problème avant d'exécuter le code.

Dim prx As New XmlDocument() 
prx.Load(Globals.appPath + prxFileName) 
Dim prxWidth As XmlAttribute = prx.SelectSingleNode("/profile/streamconfig/wmmediatype/videoinfoheader/bitmadinfoheader/@biwidth") 
Dim prxHeight As XmlAttribute = prx.SelectSingleNode("/profile/streamconfig/wmmediatype/videoinfoheader/bitmadinfoheader/@biheight") 
prx.Save(Globals.appPath + prxFileName) 

donc sans faire de montage réel du fichier, mais ré-enregistrer comme un XMLDocument, le profil devient invalide. Y at-il un moyen d'éditer les fichiers .prx dans le code tout en conservant la validité du profil?

Pour référence, un fichier .prx valide ouvert dans un éditeur de texte est ci-dessous.

<profile version="589824" 
     storageformat="1" 
     name="myProfile" 
     description=""> 
       <streamconfig majortype="{73647561-0000-0010-8000-00AA00389B71}" 
       streamnumber="1" 
       streamname="Audio Stream" 
       inputname="Audio409" 
       bitrate="48000" 
       bufferwindow="3000" 
       reliabletransport="0" 
       decodercomplexity="" 
       rfc1766langid="en-us" 
> 
     <wmmediatype subtype="{00000161-0000-0010-8000-00AA00389B71}" 
       bfixedsizesamples="1" 
       btemporalcompression="0" 
       lsamplesize="1152"> 
     <waveformatex wFormatTag="353" 
        nChannels="2" 
        nSamplesPerSec="32000" 
        nAvgBytesPerSec="6000" 
        nBlockAlign="1152" 
        wBitsPerSample="16" 
        codecdata="008800001F0000000000"/> 
     </wmmediatype> 
     </streamconfig> 
       <streamconfig majortype="{73646976-0000-0010-8000-00AA00389B71}" 
       streamnumber="2" 
       streamname="Video Stream" 
       inputname="Video409" 
       bitrate="400000" 
       bufferwindow="3000" 
       reliabletransport="0" 
       decodercomplexity="AU" 
       rfc1766langid="en-us" 
> 
       <videomediaprops maxkeyframespacing="80000000" 
           quality="100"/> 
     <wmmediatype subtype="{33564D57-0000-0010-8000-00AA00389B71}" 
       bfixedsizesamples="0" 
       btemporalcompression="1" 
       lsamplesize="0"> 
    <videoinfoheader dwbitrate="400000" 
        dwbiterrorrate="0" 
        avgtimeperframe="333333"> 
    <rcsource left="0" 
       top="0" 
       right="2000" 
       bottom="562"/> 
    <rctarget left="0" 
       top="0" 
       right="2000" 
       bottom="562"/> 
     <bitmapinfoheader biwidth="2000" 
          biheight="562" 
          biplanes="1" 
          bibitcount="24" 
          bicompression="WMV3" 
          bisizeimage="0" 
          bixpelspermeter="0" 
          biypelspermeter="0" 
          biclrused="0" 
          biclrimportant="0"/> 
    </videoinfoheader> 
     </wmmediatype> 
     </streamconfig> 
</profile> 

Avec l'aide de cette question, Video Capture output always in 320x240 despite changing resolution, j'ai changé ma stratégie un peu à utiliser IWMStreamConfig.

Dim profileData As String 
    Using reader As New StreamReader(File.OpenRead(Globals.appPath + prxFileName)) 
     profileData = reader.ReadToEnd() 
    End Using 

    Dim profileManager As IWMProfileManager 
    Dim wmProfile As IWMProfile = Nothing 
    Dim hr As Integer = WMLib.WMCreateProfileManager(profileManager) 
    If hr >= 0 Then 
     hr = profileManager.LoadProfileByData(profileData, wmProfile) 
    End If 

    If profileManager IsNot Nothing Then 
     System.Runtime.InteropServices.Marshal.ReleaseComObject(profileManager) 
     profileManager = Nothing 
    End If 

    Dim pConfig As IWMStreamConfig 
    wmProfile.GetStream("Video Stream", pConfig) 

Maintenant que j'ai au moins le flux comme un objet IWMStreamConfig, je me sens comme si je me rapproche. Mais comment éditer le BITMAPINFOHEADER.biHeight et BITMAPINFOHEADER.biWidth comme trouvé dans cet article MSDN?

http://msdn.microsoft.com/en-us/library/windows/desktop/dd756998(v=vs.85).aspx

Le SetBitRate et SetBufferWindow font leur apparition dans intelisense mais je ne suis pas sûr de savoir comment accéder à ces propriétés de niveau inférieur.

Répondre

0

Après avoir regardé le fichier dans un éditeur hexadécimal, les profils valides ont 0x00 entre chaque caractère et le fichier commence par 0xFFFE, je suppose pour un certain codage. Une fois cela déterminé, j'ai juste utilisé un lecteur de flux pour lire le texte dans une chaîne et faire mes changements avec la manipulation de chaînes.

La partie délicate était de tout écrire dans le fichier. Pour une raison quelconque, de toute façon j'ai essayé d'écrire les deux premiers caractères hexadécimaux dans le fichier, ils seraient traduits en quatre caractères hexadécimaux différents. La solution était de l'écrire octet par octet avec un FileStream.

//Read in the initial profile 
Dim profileData As String 
Using reader As New StreamReader(File.OpenRead(prxFile)) 
    profileData = reader.ReadToEnd() 
End Using 

//Make changes to the profile with string manipulation 

//Write the changed data back to the file including all the Hex characters 
File.Delete(prxFile) 
Dim FS As FileStream = New FileStream(prxFile, FileMode.CreateNew) 
//Start by writing 0xFFFE 
FS.WriteByte(&HFF) 
FS.WriteByte(&HFE) 
//Then write each character succeeded by 0x00 
For Each Character As Char In profileData.ToCharArray 
    FS.WriteByte(AscW(Character)) 
    FS.WriteByte(&H0) 
Next 
FS.Close() 
1

Le fichier est Unicode. Plus précisément, UTF-16 little-endian basé sur le code BOM 0xFFFE.

Comme il semble que vous utilisez .NET, essayez d'emballer vos FileStream dans un StreamWriter:

Dim FS As FileStream = New FileStream(prxFile, FileMode.CreateNew) 
Dim SW As StreamWriter = New StreamWriter(FS, new UnicodeEncoding(false, true)) 

Vous pouvez alors écrire des chaînes entières dans le fichier.

Les méthodes Load/Save de XmlDocument utilisent un StreamWriter qui étend TextWriter. Il suffit de le créer de la même manière avec l'encodage spécifié.

Questions connexes