directshow 获取本地音频

网上很多讲解directshow的资料,讲的都很好,但是就想说各位老大们···上份简单的代码吧,快速开发中 不一定有时间仔细阅读那么多页的文档,对着文档一段段的copy函数也很烦躁,今天我自己传一份directshow获取本地话筒录音的代码。用的时候记得插话筒。

  1. #include "stdafx.h"  
  2. #include <dshow.h>  
  3. #include <atlconv.h>  
  4.   
  5. #define OUTPUT_PIN       1  
  6. #define OUTPUT_MEDIATYPE 1  
  7.   
  8.   
  9. char* GuidToString(const GUID &guid)  
  10. {  
  11.     int buf_len=64;  
  12.     char *buf =(char *)malloc(buf_len);  
  13.     _snprintf(  
  14.         buf,  
  15.         buf_len,  
  16.         "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",  
  17.         guid.Data1, guid.Data2, guid.Data3,  
  18.         guid.Data4[0], guid.Data4[1],  
  19.         guid.Data4[2], guid.Data4[3],  
  20.         guid.Data4[4], guid.Data4[5],  
  21.         guid.Data4[6], guid.Data4[7]);  
  22.     //printf("%s\n",buf);  
  23.     return buf;  
  24. }  
  25.   
  26. HRESULT AddFilterByCLSID(  
  27.     IGraphBuilder *pGraph,  // Pointer to the Filter Graph Manager.  
  28.     const GUID& clsid,      // CLSID of the filter to create.  
  29.     LPCWSTR wszName,        // A name for the filter.  
  30.     IBaseFilter **ppF)      // Receives a pointer to the filter.  
  31. {  
  32.     if (!pGraph || ! ppF) return E_POINTER;  
  33.     *ppF = 0;  
  34.     IBaseFilter *pF = 0;  
  35.     HRESULT hr = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER,  
  36.         IID_IBaseFilter, reinterpret_cast<void**>(&pF));  
  37.     if (SUCCEEDED(hr))  
  38.     {  
  39.         hr = pGraph->AddFilter(pF, wszName);  
  40.         if (SUCCEEDED(hr))  
  41.             *ppF = pF;  
  42.         else  
  43.             pF->Release();  
  44.     }  
  45.     return hr;  
  46. }  
  47. //  
  48. //HRESULT GetUnconnectedPin(  
  49. //  IBaseFilter *pFilter,   // Pointer to the filter.  
  50. //  PIN_DIRECTION PinDir,   // Direction of the pin to find.  
  51. //  IPin **ppPin)           // Receives a pointer to the pin.  
  52. //{  
  53. //  *ppPin = 0;  
  54. //  IEnumPins *pEnum = 0;  
  55. //  IPin *pPin = 0;  
  56. //  HRESULT hr = pFilter->EnumPins(&pEnum);  
  57. //  if (FAILED(hr))  
  58. //  {  
  59. //      return hr;  
  60. //  }  
  61. //  while (pEnum->Next(1, &pPin, NULL) == S_OK)  
  62. //  {  
  63. //      PIN_DIRECTION ThisPinDir;  
  64. //      pPin->QueryDirection(&ThisPinDir);  
  65. //      if (ThisPinDir == PinDir)  
  66. //      {  
  67. //          IPin *pTmp = 0;  
  68. //          hr = pPin->ConnectedTo(&pTmp);  
  69. //          if (SUCCEEDED(hr))  // Already connected, not the pin we want.  
  70. //          {  
  71. //              pTmp->Release();  
  72. //          }  
  73. //          else  // Unconnected, 这就是我们想要的pin,空闲的pin  
  74. //          {  
  75. //              pEnum->Release();  
  76. //              *ppPin = pPin;  
  77. //              return S_OK;  
  78. //          }  
  79. //      }  
  80. //      pPin->Release();  
  81. //  }  
  82. //  pEnum->Release();  
  83. //  // Did not find a matching pin.  
  84. //  return E_FAIL;  
  85. //}  
  86. //  
  87.   
  88.   
  89. // Find an unconnected pin on a filter.  
  90. // This too is stolen from the DX9 SDK.  
  91. HRESULT GetUnconnectedPin(IBaseFilter *pFilter, // Pointer to the filter.  
  92.     PIN_DIRECTION PinDir, // Direction of the pin to find.  
  93.     IPin **ppPin) // Receives a pointer to the pin.  
  94. {  
  95.     *ppPin = 0;  
  96.     IEnumPins *pEnum = 0;  
  97.     IPin *pPin = 0;  
  98.     HRESULT hr = pFilter->EnumPins(&pEnum);  
  99.     if (FAILED(hr))  
  100.     {  
  101.         return hr;  
  102.     }  
  103.     while (pEnum->Next(1, &pPin, NULL) == S_OK)  
  104.     {  
  105.         PIN_DIRECTION ThisPinDir;  
  106.         pPin->QueryDirection(&ThisPinDir);  
  107.         if (ThisPinDir == PinDir)  
  108.         {  
  109.             IPin *pTmp = 0;  
  110.             hr = pPin->ConnectedTo(&pTmp);  
  111.             if (SUCCEEDED(hr)) // Already connected--not the pin we want  
  112.             {  
  113.                 pTmp->Release();  
  114.             }  
  115.             else // Unconnected--this is the pin we want  
  116.             {  
  117.                 pEnum->Release();  
  118.                 *ppPin = pPin;  
  119.                 return S_OK;  
  120.             }  
  121.         }  
  122.         pPin->Release();  
  123.     }  
  124.     pEnum->Release();  
  125.     // Did not find a matching pin.  
  126.     return E_FAIL;  
  127. }  
  128. HRESULT ConnectFilters(  
  129.     IGraphBuilder *pGraph, // Filter Graph Manager.  
  130.     IPin *pOut,            // Output pin on the upstream filter.  
  131.     IBaseFilter *pDest)    // Downstream filter.  
  132. {  
  133.     if ((pGraph == NULL) || (pOut == NULL) || (pDest == NULL))  
  134.     {  
  135.         return E_POINTER;  
  136.     }  
  137. #ifdef debug  
  138.     PIN_DIRECTION PinDir;  
  139.     pOut->QueryDirection(&PinDir);  
  140.     _ASSERTE(PinDir == PINDIR_OUTPUT);  
  141. #endif  
  142.   
  143.     //找一个空闲的输入pin  
  144.     IPin *pIn = 0;  
  145.     HRESULT hr = GetUnconnectedPin(pDest, PINDIR_INPUT, &pIn);  
  146.     if (FAILED(hr))  
  147.     {  
  148.         return hr;  
  149.     }  
  150.     // Try to connect them.  
  151.     hr = pGraph->Connect(pOut, pIn);  
  152.     pIn->Release();  
  153.     return hr;  
  154. }  
  155. static const GUID CLSID_WavDest =  
  156. { 0x3c78b8e2, 0x6c4d, 0x11d1, { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } };  
  157. // Enumerate all of the audio input devices  
  158. // Return the _first_ of these to the caller  
  159. // That should be the one chosen in the control panel.  
  160. HRESULT EnumerateAudioInputFilters(void** gottaFilter)  
  161. {  
  162.     // Once again, code stolen from the DX9 SDK.  
  163.     // Create the System Device Enumerator.  
  164.     ICreateDevEnum *pSysDevEnum = NULL;  
  165.     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,  
  166.         CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,  
  167.         (void **)&pSysDevEnum);  
  168.     if (FAILED(hr))  
  169.     {  
  170.         return hr;  
  171.     }  
  172.     // Obtain a class enumerator for the audio input category.  
  173.     IEnumMoniker *pEnumCat = NULL;  
  174.     hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,  
  175.         &pEnumCat, 0);  
  176.     if (hr == S_OK)  
  177.     {  
  178.         // Enumerate the monikers.  
  179.         IMoniker *pMoniker = NULL;  
  180.         ULONG cFetched;  
  181.         if (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)  
  182.         {  
  183.             // Bind the first moniker to an object.  
  184.             IPropertyBag *pPropBag;  
  185.             hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,  
  186.                 (void **)&pPropBag);  
  187.             if (SUCCEEDED(hr))  
  188.             {  
  189.                 // To retrieve the filter's friendly name,  
  190.                 // do the following:  
  191.                 VARIANT varName;  
  192.                 VariantInit(&varName);  
  193.                 hr = pPropBag->Read(L"FriendlyName", &varName, 0);  
  194.                 if (SUCCEEDED(hr))  
  195.                 {  
  196.                     wprintf(L"Selecting Audio Input Device: %s\n",  
  197.                         varName.bstrVal);  
  198.                 }  
  199.                 VariantClear(&varName);  
  200.                 // To create an instance of the filter,  
  201.                 // do the following:  
  202.                 // Remember to release gottaFilter later.  
  203.                 hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,gottaFilter);  
  204.   
  205.                 pPropBag->Release();  
  206.             }  
  207.             pMoniker->Release();  
  208.         }  
  209.         pEnumCat->Release();  
  210.     }  
  211.     pSysDevEnum->Release();  
  212.     return hr;  
  213. }  
  214.   
  215.   
  216. // Code adopted from example in the DX9 SDK.  
  217. // This code allows us to find the input pins an audio input filter.  
  218. // We'll print out a list of them, indicating the enabled one.  
  219. HRESULT EnumerateAudioInputPins(IBaseFilter *pFilter)  
  220. {  
  221.     IEnumPins *pEnum = NULL;  
  222.     IPin *pPin = NULL;  
  223.     PIN_DIRECTION PinDirThis;  
  224.     PIN_INFO pInfo;  
  225.     IAMAudioInputMixer *pAMAIM = NULL;  
  226.     BOOL pfEnable = FALSE;  
  227.     // Begin by enumerating all the pins on a filter.  
  228.     HRESULT hr = pFilter->EnumPins(&pEnum);  
  229.     if (FAILED(hr))  
  230.     {  
  231.         return NULL;  
  232.     }  
  233.     // Now, look for a pin that matches the direction characteristic.  
  234.     // When we've found it, we'll examine it.  
  235.     while(pEnum->Next(1, &pPin, 0) == S_OK)  
  236.     {  
  237.         // Get the pin direction.  
  238.         pPin->QueryDirection(&PinDirThis);  
  239.         if (PinDirThis == PINDIR_INPUT) {  
  240.             // OK, we've found an input pin on the filter.  
  241.             // Now let's get the information on that pin  
  242.             // so we can print the name of the pin to the console.  
  243.             hr = pPin->QueryPinInfo(&pInfo);  
  244.             if (SUCCEEDED(hr)) {  
  245.                 wprintf(L"Input pin: %s\n", pInfo.achName);  
  246.                 // Now let's get the correct interface.  
  247.                 hr = pPin->QueryInterface(IID_IAMAudioInputMixer,  
  248.                     (void**) &pAMAIM);  
  249.                 if (SUCCEEDED(hr)) {  
  250.                     // Find out whether the pin is enabled.  
  251.                     // Is it the active input pin on the filter?  
  252.   
  253.                     hr = pAMAIM->get_Enable(&pfEnable);  
  254.                     if (SUCCEEDED(hr)) {  
  255.                         if (pfEnable) {  
  256.                             wprintf(L"\tENABLED\n");  
  257.                         }  
  258.                     }  
  259.                     pAMAIM->Release();  
  260.                 }  
  261.                 pInfo.pFilter->Release(); // from QueryPinInfo  
  262.             }  
  263.         }  
  264.         pPin->Release();  
  265.     }  
  266.     pEnum->Release();  
  267.     return hr;  
  268. }  
  269.   
  270.   
  271. // Connect two filters together with the Filter Graph Manager,  
  272. // Stolen from the DX9 SDK.  
  273. // This is the base version.  
  274. //HRESULT ConnectFilters(IGraphBuilder *pGraph, // Filter Graph Manager.  
  275. //  IPin *pOut, // Output pin on the upstream filter.  
  276. //  IBaseFilter *pDest) // Downstream filter.  
  277. //{  
  278. //  if ((pGraph == NULL) || (pOut == NULL) || (pDest == NULL))  
  279. //  {  
  280. //      return E_POINTER;  
  281. //  }  
  282. //  // Find an input pin on the downstream filter.  
  283. //  IPin *pIn = 0;  
  284. //  HRESULT hr = GetUnconnectedPin(pDest, PINDIR_INPUT, &pIn);  
  285. //  if (FAILED(hr))  
  286. //  {  
  287. //      return hr;  
  288. //  }  
  289. //  // Try to connect them.  
  290. //  hr = pGraph->Connect(pOut, pIn);  
  291. //  pIn->Release();  
  292. //  return hr;  
  293. //}  
  294. // Enumerate all of the audio compressors.  
  295. // Return the one with the matching name to the caller.  
  296. HRESULT EnumerateAudioCompressorFilters(void** gottaCompressor,  
  297.     wchar_t* matchName)  
  298. {  
  299.     // Once again, code stolen from the DX9 SDK.  
  300.     // Create the System Device Enumerator.  
  301.     ICreateDevEnum *pSysDevEnum = NULL;  
  302.     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,  
  303.         CLSCTX_INPROC_SERVER,  
  304.         IID_ICreateDevEnum,  
  305.         (void **)&pSysDevEnum);  
  306.     if (FAILED(hr))  
  307.     {  
  308.         return hr;  
  309.     }  
  310.     // Obtain a class enumerator for the audio input category.  
  311.     IEnumMoniker *pEnumCat = NULL;  
  312.     hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioCompressorCategory,  
  313.         &pEnumCat, 0);  
  314.   
  315.     if (hr == S_OK)  
  316.     {  
  317.         // Enumerate the monikers.  
  318.         IMoniker *pMoniker = NULL;  
  319.         ULONG cFetched;  
  320.         BOOL done = false;  
  321.         while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (!done))  
  322.         {  
  323.             // Bind the first moniker to an object.  
  324.             IPropertyBag *pPropBag;  
  325.             hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,  
  326.                 (void **)&pPropBag);  
  327.             if (SUCCEEDED(hr))  
  328.             {  
  329.                 // Retrieve the filter's friendly name.  
  330.                 VARIANT varName;  
  331.                 VariantInit(&varName);  
  332.                 hr = pPropBag->Read(L"FriendlyName", &varName, 0);  
  333.                 if (SUCCEEDED(hr))  
  334.                 {  
  335.                     wprintf(L"Testing Audio Compressor: %s\n",  
  336.                         varName.bstrVal);  
  337.                     // Is it the right one?  
  338.                     if (wcsncmp(varName.bstrVal, matchName,  
  339.                         wcslen(matchName)) == 0)  
  340.                     {  
  341.                         // We found it; send it back to the caller  
  342.                         hr = pMoniker->BindToObject(NULL, NULL,  
  343.                             IID_IBaseFilter,  
  344.                             gottaCompressor);  
  345.                         done = true;  
  346.                     }  
  347.                 }  
  348.                 VariantClear(&varName);  
  349.                 pPropBag->Release();  
  350.             }  
  351.             pMoniker->Release();  
  352.         }  
  353.         pEnumCat->Release();  
  354.     }  
  355.     pSysDevEnum->Release();  
  356.     return hr;  
  357. }  
  358. // Connect two filters together with the Filter Graph Manager.  
  359. // Again, stolen from the DX9 SDK.  
  360. // This is an overloaded version.  
  361. HRESULT ConnectFilters(IGraphBuilder *pGraph,  
  362.     IBaseFilter *pSrc,  
  363.     IBaseFilter *pDest)  
  364. {  
  365.     if ((pGraph == NULL) || (pSrc == NULL) || (pDest == NULL))  
  366.     {  
  367.         return E_POINTER;  
  368.     }  
  369.     // Find an output pin on the first filter.  
  370.     IPin *pOut = 0;  
  371.     HRESULT hr = GetUnconnectedPin(pSrc, PINDIR_OUTPUT, &pOut);  
  372.     if (FAILED(hr))  
  373.     {  
  374.         return hr;  
  375.     }  
  376.     hr = ConnectFilters(pGraph, pOut, pDest);  
  377.     pOut->Release();  
  378.     return hr;  
  379. }  
  380. int _tmain(int argc, _TCHAR* argv[])  
  381. {  
  382.       
  383.     IGraphBuilder *pGraph = NULL; // Filter graph builder object  
  384.     IMediaControl *pControl = NULL; // Media control object  
  385.     IFileSinkFilter *pSink = NULL; // Interface on file writer  
  386.     IBaseFilter *pAudioInputFilter = NULL; // Audio capture filter  
  387.     IBaseFilter *pFileWriter = NULL; // File writer filter  
  388.     // Initialize the COM library.  
  389.     HRESULT hr = CoInitialize(NULL);  
  390.     if (FAILED(hr))  
  391.     {  
  392.         // We'll send our error messages to the console.  
  393.         printf("ERROR - Could not initialize COM library");  
  394.         return hr;  
  395.     }  
  396.     // Create the Filter Graph Manager and query for interfaces.  
  397.     hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  
  398.         IID_IGraphBuilder, (void **)&pGraph);  
  399.     if (FAILED(hr)) // FAILED is a macro that tests the return value  
  400.     {  
  401.         printf("ERROR - Could not create the Filter Graph Manager.");  
  402.         return hr;  
  403.     }  
  404.     // Using QueryInterface on the graph builder object,  
  405.     // get the IMediaControl object.  
  406.     hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);  
  407.     if (FAILED(hr))  
  408.     {  
  409.         printf("ERROR - Could not create the Media Control object.");  
  410.         pGraph->Release(); // Clean up after ourselves  
  411.         CoUninitialize(); // And uninitalize COM  
  412.         return hr;  
  413.     }  
  414.   
  415.     // OK, so now we want to build the filter graph  
  416.     // using an AudioCapture filter.  
  417.     // But there are several to choose from,  
  418.     // so we need to enumerate them and then pick one.  
  419.     hr = EnumerateAudioInputFilters((void**) &pAudioInputFilter);  
  420.     hr = EnumerateAudioInputPins(pAudioInputFilter);  
  421.     // Add the audio capture filter to the filter graph.  
  422.     hr = pGraph->AddFilter(pAudioInputFilter, L"Capture");  
  423.     // Next add the AVIMux. (You'll see why.)  
  424.     IBaseFilter *pAVIMux = NULL;  
  425.     hr = AddFilterByCLSID(pGraph, CLSID_AviDest, L"AVI Mux", &pAVIMux);  
  426.     // Connect the filters.  
  427.     hr = ConnectFilters(pGraph, pAudioInputFilter, pAVIMux);  
  428.     // And now we instance a file writer filter.  
  429.     hr = AddFilterByCLSID(pGraph, CLSID_FileWriter,  
  430.         L"File Writer", &pFileWriter);  
  431.     // Set the file name.  
  432.     hr = pFileWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pSink);  
  433.     pSink->SetFileName(L"C:\\MyWAVFile.AVI", NULL);  
  434.     // Connect the filters.  
  435.     hr = ConnectFilters(pGraph, pAVIMux, pFileWriter);  
  436.     if (SUCCEEDED(hr))  
  437.     {  
  438.         // Run the graph.  
  439.         hr = pControl->Run();  
  440.         if (SUCCEEDED(hr))  
  441.         {  
  442.             // Wait patiently for completion of the recording.  
  443.             wprintf(L"Started recording...press Enter to stop recording.\n");  
  444.             // Wait for completion.  
  445.             char ch;  
  446.             ch = getchar(); // We wait for keyboard input  
  447.         }  
  448.         // And stop the filter graph.  
  449.         hr = pControl->Stop();  
  450.         wprintf(L"Stopped recording.\n"); // To the console  
  451.         // Before we finish, save the filter graph to a file.  
  452.     //  SaveGraphFile(pGraph, L"C:\\MyGraph.GRF");  
  453.     }  
  454.     // Now release everything and clean up.  
  455.     pSink->Release();  
  456.     pAVIMux->Release();  
  457.     pFileWriter->Release();  
  458.     pAudioInputFilter->Release();  
  459.     pControl->Release();  
  460.     pGraph->Release();  
  461.     CoUninitialize();  
  462.     return 0;  
  463. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值