VMR9 Ignores Per-Pixel Alpha Values Below 17

I posted a few notes about this to the Microsoft DirectShow forum, but those things have a tendency to be badly indexed and less than permanent, so I’m summarizing what I have learned in the last 24 hours here, where it might be easier for others to find.

The short version of this week’s stunning discovery is that, if you provide the Video Mixing Renderer 9 with a video stream that includes an alpha channel, the VMR9 will treat all alpha values in your stream that are below 17 (0×11) as though they were zero. I have scoured the MSDN for info on this and come up with nothing. The closest I can find is their page on setting Direct3D 9′s alpha testing state.

A book on game programming, written by two Microsoft employees, is more explicit, stating what I just said here: the VMR9 ignores pixels with an alpha value of 16 or less.

What that means in pratice is that, if you have a smooth gradient in your alpha values, starting with fully opaque at (for example) the bottom of your screen, diminishing downward from 255 (full opacity) to the middle values (partial transparency), ending at 0 (full transparency), and apply that gradient to a completely black image on Input 1 of the VMR9 while a completely white image is on Input 0, the output looks like this:

That all-white band at the top is where the alpha values dropped below 17. You should still see some gray there, with only the top-most couple of rows of pixels showing bright white. But you don’t. You see what you see. Apparently, this is to avoid needless computation for pixels so close to being fully transparent that it isn’t worth the overhead to blend them. However, since the virtue of the VMR9 is supposed to be that it uses hardware acceleration, one has to wonder why this is still the way it works. Can’t a modern graphics card do compositing without CPU overhead? Maybe it can’t, but I’d be surprised. Regardless, this ought to be a setting you can change via some API call.

But you can’t.

The only way to change it appears to be to use the SetRenderState method on the Direct3DDevice used by the VMR9. And there’s no way (I can find) to get at it. If you write a filter that processes IMediaSample objects from the VMR9, you can use a series of queries and calls to get its Direct3D surface and, from that, a Direct3D device, but it’s not the one the VMR9 is using. (Why it isn’t baffles me, since you are getting access to the VRAM on the card through that same IMediaSample.)

A custom allocator-presenter would let you have control over the Direct3D device used for presentation, but, by that time in the sequence of video processing, the composition has already been done. That suggests that the solution, if there is one, might be in writing a custom compositor (or, alternatively, a custom rendering filter).

After a long day of Googling, the only other person I can find who ever noticed this was a fellow named Ulf, who posted about it online.

Seven years ago.

He likewise suggests that a custom compositor might be the way to solve it. (I have e-mailed him to ask if he ever found a solution, but it’s an old post and I certainly won’t hold it against him if he doesn’t reply.)

So, there you have it: Another day shot to Hell because Microsoft locked up an arbitrary setting that is available in Direct3D, but not in the VMR9 which relies on Direct3D. One that messes up my picture. And one that Microsoft couldn’t be bothered to document, much less make available through an API.

If anyone knows how to beat this, by getting at the VMR9′s Direct3D device or otherwise, please let me know in comments here.

Posted in Argh!, VMR9 | Leave a comment

Be Explicit with regsvr32

Today I compiled the WavDest DirectShow sample program included in the Windows SDK (the one that is oh-so-reassuringly referred to as “WavDes” on the MSDN Web page). It compiled fine after conversion to VS2010. Then, I opened a command window (running it as adminstrator, of course), changed to the directory containing wavdest.dll, and solemnly entered this:

regsvr32 wavdest.dll

What I have laughingly (ever since Windows 7) continued to refer to as “my” computer replied with this:

Which seems pretty unequivocal, wouldn’t you agree? Seemed that way to me. However, the filter didn’t show up in graphedt.exe. Hmmm…, so I tried to unregister it:

regsvr32 /u wavdest.dll

And got this:

“You have got to be kidding me,” I said to my machine. I don’t know why I keep telling my computer it must kidding me. It never is. As far as I can tell, my computer has no sense of humor whatsoever. But I said it because it seemed as though I had registered a filter that had some kind of bug preventing it from appearing on the visible list of DirectShow filters, and that also prevented me from unregistering it.

My computer had become The Black Hole for buggy filters. Once they go in, they don’t come out. (Or am I talking about New York in 1997?)

Here’s the problem: regsvr32 was trying to be helpful. For a variety of badly documented reasons, regsvr32 will ignore a file by the name of, say, “wavdest.dll,” if that exists in your current directory when you run regsvr32, provided that it can find a file of that name elsewhere first. Where does it look? Ah, well, you won’t learn the answer to that by reading a page in the technet subdomain of microsoft.com. (I only found that by following the link at Wikipedia’s page on regsvr32; a lot of searching at MSDN didn’t turn it up.) That one tells you regsvr32 registers your dll, but it doesn’t say anything about the fact that it may not register your dll. That’s elsewhere too.

