How to get the media length use directshow

来源:互联网 发布:网络打印机扫描设置 编辑:程序博客网 时间:2024/04/30 09:59

Hello ,guys!

Glad to see you again!

Now, I will tell you how to get the media length by driectshow!

First ,you should install DirectX SDK!

When you installing the Directx SDK, we can step the next!

Let's go into how to:

(1) Initialized DirectShow,defined as global,the code looks like:

 

#include
#pragma comment(lib,"strmiids.lib")

IGraphBuilder *pGB;
IMediaPosition *pMP;

#include

REFTIME m_Total = 0;

#define JIF(x) if (FAILED(hr=(x))) /
{return hr;}

the first line show that we will use DirectShow Interface,next line shows the destination library.

Before we use the DirectShow Interface, we must build the FilterGraph,so we must use IGraphBuilder interface, it is used to query the DirectShow Interface about the media process!

m_Total is used to storage the media length, and  REFTIME is defined in strmif.h file,so included this head file.

Next ,the IMediaPosition interface used to get the destination media's length!

When we query the destination interface of the DirectShow,sometimes it maybe fail,

so I add  a micro , use to estimate failure or not:

#define JIF(x) if (FAILED(hr=(x))) /
{return hr;}

(2) When we had initialized,we will get the media length,code looks like:

HRESULT InitDirectShow(CString strFileName)

{

 WCHAR wFile[MAX_PATH];
 HRESULT hr;
 
 CoInitialize(NULL);

#ifndef UNICODE
    MultiByteToWideChar(CP_ACP, 0, strFileName, -1, wFile, MAX_PATH);
#else
    wcscpy(wFile, strFileName);
#endif 
 
 JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
  IID_IGraphBuilder, (void **)&pGB));
 
 JIF(pGB->RenderFile(wFile, NULL));
 
 if(SUCCEEDED(hr))
 {
  JIF(pGB->QueryInterface(IID_IMediaPosition, (void **)&pMP));
 }
 else
 {
  pGB->Release();
  CoUninitialize();
  return hr;
 }

 Sleep(1000);
 
 JIF(pMP->get_Duration(&m_Total));

 pMP->Release();
 pGB->Release();

 CoUninitialize();
 
 return hr;

}

Before we use DirectShow,we must initialized COM Library first,so CoInitialize(NULL);

Because the COM interface support UNICODE , so we must transform the file name from ANSI to UNICODE, use the lasted code :

#ifndef UNICODE
    MultiByteToWideChar(CP_ACP, 0, strFileName, -1, wFile, MAX_PATH);
#else
    wcscpy(wFile, strFileName);
#endif 

Next , we must initialize  FilterGraph interface and return pGB, in order to use to query the IMediaPosition, use it to get the media length.

When we get the pGB,we can render the file to FilterGraph, which can use FilterGraph to process the destination media file.

then, we can get the media file's play time by get_Duration of the IMediaPosition interface pointer pGB.The getting time of the media file in second.

When we query the interface , the count will add auto, so when we used complete,we should Release the count, in order to release the COM object safely!

The last, we should release the COM library use the code CoUninitialize();

(3)  How to call:

    TCHAR bigBuff[MAX_PATH] /* = _T("")*/;  // maximum common dialog buffer size
    TCHAR szFilter[] =
     _T("Video Files (*.avi; *.dat; *.mpg; *.mpeg)|*.avi; *.dat; *.mpg; *.mpeg|Audio files (*.wav; *.mp3)|*.wav; *.mp3||");
    //All Files (*.*)|*.*|
    ZeroMemory(bigBuff,sizeof(bigBuff));
    CFileDialog dlg(TRUE, NULL, NULL,
     OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT, szFilter);
   
    // Modify OPENFILENAME members directly to point to bigBuff
    dlg.m_ofn.lpstrFile = bigBuff;
    dlg.m_ofn.nMaxFile = sizeof(bigBuff);
   
    if(IDOK == dlg.DoModal())
    {
     CString strFileName;

     strFileName = dlg.GetPathName();
     if(S_OK == InitDirectShow(strFileName))
     {
      CString strMediaLen;
      strMediaLen.Format(_T("The destination media length :%.2f s"),m_Total);
      AfxMessageBox(strMediaLen);
      return;
     }
     else
     {
      AfxMessageBox(_T("Get Media length error!"));
     }
    }

Very easy , isn't it?

DirectXSDK9.0 + VC6.0 + VSP6.0 + WINXP!

Good luck!