⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netpushsource.cpp

📁 MP4播放程序,好的很~~~喜欢就拿去
💻 CPP
字号:
//------------------------------------------------------------------------------
// File: NetPushSource.cpp
//
// Desc: DirectShow sample code - In-memory push mode source filter
//       Provides a static bitmap as the video output stream.
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------
#include "mediastream.h"
#include "streams.h"
#include "PushSource.h"
#include "PushGuids.h"
#include "MemSafe.h"
#include "atlbase.h"
#include <INITGUID.H>
// 30323449-0000-0010-8000-00AA00389B71  'YV12' ==  MEDIASUBTYPE_I420 
EXTERN_GUID(WMMEDIASUBTYPE_I420, 
  0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 

/**********************************************
*  CNetPushSourcePin Class
**********************************************/
CNetPushSourcePin::CNetPushSourcePin(HRESULT *phr, CSource *pFilter)
:CSourceStream(NAME("Video Output Pin"), phr, pFilter, L"Out")
,m_iFrameNumber(0)
,m_iVideoTrack(0)
,m_iMaxW(352)
,m_iMaxH(288)
,m_hEvent(NULL)
{
  g_pMediaRcv=NULL;
  m_VidoeHeader=new FRAMEHDR;
  m_pVideoData=new BYTE[256<<10];
  m_iRcvFNum=0;
  m_rtSampleTime=0;
  m_rtFrameLength=40;
  m_wRtpAddr=0;
  m_wRtpPort=64000;
  mediastreamStartup();
  m_hEvent=CreateEvent(NULL, FALSE, FALSE, NULL);
}

CNetPushSourcePin::~CNetPushSourcePin()
{
  if(m_VidoeHeader){
    delete[] m_VidoeHeader;
    m_VidoeHeader=NULL;
  }
  if(m_pVideoData){
    delete[] m_pVideoData;
    m_pVideoData;
  }
  mediastreamCleanup();
  if(m_hEvent){
    CloseHandle(m_hEvent);
  }
}

STDMETHODIMP CNetPushSourcePin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
  CheckPointer(ppv, E_POINTER);
  if(IID_IiFlyNetParams == riid){
    return GetInterface((IiFlyNetParams*)this, ppv);
  }else{
    return CSourceStream::NonDelegatingQueryInterface(riid, ppv);
  }
}

////////////////////////////////////////////////////////////////////////////////////////
// GetMediaType: This method tells the downstream pin what types we support.
// Here is how CSourceStream deals with media types:
// If you support exactly one type, override GetMediaType(CMediaType*). It will then be
// called when (a) our filter proposes a media type, (b) the other filter proposes a
// type and we have to check that type.
// If you support > 1 type, override GetMediaType(int,CMediaType*) AND CheckMediaType.
// In this case we support only one type, which we obtain from the bitmap file.
HRESULT CNetPushSourcePin::GetMediaType(CMediaType *pMediaType)
{
  CAutoLock cAutoLock(m_pFilter->pStateLock());
  CheckPointer(pMediaType, E_POINTER);
  
  pMediaType->SetType(&MEDIATYPE_Video);
  pMediaType->SetSubtype(&WMMEDIASUBTYPE_I420);//&MEDIASUBTYPE_IYUV;
  pMediaType->SetTemporalCompression(TRUE);
  pMediaType->SetSampleSize(1);
  pMediaType->SetFormatType(&FORMAT_VideoInfo);
  VIDEOINFOHEADER vf;
  ZeroMemory(&vf, sizeof(vf));
  vf.bmiHeader.biCompression=mmioFOURCC('X','V','I','D');
  vf.bmiHeader.biWidth=m_iMaxW;//352
  vf.bmiHeader.biHeight=m_iMaxH;//288
  SetRectEmpty(&vf.rcSource);
  SetRectEmpty(&vf.rcTarget);
  /*
  ULARGE_INTEGER uliSize;
  if (!m_pMp4 || m_pMp4->stream == INVALID_HANDLE_VALUE) 
  {
  */
  vf.bmiHeader.biBitCount = 0;
  /*
  }else{
  uliSize.LowPart = GetFileSize(m_pMp4->stream, &uliSize.HighPart);
  vf.bmiHeader.biBitCount=(WORD)uliSize.LowPart;
  }
  */
  pMediaType->SetFormat((BYTE*)&vf, sizeof(vf));
  
  m_mt=*pMediaType;
  return S_OK;
}

