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++; } }