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

📄 dshowtools.cpp

📁 Window Mobile Capture with DirectDraw
💻 CPP
📖 第 1 页 / 共 2 页
字号:
CxImageRenderer::CxImageRenderer(LPUNKNOWN pUnk, HRESULT* phr)
	: CBaseRenderer(CxImageRenderer_GUID, NAME("CxImageRenderer"), pUnk, phr)
{
	NOTE("CxImageRenderer::CxImageRenderer()");
	*phr = S_OK;
	m_ImageValid = false;
};

HRESULT CxImageRenderer::CheckMediaType(const CMediaType* pmt)
{
	NOTE("CxImageRenderer::CheckMediaType()");
	//Check the stream type
	bool bIsVideo = (pmt->majortype == MEDIATYPE_Video) 
		&& ((pmt->formattype == FORMAT_VideoInfo) 
		|| (pmt->formattype == FORMAT_VideoInfo2));		
	//Check the colorspace
	bool bColorspaceOk =
		pmt->subtype == MEDIASUBTYPE_RGB32
		|| pmt->subtype == MEDIASUBTYPE_RGB24
		|| pmt->subtype == MEDIASUBTYPE_YUY2
		|| pmt->subtype == MEDIASUBTYPE_YV12
		;
	if (bIsVideo && bColorspaceOk)
		return S_OK;
	else
		return E_FAIL;
};

HRESULT CxImageRenderer::DoRenderSample(IMediaSample *pSample)
{
	NOTE("CxImageRenderer::DoRenderSample()");

	CMediaType mt;
	m_pInputPin->ConnectionMediaType(&mt);
	BITMAPINFOHEADER bih;		

	//See if we are using VideoHeader2
	if (mt.formattype == FORMAT_VideoInfo2) {
		VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)mt.Format();
		bih = vih2->bmiHeader;
	} else {
		VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt.Format();
		bih = vih->bmiHeader;
	}
	if (bih.biSize == 0) {
		// A hack for a strange bug, it's VideoHeader2 but it's not?
		VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt.Format();
		bih = vih->bmiHeader;
	}
	BYTE* p;
	pSample->GetPointer(&p);
	long dataSize = pSample->GetSize();

	//Do something with the pic
	if (mt.subtype == MEDIASUBTYPE_RGB32) {
		lastImage.CreateFromARGB(bih.biWidth, bih.biHeight, p);
		lastImage.Flip();
		m_ImageValid = lastImage.IsValid();						
	} else if (mt.subtype == MEDIASUBTYPE_RGB24) {				
		lastImage.Create(bih.biWidth, bih.biHeight, 24);					
		// Do a direct memory copy
		memcpy(lastImage.GetBits(), p, bih.biWidth * bih.biHeight * 3);
		m_ImageValid = lastImage.IsValid();						
	} else if (mt.subtype == MEDIASUBTYPE_YV12) {				
		BYTE *yuvBuffer = new BYTE[bih.biHeight * bih.biWidth * 16];
		
		// Call Klaus Post's mmx YV12->YUY2 conversion routine
		BYTE *y = p;
		BYTE *u = y + (bih.biHeight/2 * bih.biWidth/2);
		BYTE *v = u + (bih.biHeight/2 * bih.biWidth/2);
		mmx_yv12_to_yuy2(
			y,
			u, 
			v, 
			bih.biWidth, // rowsize
			bih.biWidth, // pitch
			bih.biWidth/2, // pitch_uv
			yuvBuffer, 
			bih.biWidth*2, // dst_pitch
			bih.biHeight);

		lastImage.Create(bih.biWidth, bih.biHeight, 24);					
		//Using alexnoe's YUV2->RGB24 Assembly rountines
		YUV422toRGB24_MMX(yuvBuffer, lastImage.GetBits(), 0, bih.biWidth, bih.biHeight, bih.biWidth * 2, bih.biWidth * 3);
		m_ImageValid = lastImage.IsValid();						
		//lastImage.Draw(GetDC(NULL));
		delete [] yuvBuffer;

	}else if (mt.subtype == MEDIASUBTYPE_YUY2) {				
		lastImage.Create(bih.biWidth, bih.biHeight, 24);					
		//Using alexnoe's YUV2->RGB24 Assembly rountines
		YUV422toRGB24_MMX(p, lastImage.GetBits(), 0, bih.biWidth, bih.biHeight, bih.biWidth * 2, bih.biWidth * 3);
		m_ImageValid = lastImage.IsValid();						
	}

	//We only need one good sample
	m_bAbort = true;

	return S_OK;
};

CxImage &CxImageRenderer::GetImage()
{
	NOTE("CxImageRenderer::GetImage()");
	return lastImage;
};