HRESULT CNetPushSourcePin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)
{
  CAutoLock cAutoLock(m_pFilter->pStateLock());
  HRESULT hr=E_POINTER;
  
  CheckPointer(pAlloc, hr);
  CheckPointer(pRequest, hr);
  
  // Ensure a minimum number of buffers
  if (pRequest->cBuffers == 0)
  {
    pRequest->cBuffers = 2;
  }
  pRequest->cbBuffer = m_iMaxW*m_iMaxH;
  
  ALLOCATOR_PROPERTIES Actual;
  hr = pAlloc->SetProperties(pRequest, &Actual);
  if (FAILED(hr)) 
  {
    return hr;
  }
  
  // Is this allocator unsuitable?
  if (Actual.cbBuffer < pRequest->cbBuffer) 
  {
    return E_FAIL;
  }
  
  return S_OK;
}

// This is where we insert the DIB bits into the video stream.
// FillBuffer is called once for every sample in the stream.
HRESULT CNetPushSourcePin::FillBuffer(IMediaSample* pSample)
{
  if(m_iRcvFNum==-1){
    m_iRcvFNum=0;
    return E_FAIL;
  }
  BYTE* pData;
  long cbData;
  
  CheckPointer(pSample, E_POINTER);
  CAutoLock cAutoLockShared(&m_cSharedState);
  
  // Access the sample's data buffer
  pSample->GetPointer(&pData);
  CheckPointer(pData, E_POINTER);
  cbData = pSample->GetSize();
  // Check that we're still using video
  ASSERT(m_mt.formattype == FORMAT_VideoInfo);
  
  if(WaitForSingleObject(m_hEvent, 100)==WAIT_TIMEOUT)
    return E_FAIL;
  memcpy(pData, m_VidoeHeader->m_pData, m_VidoeHeader->m_dwDataSize);
  m_iFrameNumber++;
  if(m_VidoeHeader->m_tVideoParam.m_bKeyFrame==1)
    pSample->SetSyncPoint(TRUE);
  else
    pSample->SetSyncPoint(FALSE); 
  return S_OK;
}

void DealMediaFrame(PFRAMEHDR pFrmHdr, u32 dwContext)
{
  CNetPushSourcePin* lpPin=(CNetPushSourcePin*)dwContext;
  if(!lpPin){
    return;
  }
  if(lpPin->m_iRcvFNum==0){
    if(pFrmHdr->m_tVideoParam.m_bKeyFrame==1){
      lpPin->m_iRcvFNum=1;
    }else{
      return;
    }
  }
  *(lpPin->m_VidoeHeader)=*pFrmHdr;
  memcpy(lpPin->m_pVideoData, pFrmHdr->m_pData, pFrmHdr->m_dwDataSize);
  lpPin->m_VidoeHeader->m_pData=lpPin->m_pVideoData;
  SetEvent(lpPin->m_hEvent);
}

// OnThreadCreate()
// As we go active reset the stream time to zero
HRESULT CNetPushSourcePin::OnThreadCreate()
{
  CAutoLock cAutoLockShared(&m_cSharedState);
  m_rtSampleTime = 0;
  m_rtFrameLength=40;
  g_pMediaRcv = CreateMediaRcv(MAX_FRAME_SIZE, DealMediaFrame, (u32)this, 0);
  if(!g_pMediaRcv)
    return E_FAIL;
  TLocalNetParam tLocalNetParam;
  tLocalNetParam.m_tLocalNet.m_wRTPPort = m_wRtpPort;
  tLocalNetParam.m_tLocalNet.m_dwRTPAddr = m_wRtpAddr;
  WORD wRet = SetMediaRcvLocalParam(g_pMediaRcv, tLocalNetParam);
  if(wRet!=S_OK)
    return E_FAIL;
  wRet = StartMediaRcv(g_pMediaRcv);
  if(wRet!=S_OK)
    return E_FAIL;
  return NOERROR;
}

HRESULT CNetPushSourcePin::OnThreadStartPlay(void)
{
  //  if(!g_pMediaRcv)
  //    return E_POINTER;
  return NOERROR;
}

HRESULT CNetPushSourcePin::OnThreadDestroy(void)
{
  m_iRcvFNum=0;
  if(g_pMediaRcv){
    WORD wRet=StopMediaRcv(g_pMediaRcv);
    DestroyMediaRcv(g_pMediaRcv);
    g_pMediaRcv=NULL;
  }
  return NOERROR;
}

