1

In order to render a DirectShow graph in my WPF application, I use a sample grabber to write a bitmap to memory, and read it elsewhere in code. This may seem as a wierd solution, but seems to be the only way to get a WPF brush out of it.

The following code gives me the information I need about the bitmap:

AMMediaType mt = grabber.GetConnectedMediaType();
VideoInfoHeader header = (VideoInfoHeader)Marshal.PtrToStructure(mt.formatPtr, typeof VideoInfoHeader);
header.BmiHeader // ...

Now, header.BmiHeader is of type BitmapInfoHeader and provides information such as the width and height of the bitmap. I need this information to write the bitmap to memory.

However, this code does not seem to work always. For example, when the sample grabber filter is connected to a MPEG-2 Program Stream pin, header will be null. Why does my code not work with certain media types, and what other ways are there to get it's BitmapInfoHeader structure?

Please note that even though I am using the directshow.net library, answers in C++ are also welcome.

Edit: This is how my graph looks like:

*source* -> MPEG2-Demultiplexer -> SampleGrabber -> MS DTV-DVD Video Decoder -> Video Renderer

I'm not allowed to place the grabber between the decoder and renderer. About the demux's video pin:

Major Type: Video

Sub Type: MPEG2_VIDEO
Format: MPEG2Video

After I have connected the sample grabber, it's input pin also has the above media type. When I open this graph file in my application and use grabber.GetConnectedMediaType();, I also get the same media type. However, the formatPtr or (pbFormat in C++) of this media type is 0.

Rudey
  • 4,717
  • 4
  • 42
  • 84
  • 1
    For mpeg, is your sample grabber placed after the decoder. One reason I can think of is that the grabber is placed before the decoder in which case, you would not get the bitmap header. – Saibal Jan 03 '13 at 17:55
  • @Saibal: My sample grabber is placed after a demux, which is placed after the decoder. – Rudey Jan 04 '13 at 09:13
  • What are the full media type and video info headers that you have? Even if you have null header, you still have media type fields, including format type. – Roman R. Jan 04 '13 at 09:39
  • @RuudLenders the order should be demux->decoder->samplegrabber. – wimh Jan 04 '13 at 09:39
  • @Wimmel: I probably found the cause of my problem: I can't seem to connect the decoder to the sample grabber directly. Not in GraphEdit, not in code. What should I do? Would TransNull24 help here? – Rudey Jan 04 '13 at 10:02
  • Hard to say without more information. Check in GraphEdit the media types of the output pin of the decoder. Otherwise show the whole graph. – wimh Jan 04 '13 at 10:19
  • @Wimmel: I've added more information to my post. – Rudey Jan 04 '13 at 10:32
  • @RuudLenders: Sample grabber needs `VIDEOINFOHEADER` while MPEG-2 often uses `VIDEOINFOHEADER2` (or even `MPEG2VIDEOINFO`), hence inability to connect. You can insert decoder as suggested: this is easiest because you already have the component handy, however the cleanest would be a custom filter, or custom sample grabber that accepts `VIDEOINFOHEADER2` just for the purpose to succeeed with connection and being able to query resolution from media type. – Roman R. Jan 04 '13 at 10:33
  • @RomanR.: I don't understand, which decoder should I insert then? – Rudey Jan 04 '13 at 10:51
  • @RuudLenders: Any decoder that would accept this `MPEGVIDEOINFO2` and decoder into something else, typically formatted as `VIDEOINFOHEADER` so that you could connect there with sample grabber. An alternate option is to connect demultiplexer output to Null Renderer and query `MPEGVIDEOINFO2` member to find out resolution. – Roman R. Jan 04 '13 at 11:11
  • One additional note, if you not only want the resolution, but also the bitmap itself, you have to put the samplegrabber between the decoder and renderer. If the MS Decoder is not working, try [ffdshow](http://ffdshow-tryout.sourceforge.net/) – wimh Jan 04 '13 at 11:37

1 Answers1

0

If you want a bitmap, you need to place the sample grabber somewhere where you receive uncompressed video. When the samplegrabber is behind the MPEG-2 Program Stream pin, you will receive a mpeg2 program stream. Of course it it possible to get a bitmap out of that, but then you need to demultiplex and decompress manually. Both are task which you want to perform in the directshow filter.

But even if you receive uncompressed video, you might still get different formats. depending on the decoder you can receive RGB24, YUY2, YV12, ... Check the MediaSubType for what you exactly receive. If you always want to receive RGB24, you can use the RGBFilters/TransNull24 filter which is included in the sdk. See also this answer.

Edit: One additional note, if you not only want the resolution, but also the bitmap itself, you have to put the samplegrabber between the decoder and renderer. If the MS Decoder is not working, try ffdshow.

Community
  • 1
  • 1
wimh
  • 15,072
  • 6
  • 47
  • 98
  • Where can I find these RGBFilters? I have installed the SDK but I can't seem to find them. – Rudey Jan 04 '13 at 09:14
  • I am currently not able to look myself, but it is included in the directx 9 sdk. In newer versions, most of directshow has been moved to the windows sdk, but some samples have been removed. So if you have access to the DX9SDK, I'm sure you will find it there, otherwise search for example for `TransNull24.cpp` on your harddisk. – wimh Jan 04 '13 at 09:38
  • Are your sure they are in that SDK? I've installed Direct X SDK (10 Jun) and the latest Windows SDK, but I haven't found any DirectShow samples. Searching for `TransNull24.cpp` or even `TransNull` gives me no results either. – Rudey Jan 07 '13 at 09:46
  • @RuudLenders I did a quick check, it is included in the DirectX 9.0c SDK. At April 2005 Directshow was moved to the platform sdk (now called windows sdk). I see the sample is included in the Windows Server 2003 R2 SDK (March 2006), but not in the vista/6.0 (October 2006) any more. So you have to try an older sdk. [Wikipedia](http://en.wikipedia.org/wiki/Microsoft_Windows_SDK) has download links. – wimh Jan 07 '13 at 10:59
  • Thanks, I now have the RGB filters. I'm sorry to ask, but do you have any tips for me registering these .cpp files as DirectShow filters, so I can use them in GraphEdit? – Rudey Jan 07 '13 at 12:29
  • After compiling you should get a RGBFilters.dll, then execute `regsvr32 RGBFilters.dll` in an elevated console window. – wimh Jan 07 '13 at 12:43
  • There are no `.sln` or `.csproj` files. Building `Makefile` does not seem to work. Would you suggest opening each `.cpp` file seperately? – Rudey Jan 07 '13 at 12:45
  • Try the .dsp / .dsw files. Those are visual c 6 project files. It should be possible to import this into newer versions of visual studio. – wimh Jan 07 '13 at 12:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22316/discussion-between-ruud-lenders-and-wimmel) – Rudey Jan 07 '13 at 12:51