利用DirectShow实现对视频文件H264编码与解码基类 2

/**************编码Graph的创建*************/
  HRESULT hr = E_FAIL;
  hr = _CreateFilterGraph(&m_nDecode.pGraph, &m_nDecode.pBuilder);
  if(FAILED(hr))
  {
   AfxMessageBox("Uninitialize COM Library!");
      return -7;
  }
  int iResult = -7;
     do
  {
  /***************************查询接口***************************/
  hr = m_nDecode.pGraph->QueryInterface(IID_IMediaControl, (void**)&m_nDecode.pControl);
  if (FAILED(hr))//查询失败
   break ;
  hr = m_nDecode.pGraph->QueryInterface(IID_IMediaEventEx, (void**)&m_nDecode.pEvent);
  if (FAILED(hr))//查询失败
   break ; 
  hr = m_nDecode.pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m_nDecode.pSeek);
  if (FAILED(hr))//查询失败
   break ; 
  hr = m_nDecode.pGraph->QueryInterface(IID_IMediaFilter, (void**)&m_nDecode.pMedia);
  if (FAILED(hr))//查询失败
   break ; 
        
  /*************************辅助Filter的创建*********************/
  hr = m_nDecode.pGraph->AddSourceFilter(strSourcePathName.AllocSysString(), L"Source Filter", &m_nDecodeFilter.pSrc);
  if(FAILED(hr))//添加失败
   break ;
  hr = CoCreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_nDecodeFilter.pAviMux);
  if (FAILED(hr)) //创建失败
   break;
  hr = m_nDecodeFilter.pAviMux->QueryInterface(IID_IMediaSeeking, (void**)&m_nDecode.pSeek);
  if (FAILED(hr))//查询失败
   break ; 
  hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC, IID_IFileSinkFilter2, (void**)&m_nDecodeFilter.pSink);
  if (FAILED(hr))  //创建失败
   break ;
        hr = m_nDecodeFilter.pSink->QueryInterface(IID_IBaseFilter, (void**)&m_nDecodeFilter.pFileWrite);
  if(FAILED(hr)) //创建失败
   break ; 
  if (!m_nDecodeFilter.H264Decode) //H264Encode Filter 未被创建
   break;  
  hr = m_nDecode.pGraph->AddFilter(m_nDecodeFilter.H264Decode, L"H264 UnCompress Filter");

/*********************创建Graph中的上游链路(H264Decode)*****************/
  hr = m_nDecode.pBuilder->RenderStream(NULL, NULL, m_nDecodeFilter.pSrc, NULL, m_nDecodeFilter.H264Decode);
  if (FAILED(hr)) //创建链路失败
  {
  AfxMessageBox("/r该编解码器不支持所选的媒体类型,请下载相应的插件。/rCreate pSrc->pAviSplitter->H264UnCompressFilter Failed!");
   break;
  }

  /**********************第三方编码器的检测********************/
  if(strCompressorName.IsEmpty()) //压缩设备名为空
   m_nDecodeFilter.pEncode = NULL;
     else
   if(!_CreateCompressDevice(strCompressorName, &m_nDecodeFilter.pEncode)) //创建压缩设备失败
   {
    iResult = -3; 
    break ;
   }

  /************************添加Filter到Graph中********************/
  if(m_nDecodeFilter.pEncode)
  {
   hr = m_nDecode.pGraph->AddFilter(m_nDecodeFilter.pEncode, L"Compress Filter");
   if(FAILED(hr))
    break;
  }
  hr = m_nDecode.pGraph->AddFilter(m_nDecodeFilter.pAviMux, L"AVI Dest Filter");
  if(FAILED(hr))
   break;
  hr = m_nDecode.pGraph->AddFilter((IBaseFilter *)m_nDecodeFilter.pFileWrite, L"File Write Filter");
  if(FAILED(hr))
   break;
  hr = m_nDecodeFilter.pSink->SetMode(AM_FILE_OVERWRITE);
  if(FAILED(hr))
   break;
  hr = m_nDecodeFilter.pSink->SetFileName(strDestPathName.AllocSysString() , NULL);
  if(FAILED(hr))
  {
   iResult = -5;
   break;
  }

  /*********************创建Graph中的下游链路(H264Decode)*****************/
  hr = m_nDecode.pBuilder->RenderStream(NULL, NULL, m_nDecodeFilter.H264Decode, m_nDecodeFilter.pEncode, m_nDecodeFilter.pFileWrite);
  if (FAILED(hr)) 
  {
   AfxMessageBox("/r该编解码器不支持所选的媒体类型,请下载相应的插件。/rCreate H264 Filter->---->File Write Filter Failed!");
   break;
  }
  hr=m_nDecode.pMedia->SetSyncSource(NULL); 

  hr = m_nDecode.pControl->Run(); //运行filter graph 
  if(SUCCEEDED(hr))
  {
   iResult = 1;
   m_nDecodeCtl.bStopFlag = true;
  } 
  }while(false);
