4

I've asked a very similar question before for a video renderer filter.

See here: Custom DirectShow Video Renderer Filter - Dynamic Resolution Change

But this time, I need a solution for a source filter. This source filter connects directly to the video renderer. Decoder is embedded.

I'm able to get the resolution changes from the stream. I also resize the buffers when I get a new resolution. But I don't know how to notify my new resolution through the pin. Should I somehow create an instance from CMediaType, fill in the new values and call pin's SetMediaType() method or what is the proper solution? I'm currently doing this.

if(nWidth * nHeight * 3 != reader->m_RGB24BufferSize) { // if resolution changed
    reader->m_RGB24BufferSize = nWidth * nHeight * 3;
    reader->m_RGB24Buffer = (BYTE*)malloc(reader->m_RGB24BufferSize);

    reader->m_pin->m_bmpInfo.biWidth = nWidth;
    reader->m_pin->m_bmpInfo.biHeight = nHeight;
    reader->m_pin->m_bmpInfo.biSizeImage = GetBitmapSize(&reader->m_pin->m_bmpInfo);

    // Now what? How to notify the video renderer?
}

m_pin is the only output pin of the source filter here which is declared like;

class MyPin : public CSourceStream { ... };

I know the answer should be simple and there should be many examples around but since I'm a little bit confused about these subjects, I prefer a nice explanation besides the example.

Community
  • 1
  • 1
Emir Akaydın
  • 5,708
  • 1
  • 29
  • 57

2 Answers2

2

You can have output pin derived from CDynamicOutputPin and perform the following when you need to send notification downstream (to the renderer) about the format change:

hr = StartUsingOutputPin();
if (SUCCEEDED(hr))
{
    hr = ChangeMediaType(&m_mt);
    StopUsingOutputPin();
}

There is an implementation of CDynamicSourceStream and matching CDynamicSource in DirectShow samples from Windows SDK that you may find helpful.

Dmitry Shkuropatsky
  • 3,902
  • 2
  • 21
  • 13
1

From MSDN Dynamic Format Changes:

  1. QueryAccept (Downstream) is used when If an output pin proposes a format change to its downstream peer, but only if the new format does not require a larger buffer.

  2. ReceiveConnection is used when an output pin proposes a format change to its downstream peer, and the new format requires a larger buffer.

Did you have a chance to try any of these two?

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • Let's say I will use ReceiveConnection to send a new resolution event. Should I directly call this function from pin's methods? And how should I create the parameter "AM_MEDIA_TYPE" from scratch? (When I get a new resolution, I'm in a callback function of a third party library). These are my problems. – Emir Akaydın Jan 11 '12 at 09:25
  • 1. `VMR` does not see from where exactly you make a call, from a pin method or not. 2. You have the resolution, so why cannot you build a new media type? You can. – Roman R. Jan 11 '12 at 10:20
  • I'm not using VMR but my own renderer filter. I'm only able to get the resolution change by overriding the "Receive" method of the input pin of the renderer. And I can only see it over "IMediaSample" interface and its "GetActualDataLength()" method. So, at the moment, i'm able to see when exactly video stream is resized but still I don't know how to get the exact resolution and resize it by building a AM_MEDIA_TYPE etc. I tried many ways but none of them worked. Actually, from some other source filters, i get "ReceiveConnection()" call when size is changed – Emir Akaydın Jan 11 '12 at 16:21
  • and it's easy to trigger "SetMediaType()" from there since i get "const AM_MEDIA_TYPE *pmt" from parameter. But I couldn't find a way to trigger that method (ReceiveConnection()) from my own source filter. When I call "QueryAccept()" with a new media type, "GetMediaSample()" is called at the source filter side. But at renderer filter side, none of the "CheckMediaSample()", "SetMediaSample()", "ReceiveConnection()" etc. are called. Only "Receive()" is called for per sample but I don't know how to get correct mediatype from "IMediaSample *pSample" parameter variable. – Emir Akaydın Jan 11 '12 at 16:25
  • I tried "pSample->GetMediaType()" etc. but the result is always NULL. I'm stuck at this point. – Emir Akaydın Jan 11 '12 at 16:26
  • Both connected filters are yours, so you are not even limited by using standard API in order to re-agree resolution. If you call `ReceiveConnection` from your upstream filter, the call definitely reaches your renderer, provided that no filters are connected in between. – Roman R. Jan 12 '12 at 07:36
  • That's exactly how i expected but didn't work. I'm using DebugView and every function has a log like "X filter - Y function reached" and Renderer filter's "ReceiveConnection()" function is reached at the startup but not after i manually call it from the source filter. I just noticed that "QueryAccept()" return false. So, probably my media type is not accepted. I thought reconnecting pins would work but to do that I has to stop the source filter. So, at the moment, I stop the filter, reconnect pins (RecieveConnection is triggered that way) and run the filter again. – Emir Akaydın Jan 12 '12 at 08:04
  • But there are still some weird problems like OnThreadDestroy is called when I stop the filter but OnThreadCreate is not called when I run it again. I tried to bypass OnThreadDestroy using some flags and it worked to the some point but still i'm unable to receive the video. I'm examining the problem at the moment. – Emir Akaydın Jan 12 '12 at 08:07