rdp / screen-capture-recorder-to-video-windows-free

a free open source windows "screen capture" device and recorder (also allows VLC/ffmpeg and others to capture/stream desktop/audio)
https://github.com/rdp/screen-capture-recorder-to-video-windows-free/releases
Other
2.06k stars 456 forks source link

IAMStreamConfig::GetStreamCaps get wrong SubType when enum twice because CPushPinDesktop::GetMediaType has a bug #162

Open yinkaisheng opened 1 year ago

yinkaisheng commented 1 year ago

the following code outputs:

Camera capability 0, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0
Camera capability 1, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0
Camera capability 2, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0
Camera capability 3, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0
Camera capability 4, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0
Camera capability 5, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0
Camera capability 6, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0

----

Camera capability 0, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
Camera capability 1, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
Camera capability 2, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
Camera capability 3, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
Camera capability 4, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
Camera capability 5, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
Camera capability 6, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0
ComPtr<IAMStreamConfig> streamConfig;
hr = outputPin->QueryInterface(IID_IAMStreamConfig, (void**)&streamConfig);

AM_MEDIA_TYPE* pmt = nullptr;
VIDEO_STREAM_CONFIG_CAPS caps;
int count = 0;
int size = 0;
hr = streamConfig->GetNumberOfCapabilities(&count, &size);

int enumTimes = 2;
for (int n = 0; n < enumTimes; ++n)
{
    for (int index = 0; index < count; ++index)
    {
        hr = streamConfig->GetStreamCaps(index, &pmt, reinterpret_cast<BYTE*>(&caps));
        //print pmt properties;
    }
    printf("\n----\n");
}   

In CPushPinDesktop::GetMediaType, pmt->Subtype() is always I420 (!=GUID_NULL) after enumerating once, pmt->SetSubType is never called when enumerating the second time.

HRESULT CPushPinDesktop::GetMediaType(int iPosition, CMediaType *pmt) // AM_MEDIA_TYPE basically == CMediaType
{
    //...
    if (*pmt->Subtype() == GUID_NULL) {
      const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
      pmt->SetSubtype(&SubTypeGUID);
    }
}

if I change the code to the following, then IAMStreamConfig::GetStreamCaps will get correct result when enumerating twice.

HRESULT CPushPinDesktop::GetMediaType(int iPosition, CMediaType *pmt) // AM_MEDIA_TYPE basically == CMediaType
{
    //...
    if (iPosition < 6) {
      const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
      pmt->SetSubtype(&SubTypeGUID);
    }
}
rdp commented 1 year ago

this is a bug in GetMediaType?

On Tue, Jan 31, 2023 at 7:51 PM yin kaisheng @.***> wrote:

the following code outputs:

Camera capability 0, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0 Camera capability 1, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0 Camera capability 2, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0 Camera capability 3, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0 Camera capability 4, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0 Camera capability 5, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kRGB32, rateControl:0 Camera capability 6, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0


Camera capability 0, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0 Camera capability 1, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0 Camera capability 2, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0 Camera capability 3, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0 Camera capability 4, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0 Camera capability 5, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0 Camera capability 6, VideoInfo1, size:2560 x 1440, fps:30, video sub type:kI420, rateControl:0

ComPtr streamConfig; hr = outputPin->QueryInterface(IID_IAMStreamConfig, (void**)&streamConfig);

AM_MEDIA_TYPE pmt = nullptr; VIDEO_STREAM_CONFIG_CAPS caps;int count = 0;int size = 0; hr = streamConfig->GetNumberOfCapabilities(&count, &size); int enumTimes = 2;for (int n = 0; n < enumTimes; ++n) { for (int index = 0; index < count; ++index) { hr = streamConfig->GetStreamCaps(index, &pmt, reinterpret_cast<BYTE>(&caps)); //print pmt properties; } printf("\n----\n"); }

In CPushPinDesktop::GetMediaType, pmt->Subtype() is always I420 (!=GUID_NULL) after enumerating once, pmt->SetSubType is never called.

HRESULT CPushPinDesktop::GetMediaType(int iPosition, CMediaType pmt) // AM_MEDIA_TYPE basically == CMediaType { //... if (pmt->Subtype() == GUID_NULL) { const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader); pmt->SetSubtype(&SubTypeGUID); } }

if I change the code to the following, then IAMStreamConfig::GetStreamCaps will get correct result when enumerating twice.

HRESULT CPushPinDesktop::GetMediaType(int iPosition, CMediaType *pmt) // AM_MEDIA_TYPE basically == CMediaType { //... if (iPosition < 6) { const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader); pmt->SetSubtype(&SubTypeGUID); } }

— Reply to this email directly, view it on GitHub https://github.com/rdp/screen-capture-recorder-to-video-windows-free/issues/162, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAADBUC2C6ABGYUF5OT4NVTWVHFSVANCNFSM6AAAAAAUNFPJM4 . You are receiving this because you are subscribed to this thread.Message ID: @.*** com>

yinkaisheng commented 1 year ago

Yes, when app calls streamConfig->GetStreamCaps with index 0,... 6, CPushPinDesktop::GetStreamCaps will be called. m_mt's Subtype is set and is not GUID_NULL anymore, SubType is I420 when the last index is 6. If app calls streamConfig->GetStreamCaps with index 0,... 6 again, pmt->SetSubtype is never called because *pmt->Subtype() != GUID_NULL, the SubType in pmt that app gets is always I420。

HRESULT STDMETHODCALLTYPE CPushPinDesktop::GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC)
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());
    HRESULT hr = GetMediaType(iIndex, &m_mt); // setup then re-use m_mt ... why not?
    ...
    *pmt = CreateMediaType(&m_mt);
}
HRESULT CPushPinDesktop::GetMediaType(int iPosition, CMediaType *pmt) // AM_MEDIA_TYPE basically == CMediaType
{
//...
    if (*pmt->Subtype() == GUID_NULL) {
      const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
      pmt->SetSubtype(&SubTypeGUID);
    }
}
rdp commented 1 year ago

Check it, see if it works for you...