2011-04-07 76 views
1

的我实现了EVR渲染到我的播放器来处理在Windows Vista上+坏调整大小和质量来问题...透明度在Vista/Windows的字幕7

我与EVR字幕叠加的问题:

try to see what i'm talking about - 您必须在选项中设置EVR。

我用这个应用32位阿尔法位图到VMR9,使用DirectX的表面:

private void SetVRM9MixerSettings(int width, int height, int lines) 
     { 
      int hr = 0; 
      VMR9AlphaBitmap alphaBmp;    

      // Set Alpha Bitmap Parameters for using a Direct3D surface 
      alphaBmp = new VMR9AlphaBitmap(); 
      alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS | VMR9AlphaBitmapFlags.FilterMode; 

      // on unmanagedSurface the bitmap was drawn with transparency 
      alphaBmp.pDDS = unmanagedSurface; 
      alphaBmp.rDest = GetDestRectangle(width, height, lines); 
      alphaBmp.fAlpha = 1.0f; 
      alphaBmp.dwFilterMode = VMRMixerPrefs.BiLinearFiltering; 

      // for anaglyph half SBS 
      if (FrameMode == Mars.FrameMode.HalfSideBySide) 
      { 
       alphaBmp.rDest.left /= 2; 
       alphaBmp.rDest.right /= 2; 
      } 

      // Set Alpha Bitmap Parameters 
      hr = mixerBitmap.SetAlphaBitmap(ref alphaBmp); 
      DsError.ThrowExceptionForHR(hr); 

     } 

但是现在项目MediaFoundation.NET犯规有alphaBmp.pDDS指针设置,所以我不能使用直接绘制表面并需要使用GDI(如果某人有一种方法可以做到这一点,它会很酷)。但随着GDI我不能使用32位的α位图的真正的透明度 - 我只得到1位的透明度,这种做法:

private void SetEVRMixerSettings(int width, int height, int subtitleLines) 
     { 
      MFVideoAlphaBitmap alphaBmp = new MFVideoAlphaBitmap(); 

      //alphaBitmap is a 32bit semitransparent Bitmap 
      Graphics g = Graphics.FromImage(alphaBitmap); 

      // get pointer to needed objects 
      IntPtr hdc = g.GetHdc(); 
      IntPtr memDC = CreateCompatibleDC(hdc); 
      IntPtr hBitmap = alphaBitmap.GetHbitmap(); 
      IntPtr hOld = SelectObject(memDC, hBitmap); 

      alphaBmp.GetBitmapFromDC = true; 
      alphaBmp.stru = memDC; 
      alphaBmp.paras = new MFVideoAlphaBitmapParams(); 
      alphaBmp.paras.dwFlags = MFVideoAlphaBitmapFlags.Alpha | MFVideoAlphaBitmapFlags.SrcColorKey | MFVideoAlphaBitmapFlags.DestRect; 

      // calculate destination rectangle 
      MFVideoNormalizedRect mfNRect = new MFVideoNormalizedRect(); 
      NormalizedRect nRect = GetDestRectangle(width, height, subtitleLines); 

      mfNRect.top = nRect.top; 
      mfNRect.left = nRect.left; 
      mfNRect.right = nRect.right; 
      mfNRect.bottom = nRect.bottom; 

      // used when viewing half side by side anaglyph video that is stretched to full width 
      if (FrameMode == Mars.FrameMode.HalfSideBySide) 
      { 
       mfNRect.left /= 2; 
       mfNRect.right /= 2; 
      } 

      alphaBmp.paras.nrcDest = mfNRect; 

      // calculate source rectangle (full subtitle bitmap) 
      MFRect rcSrc = new MFRect(); 
      rcSrc.bottom = alphaBitmap.Height; 
      rcSrc.right = alphaBitmap.Width; 
      rcSrc.top = 0; 
      rcSrc.left = 0; 

      alphaBmp.paras.rcSrc = rcSrc; 

      // apply 1-bit transparency 
      System.Drawing.Color colorKey = System.Drawing.Color.Black; 
      alphaBmp.paras.clrSrcKey = ColorTranslator.ToWin32(colorKey); 

      // 90% visible 
      alphaBmp.paras.fAlpha = 0.9F; 

      // set the bitmap to the evr mixer 
      evrMixerBitmap.SetAlphaBitmap(alphaBmp); 

      // cleanup 
      SelectObject(memDC, hOld); 
      DeleteDC(memDC); 
      g.ReleaseHdc(); 

     } 

所以问题是:

  • 如何使用DirectDraw表面混合位图在EVR视频 或
  • 如何混合没有DirectDraw的半透明位图?

非常感谢!

回答

2

我会尝试回答第二个问题...

Alpha混合是相当简单的任务。 假设alpha在0.0 - 1.0范围内,其中0.0表示完全透明,1.0表示完全不透明的颜色。

R_result = R_Source * alpha + R_destination * (1.0 - alpha) 

由于我们并不真的需要漂浮在这里,我们可以将alpha切换到0-255范围。

R_result = (R_Source * alpha + R_destination * (255 - alpha)) >> 8 

您可以进一步优化它......取决于您。
当然,这同样适用于G和B.

+0

感谢natko的努力,但不幸的是,这将需要在CPU上本地获取帧数据,并在CPU本身进行alpha混合,以获得全高清视频。 CPU。第二个片段的结果是发送给EVR混合器的位图,并将位图混合到GPU上的视频帧。 – 2011-05-19 20:23:51

+0

由于您只会混合字幕区域,因此CPU负载不会明显更高。这甚至适用于旧的和慢速的单核CPU。无论如何,RGB色彩空间是一种不好的选择。在全帧操作中,通过使用一些YUV颜色格式可以大大减少CPU负载。一些16位格式甚至12位平面格式是这种用途的某种标准,而图像质量保持不变。 – 2011-05-20 06:51:59