return iResult;
}


int CEncode::GetProgress(bool bFlag)
{
HRESULT hr = E_FAIL;
if(bFlag) //压缩状态
{
  if(m_nEncodeCtl.bCompleted) //数据传输完成
  {
            m_nEncodeCtl.bCompleted = false;
   return 100;
  }
  
}
else  //解压状态

  if(m_nDecodeCtl.bCompleted) //数据传输完成
  {
            m_nDecodeCtl.bCompleted = false;
   return 100;
  }

}

/********************获得数据传输的当前状态*********************/
IMediaSeeking * pSeek = bFlag? m_nEncode.pSeek : m_nDecode.pSeek;
LONGLONG lDuration = 1;
if(pSeek == NULL)
  return -1;
hr = pSeek->GetDuration(&lDuration);
if(SUCCEEDED(hr)) //得到总的持续时间成功
{
  LONGLONG Start = 0;
  hr = pSeek->GetCurrentPosition(&Start); //得到当前的位置
  if(SUCCEEDED(hr)) //获得当前的位置成功
  {
   int iProgress = (int)(100*(Start/((double)lDuration)));
   if (bFlag)  //压缩状态
   {
    m_nEncodeCtl.iProgress = iProgress;
    return m_nEncodeCtl.iProgress;
   }
   else   //解缩状态
   {
    m_nDecodeCtl.iProgress = iProgress;
    return m_nDecodeCtl.iProgress;
   }
  }
  return -1;
}
else
  return -1;

}


bool CEncode::TerminiateProgress(bool bFlag)
{
HRESULT hr = E_FAIL;
if(bFlag)
{
  /*********************终止编码*******************/
  if(m_nEncode.pControl!=NULL&&m_nEncodeCtl.bStopFlag)
  {
   OAFilterState state = State_Stopped;
      if (SUCCEEDED(m_nEncode.pControl->GetState(15, &state)/*得到当前状态*/))
   {
    if(state != State_Stopped)
      hr = m_nEncode.pControl->Stop(); //停止filter graph
   }
      _DestroyEncodeGraph();
  }
  return SUCCEEDED(hr);
}
else
{
  /*********************终止解码*******************/
  if(m_nDecode.pControl!=NULL&&m_nDecodeCtl.bStopFlag)
  {
   OAFilterState state = State_Stopped;
      if (SUCCEEDED(m_nDecode.pControl->GetState(15, &state)/*得到当前状态*/))
   {
    if(state != State_Stopped)
      hr = m_nDecode.pControl->Stop(); //停止filter graph
   }
     _DestroyDecodeGraph();
  }
  return SUCCEEDED(hr);
}
}


