Skip to content

Commit 3ca793d

Browse files
committed
Fix frame orientation detection on Windows based on biHeight sign
- Use abs(biHeight) to get actual frame height - Check biHeight sign to determine orientation (negative=top-to-bottom, positive=bottom-to-top) - Remove incorrect pixel-format-based orientation detection - Add m_inputOrientation member variable to store orientation across frames - Reset m_firstFrameArrived when opening device Fixes #34
1 parent 41a9dad commit 3ca793d

2 files changed

Lines changed: 11 additions & 3 deletions

File tree

src/ccap_imp_windows.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ bool ProviderDirectShow::open(std::string_view deviceName) {
727727
m_isOpened = true;
728728
m_isRunning = false;
729729
m_frameIndex = 0;
730+
m_firstFrameArrived = false;
730731
return true;
731732
}
732733

@@ -757,7 +758,14 @@ HRESULT STDMETHODCALLTYPE ProviderDirectShow::SampleCB(double sampleTime, IMedia
757758
if (SUCCEEDED(hr)) {
758759
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
759760
m_frameProp.width = vih->bmiHeader.biWidth;
760-
m_frameProp.height = vih->bmiHeader.biHeight;
761+
// biHeight may be negative. Negative height indicates top-to-bottom orientation.
762+
// Positive height indicates bottom-to-top orientation (standard Windows DIB format).
763+
m_frameProp.height = abs(vih->bmiHeader.biHeight);
764+
if (vih->bmiHeader.biHeight < 0) {
765+
m_inputOrientation = FrameOrientation::TopToBottom;
766+
} else {
767+
m_inputOrientation = FrameOrientation::BottomToTop;
768+
}
761769
m_frameProp.fps = 10000000.0 / vih->AvgTimePerFrame;
762770
auto info = findPixelFormatInfo(mt.subtype);
763771
if (info.pixelFormat != PixelFormat::Unknown) {
@@ -781,15 +789,14 @@ HRESULT STDMETHODCALLTYPE ProviderDirectShow::SampleCB(double sampleTime, IMedia
781789
uint32_t bufferLen = mediaSample->GetActualDataLength();
782790
bool isInputYUV = (m_frameProp.cameraPixelFormat & kPixelFormatYUVColorBit);
783791
bool isOutputYUV = (m_frameProp.outputPixelFormat & kPixelFormatYUVColorBit);
784-
auto inputOrientation = isInputYUV ? FrameOrientation::TopToBottom : FrameOrientation::BottomToTop;
785792

786793
newFrame->pixelFormat = m_frameProp.cameraPixelFormat;
787794
newFrame->width = m_frameProp.width;
788795
newFrame->height = m_frameProp.height;
789796
newFrame->orientation = isOutputYUV ? FrameOrientation::TopToBottom : m_frameOrientation;
790797
newFrame->nativeHandle = mediaSample;
791798

792-
bool shouldFlip = newFrame->orientation != inputOrientation && !isOutputYUV;
799+
bool shouldFlip = newFrame->orientation != m_inputOrientation && !isOutputYUV;
793800
bool shouldConvert = m_frameProp.cameraPixelFormat != m_frameProp.outputPixelFormat;
794801
bool zeroCopy = !shouldConvert && !shouldFlip;
795802

src/ccap_imp_windows.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class ProviderDirectShow : public ProviderImp, public ISampleGrabberCB {
119119

120120
std::chrono::steady_clock::time_point m_startTime{};
121121
bool m_firstFrameArrived = false;
122+
FrameOrientation m_inputOrientation = FrameOrientation::TopToBottom;
122123

123124
// State variables
124125
bool m_didSetup{ false };

0 commit comments

Comments
 (0)