Apparently, regsvr32 works by calling LoadLibrary (or, in some opinions, by calling LoadLibraryEx). Both of which include in their documentation a whole bunch of convoluted language that, in simple terms that even I can understand, amount to, “You should use a fully qualified path to specify your down dll when using regsvr32.” That’s because those functions look in a whole convoluted list of places for files that match any not-fully qualified path you might give regsvr32 first.

In the case of wavdest.dll, it finds one. It is in C:\Windows and, as far as I can tell, has no connection to the DirectShow sample I was interested in. Nor, apparently, can it be unregistered, notwithstanding that it returns success when registered with regsvr32. In any case, the sure way to register what you think you are registering is to use fully qualified paths, every time you use regsvr32.exe, like this:

regsvr32 C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\
multimedia\directshow\filters\wavdest\Debug\wavdest.dll

No, I am not kidding you. (Gee, it’s rare when I get to say that.) Note that, despite what it says on Wikipedia, a relative path will not make any difference. That is, if you try this:

regsvr32 .\wavdest.dll

you will still load the wrong one.

Lesson from all this: When you specify a file for regsvr32 to register, be explicit and use a fully qualified path.


By the way, I ran into a similar problem using Java, which should have tipped me off to this sooner, but the art of computer programming would appear to be defined by the act of figuring out why something you’ve done right still doesn’t work.

Posted in Argh! | Leave a comment

VMR9 Property Pages

Before I retire from computer programming (something my accountant tells me I can do in the grave), I hope to find my last reason to complain about graphedt.exe (aka GraphEdit). For now, I will continue to grouse.

Today’s gripe is that it shows a perfectly good property page for the Video Mixing Renderer 9 (aka VMR9). Why is that a problem? Well, here’s that page:

Seems fine, eh? Well, it is fine. It’s just not what you want. You want this:

Man, that’s cool! When you have a couple of video sources streaming into the inputs on the VMR9, you can use that second page, above, to do all kinds of neat things like squash and stretch the output rectangles independently, fade them in and out with full transparency, and a few other tricks.

So how come you don’t get what you want? Because (in the particular case that has me hammering away at my keyboard today, eyes wide and lips pulled back from my clenched teeth in a demon’s rictus) it is easy to forget that, months ago, when you first started using graphedt.exe on your Windows 7 development computer, you registered proppage.dll and evrprop.dll, without which you get only the first property page above, and not the second. So, when you move your filter to your Windows XP testing machine, and ask for the property page, because you never registered those .dll files on the XP machine, you get only the first property page above, and not the second.

Now, the inestimable authors of the MSDN page on graphedt.exe knew you would do this, so they have left you this note therein:

Before running GraphEdit, use the regsvr32 utility to register the following DLLs, which are located in the same directory:

  • proppage.dll
  • evrprop.dll

These DLLs enable GraphEdit to display property pages for some of the built-in DirectShow filters.

I think that’s misleading on two levels. First, because the VMR9 displays a property page without those .dll files having been registered, it would be easy to assume they are registered when, in fact, they are not. Second, it suggests that those .dll files make the superior property page available for graphedt.exe’s benefit. In fact, those property pages show up for any program that asks the VMR9 to display its property page.

Now, if you have graphedt, then you (most likely) have the Windows SDK, which means you have those .dll files. They’re in the same directory where you found graphedt.exe, just as the MSDN page says they are. Register them and you’re all set. But don’t forget to do it on every machine where you are going to use graphedt.exe (or, if you’re like me, on every machine where you’re going to use the often superior GraphEditPlus, which is what I was doing when I encountered this problem, and my public apologies to Infognition for even suggesting this might a problem in their product, not mine).

Why these .dll files come with the SDK, requiring manual installation, rather than being installed with Windows itself (like the VMR9 is) is one of those mysteries we Windows programmers must learn to live with, I suppose. But, if you have had that problem, maybe you’ll find this page, and feel just a little better by knowing you’re not the only one it has driven mad.

Posted in Argh!, GraphEdit | 1 Comment

Error Code 0×80070005