HRESULT CNetPushSourcePin::DoBufferProcessingLoop(void)
{
  Command com;
  OnThreadStartPlay();
  do {
    while(!CheckRequest(&com)){
      IMediaSample *pSample;
      HRESULT hr=GetDeliveryBuffer(&pSample,NULL,NULL,0);
      if(FAILED(hr)){
        Sleep(1);
        continue;	// go round again. Perhaps the error will go away
        // or the allocator is decommited & we will be asked to
        // exit soon.
      }
      // Virtual function user will override.
      hr = FillBuffer(pSample);
      if(hr == S_OK){
        hr = Deliver(pSample);
        pSample->Release();
        // downstream filter returns S_FALSE if it wants us to
        // stop or an error if it's reporting an error.
        if(hr != S_OK)
        {
          DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
          return S_OK;
        }
      }else if (hr == S_FALSE){
        // derived class wants us to stop pushing data
        pSample->Release();
        DeliverEndOfStream();
      }else if(hr==E_FAIL){
        pSample->Release();
      }else{
        // derived class encountered an error
        pSample->Release();
        DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
        DeliverEndOfStream();
        m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
        return hr;
      }
      // all paths release the sample
    }
    // For all commands sent to us there must be a Reply call!
    if(com == CMD_RUN || com == CMD_PAUSE){
      Reply(NOERROR);
    }else if (com != CMD_STOP) {
      Reply((DWORD) E_UNEXPECTED);
      DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
    }
  }while(com!=CMD_STOP);
  return S_FALSE;
}

STDMETHODIMP CNetPushSourcePin::put_RtpPort(const TCHAR* inRtpPort, UINT inStrLength)
{
  CheckPointer(inRtpPort, E_INVALIDARG);
  for(UINT i=0;i<inStrLength;i++){
    if(inRtpPort[i]<TEXT('0') || inRtpPort[i]>TEXT('9')){
      return E_FAIL;
    }
  }
  long lPort=(long)
#ifdef UNICODE
    _wtol
#else
    atol
#endif
    (inRtpPort);
  if(lPort<=0 || lPort>65535){
    return E_FAIL;
  }
  m_wRtpPort=(WORD)lPort;
  return S_OK;
}

STDMETHODIMP CNetPushSourcePin::get_RtpPort(TCHAR* outRtpPort, UINT* outBufLength)
{
  CheckPointer(outBufLength, E_INVALIDARG);
  UINT MaxLen=
#ifdef UNICODE
    wcslen
#else
    strlen
#endif
    (TEXT("18446744073709551615"))+1;
  TCHAR* ch=new TCHAR[MaxLen];
  if(!ch){
    return E_OUTOFMEMORY;
  }
  MaxLen=0;
#ifdef UNICODE
  _ltow
#else
    ltoa
#endif
    (m_wRtpPort, ch, 10);
  if(outRtpPort){
#ifdef UNICODE
    wcscpy
#else
      strcpy
#endif
      (outRtpPort, ch);
    MaxLen=
#ifdef UNICODE
      min(wcslen(outRtpPort), wcslen(ch));
#else
    min(strlen(outRtpPort), strlen(ch));
#endif
  }else{
    MaxLen=
#ifdef UNICODE
      wcslen
#else
      strlen
#endif
      (ch);
  }
  *outBufLength=(MaxLen+1)*sizeof(TCHAR);
  delete[] ch;
  return S_OK;
}

STDMETHODIMP CNetPushSourcePin::put_VideoHeight(const UINT inVideoHeight)
{
  m_iMaxH=inVideoHeight;
  return S_OK;
}

STDMETHODIMP CNetPushSourcePin::get_VideoHeight(UINT* outVideoHeight)
{
  CheckPointer(outVideoHeight, E_INVALIDARG);
  *outVideoHeight=m_iMaxH;
  return S_OK;
}

STDMETHODIMP CNetPushSourcePin::put_VideoWidth(const UINT inVideoWidth)
{
  m_iMaxW=inVideoWidth;
  return S_OK;
}

STDMETHODIMP CNetPushSourcePin::get_VideoWidth(UINT* outVideoWidth)
{
  CheckPointer(outVideoWidth, E_INVALIDARG);
  *outVideoWidth=m_iMaxW;
  return S_OK;
}

/**********************************************
* CNetPushSource Class
**********************************************/
CNetPushSource::CNetPushSource(IUnknown *pUnk, HRESULT *phr)
:CSource(NAME("iFly Net Push Source"), pUnk, CLSID_iFlyNetPushSource)
,m_pPin(NULL)
,m_ptsURL(NULL)
{
  m_pPin = new CNetPushSourcePin(phr, this);
  if (phr)
  {
    if (m_pPin == NULL)
      *phr = E_OUTOFMEMORY;
    else
      *phr = S_OK;
  }
}

