locked
MFT help RRS feed

  • Question

  • I'm trying to create an MFT for Windows Media Player 11, based on the GrayScale sample in the SDK.

    The problem is in the ProcessOutput method.  I'm unable to "Lock" the input buffer; it works fine on the output buffer.

    hr = pIn->QueryInterface(IID_IMF2DBuffer, (void**)&pIn2D);
        if (SUCCEEDED(hr))
        {
            ::OutputDebugString("input buffer: 2D\n");
            hr = pIn2D->Lock2D(&pSrc, &lSrcStride);
        }
        else if (hr == E_NOINTERFACE)
        {
            hr = pIn->Lock(&pSrc, 0, 0);
            lSrcStride = lStrideIfContiguous;

            //assert (cb == m_cbImageSize);

        }

    The first QI returns E_NOINTERFACE and the attempt to call Lock on pIn results in E_NOTIMPL.   If I check the size of the input buffer, it's zero -- is this normal?

    DWORD dwBufferLength(0), dwMaxLength(0);
        hr = pIn->GetCurrentLength(&dwBufferLength);
        hr = pIn->GetMaxLength(&dwMaxLength);

    -> both are zero.
    Wednesday, January 17, 2007 1:46 AM

Answers

  • OK, you did give me some useful clues.  Let me tell you what this all means, and maybe you can make enough sense of it to figure out what's going on.

    • By "topology" I just mean that if you know what kinds of nodes are upstream and downstream from your MFT, that's useful info.  (Another MFT?  A video renderer sink (EVR)?)  But a lot of the later information you gave me does provide some clues.
    • So pIn comes from ProcessInput.  If you're using an ATL smart pointer for it, you're right that you won't need another AddRef. 
    • Since the ProcessInput buffer comes from upstream, that means it's just a plain old buffer in system memory.  So it's not going to QI for IMF2DBuffer, just IMFMediaBuffer.  It should, however, allow you to Lock() it.
    • The reason why the playbackFX sample runs your topology inproc, whereas WMP runs it in mfpmp.exe: WMP always runs the MF pipeline in mfpmp.exe (this is useful for playing back DRM-protected content, though WMP runs all content in mfpmp.exe).  PlaybackFX just uses an inproc pipeline.  This shouldn't really be a significant difference to your MFT, though: Since everything your MFT needs is in the same process as the MFT, it's not going to need any special marshaling.
    • The fact that the methods are implemented in mf.dll vs. evr.dll is telling.  When the buffer appears to belong to evr.dll, that means that the next node downstream is the EVR, and you are getting a DX render target.  That said, you should be able to Lock() it (and it should QI for IMF2DBuffer).  Try using MFT_Grayscale in this scenario exactly where you were using your MFT.  And if it works and yours doesn't... well, start looking for differences.  Getting a buffer that belongs to mf.dll, on the other hand, means that you're getting regular system memory, and IMFMediaBuffer::Lock should definitely work.  One shot in the dark: Have you tried turning off DXVA on your system?

    Hope all this information helps...

    Tuesday, January 23, 2007 4:17 PM