Odds are pretty good that, if you are developing a DirectShow filter, you will want to register your filter so graphedt.exe¹ can “see” it. That is, you will want it to show up on the list of filters graphedt.exe offers when you pick “Insert Filters…” from the “Graph” menu. (You can add filters to a DirectShow graph without registering them, which can be useful if you want to keep your filter contained within your application, and not available to others; see Geraint Davies’s explanation on how this can be done.)

A simple way to do this is to open a command window, “cd” your way to the directory containing your filter’s .dll file, and use this command:

regsvr32 myfilter.dll

When you do, you might see this:

That’s what I got, the first time I used that command. The advice is the kind of thing that gives DirectShow some of its notoriety: search online it says. Might as well say, here there be dragons, eh? Anyway, the solution (in my case) was to right-click on the “Command Prompt” application under “Accessories” in the Start menu (or whatever it’s called now on Windows 7, which only shows you the funny waving-flag Windows logo, so maybe it doesn’t have a name anymore), and choose “Run as administrator” to start it up. Then that regsvr32 command worked fine.

But what about searching online? Well, the first (non-paid) hit on Google took me to a page in Microsoft’s Knowledge Base. It wasn’t about installing .dll files. It was about updating your operating system. Nice to imagine that installing your own code and updating your system might, in some way, be the same thing, but it doesn’t immediately suggest this is really related to the problem I’m talking about here. Regardless, it does, sort of, offer the same solution: it says, “Log in as an administrator.”

Now, one of the things I really have grown to dislike about Windows 7 is the frequency with which it decides I don’t have rights to my own computer. For example, if I click on “Documents and Settings” under the “C:” drive in the directory tree in Windows Explorer, I get this:

Dear God, how emphatic do they have to be? “Location is not available,” it says. My (my!) directory “is not accessible” it says. “Access is denied,” it says. Okay, I get it. Seems like there are a lot of things you can’t do without being an administrator on Windows 7 (the whole point of this post, btw, doesn’t arise in XP, which happily installs my filter .dll files like the obedient little robot it’s supposed to be, no matter who I’m logged in as).

But, Microsoft’s Knowledge Base overstates the situation, imho. You don’t have to “log in” as anything, if you can run Command Prompt as an administrator. Wish they’d just say so, but they don’t. I found the solution when I first needed it by Googling a bit farther, but it still took longer than it should. So, this post is an effort to help the next guy. Just run Command Prompt as an adminstrator and regsvr32 will do your bidding (until some other problem comes along).

Just to be more expansive (and to avoid going back to work on my latest annoying filter bug), I will mention the err.exe program that is part of the v7.1 Windows SDK. From time to time, when I am feeling adventurous, I run one of the .exe files that is in the SDK bin directory. If they’re all documented somewhere, someone please tell me. Until then, it will continue to be a thrilling little moment when I run another one for the first time and find out what it does. err.exe (when run without arguments) tells you it does this:

All values on the command line will be looked up in our internal
tables and presented to you. If available, informational data
associated with the value(s) will also be shown (see below).
All tables are searched by default, but you can restrict the
output to those tables you deem appropriate by adding
"/<tablename>" to the beginning of the commandline

If you’re one of those people who has laboriously compiled a spreadsheet or other centralized list of all those HRESULT error codes, this might be appealing. For 0×80070005, you get this:

COR_E_UNAUTHORIZEDACCESS corerror.h
# Access is denied.
DIERR_OTHERAPPHASPRIO dinput.h
DIERR_READONLY dinput.h
DIERR_HANDLEEXISTS dinput.h
DSERR_ACCESSDENIED dsound.h
ecAccessDenied ec.h
ecPropSecurityViolation ec.h
MAPI_E_NO_ACCESS mapicode.h
STIERR_READONLY stierr.h
STIERR_NOTINITIALIZED stierr.h
E_ACCESSDENIED winerror.h
# General access denied error
# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x5
# for hex 0x5 / decimal 5 ERROR_ACCESS_DENIED winerror.h
# Access is denied.

There it is again, “Access is denied.” Funny, how often the errors you get from Microsoft’s products add up to one form or another of that phrase, but that’s life in the fast lane, I guess. Anyway, that’s my rant on the fact that you can’t run regsvr32 on Windows 7 the way you did on XP, and what it takes (or took me) to figure out how to get it to work. Maybe that will help someone else, somewhere. Drop me a line, if that’s you.

¹If, like me, you are over 50 and have been programming since computers ran on coal, you will remember a time when “8.3″ was an informal standard for file names (as opposed to the unemployment rate in a lot of Virginia since “Bob’s for Jobs” McDonnell got elected governor, but this isn’t a political blog anymore). Of course, those days were over long before DirectShow arrived, so one has to wonder why Microsoft gave a broken keyboard to the person who wrote graphedt.exe. I mean, Microsoft itself calls this thing “GraphEdit” (camel-case and missing “i” included) on their Web site. Yet, that very same site says, without apology or explanation, that, “The name of the GraphEdit application is ‘graphedt.exe’.” Which means that, whenever you Google for it, you have to Google for it twice, as half of us appear to call it GraphEdit most of the time, while the other half of us call it graphedt most of the time. Even if one uses the immensely superior GraphEditPlus,
there is no way out of Googling for GraphEdit/graphedt if you are going to do DirectShow work, as everyone uses it (and, when discussing what they are doing, everyone makes mention of it). You just have to get used to it.

Posted in Argh! | 3 Comments

Storing an IMediaSample Pointer

A question came up in the MS DirectShow forum that, in one form or another, I’ve seen a lot. I had to cope with it myself to write a filter recently, so I’m copying my answer here. The full discussion is on the forum.

The question is, essentially, “When my filter method is called with an IMediaSample pointer, can I store the pointer for later use?”

Because a media sample is a COM object (http://msdn.microsoft.com/en-us/library/windows/desktop/dd407001(v=vs.85).aspx), you can call IMediaSample’s AddRef method to stop your sample’s buffer from being deallocated by the upstream allocator (if, as Roman Ryltsov points out, you can trust the upstream allocator to respect the COM rules; I’ve never had a problem with that, but I can easily see how you might, so be wary of this possibility if you hold a reference to a buffer and it seems to change or cause exceptions when you access it). You do this by simply calling pSample->AddRef() before returning to the caller that passed you the IMediaSample pointer. Later, when you’re done with the sample, call pSample->Release() to return the sample to the buffer pool. (Note that failure to release the sample before your program exits can actually cause errors at exit time, so be sure to release it at some point before exiting, even if you never used it and don’t care if it returns to the buffer pool or not.)

Tim Roberts has a good point: if you AddRef all the buffers in a pool, your graph will probably lock up because you will end up waiting for new samples you never get (since they come from that limited buffer pool). Now, that would be okay if you can be sure of a couple of things. First, that you will eventually get around to releasing one or more buffers. If you do that before returning, you don’t need to AddRef a sample, because the caller has done that for you, and will be blocked or otherwise waiting for your code to return, before calling Release. Buf, if you AddRef and return, the caller won’t have the buffer you added the reference to in its buffer pool anymore. If the caller runs out of buffers (and, there may only be just one in the pool), it will block until you release one. If, after returning, your code waits until the caller calls it again with another sample, your code will also block, in a classic deadlock, with your code waiting for a sample from the caller, and the caller waiting for your code to release a buffer back into the pool. To avoid that, either the caller and your code would have to run in separate threads. In that case, even if the caller blocks while waiting for a buffer to return to the (empty) pool, your code will not be blocked and, one hopes, will eventually free a buffer so the caller (in its separate thread) can have it and unblock.

The other thing you might have to be sure of (at least) is that your code may not mind missing a sample. For example, if your caller is a capture filter (that is, a camera), and your code uses up all the buffers available to the capture filter for longer than the interval between captures, you’re going to miss whatever samples the capture filter would have sent you. That is, a camera can’t pause what it sees or rewind back into time. Now, if you don’t mind that, then a multi-threaded graph that simply processes frames as fast as it can, missing the ones it can’t keep up with, might still meet your needs. It may use up all the buffers from time to time, but as long as at least one thread is guaranteed not to block before it releases a buffer, your graph won’t lock up. (This sounds kind of complicated, but I’ve actually done it and, as it turned out, it required rather little code to be added to my graph to make it work. However, multi-threaded programming is hard to explain–well, it was to me, anyway, years ago–so don’t be put off if my description here seems a bit opaque.)

Anyway, that’s how it looks to me. Others should chime in, if they see mistakes or omissions.

Posted in COM, DirectShow Filters, Media Samples | Leave a comment

Adventures with DirectShow

Welcome to Without Supervision MkII! I invite anyone and everyone with an interest in video and/or graphics programming to come here and discuss what they know (or what they wish they knew). Lately, I’m deep into some DirectShow programming and will be posting about that over the days ahead. Once I figure out how to do it, I’ll have some source and/or DLL files, etc., to make available. Meanwhile, make a link and check back here from time to time. I work alone and could use the company of others fighting with the sorts of issues that DirectShow creates. That’s one of the prices a person has to pay, if they are going to work Without Supervision.

Posted in Administrivia | Leave a comment