CNetPushSource::~CNetPushSource()
{
  if(m_ptsURL){
    CoTaskMemFree(m_ptsURL);
    m_ptsURL=NULL;
  }
  //SAFE_DELETE(m_pPin);//父类会释放。
}

CUnknown * WINAPI CNetPushSource::CreateInstance(IUnknown *pUnk, HRESULT *phr)
{
  CNetPushSource *pNewFilter = new CNetPushSource(pUnk, phr);
  if (phr)
  {
    if (pNewFilter == NULL) 
      *phr = E_OUTOFMEMORY;
    else
      *phr = S_OK;
  }
  return pNewFilter;
}

STDMETHODIMP CNetPushSource::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
  CheckPointer(ppv, E_POINTER);
  if(IID_ISpecifyPropertyPages==riid){
    return GetInterface((ISpecifyPropertyPages*)this, ppv);
  }else if(IID_IFileSourceFilter==riid){
    return GetInterface((IFileSourceFilter*)this, ppv);
  }else if(IID_IiFlyNetParams==riid){
    if(!m_pPin){
      return E_FAIL;
    }
    return m_pPin->QueryInterface(riid, ppv);
  }else{
    return CSource::NonDelegatingQueryInterface(riid, ppv);
  }
}

STDMETHODIMP CNetPushSource::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt)
{
  CheckPointer(pszFileName, E_INVALIDARG);
  CAutoLock lckit(&m_cStateLock);
  int iBufLen=WideCharToMultiByte(GetACP(), NULL, pszFileName, -1, NULL, 0, NULL, NULL);
  if(iBufLen<=0)
    return E_INVALIDARG;
  if(m_ptsURL){
    CoTaskMemFree(m_ptsURL);
    m_ptsURL=NULL;
  }
  m_ptsURL=(TCHAR*)CoTaskMemAlloc(sizeof(TCHAR)*(iBufLen));
  if(!m_ptsURL)
    return E_OUTOFMEMORY;
#ifdef UNICODE
  CopyMemory(m_ptsURL, pszFileName, sizeof(WCHAR)*iBufLen);
#else
  WideCharToMultiByte(GetACP(), NULL, pszFileName, -1, m_ptsURL, iBufLen, NULL, NULL);
#endif
  
  //对m_ptsURL解析:设置Filter其它参量:
  //...
  
  if(pmt)
    m_mt=*pmt;
  return NOERROR;
}

STDMETHODIMP CNetPushSource::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE *pmt)
{
  CheckPointer(ppszFileName, E_INVALIDARG);
  *ppszFileName=NULL;
  CAutoLock lckit(&m_cStateLock);
  if(m_ptsURL){
    DWORD n=
#ifdef UNICODE
      (wcslen
#else
      (strlen
#endif
      (m_ptsURL)+1);
    *ppszFileName=(LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*n);
    if (*ppszFileName!=NULL) {
      //ZeroMemory(*ppszFileName,sizeof(WCHAR)*n);//测试语句。
#ifdef UNICODE
      CopyMemory(*ppszFileName, m_ptsURL, sizeof(WCHAR)*n);
#else
      MultiByteToWideChar(GetACP(), 0, m_ptsURL, -1, *ppszFileName,n);
#endif
    }
    if (pmt!=NULL) {
      CopyMediaType(pmt, &m_mt);
    }
  }
  return NOERROR;
}

STDMETHODIMP CNetPushSource::Pause()
{
  HRESULT hr=S_OK;
  FILTER_STATE ost, cst;
  if(GetState(INFINITE, &ost)!=S_OK){
    return E_FAIL;
  }
  hr=CSource::Pause();
  /*
  if(ost==State_Paused){
  return hr;
  }
  */
  if(GetState(INFINITE, &cst)!=S_OK){
    return E_FAIL;
  }
  if(cst==State_Paused){
    m_pPin->m_iRcvFNum=-1;
  }else if(cst==State_Running){
    m_pPin->m_iRcvFNum=0;
  }
  return hr;
}

//Implement ISpecifyPropertyPages Interface:
STDMETHODIMP CNetPushSource::GetPages(CAUUID *pPages)
{
  pPages->cElems = 1;
  pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  if (pPages->pElems == NULL)
  {
    return E_OUTOFMEMORY;
  }
  *(pPages->pElems) = CLSID_iFlyNetParamsProp;
  return NOERROR;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -