VideoInfoをVideoInfo2に変換するには?


momo  2012-07-23 18:55:57  No: 73476  IP: 192.*.*.*

皆さん、始めまして。
VideoInfoをVideoInfo2に変換するためには、「ConvertVideoInfoToVideoInfo2」を使ってDirectsowのFilterを作くればいいことが分かったので、「http://www.independence-sys.com/weblog/item/158」を参考にしました。
GetMediaTypeで、「ConvertVideoInfoToVideoInfo2」の処理を入れれば良いと思ったのですが、映像が斜めのシマシマ映像になってしまい行き詰っています。
大きく変えた所は以下のとおりです。
御教授願えませんでしょうか。

HRESULT CTransEffectFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
  if (CanPerformTransform(mtIn)) 
  {
    if (*mtOut->Subtype() == *mtIn->Subtype())
      return S_OK;
    else
      return VFW_E_TYPE_NOT_ACCEPTED;
      //return S_OK;
  }
  return VFW_E_TYPE_NOT_ACCEPTED;
}

HRESULT CTransEffectFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
{
  if(iPosition == 0)
  {  
    CopyMediaType(pMediaType,&(m_pInput->CurrentMediaType()));
    pMediaType->SetSubtype(&MEDIASUBTYPE_UYVY);
    ConvertVideoInfoToVideoInfo2(pMediaType);
    return S_OK;
  }
  return VFW_S_NO_MORE_ITEMS;
}

HRESULT CTransEffectFilter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pPropInputRequest)
{
  IMemAllocator *InAlloc;
  ALLOCATOR_PROPERTIES InProps;
 
  CheckPointer(pAlloc,E_POINTER);
  CheckPointer(pPropInputRequest,E_POINTER);
 
  // Is the input pin connected
  if(m_pInput->IsConnected() == FALSE)
  {
    return E_UNEXPECTED;
  }
 
  HRESULT hr = NOERROR;
  pPropInputRequest->cBuffers = 1;
  pPropInputRequest->cbBuffer;
  m_pInput->CurrentMediaType().GetSampleSize();
 
  HRESULT result;
  result = m_pInput->GetAllocator(&InAlloc);
  if(SUCCEEDED(result))
  {
    result = InAlloc->GetProperties(&InProps);
    if(SUCCEEDED(result))
    {
      pPropInputRequest->cbBuffer = InProps.cbBuffer;
      InAlloc = NULL;
    }
  } ////THIS WHOLE
  //CHECK GOES OK
 
if(FAILED(result))
 return S_FALSE;


  // Ask the allocator to reserve us some sample memory, NOTE the function
  // can succeed (that is return NOERROR) but still not have allocated the
  // memory that we requested, so we must check we got whatever we wanted
 
  ALLOCATOR_PROPERTIES Actual;
 
  hr = pAlloc->SetProperties(pPropInputRequest,&Actual);
  if(FAILED(hr))
  {
    return hr;
  } ////THIS ONE FAILS
 
  ASSERT(Actual.cBuffers == 1);
 
if(pPropInputRequest->cBuffers > Actual.cBuffers ||pPropInputRequest->cbBuffer > Actual.cbBuffer)
 {
  return E_FAIL;
 } ///FAILS TOO!
 
return NOERROR;
}

HRESULT CTransEffectFilter::Transform(IMediaSample *pIn, IMediaSample *pOut) {
  LPDWORD pSrc, pDest;
  long act_size;
  //unsigned int grey;
  DWORD r,g,b;

  pIn->GetPointer((BYTE**)&pSrc);
  pOut->GetPointer((BYTE**)&pDest);
  act_size = pIn->GetActualDataLength();
  
  //ここでは適当にグレーに変換
  for(LONG y=0; y<m_Vih.bmiHeader.biHeight; y++) {
    for(LONG x=0; x<m_Vih.bmiHeader.biWidth; x++) {
            
      r = ((*pSrc) & 0xff0000) >> 16;
      g = ((*pSrc) & 0xff00) >> 8;
      b = (*pSrc) & 0xff;

      /*grey = (30 * r + 59 * g + 11 * b) / 100;
            r = g = b = (BYTE) grey;*/
      
      *pDest = (r << 16) | (g << 8) | (b);

      pSrc++;
      pDest++;
    }
  }

  //サンプルタイムの設定
  LONGLONG media_start, media_end;
  pIn->GetMediaTime(&media_start, &media_end);
  pOut->SetMediaTime(&media_start, &media_end);

  REFERENCE_TIME ref_start, ref_end;
  pIn->GetTime(&ref_start, &ref_end);
  pOut->SetTime(&ref_start, &ref_end);

  //同期ポイントのプロパティ設定
  pOut->SetSyncPoint(TRUE);

  //データ長設定
  pOut->SetActualDataLength(act_size);
  
  return S_OK;
}

編集 削除
forty-five  2012-07-23 23:30:05  No: 73477  IP: 192.*.*.*

そのサイトのソースに ConvertVideoInfoToVideoInfo2() を加えてみましたが、何の問題もないです。というか動作に変わりはありませんでした。

どういう動作にしたいのか明確にしないと何とも言えないですね。

//
// このフィルタが出力するメディアタイプを提示する
//
HRESULT CTransEffectFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
{
    //チェック
    if(iPosition < 0){  
        return E_INVALIDARG;  
    }else if(iPosition > 0) {  
        return VFW_S_NO_MORE_ITEMS;  
    }  

    //入力をそのまま設定
    *pMediaType=m_pInput->CurrentMediaType();  
    ::ConvertVideoInfoToVideoInfo2(pMediaType);
    return S_OK;
}

編集 削除
momo  2012-07-24 11:08:37  No: 73478  IP: 192.*.*.*

forty-fiveさん返事ありがとうございます。

私の場合、参考サイトのソースに ConvertVideoInfoToVideoInfo2() を追加して、GraphEditでは「ストリームをレンダリングするためのフィルターの組み合わせが見つかりませんでした。」とエラーが帰ってきました。
ですので、いろんな所を参考にして上記の様なソースになりました。

やりたい事は、VideoInfoをVideoInfo2に変換するFilterを作ろうとしています。Filterを作るのは初めてで、Filterの動作はなんとなくでしか把握できていません。

編集 削除
momo  2012-07-24 11:08:38  No: 73479  IP: 192.*.*.*

forty-fiveさん返事ありがとうございます。

私の場合、参考サイトのソースに ConvertVideoInfoToVideoInfo2() を追加して、GraphEditでは「ストリームをレンダリングするためのフィルターの組み合わせが見つかりませんでした。」とエラーが帰ってきました。
ですので、いろんな所を参考にして上記の様なソースになりました。

やりたい事は、VideoInfoをVideoInfo2に変換するFilterを作ろうとしています。Filterを作るのは初めてで、Filterの動作はなんとなくでしか把握できていません。

編集 削除
forty-five  2012-07-25 21:09:55  No: 73480  IP: 192.*.*.*

少なくとも私の環境では CTransEffectFilter::GetMediaType() 自体が呼ばれないです。なので、ここを修正してもエラーは出ないはずです。もちろん動作も変わりません。

ヘッダーでこうして、

    //入力ピンのメディアフォーマット
    VIDEOINFOHEADER2 m_Vih;

ソースでこうすればいいんじゃないの?

//
// ピンの接続が完了した時の処理
//
HRESULT CTransEffectFilter::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin) {

    // 入力ピンのメディアフォーマットを取得
    CMediaType type = m_pInput->CurrentMediaType();
    ::ConvertVideoInfoToVideoInfo2(&type);
    CopyMemory(&m_Vih, type.Format(), sizeof(VIDEOINFOHEADER2));

    return S_OK;
}

編集 削除
momo  2012-07-28 17:59:22  No: 73481  IP: 192.*.*.*

forty-fiveさん、返事遅れてすみません。
早速やってみたら、正常な映像が表示されました。
後は、Outpinから出力されているのはVideoInfo2の映像か調べてみます。
ありがとうございます。

編集 削除