2013-03-16 2 views
0

Я работал с фильтрами DirectShow для преобразования и сжатия аудио из одного формата в другой. Я использую GraphStudio и GraphStudioNext для создания графика фильтра, который затем переводим в фильтры в VB.Net. До сих пор они отлично работали. Я пытаюсь преобразовать WAV-файл в .mp3. Используя GraphStudio и следующие фильтры, соединенные вместе со стандартными соединениями, я получаю сжатые файлы. FileSource-Async -> WaveParser -> MPEG Layer3 -> WAV Dest -> Filewriter.DirectShow MP3 Compression

Однако, когда я соединяю те же фильтры вместе в своей программе VB.Net, я вообще не получаю никакого сжатия. Я даже пытался установить сжатие с использованием интерфейса IAMStreamConfig, но сжатие, которое отображается в GraphStudio, недоступно, когда я перечисляю контакты в своей программе. Функция (включая некоторые комментарии) ниже. Любые мысли, предложения очень ценятся.

Private Function PlayInitMP3(ByVal path As String, ByVal dstPath As String) As Integer 

    Dim asyncReader As DirectShowNET.IBaseFilter = Nothing 
    Dim WaveParser As DirectShowNET.IBaseFilter = Nothing 
    'Dim ACMWrapper As DirectShowNET.IBaseFilter = Nothing 
    Dim MPEG3Wrapper As DirectShowNET.IBaseFilter = Nothing 
    Dim WavDestWrapper As DirectShowNET.IBaseFilter = Nothing 

    Dim fileSource As DirectShowNET.IFileSourceFilter = Nothing 
    Dim fileDestination As DirectShowNET.IBaseFilter = Nothing 




    Dim result As Integer = -1 
    Dim srcFileInfo As System.IO.FileInfo = New FileInfo(path) 

    Service1.nlog.LogError(0, "Starting Init", "", "") 

    'Set to Null Renderer 
    Try 
     result = WaveParser.SetSyncSource(DBNull.Value) 
     Marshal.ThrowExceptionForHR(result) 
     Service1.nlog.LogError(0, "SetSyncSource-WaveParser", result.ToString, "") 

     'result = ACMWrapper.SetSyncSource(DBNull.Value) 
     'Marshal.ThrowExceptionForHR(result) 
     'Service1.nlog.LogError(0, "SetSyncSource-ACMWrapper", result.ToString, "") 

     result = MPEG3Wrapper.SetSyncSource(DBNull.Value) 
     Marshal.ThrowExceptionForHR(result) 
     Service1.nlog.LogError(0, "SetSyncSource-MPEG3Wrapper", result.ToString, "") 

     result = WavDestWrapper.SetSyncSource(DBNull.Value) 
     Marshal.ThrowExceptionForHR(result) 
     Service1.nlog.LogError(0, "SetSyncSource-WavDestWrapper", result.ToString, "") 

    Catch ex As Exception 

    End Try 


    Try 

     If IsNothing(Me.graphBuilder) = False Then 
      Marshal.ReleaseComObject(Me.mediaSeeking) 
      Marshal.ReleaseComObject(Me.mediaControl) 
      Marshal.ReleaseComObject(Me.graphBuilder) 

      Me.mediaSeeking = Nothing 
      Me.mediaControl = Nothing 
      Me.graphBuilder = Nothing 

     End If 

     ' Create IGraphBuilder instance 
     Me.graphBuilder = New DirectShowNET.FilterGraph() 


     ' Create MediaControl 

     ' File source filter addition 
     asyncReader = New DirectShowNET.AsyncReader 
     result = graphBuilder.AddFilter(asyncReader, System.IO.Path.GetFileName(path)) 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "SourceFilter", result.ToString, "") 

     ' Add Wave Parser 
     WaveParser = New DirectShowNET.WaveParser 
     result = Me.graphBuilder.AddFilter(WaveParser, "Wave Parser") 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "WaveParser", result.ToString, "") 

     '' Add ACMWrapper 
     'ACMWrapper = New DirectShowNET.ACMWrapper 
     'result = Me.graphBuilder.AddFilter(ACMWrapper, "ACMWrapper Parser") 
     'Marshal.ThrowExceptionForHR(result) 

     'Service1.nlog.LogError(0, "ACMWrapper", result.ToString, "") 

     ' Add MPEG3Wrapper 
     MPEG3Wrapper = New DirectShowNET.MPEG3Layer 
     result = Me.graphBuilder.AddFilter(MPEG3Wrapper, "MPEG3Layer Parser") 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "MPEG3Wrapper", result.ToString, "") 


     ' Add WAVDest 
     WavDestWrapper = New DirectShowNET.WaveDestination 
     result = Me.graphBuilder.AddFilter(WavDestWrapper, "WaveDestination") 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "WaveDestination", result.ToString, "") 


     ' FileWriter filter addition 
     fileDestination = New DirectShowLib.FileWriter 
     Dim fs As DirectShowLib.IFileSinkFilter = DirectCast(fileDestination, DirectShowLib.IFileSinkFilter) 
     result = fs.SetFileName(dstPath, Nothing) 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "FileWriter", result.ToString, "") 

     result = Me.graphBuilder.AddFilter(DirectCast(fileDestination, DirectShowNET.IBaseFilter), "Filewriter") 
     Marshal.ThrowExceptionForHR(result) 



     ' Set the Filename using the IFileSinkFilter interface 

     ' The file is loaded. 
     fileSource = asyncReader 
     result = fileSource.Load(path, Nothing) 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "SourceFileLoad", result.ToString, "") 

     ' Wave Parser is connected with FileSourceFilter. 
     Try 
      result = ConnectFilters(Me.graphBuilder, asyncReader, WaveParser) 
      Marshal.ThrowExceptionForHR(result) 
     Catch ex As Exception 
      Service1.nlog.LogError(0, "ConnectWaveParser", ex.Message, "") 
     End Try 

     Service1.nlog.LogError(0, "WaveParser Result", result.ToString, "") 

     ' Wave Parser is connected with MPEG3. 
     Try 
      result = ConnectFilters(Me.graphBuilder, WaveParser, MPEG3Wrapper) 
      Marshal.ThrowExceptionForHR(result) 
     Catch ex As Exception 
      Service1.nlog.LogError(0, "ConnectWaveParser", ex.Message, "") 
     End Try 

     Service1.nlog.LogError(0, "WaveParser Result", result.ToString, "") 
     '' ACMParser is connected with WaveParser. 
     'Try 
     ' result = ConnectFilters(Me.graphBuilder, WaveParser, ACMWrapper) 
     ' Marshal.ThrowExceptionForHR(result) 
     'Catch ex As Exception 
     ' Service1.nlog.LogError(0, "ConnectACMWrapper", ex.Message, "") 
     'End Try 

     'Service1.nlog.LogError(0, "ACMWrapper Result", result.ToString, "") 

     ''COMPRESSION 
     'Try 
     ' 'Configure the Compression Stream Variables 
     ' Dim NewConfig As IAMStreamConfig 
     ' Dim mp3Pin As IPin 
     ' Dim ppEnum As IEnumPins 
     ' Dim aPin(1) As IPin 
     ' Dim dPin As PinDirection = PinDirection.Output 
     ' Dim nPin As Integer 


     ' Service1.nlog.LogError(0, "Beginning ACMWrapper Compression", "", "") 
     ' ACMWrapper.EnumPins(ppEnum) 
     ' While ppEnum.Next(1, aPin, nPin) = 0 
     '  mp3Pin = aPin(0) 
     '  mp3Pin.QueryDirection(dPin) 
     '  If dPin = PinDirection.Output Then 
     '   Exit While 
     '  End If 
     ' End While 


     ' NewConfig = TryCast(mp3Pin, IAMStreamConfig) 
     ' If NewConfig Is Nothing Then 
     '  Service1.nlog.LogError(0, "NewConfig Is nothing", "", "") 

     ' End If 
     ' Service1.nlog.LogError(0, "After TryCast", "", "") 

     ' Dim nCap As Integer 
     ' Dim sCap As Integer 
     ' Dim pmt As New DirectShowLib.AMMediaType 
     ' Service1.nlog.LogError(0, "After pmt", "", "") 

     ' NewConfig.GetNumberOfCapabilities(nCap, sCap) 
     ' Dim i As Integer 
     ' Dim sArray(sCap) As System.IntPtr 
     ' Dim intPtr As IntPtr = Marshal.AllocCoTaskMem(sCap) 

     ' Dim audioFormatACM As WaveFormatEx 

     ' For i = 0 To nCap - 1 
     '  NewConfig.GetStreamCaps(i, pmt, intPtr) 

     '  audioFormatACM = New WaveFormatEx() 

     '  Marshal.PtrToStructure(pmt.formatPtr, audioFormatACM) 
     '  'Print Audio Format 
     '  Service1.nlog.LogError(0, "Index:", i.ToString, "") 
     '  Service1.nlog.LogError(0, "AudioFormat:BitsPerSample", audioFormatACM.wBitsPerSample.ToString, "") 
     '  Service1.nlog.LogError(0, "AudioFormat:nSamplesPerSec", audioFormatACM.nSamplesPerSec.ToString, "") 
     '  Service1.nlog.LogError(0, "AudioFormat:AvgBytesPerSec", audioFormatACM.nAvgBytesPerSec.ToString, "") 

     '  ''Once find the proper format then save it and exit 
     '  If audioFormatACM.nAvgBytesPerSec = 8000 AndAlso audioFormatACM.nSamplesPerSec = 8000 Then 
     '   'audioFormatACM.nAvgBytesPerSec = 8000 
     '   'audioFormatACM.wBitsPerSample = 8 
     '   'audioFormatACM.nSamplesPerSec = 8000 
     '   Marshal.StructureToPtr(audioFormatACM, pmt.formatPtr, True) 
     '   Exit For 
     '  End If 
     ' Next 

     ' 'Use Selected format from enum to set 

     ' If NewConfig.SetFormat(pmt) <> 0 Then 
     '  Service1.nlog.LogError(0, "ACM Setformat Error", "", "") 
     ' End If 

     ' 'See if Successfully Set 

     ' audioFormatACM = New WaveFormatEx() 

     ' Marshal.PtrToStructure(pmt.formatPtr, audioFormatACM) 

     ' If NewConfig.GetFormat(pmt) <> 0 Then 
     '  Service1.nlog.LogError(0, "ACM GetFormat Error", "", "") 
     ' End If 
     ' Service1.nlog.LogError(0, "ACM Updated AvgBytesPerSec", audioFormatACM.nAvgBytesPerSec.ToString, "") 
     ' Service1.nlog.LogError(0, "ACM Updated SamplesPerSec", audioFormatACM.nSamplesPerSec.ToString, "") 

     ' 'Release Memory 

     'Catch ex As Exception 
     ' Service1.nlog.LogError(0, "Compression Error:", ex.Message, ex.Source) 

     'End Try 

     '' WaveParser is connected with MPEG3. 
     'Try 
     ' result = ConnectFilters(Me.graphBuilder, ACMWrapper, MPEG3Wrapper) 
     ' Marshal.ThrowExceptionForHR(result) 
     'Catch ex As Exception 
     ' Service1.nlog.LogError(0, "Connect MPEG3Wrapper", ex.Message, "") 
     'End Try 

     'Service1.nlog.LogError(0, "MPEG3Wrapper Result", result.ToString, "") 

     'COMPRESSION 
     Try 
      'Configure the Compression Stream Variables 
      Dim NewConfig1 As IAMStreamConfig 
      Dim mp3Pin1 As IPin 
      Dim ppEnum1 As IEnumPins 
      Dim aPin1(1) As IPin 
      Dim dPin1 As PinDirection = PinDirection.Output 
      Dim nPin1 As Integer 

      MPEG3Wrapper.EnumPins(ppEnum1) 
      While ppEnum1.Next(1, aPin1, nPin1) = 0 
       mp3Pin1 = aPin1(0) 
       mp3Pin1.QueryDirection(dPin1) 
       If dPin1 = PinDirection.Output Then 
        Exit While 
       End If 
      End While 


      NewConfig1 = TryCast(mp3Pin1, IAMStreamConfig) 
      If NewConfig1 Is Nothing Then 
       Service1.nlog.LogError(0, "NewConfig Is nothing", "", "") 

      End If 
      Service1.nlog.LogError(0, "After TryCast", "", "") 

      Dim nCap1 As Integer 
      Dim sCap1 As Integer 
      Dim pmt1 As New DirectShowLib.AMMediaType 
      Service1.nlog.LogError(0, "After pmt", "", "") 

      NewConfig1.GetNumberOfCapabilities(nCap1, sCap1) 
      Dim i As Integer 
      Dim sArray1(sCap1) As System.IntPtr 
      Dim intPtr1 As IntPtr = Marshal.AllocCoTaskMem(sCap1) 

      Dim audioFormat As MPEGLAYER3WAVEFORMAT 

      For i = 0 To nCap1 - 1 
       NewConfig1.GetStreamCaps(i, pmt1, intPtr1) 

       audioFormat = New MPEGLAYER3WAVEFORMAT() 

       Marshal.PtrToStructure(pmt1.formatPtr, audioFormat) 
       'Print Audio Format 
       Service1.nlog.LogError(0, "Index:", i.ToString, "") 
       Service1.nlog.LogError(0, "AudioFormat:BitsPerSample", audioFormat.wfx.wBitsPerSample.ToString, "") 
       Service1.nlog.LogError(0, "AudioFormat:nSamplesPerSec", audioFormat.wfx.nSamplesPerSec.ToString, "") 
       Service1.nlog.LogError(0, "AudioFormat:AvgBytesPerSec", audioFormat.wfx.nAvgBytesPerSec.ToString, "") 

       'Once find the proper format then save it and exit 
       'If audioFormat.wfx.nAvgBytesPerSec = 8000 AndAlso audioFormat.wfx.wBitsPerSample = 8 Then 
       ' audioFormat.wfx.nAvgBytesPerSec = 8000 
       ' 'audioFormat.wfx.wBitsPerSample = 8 
       ' 'audioFormat.wfx.wFormatTag = 85 
       ' 'audioFormat.wfx.nSamplesPerSec = 1000 
       ' Service1.nlog.LogError(0, "MP3 Selected Format AvgBytesPerSec", audioFormat.wfx.nSamplesPerSec.ToString, "") 
       ' Marshal.StructureToPtr(audioFormat, pmt1.formatPtr, True) 
       ' Exit For 
       'End If 
      Next 

      'Use Selected format from enum to set 

      'If NewConfig1.SetFormat(pmt1) <> 0 Then 
      ' Service1.nlog.LogError(0, "Setformat Error:", NewConfig1.SetFormat(pmt1).ToString, "") 
      'End If 

      'See if Successfully Set 

      audioFormat = New MPEGLAYER3WAVEFORMAT() 
      pmt1 = New AMMediaType 

      If NewConfig1.GetFormat(pmt1) <> 0 Then 
       Service1.nlog.LogError(0, "GetFormat Error", "", "") 
      End If 

      Marshal.PtrToStructure(pmt1.formatPtr, audioFormat) 
      Service1.nlog.LogError(0, "Updated AvgBytesPerSec", audioFormat.wfx.nAvgBytesPerSec.ToString, "") 
      Service1.nlog.LogError(0, "Updated SamplesPerSec", audioFormat.wfx.nSamplesPerSec.ToString, "") 
      Service1.nlog.LogError(0, "Updated FormatTag", audioFormat.wfx.wFormatTag.ToString, "") 

     Catch ex As Exception 
      Service1.nlog.LogError(0, "Compression Error:", ex.Message, ex.Source) 

     End Try 


     ' MPEG3 is connected with WavDest. 
     Try 
      result = ConnectFilters(Me.graphBuilder, MPEG3Wrapper, WavDestWrapper) 
      Marshal.ThrowExceptionForHR(result) 
     Catch ex As Exception 
      Service1.nlog.LogError(0, "Connect WavDestWrapper", ex.Message, "") 
     End Try 

     Service1.nlog.LogError(0, "WaveDestWrapper Result", result.ToString, "") 


     ' Connect to the File Writer 
     result = ConnectFilters(Me.graphBuilder, WavDestWrapper, fileDestination) 
     Marshal.ThrowExceptionForHR(result) 

     Service1.nlog.LogError(0, "ConnectFileWriter", result.ToString, "") 



     'Actually Write The File 

     ' The IMediaSeeking interface is acquired. 
     Me.mediaSeeking = Me.graphBuilder 
     Me.mediaSeeking.GetDuration(Me.duration) 
     Me.duration /= DSS_MEDIA_TIME ' MEDIA_TIME to Millisecond 
     Service1.nlog.LogError(0, "Duration=", Me.duration.ToString, "") 


    Catch ex As Exception 

     Marshal.ReleaseComObject(Me.graphBuilder) 
     Me.graphBuilder = Nothing 
     Service1.nlog.LogError(0, "Exception MP3Convert", ex.Message, "") 
    Finally 

     asyncReader = Nothing 
     WaveParser = Nothing 
     'ACMWrapper = Nothing 
     MPEG3Wrapper = Nothing 
     WavDestWrapper = Nothing 
     fileSource = Nothing 
     fileDestination = Nothing 

    End Try 

     Service1.nlog.LogError(0, "Ending Init MP3", " Result:", result.ToString) 

     Return result 

