Exemplo n.º 1
0
        private void RunAnalyzeVideo()
        {
            Log.Info("Auto3D: Start Video Analysis");

            FrameGrabber fg = FrameGrabber.GetInstance();

            int maxAnalyzeSteps = 20;
            int treshold        = 5;

            VideoFormat[] vf = new VideoFormat[maxAnalyzeSteps + 1];

            int iStep = 0;

            while (_run && _bPlaying)
            {
                // wait 200 ms

                for (int i = 0; i < 10; i++)
                {
                    if (!_bPlaying) // if playing is stopped while we wait then return
                    {
                        return;
                    }

                    Thread.Sleep(20);
                }

                System.Drawing.Bitmap image = fg.GetCurrentImage();

                if (image != null)
                {
                    Bitmap fastCompareImage = new Bitmap(96, 96);

                    // set the resolutions the same to avoid cropping due to resolution differences
                    fastCompareImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

                    //use a graphics object to draw the resized image into the bitmap
                    using (Graphics graphics = Graphics.FromImage(fastCompareImage))
                    {
                        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bicubic;
                        graphics.DrawImage(image, 0, 0, fastCompareImage.Width, fastCompareImage.Height);
                    }

                    // Lock the bitmap's bits.
                    Rectangle rect = new Rectangle(0, 0, fastCompareImage.Width, fastCompareImage.Height);
                    System.Drawing.Imaging.BitmapData bmpData = fastCompareImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                    double similarity = 0;

                    vf[iStep] = VideoFormat.Fmt2D; // assume normal format

                    if (bCheckSideBySide)
                    {
                        similarity = Auto3DAnalyzer.CheckFor3DFormat(bmpData, bmpData.Width / 2, bmpData.Height, true);
                    }

                    if (similarity == -1) // not bright enough for analysis
                    {
                        continue;
                    }

                    if (similarity > 0.925)
                    {
                        vf[iStep] = VideoFormat.Fmt3DSBS;
                    }
                    else
                    {
                        if (bCheckTopAndBottom)
                        {
                            similarity = Auto3DAnalyzer.CheckFor3DFormat(bmpData, bmpData.Width, bmpData.Height / 2, false);
                        }

                        if (similarity == -1) // not bright enough for analysis -> continue
                        {
                            continue;
                        }

                        if (similarity > 0.925)
                        {
                            vf[iStep] = VideoFormat.Fmt3DTAB;
                        }
                    }

                    fastCompareImage.UnlockBits(bmpData);

                    Log.Debug("Similarity: " + similarity + " - " + vf[iStep].ToString());
                }

                if (iStep > 3)
                {
                    // check if we can make a decision

                    int countNormal       = 0;
                    int countSideBySide3D = 0;
                    int countTopBottom3D  = 0;

                    for (int i = 0; i <= iStep; i++)
                    {
                        switch (vf[i])
                        {
                        case VideoFormat.Fmt2D:

                            countNormal++;
                            break;

                        case VideoFormat.Fmt3DSBS:

                            countSideBySide3D++;
                            break;

                        case VideoFormat.Fmt3DTAB:

                            countTopBottom3D++;
                            break;
                        }
                    }

                    Log.Debug("Results(" + iStep + ") - Normal=" + countNormal + " - SBS3D=" + countSideBySide3D + " - TB3D=" + countTopBottom3D);

                    if ((countSideBySide3D >= (countNormal + treshold)) || (countTopBottom3D >= (countNormal + treshold)) || (countSideBySide3D >= countNormal && iStep == maxAnalyzeSteps) || (countTopBottom3D >= countNormal && iStep == maxAnalyzeSteps))
                    {
                        VideoFormat videoFormat = countTopBottom3D > countSideBySide3D ? VideoFormat.Fmt3DTAB : VideoFormat.Fmt3DSBS;

                        if ((videoFormat == VideoFormat.Fmt3DSBS) || (videoFormat == VideoFormat.Fmt3DTAB))
                        {
                            if (videoFormat == VideoFormat.Fmt3DTAB)
                            {
                                Log.Info("Auto3D: Video Analysis Finished: Switch TV to TAB 3D");
                            }
                            else
                            {
                                Log.Info("Auto3D: Video Analysis Finished: Switch TV to SBS 3D");
                            }

                            if (bConvert3DTo2D)
                            {
                                switch (videoFormat)
                                {
                                case VideoFormat.Fmt3DSBS:

                                    GUIGraphicsContext.Render3DMode = GUIGraphicsContext.eRender3DMode.SideBySideTo2D;
                                    break;

                                case VideoFormat.Fmt3DTAB:

                                    GUIGraphicsContext.Render3DMode = GUIGraphicsContext.eRender3DMode.TopAndBottomTo2D;
                                    break;
                                }

                                _currentMode = videoFormat;
                            }
                            else
                            {
                                if (_activeDevice.SwitchFormat(_currentMode, videoFormat))
                                {
                                    switch (videoFormat)
                                    {
                                    case VideoFormat.Fmt3DSBS:

                                        GUIGraphicsContext.Render3DMode = GUIGraphicsContext.eRender3DMode.SideBySide;
                                        break;

                                    case VideoFormat.Fmt3DTAB:

                                        GUIGraphicsContext.Render3DMode = GUIGraphicsContext.eRender3DMode.TopAndBottom;
                                        break;
                                    }

                                    _currentMode = videoFormat;
                                }
                            }

                            UpdateSubtitleRenderFormat();
                        }
                        else
                        {
                            ManualSelect3DFormat(videoFormat);
                            UpdateSubtitleRenderFormat();
                        }

                        return; // exit thread
                    }
                    else
                    if ((_currentMode == VideoFormat.Fmt2D) && ((countNormal > countSideBySide3D + treshold) || (countNormal > countTopBottom3D + treshold)))
                    {
                        // current format is normal and video is normal too, we do not need to switch
                        Log.Info("Auto3D: Format is 2D. No switch necessary");
                        return; // exit thread
                    }
                    else
                    if (_currentMode != VideoFormat.Fmt2D)
                    {
                        // current format 3d and video is 2d, so we must switch back to normal
                        RunSwitchBack();
                        return; // exit thread
                    }
                    else
                    if (iStep > maxAnalyzeSteps)
                    {
                        // we could not make a decision within the maximum allowed steps
                        Log.Info("Auto3D: Video Analysis failed!");
                        return; // exit thread
                    }
                }

                iStep++;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Finds the bounds and crops accordingly immediately
        /// </summary>
        private void SingleCrop()
        {
            bool updateCrop = false;

            if (LastSwitchedAspectRatio < 0.1f)
            {
                LastDetectionResult = false;
                return;
            }

            if (GUIGraphicsContext.RenderBlackImage)
            {
                LastDetectionResult = false;
                return;
            }

            Bitmap frame = grabber.GetCurrentImage();

            if (frame == null || frame.Height == 0 || frame.Width == 0)
            {
                LastDetectionResult = false;
                return;
            }

            Rectangle bounds = new Rectangle();

            if (!analyzer.FindBounds(frame, ref bounds))
            {
                LastDetectionResult = false;
                frame.Dispose();
                frame = null;
                return;
            }

            double Hsym = 1.0;
            double Vsym = 1.0;

            if (bounds.Left > 20 || ((frame.Width - bounds.Right) > 20 && bounds.Left > 0))
            {
                Hsym = (double)(frame.Width - bounds.Right) / (double)bounds.Left;
            }
            if (bounds.Top > 20 || ((frame.Height - bounds.Bottom) > 20 && bounds.Top > 0))
            {
                Vsym = (double)(frame.Height - bounds.Bottom) / (double)bounds.Top;
            }

            if (currentSettings.verboseLog)
            {
                Log.Debug("ViewModeSwitcher: SingleCrop(), Detected BB -> left: {0}, right: {1}, top: {2}, bottom: {3}, Hsym: {4}, Vsym: {5}", bounds.Left, (frame.Width - bounds.Right), bounds.Top, (frame.Height - bounds.Bottom), Hsym, Vsym);
            }

            //Check for symmetry of black bars - asymmetric bars are probably a false detection
            if ((Hsym > SymLimHigh) || (Hsym < SymLimLow) || (Vsym > SymLimHigh) || (Vsym < SymLimLow))
            {
                if (currentSettings.verboseLog)
                {
                    Log.Debug("ViewModeSwitcher: SingleCrop(), Symmetry check failed");
                }
                if (NoMatchCropCount < 3)
                {
                    NoMatchCropCount++;
                    LastDetectionResult = false;
                }
                frame.Dispose();
                frame = null;
                return;
            }

            //Use the smallest black bar size
            double cropH = (double)(Math.Min(frame.Width - bounds.Right, bounds.Left));
            double cropV = (double)(Math.Min(frame.Height - bounds.Bottom, bounds.Top));

            //Check for a close match (within 1% of width/height) to the previous crop values
            if ((((Math.Abs(cropV - LastRawCropV)) / (double)frame.Height) > 0.01) ||
                (((Math.Abs(cropH - LastRawCropH)) / (double)frame.Width) > 0.01))
            {
                LastRawCropH = cropH;
                LastRawCropV = cropV;
                if (NoMatchCropCount < 3)
                {
                    NoMatchCropCount++;
                    LastDetectionResult = false;
                }
                if (currentSettings.verboseLog)
                {
                    Log.Debug("ViewModeSwitcher: SingleCrop(), No match with last crop : " + NoMatchCropCount);
                }
                frame.Dispose();
                frame = null;
                return;
            }

            LastRawCropH = cropH;
            LastRawCropV = cropV;

            //Work out actual picture aspect ratio
            double newasp = ((double)frame.Width - cropH * 2) / ((double)frame.Height - cropV * 2);

            bool checkPBv = false;

            if (LastAnamorphFactor > 0.0)
            {
                //Correction for anamorphic video i.e. when pixel aspect ratio != video aspect ratio.
                newasp *= LastAnamorphFactor;

                //Check for letterbox/pillarbox video
                if (LastSwitchedAspectRatio > 1.68 && LastSwitchedAspectRatio < 1.87)
                {
                    if ((cropV / (double)frame.Height < 0.02) && newasp > 1.2 && newasp < 1.46)
                    {
                        checkPBv = true;
                    }
                    else if ((cropH / (double)frame.Width < 0.02) && newasp > 2.1 && newasp < 2.57)
                    {
                        checkPBv = true;
                    }
                }
                else if (LastSwitchedAspectRatio > 1.25 && LastSwitchedAspectRatio < 1.41)
                {
                    if ((cropH / (double)frame.Width < 0.02) && newasp > 1.47 && newasp < 1.95)
                    {
                        checkPBv = true;
                    }
                    else if ((cropH / (double)frame.Width < 0.02) && newasp > 2.1 && newasp < 2.57)
                    {
                        checkPBv = true;
                    }
                }

                //After this correction, cropH value is in 'real' video pixels, not source pixels
                cropH *= LastAnamorphFactor;
            }

            if (newasp < 1.1 || newasp > 2.7) // faulty crop
            {
                if (NoMatchCropCount < 3)
                {
                    NoMatchCropCount++;
                    LastDetectionResult = false;
                }
                frame.Dispose();
                frame = null;
                return;
            }

            NoMatchCropCount = 0;

            if (currentSettings.verboseLog)
            {
                Log.Debug("ViewModeSwitcher: SingleCrop(), Video AR: {0}, Cropped AR: {1}", LastSwitchedAspectRatio, newasp);
            }

            //Check for 'Pillar Boxed' 4:3 inside 16:9 video, and 'Letter Boxed' 16:9 inside 4:3 video
            if (CheckRulesPBLB(-newasp, frame.Width, frame.Height, checkPBv))
            {
                if (LastSwitchedGeometry != Geometry.Type.NonLinearStretch)
                {
                    //NonLinearStretch needs full side bar cropping, other modes don't
                    cropH = overScan;
                    cropV = overScan / LastSwitchedAspectRatio;
                }
                else
                {
                    //Add overscan to NonLinearStretch
                    cropH += overScan;
                    cropV += overScan / LastSwitchedAspectRatio;
                }

                if (!isPBorLB) //Only update on first detection
                {
                    updateCrop = true;
                }
                isPBorLB = true;
            }
            else //Normal video cropping
            {
                //Use overscan cropping if larger than detected black bars
                cropH = Math.Max(cropH, overScan);
                cropV = Math.Max(cropV, overScan / LastSwitchedAspectRatio);

                if (isPBorLB)
                {
                    if (currentSettings.verboseLog)
                    {
                        Log.Debug("ViewModeSwitcher: SingleCrop(), PillarBox -> Normal");
                    }
                    //Force CheckAspectRatios() update
                    updatePending           = false;
                    isPBorLB                = false;
                    LastSwitchedAspectRatio = 0.0;
                    frame.Dispose();
                    frame = null;
                    return;
                }
                isPBorLB = false;
            }

            if (currentSettings.verboseLog)
            {
                Log.Debug("ViewModeSwitcher: SingleCrop(), Real cropH: {0}, cropV: {1}", cropH, cropV);
            }

            if ((Math.Abs(cropH - fCropH) > 5) || (Math.Abs(cropV - fCropV) > 3))
            {
                fCropH     = cropH;
                fCropV     = cropV;
                updateCrop = true;
            }

            if (updateCrop)
            {
                updatePending = true;
            }

            frame.Dispose();
            frame = null;
        }
Exemplo n.º 3
0
 /// <summary>
 /// Get the last frame of video from the Video Mixing Renderer
 ///  (only works for WMR9 Renderless)
 /// </summary>
 /// <returns></returns>
 private Bitmap GetFrame()
 {
     //Log.Debug("GetFrame");
     return(grabber.GetCurrentImage());
 }
Exemplo n.º 4
0
        /// <summary>
        /// Finds the bounds and crops accordingly immediately
        /// </summary>
        private void SingleCrop()
        {
            if (GUIGraphicsContext.RenderBlackImage)
            {
                LastDetectionResult = false;
                return;
            }

            Bitmap frame = grabber.GetCurrentImage();

            if (frame == null || frame.Height == 0 || frame.Width == 0)
            {
                LastDetectionResult = false;
                return;
            }

            Rectangle bounds = new Rectangle();

            if (!analyzer.FindBounds(frame, ref bounds))
            {
                LastDetectionResult = false;
                return;
            }

            int cropH = Math.Min(GUIGraphicsContext.VideoSize.Width - bounds.Right, bounds.Left);

            if (cropH < overScan)
            {
                cropH = overScan;
            }

            int cropV = Math.Min(GUIGraphicsContext.VideoSize.Height - bounds.Bottom, bounds.Top);

            if (cropV < overScan / LastSwitchedAspectRatio)
            {
                cropV = (int)(overScan / LastSwitchedAspectRatio);
            }

            if (cropV > cropH / LastSwitchedAspectRatio)
            {
                cropV = (int)(cropH / LastSwitchedAspectRatio);
            }

            float newasp = (float)(frame.Width - cropH * 2) / (float)(frame.Height - cropV * 2);

            if (newasp < 1) // faulty crop
            {
                cropH = overScan;
                cropV = (int)(overScan / LastSwitchedAspectRatio);
            }

            if (cropH != cropSettings.Left || cropV != cropSettings.Top)
            {
                cropSettings.Top    = cropV; //bounds.Top;
                cropSettings.Bottom = cropV; // GUIGraphicsContext.VideoSize.Height - (bounds.Bottom + 1);
                cropSettings.Left   = cropH; // bounds.Left;
                cropSettings.Right  = cropH; // GUIGraphicsContext.VideoSize.Width - (bounds.Right + 1);
                SetCropMode();
            }
            if (newasp >= 1)
            {
                float asp = (float)(frame.Width) / (float)(frame.Height);
                //Log.Debug("asp: {0}, newasp: {1}", asp, newasp);
                if (Math.Abs(asp - newasp) > 0.2 && LastSwitchedAspectRatio > 1.5)
                {
                    SetAspectRatio("4:3 inside 16:9", Geometry.Type.NonLinearStretch);
                }
            }

            frame.Dispose();
            frame = null;
        }