0

f ContentControl があり、その Content がカスタム イメージに設定されています。カスタム イメージには、Bitmap データを保持する Source というフィールドがあります。ContentControl がそのビットマップ データを表示するために必要な追加の手順? 私はこのステップを間違えたと思っています...ソースは単なるフィールドなので?

また、ビットマップ データは常に変化します。

public class VideoRenderer : System.Windows.Controls.Image
{
    #region Fields
    protected DateTime lastFrameTimestamp;
    protected Rectangle rect;
    protected System.Timers.Timer timer;
    protected BitmapData bitmapData;
    protected Bitmap bitmap = null;
    private Video videoObject = null;
    private Participant participantObject = null;
    private bool isRunning = false;
    private int updateInterval = 50;
    private uint key = 0;
    private int videoWidth = 0;
    private int videoHeight = 0;
    private SkypeRoot skypeRef;
    private FrameTransport frameTransport;
    private double fps = 0;
    private System.Windows.Media.ImageSource source;
    object bitmapLock = new object();
    #endregion


    /// <summary>
    /// Gets and sets the source of the video renderer image.
    /// </summary>
    public new System.Windows.Media.ImageSource Source
    {
        get { return source; }
        set { source = value; }
    }


    #region Constructors
    /// <summary>
    /// Constructor.
    /// </summary>
    /// <param name="skype"></param>
    public VideoRenderer(SkypeRoot skype)
    {
        this.skypeRef = skype;
    }
    #endregion


    #region Internal Members
    /// <summary>
    /// Convert frame to a bitmap.
    /// </summary>
    /// <returns></returns>
    internal bool MoveFrameToBitmap()
    {
        lock (bitmapLock)
        {
            if (frameTransport.bitmapDataSize == 0)
            {
                return false;
            }

            bool ResolutionHasChanged = ((videoWidth != frameTransport.width) | (videoHeight != frameTransport.height));

            if ((bitmap == null) | ResolutionHasChanged)
            {
                if (bitmap != null)
                {
                    bitmap.Dispose();
                }

                videoHeight = frameTransport.height;
                videoWidth = frameTransport.width;
                bitmapData = null;
                bitmap = new Bitmap(videoWidth, videoHeight);
                bitmapData = new BitmapData();
                bitmapData.Width = videoWidth;
                bitmapData.Height = videoHeight;
                bitmapData.PixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
                rect = new Rectangle(0, 0, videoWidth, videoHeight);
            }

            bitmap.LockBits(rect, ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb, bitmapData);
            IntPtr ptr = bitmapData.Scan0;
            Marshal.Copy(frameTransport.bitmapData, 0, ptr, frameTransport.bitmapDataSize);
            bitmap.UnlockBits(bitmapData);

            if (ResolutionHasChanged) skypeRef.events.FireOnVideoResolutionChanged(this, new RootEvents.OnVideoResolutionChangedArgs(videoWidth, videoHeight));

            return true;
        }
    }

    /// <summary>
    /// Draw the bitmap to the picturebox.
    /// </summary>
    internal void DrawBitmap()
    {
        lock (bitmapLock)
        {
            using (MemoryStream memory = new MemoryStream())
            {
                bitmap.Save(memory, ImageFormat.Png);
                memory.Position = 0;
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memory;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                source = bitmapImage;
            }
        }
    }
    #endregion


    #region External Members
    /// <summary>
    /// Start the video rendering.
    /// </summary>
    public void Start()
    {
        if (isRunning)
        {
            return;
        }

        if (videoObject == null)
        {
            throw new Exception("Error: cannot start rendering when the associated video object is null.");
        }

        isRunning = true;
        frameTransport = new FrameTransport();

        timer = new System.Timers.Timer();
        timer.Interval = updateInterval;
        timer.Enabled = false;
        timer.Elapsed += TimerTick;

        Int32[] preferences = new Int32[1];
        preferences[0] = MakeFourCC('B', 'I', '2', '4');
        frameTransport.SetPreferences(1, preferences);
        key = frameTransport.Key();
        videoObject.SetRemoteRendererID(key);
        lastFrameTimestamp = DateTime.Now;
        timer.Start();
    }
    #endregion


    #region Events
    /// <summary>
    /// Handle the timer when video is running.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void TimerTick(object sender, EventArgs e)
    {
        if (frameTransport.IsNewFrameAvailable())
        {
            bool frameOk = frameTransport.GetFrame();

            if (frameOk)
            {
                bool bitmapOk = MoveFrameToBitmap();

                if (bitmapOk)
                {
                    AddCustomGraphics();
                    DrawBitmap();
                    double msSinceLastFrame = (Int32)DateTime.Now.Subtract(lastFrameTimestamp).TotalMilliseconds;
                    fps = 1000 / msSinceLastFrame;
                    lastFrameTimestamp = DateTime.Now;
                }
            }
        }
    }
    #endregion
}

乾杯。

4

1 に答える 1

0

この問題は、ImageSource の設定方法でした...オーバーロードされていない Source プロパティを作成することが問題でした...これの名前を変更し、そのプロパティを継承されたソースに設定すると、問題が修正されました。

乾杯。

于 2012-07-24T14:18:29.283 に答える