All replies

  • I'll assume (because your code compiles) that pIn is an IMFMediaBuffer *.  Calling Lock() on it should succeed, and those second and third params should tell you valid current and max length values. 

    Three questions:

    1. You mention that this code is in ProcessOutput.  Does pIn refer to an input buffer (i.e. that you received some time in the past from ProcessInput), or are you referring to the pSample in the MFT_OUTPUT_DATA_BUFFER that ProcessOutput got?  That is, is this an input or an output buffer?  And if it's a ProcessInput buffer, did you make sure to AddRef() it for the time you'll be sitting on it?

    2. What does your topology look like?

    3. Go back to the original MFT_Grayscale sample.  Does it work for you?  What's different about about how it calls Lock() and how you're calling it?  (set a breakpoint at CVideoBufferLock::LockBuffer to see what the sample is doing)

     

    Wednesday, January 17, 2007 4:29 PM
  • Hi Becky,

    Thanks for your answer.  I can answer question (1) now, but I'll plead ignorance on (2) and laziness on (3)   I wanted to get this info to you while I work on trying other things.

    1) pIn does indeed come from the IMFSample passed in ProcessInput.  The code is this:

    hr = _spSample->GetBufferByIndex(0, &spInput);

    _spSample is an ATL smart pointer templated around IMFSample.  This succeeds (hr==S_OK), and I end up with...something, in spInput (which is a smart pointer of IMFMediaBuffer).

    The output buffer is obtained from the pOutputSamples parameter passed to ProcessOutput:

    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &spOutput);

    The output buffer spOutput works fine -- I can QI it for IMF2DBuffer, and call Lock2D on the resulting interface with no problems.

    When I try the same on spInput, I get E_NOINTERFACE for IMF2DBuffer, and E_NOTIMPL when I try to call Lock() on spInput itself.

    As far as AddRef -- I'm using a smart pointer so the assignment operator should do that, right?  I looked in atlcom.h and it appears that the smart pointer class does indeed AddRef on assignment.  If I had a ref counting problem, wouldn't I get null pointer or access violation type error?  In my case, it appears that spInput is pointing to something valid, but not to a buffer that I can use.

    As an experiment, I tried the alternative route of:

     _spSample->ConvertToContiguousBuffer(&spBuff);

    My MFT only handles a single input & output buffer so from what I read on MSDN, this should just give me me the buffer.  It succeeds, but then I have the same problems when I try to Lock() it or QI() for IMF2DBuffer.

    2) Sorry, I'm totally new to MF development; I'm not sure what "topology" means or how to find out what mine looks like.  I'll do some searching and get back to you with this answer.

    3) The MFT_Grayscale sample doesn't appear to be built as a WMP plugin, but just as a regular MFT, so I realized I'll need to implement all the "WMP machinery" to get it to run inside WMP, or else build the other "player" sample and try it there.  That's my next experiment.

    Thanks again for your help.

    -Darren.
    Wednesday, January 17, 2007 5:24 PM
  • OK, I tried the MFT_Grayscale sample within the PlaybackFX sample.

    It works!  In the debugger I can see that the QI on the input buffer for IMF2DBuffer still fails, but it manages to successfully call Lock() on that buffer, unlike when I try it inside a WMP plugin.  I guess the next step is to make the Grayscale sample into a full-blown WMP plugin and see what happens.

    One big difference I've noticed -- when I open the wmv file in the PlaybackFX sample, it seems to render "inproc" -- it doesn't launch a separate mfpmp.exe process.  When I play within WMP, I do see a separate mfpmp process.  What determines whether the content will be rendered in the separate Protected Media Path process?
    Wednesday, January 17, 2007 6:58 PM
  • Becky -- I think this experiment is very telling:

    I modified the PlaybackFX sample to use my MFT instead of the MFT_Grayscale one.  When I run PlaybackFX and open up a WMV file, there is no mfpmp.exe process, so everything happens inproc.  Moreover, even though the QI on the input buffer still fails, the Lock() succeeds, just like for the Grayscale MFT.

    Does this mean I have some kind of marshaling issue?  I do not have any custom interfaces on my MFT -- only the standard ones, so it was my understanding that I shouldn't need a proxy-stub DLL. 
    Wednesday, January 17, 2007 7:38 PM
  • Sorry for the barrage of posts, but I think this information is key:

    I noticed that in the case where it works, i.e. using the PlaybackFx sample, the methods on IMediaBuffer are implemented in mf.dll.

    In the case where it doesn't work, they are in evr.dll.  The assembler in evr.dll shows that the Lock() method is just hard-wired to return E_NOTIMPL...I've no idea why.

    Does that give you any clues?
    Thursday, January 18, 2007 5:58 AM
  • OK, you did give me some useful clues.  Let me tell you what this all means, and maybe you can make enough sense of it to figure out what's going on.

    • By "topology" I just mean that if you know what kinds of nodes are upstream and downstream from your MFT, that's useful info.  (Another MFT?  A video renderer sink (EVR)?)  But a lot of the later information you gave me does provide some clues.
    • So pIn comes from ProcessInput.  If you're using an ATL smart pointer for it, you're right that you won't need another AddRef. 
    • Since the ProcessInput buffer comes from upstream, that means it's just a plain old buffer in system memory.  So it's not going to QI for IMF2DBuffer, just IMFMediaBuffer.  It should, however, allow you to Lock() it.
    • The reason why the playbackFX sample runs your topology inproc, whereas WMP runs it in mfpmp.exe: WMP always runs the MF pipeline in mfpmp.exe (this is useful for playing back DRM-protected content, though WMP runs all content in mfpmp.exe).  PlaybackFX just uses an inproc pipeline.  This shouldn't really be a significant difference to your MFT, though: Since everything your MFT needs is in the same process as the MFT, it's not going to need any special marshaling.
    • The fact that the methods are implemented in mf.dll vs. evr.dll is telling.  When the buffer appears to belong to evr.dll, that means that the next node downstream is the EVR, and you are getting a DX render target.  That said, you should be able to Lock() it (and it should QI for IMF2DBuffer).  Try using MFT_Grayscale in this scenario exactly where you were using your MFT.  And if it works and yours doesn't... well, start looking for differences.  Getting a buffer that belongs to mf.dll, on the other hand, means that you're getting regular system memory, and IMFMediaBuffer::Lock should definitely work.  One shot in the dark: Have you tried turning off DXVA on your system?

    Hope all this information helps...

    Tuesday, January 23, 2007 4:17 PM
  • Hi Becky,

    That was better than a shot in the dark...it was spot on.

    As soon as I disabled DXVA, the Lock() worked fine -- no more E_NOTIMPL.  I'm assuming the correct way to disable DXVA is through the checkbox in WMP, right?  Is there a way to do this programatically? If this is to be the default for WMP 11 then our end users will have it checked on their machine, and our plugin won't work.

    Thanks for all your help!

    -Darren.
    Tuesday, January 23, 2007 9:12 PM