End Function 
+0

Зачем вставлять код с кодом? как это полезно? –

+0

Здесь я должен показать, как я попытался установить параметры сжатия, как я отметил в своем описании, чтобы, если кто-то захотел проверить его, они могли. Суть в том, что либо пытаться установить IAMStreamConfig, либо нет - я не получаю тот же результат, что и в GraphStudio. – user2176065

+1

'1' Что такое DirectShowNET.MPEG3Layer? '2' Вы не должны делать SetSyncSource для отдельных фильтров, это не хорошо, но это может быть плохо. –

ответ

0

После долгих исследований я не смог сделать работу сжатия так же, как с графедитом. Поэтому я решил полностью изменить проект и использовать хромовый кодировщик для преобразования. Он отлично работает с очень маленьким кодом. Вот новый код:

Private Function PlayInitMP3(ByVal WaveFile As String, ByVal MP3File As String) As Integer 
    Try 
     'Convert WAV to MP3 using Lame 
     Dim WaveFileInfo As New FileInfo(WaveFile) 
     Dim MP3FileInfo As New FileInfo(MP3File) 
     Dim strLameLine As String 
     Dim LameExe As String = ConfigurationManager.AppSettings("LameExe") '"C:\scribe\lame\lame.exe -h" 
     Dim sBlank As String = " " 
     Dim waitTime As Integer = System.Convert.ToInt16(ConfigurationManager.AppSettings("LameWait")) '-1 

     strLameLine = LameExe & sBlank & WaveFileInfo.FullName & sBlank & MP3FileInfo.FullName 

     Shell(strLameLine, AppWinStyle.Hide, True, waitTime) 

     'Debug 
     Service1.nlog.LogError(0, WaveFileInfo.Name, strLameLine, "LAME MP3 Conversion Complete") 

    Catch ex As Exception 

    End Try 

End Function