bool CEncode::SetNotifyWindow(HWND inWindow, bool bFlag)
{
HRESULT hr = E_FAIL;
if (bFlag) //压缩过程
{
  if(m_nEncode.pEvent)
  {
   hr = m_nEncode.pEvent->SetNotifyWindow((OAHWND)inWindow, WM_ENCODE_NOTIFY, 0);
      return SUCCEEDED(hr);
  }
}
else //解压过程
  if(m_nDecode.pEvent)
  {
   hr = m_nDecode.pEvent->SetNotifyWindow((OAHWND)inWindow, WM_DECODE_NOTIFY, 0);
   return SUCCEEDED(hr);
  }
return false;
}



void CEncode::OnCodecNotify(WPARAM inWParam, LPARAM inLParam, bool bFlags)
{
IMediaEventEx * pEvent = bFlags? m_nEncode.pEvent:m_nDecode.pEvent;
if (pEvent)
{
  LONG   eventCode = 0, eventParam1 = 0, eventParam2 = 0;
  while (SUCCEEDED(pEvent->GetEvent(&eventCode, &eventParam1, &eventParam2, 0)))
  {    
   switch (eventCode)
   {
   case EC_COMPLETE: //数据传输完毕
    TerminiateProgress(bFlags);
    bFlags? (m_nEncodeCtl.bCompleted = true) : (m_nDecodeCtl.bCompleted = true);
    break;
   case EC_USERABORT: //运行出错
   case EC_ERRORABORT:
    TerminiateProgress(bFlags);
    bFlags? (m_nEncodeCtl.bCompleted = true) : (m_nDecodeCtl.bCompleted = true);
    break;    
   default:
    break;
   }
   pEvent->FreeEventParams(eventCode, eventParam1, eventParam2);
  }
}  
}


int CEncode::_IsH264Encoded(CString strFileName)
{
IGraphBuilder * pGraph = NULL;
IBaseFilter * pSrc = NULL;
IBaseFilter * pAviSplitter = NULL;
HRESULT hr = E_FAIL;
int nResult = -1;
do
{
  /******************创建Filter Graph Manager******************/
  hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
  if(FAILED(hr)) //创建Filter Graph Manager失败
  {
   AfxMessageBox("Create Filter Graph Manager Failed!");
   return nResult;
  }
  int nlen = MultiByteToWideChar(CP_ACP, 0, strFileName, -1, NULL, NULL);
  LPWSTR  pstrFile = new WCHAR[nlen];
  MultiByteToWideChar(CP_ACP, 0, strFileName, -1, pstrFile, nlen);
  
  /***************创建Source Filter与AVI Splitter Filter***************/
  hr = pGraph->AddSourceFilter(pstrFile, L"Source Filter", &pSrc);
  if(pstrFile) 
   delete pstrFile; //释放资源
  if(FAILED(hr))//添加Source Filter失败

{
   AfxMessageBox("Create Source Filter Failed!");
   return nResult;
  }
  hr = CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviSplitter);
  if(FAILED(hr))//创建Avi Splitter Filter 失败
  {
   AfxMessageBox("Add Avi Splitter Filer Failed!");
   return nResult;
  }
  pGraph->AddFilter(pAviSplitter, L"AVI Splitter");

  /****************链接Source Filter 与AVI Splitter Filter**************/
  IPin * pSrcOutPin = NULL;
  IPin * pAviInPin = NULL;
  IPin * pAviOutPin = NULL;
  if(_FindPins(pSrc, false, &pSrcOutPin)&&_FindPins(pAviSplitter, true, &pAviInPin))
  {
   hr = pGraph->Connect(pSrcOutPin, pAviInPin);
   if(FAILED(hr)) //连接失败
   {
    pSrcOutPin->Release();
    pAviInPin->Release();
    AfxMessageBox("Connect Source Filter to Avi Splitter Failed!");
    break;
   }
   else //连接成功
   {
    if(_FindPins(pAviSplitter, false, &pAviOutPin))
    {
     IEnumMediaTypes * pEnumType = NULL;
     hr = pAviOutPin->EnumMediaTypes(&pEnumType);
     if(FAILED(hr))//枚举pin的媒体类型失败
     {
      pAviOutPin->Release();
      AfxMessageBox("Enum MediaTypes Failed!");
      break;
     }
     else //枚举pin的媒体类型成功
     {
      AM_MEDIA_TYPE * mediaType;
      ULONG nfeched = 0;
      pEnumType->Reset();
      while(SUCCEEDED(pEnumType->Next(1, &mediaType, &nfeched))&&nfeched)//枚举媒体类型
      {
                              static const GUID MEDIASUBTYPE_DT264=
         {0x52445444, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}};
         if(mediaType->subtype == MEDIASUBTYPE_DT264) //为H264编码文件
         {
                                  nResult = 1;
          DeleteMediaType(mediaType);
          break;
         }
         else 不为H264编码文件
          nResult = 0;
         DeleteMediaType(mediaType);
      }
      pEnumType->Release();
     }
                    pAviOutPin->Release();
    }
    pGraph->Disconnect(pSrcOutPin);
    pGraph->Disconnect(pAviInPin);
    pSrcOutPin->Release();
    pAviInPin->Release();
   }
  }
  else //查找Source Filter的输出pin或Avi Splitter Filter的输入pin失败
   return nResult;
}while(false);

