Fix: Bug fix in determination of scanline direction
authorWouter Huysentruit <wouter.huysentruit@dzine.be>
Fri, 11 Jan 2013 10:21:35 +0000 (11:21 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 14 Jan 2013 08:05:20 +0000 (09:05 +0100)
YUV and other compressed frame formats are always TopToBottom. Only for uncompressed RGB formats the sign of their height is used to indicate the scanline direction.

Change-Id: I6474783583672861eeeb538b79d14ee3d6995f59
Reviewed-by: Dmytro Poplavskiy <dmytro.poplavskiy@gmail.com>
src/plugins/directshow/player/directshowmediatype.cpp
src/plugins/directshow/player/directshowmediatype.h

index b64e47c..7b3a3bc 100644 (file)
@@ -127,9 +127,7 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ
                 if (header->AvgTimePerFrame > 0)
                     format.setFrameRate(10000 /header->AvgTimePerFrame);
 
-                format.setScanLineDirection(header->bmiHeader.biHeight < 0
-                        ? QVideoSurfaceFormat::TopToBottom
-                        : QVideoSurfaceFormat::BottomToTop);
+                format.setScanLineDirection(scanLineDirection(format.pixelFormat(), header->bmiHeader));
 
                 return format;
             } else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) {
@@ -142,9 +140,7 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ
                 if (header->AvgTimePerFrame > 0)
                     format.setFrameRate(10000 / header->AvgTimePerFrame);
 
-                format.setScanLineDirection(header->bmiHeader.biHeight < 0
-                        ? QVideoSurfaceFormat::TopToBottom
-                        : QVideoSurfaceFormat::BottomToTop);
+                format.setScanLineDirection(scanLineDirection(format.pixelFormat(), header->bmiHeader));
 
                 return format;
             }
@@ -183,3 +179,31 @@ int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
         return 0;
     }
 }
+
+QVideoSurfaceFormat::Direction DirectShowMediaType::scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader)
+{
+    /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx */
+    /* For uncompressed RGB bitmaps:
+     *    if biHeight is positive, the bitmap is a bottom-up DIB with the origin at the lower left corner.
+     *    If biHeight is negative, the bitmap is a top-down DIB with the origin at the upper left corner.
+     *
+     * For YUV bitmaps:
+     *    the bitmap is always top-down, regardless of the sign of biHeight.
+     *    Decoders should offer YUV formats with postive biHeight, but for backward compatibility they should accept YUV formats with either positive or negative biHeight.
+     *
+     * For compressed formats:
+     *    biHeight must be positive, regardless of image orientation.
+     */
+    switch (pixelFormat)
+    {
+    case QVideoFrame::Format_RGB32:
+    case QVideoFrame::Format_BGR24:
+    case QVideoFrame::Format_RGB565:
+    case QVideoFrame::Format_RGB555:
+        return bmiHeader.biHeight < 0
+            ? QVideoSurfaceFormat::TopToBottom
+            : QVideoSurfaceFormat::BottomToTop;
+    default:
+        return QVideoSurfaceFormat::TopToBottom;
+    }
+}
index 378c163..3808d1c 100644 (file)
@@ -69,6 +69,9 @@ public:
     static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type);
 
     static int bytesPerLine(const QVideoSurfaceFormat &format);
+
+private:
+    static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader);
 };
 
 #endif