bool CxImageRenderer::GetImageOk()
{
	NOTE("CxImageRenderer::GetImageOk()");
	return m_ImageValid;
}

/*************************************
 * Progressive YV12 -> YUY2 conversion
 *
 * (c) 2003, Klaus Post.
 *
 * Requires mod 8 rowsize.
 * MMX version.
 *************************************/

void mmx_yv12_to_yuy2(const BYTE* srcY, const BYTE* srcU, const BYTE* srcV, int src_rowsize, int src_pitch, int src_pitch_uv, 
                    BYTE* dst, int dst_pitch,
                    int height) {
  static __int64 add_64=0x0002000200020002;
  const BYTE** srcp= new const BYTE*[3];
  int src_pitch_uv2 = src_pitch_uv*2;
  int skipnext = 0;

  int dst_pitch2=dst_pitch*2;
  int src_pitch2 = src_pitch*2;


  
  /**** Do first and last lines - NO interpolation:   *****/
  // MMX loop relies on C-code to adjust the lines for it.
  const BYTE* _srcY=srcY;
  const BYTE* _srcU=srcU;
  const BYTE* _srcV=srcV;
  BYTE* _dst=dst;

  for (int i=0;i<4;i++) {
    switch (i) {
    case 1:
      _srcY+=src_pitch;  // Same chroma as in 0
      _dst+=dst_pitch;
      break;
    case 2:
      _srcY=srcY+(src_pitch*(height-2));
      _srcU=srcU+(src_pitch_uv*((height>>1)-1));
      _srcV=srcV+(src_pitch_uv*((height>>1)-1));
      _dst = dst+(dst_pitch*(height-2));
      break;
    case 3: // Same chroma as in 4
      _srcY += src_pitch;
      _dst += dst_pitch;
      break;
    default:  // Nothing, case 0
        break;
    }


    __asm {
    mov edi, [_dst]
    mov eax, [_srcY]
    mov ebx, [_srcU]
    mov ecx, [_srcV]
    mov edx,0
    pxor mm7,mm7
    jmp xloop_test_p
xloop_p:
    movq mm0,[eax]    //Y
      movd mm1,[ebx]  //U
    movq mm3,mm0  
     movd mm2,[ecx]   //V
    punpcklbw mm0,mm7  // Y low
     punpckhbw mm3,mm7   // Y high
    punpcklbw mm1,mm7   // 00uu 00uu
     punpcklbw mm2,mm7   // 00vv 00vv
    movq mm4,mm1
     movq mm5,mm2
    punpcklbw mm1,mm7   // 0000 00uu low
     punpcklbw mm2,mm7   // 0000 00vv low
    punpckhbw mm4,mm7   // 0000 00uu high
     punpckhbw mm5,mm7   // 0000 00vv high
    pslld mm1,8
     pslld mm4,8
    pslld mm2,24
     pslld mm5,24
    por mm0, mm1
     por mm3, mm4
    por mm0, mm2
     por mm3, mm5
    movq [edi],mm0
     movq [edi+8],mm3
    add eax,8
    add ebx,4
    add ecx,4
    add edx,8
    add edi, 16
xloop_test_p:
      cmp edx,[src_rowsize]
      jl xloop_p
    }
  }

/****************************************
 * Conversion main loop.
 * The code properly interpolates UV from
 * interlaced material.
 * We process two lines in the same field
 * in the same loop, to avoid reloading
 * chroma each time.
 *****************************************/

  height-=4;

  dst+=dst_pitch2;
  srcY+=src_pitch2;
  srcU+=src_pitch_uv;
  srcV+=src_pitch_uv;

  srcp[0] = srcY;
  srcp[1] = srcU-src_pitch_uv;
  srcp[2] = srcV-src_pitch_uv;

  int y=0;
  int x=0;

  __asm {
    mov esi, [srcp]
    mov edi, [dst]

    mov eax,[esi]
    mov ebx,[esi+4]
    mov ecx,[esi+8]
    mov edx,0
    jmp yloop_test
    align 16
yloop:
    mov edx,0               // x counter
    jmp xloop_test
    align 16
xloop:
    mov edx, src_pitch_uv
    movq mm0,[eax]          // mm0 = Y current line
     pxor mm7,mm7
    movd mm2,[ebx+edx]            // mm2 = U top field
     movd mm3, [ecx+edx]          // mm3 = V top field
    movd mm4,[ebx]        // U prev top field
     movq mm1,mm0             // mm1 = Y current line
    movd mm5,[ecx]        // V prev top field

    punpcklbw mm2,mm7        // U 00uu 00uu 00uu 00uu
     punpcklbw mm3,mm7         // V 00vv 00vv 00vv 00vv
    punpcklbw mm4,mm7        // U 00uu 00uu 00uu 00uu
     punpcklbw mm5,mm7         // V 00vv 00vv 00vv 00vv
    paddusw mm4,mm2
     paddusw mm5,mm3
    paddusw mm4,mm2
     paddusw mm5,mm3
    paddusw mm4,mm2
     paddusw mm5,mm3
    paddusw mm4, [add_64]
     paddusw mm5, [add_64]
    psrlw mm4,2
     psrlw mm5,2


     punpcklbw mm0,mm7        // Y low
    punpckhbw mm1,mm7         // Y high*
     pxor mm6,mm6
    punpcklbw mm6,mm4         // U 0000 uu00 0000 uu00 (low)
     punpckhbw mm7,mm4         // V 0000 uu00 0000 uu00 (high
    por mm0,mm6
     por mm1,mm7
    movq mm6,mm5
     punpcklbw mm5,mm5          // V 0000 vvvv 0000 vvvv (low)
    punpckhbw mm6,mm6           // V 0000 vvvv 0000 vvvv (high)
     pslld mm5,24
    pslld mm6,24
     por mm0,mm5
    por mm1,mm6
    mov edx, src_pitch_uv2
     movq [edi],mm0
    movq [edi+8],mm1

    //Next line 
     
    movd mm4,[ebx+edx]        // U next top field
     movd mm5,[ecx+edx]       // V prev top field
    mov edx, [src_pitch]
     pxor mm7,mm7
    movq mm0,[eax+edx]        // Next U-line
    movq mm1,mm0             // mm1 = Y current line

    punpcklbw mm4,mm7        // U 00uu 00uu 00uu 00uu
     punpcklbw mm5,mm7         // V 00vv 00vv 00vv 00vv
    paddusw mm4,mm2
     paddusw mm5,mm3
    paddusw mm4,mm2
     paddusw mm5,mm3
    paddusw mm4,mm2
     paddusw mm5,mm3
    paddusw mm4, [add_64]
     paddusw mm5, [add_64]
    psrlw mm4,2
     psrlw mm5,2

     punpcklbw mm0,mm7        // Y low
    punpckhbw mm1,mm7         // Y high*
     pxor mm6,mm6
    punpcklbw mm6,mm4         // U 0000 uu00 0000 uu00 (low)
     punpckhbw mm7,mm4         // V 0000 uu00 0000 uu00 (high
    por mm0,mm6
     por mm1,mm7
    movq mm6,mm5
     punpcklbw mm5,mm5          // V 0000 vvvv 0000 vvvv (low)
    punpckhbw mm6,mm6           // V 0000 vvvv 0000 vvvv (high)
     pslld mm5,24
    mov edx,[dst_pitch]
    pslld mm6,24
     por mm0,mm5
    por mm1,mm6
     movq [edi+edx],mm0
    movq [edi+edx+8],mm1
     add edi,16
    mov edx, [x]
     add eax, 8
    add ebx, 4
     add edx, 8
    add ecx, 4
xloop_test:
    cmp edx,[src_rowsize]
    mov x,edx
    jl xloop
    mov edi, dst
    mov eax,[esi]
    mov ebx,[esi+4]
    mov ecx,[esi+8]

    add edi,[dst_pitch2]
    add eax,[src_pitch2]
    add ebx,[src_pitch_uv]
    add ecx,[src_pitch_uv]
    mov edx, [y]
    mov [esi],eax
    mov [esi+4],ebx
    mov [esi+8],ecx
    mov [dst],edi
    add edx, 2

yloop_test:
    cmp edx,[height]
    mov [y],edx
    jl yloop
    emms
  }
   delete[] srcp;
}

HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister) 
{
	IMoniker * pMoniker;
	IRunningObjectTable *pROT;
	if (FAILED(GetRunningObjectTable(0, &pROT))) 
	{
		return E_FAIL;
	}

	WCHAR wsz[128];
	wsprintfW(wsz, L"FilterGraph %08x pid %08x - AudioDShowEncoder", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());

	HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
	if (SUCCEEDED(hr)) 
	{
		// Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
		// to the object.  Using this flag will cause the object to remain
		// registered until it is explicitly revoked with the Revoke() method.
		//
		// Not using this flag means that if GraphEdit remotely connects
		// to this graph and then GraphEdit exits, this object registration 
		// will be deleted, causing future attempts by GraphEdit to fail until
		// this application is restarted or until the graph is registered again.
		hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister);
		pMoniker->Release();
	}

	pROT->Release();
	return hr;
}

void RemoveGraphFromRot(DWORD pdwRegister)
{
	IRunningObjectTable *pROT;

	if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) 
	{
		pROT->Revoke(pdwRegister);
		pROT->Release();
	}
}

⌨️ 快捷键说明

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