/********************释放资源*********************/
    if(pAviSplitter)
{
  pGraph->RemoveFilter(pAviSplitter);
  SafeRelease(pAviSplitter);
}
if(pSrc)
{
  pGraph->RemoveFilter(pSrc);
  SafeRelease(pSrc);
}
SafeRelease(pGraph);
return nResult;
}


bool CEncode::_IsFileOpenedCorrectly(CString strFileName)
{
bool bOpened = false;
char * pFileName = (LPSTR)(LPCTSTR)strFileName;
try
{
  CFile f(pFileName, CFile::modeRead|CFile::shareDenyNone);
  bOpened = true;
  f.Close();
}
catch(CFileException e)
{
  bOpened = false;
  throw;
}
    return bOpened;
}


bool CEncode::_IsSuitedFileType(CString strFileName)
{
if(strFileName.IsEmpty())
  return false;
if (strFileName.GetLength()<5) //文件名长度小于5
  return false;
else //文件名长度大于5
    {
  if ((strFileName.Right(4)).Compare(".avi")!=0) //文件名后四位不为.avi

return false;
    }
return true;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Qt中,可以使用基类来管理文件类型解析。具体来说,可以创建一个基类,定义文件类型解析的接口和数据结构,然后创建子类来实现具体的文件类型解析。 以下是一个简单的示例: ``` class FileParser { public: virtual bool parseFile(const QString& fileName) = 0; virtual QString getType() const = 0; }; class TextFileParser : public FileParser { public: bool parseFile(const QString& fileName) override { // 实现文本文件解析逻辑 return true; } QString getType() const override { return "Text"; } }; class ImageFileParser : public FileParser { public: bool parseFile(const QString& fileName) override { // 实现图像文件解析逻辑 return true; } QString getType() const override { return "Image"; } }; ``` 在上述示例中,我们定义了一个FileParser基类,包含了解析文件和获取文件类型的接口。然后,我们创建了两个子类TextFileParser和ImageFileParser,分别实现了文本文件和图像文件的解析逻辑,并返回了对应的文件类型。 使用时,我们可以根据文件类型创建相应的子类实例,然后调用parseFile方法进行文件解析: ``` QString fileName = "example.txt"; FileParser* parser = new TextFileParser(); if (parser->parseFile(fileName)) { qDebug() << "File parsed successfully"; } delete parser; ``` 在上述示例中,我们创建了一个TextFileParser实例来解析文本文件,调用parseFile方法进行解析。当解析成功时,输出调试信息。解析完成后,我们需要手动释放parser对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值