Mjpeg decompression to SampleGrabberCB

Steve
2012-05-18
2012-10-29
  • Steve

    Steve - 2012-05-18

    Hi,

    I'm trying to get images from my Microsoft Lifecam Studio into Emgu. I have a
    system that works with the 640x480 format, but when I try to change to a
    1280x720 (or any other size) format I am given the following error:
    "An invalid media type was specified."

    My graph looks like:
    Capture filter -> MJpegDec -> SampleGrabberCB

    I create the capture filter like this:

    IBaseFilter capFilter;
    int hr = _filterGraph.AddSourceFilterForMoniker(device.Mon, null, device.Name, out capFilter);
    DsError.ThrowExceptionForHR(hr);
    IPin capOutPin = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0);
    

    Here's how I create the sample grabber:

    var sampleGrabber = new SampleGrabber() as ISampleGrabber;
    if (sampleGrabber == null) throw new NullReferenceException("Unable to create sample grabber");
    // set the media type that the SampleGrabber will hold
    var mediaType = new AMMediaType
    {
        majorType = MediaType.Video,
        subType = MediaSubType.RGB24,
        formatType = FormatType.VideoInfo
    };
    sampleGrabber.SetMediaType(mediaType);
    
    sampleGrabber.SetOneShot(false);
    sampleGrabber.SetBufferSamples(false);
    

    Here's how I'm creating the MJpegDecompressor and gluing them together:

    //Need to add an mjpeg decompressor
    IBaseFilter pMjpgDecompressor = (IBaseFilter) new MjpegDec();
    hr = filterGraph.AddFilter(pMjpgDecompressor,"Mjpeg Decompressor");
    DsError.ThrowExceptionForHR(hr);
    IPin inPin =DsFindPin.ByName(pMjpgDecompressor, "XForm In");
    IPin outPin = DsFindPin.ByName(pMjpgDecompressor, "XForm Out");
    hr = filterGraph.Connect(captureOutPin, inPin);
    DsError.ThrowExceptionForHR(hr);
    hr = filterGraph.Connect(outPin, sampleInPin);
    DsError.ThrowExceptionForHR(hr);
    

    My graph is
    SourceFilter -> MJpegDec->SampleGrabberCB

    I have set the sample grabber to:
    majorType = MediaType.Video,
    subType = MediaSubType.RGB24,
    formatType = FormatType.VideoInfo

    I tried to set up a graph like mine in GraphStudioPlus, but am told that "No
    combination of intermediate filters could be found to make the connection."

    I've been trying to get this to work for three days now, and am completely
    lost.
    Regards,
    Steve

     
  • Steve

    Steve - 2012-05-18

    I just realised that I should add that I am setting the format with

                        int iC, iS;
                        _videoStreamConfig.GetNumberOfCapabilities(out iC, out iS);
                        IntPtr ssc = Marshal.AllocCoTaskMem(iS);
                        _videoStreamConfig.GetStreamCaps(capability.StreamID, out media, ssc);
                        hr = _videoStreamConfig.SetFormat(media);
                        DsError.ThrowExceptionForHR(hr);
    

    If I've missed anything else I'd be happy to provide it.
    Thanks for reading this far,
    Steve

     
  • snarfle

    snarfle - 2012-05-18

    I'm not clear on what capability.StreamID would be in this context.

    When you want to call GetStreamCaps, the first parameter can be anywhere from
    zero to iC. For example, you could walk thru the entire list with a for/next
    loop. Each time you call it, you will get back a different AMMediaType, and a
    different VIDEO_STREAM_CONFIG_CAPS (in ssc). Typically you would find one you
    like, possibly modify it (see the discussion here), then call
    SetFormat.

    You can see an example of modifying the media type in
    Samples\Capture\DxLogo\Capture.cs. Note that instead of walking the capability
    entries, it just takes whatever the current media type is and tries to force
    it to the new settings.

     
  • Steve

    Steve - 2012-05-19

    Hi Snarfle,
    Thanks for the tip.
    I did try the method from DxLogo, but it wasn't working either. I found the
    method I'm describing elsewhere, so I thought I should give it a go - the
    effect seems to be identical.

    I'm getting a collection of capabilities from the camera with the code below.
    Essentially, I'm doing what you suggested - this method gets all capabilities
    that fall into formats I would like to handle (I know it could be cleaner than
    how I wrote it, but I'll worry about that after I've gotten it to work). The
    user selects a capability and then the capability is set using the code in my
    second post.

    I've stepped through with a debugger, and it appears that my code is correctly
    picking the format I desire.

    for (int i = 0; i < capCount; ++i)
    {
        // the video format is described in AMMediaType and VideoStreamConfigCaps
        hr = _videoStreamConfig.GetStreamCaps(i, out mt, streamCaps);
        DsError.ThrowExceptionForHR(hr);
    
        // copy the unmanaged structures to managed in order to check the format
        Marshal.PtrToStructure(mt.formatPtr, vih);
        Marshal.PtrToStructure(streamCaps, vsc);
    
        if (mt.subType == MediaSubType.RGB24)
        {
            var maxFramRate = (int)(TimeSpan.TicksPerSecond / vsc.MinFrameInterval);
            var capability = new Capability(mt.subType, maxFramRate, vih.BmiHeader.Width,
                                        vih.BmiHeader.Height, vih.BmiHeader.BitCount,i, CameraFrameFormat.RGB24);
            ret.Add(capability);
        } 
        else if (mt.subType == MediaSubType.YUY2)
        {
            var maxFramRate = (int)(TimeSpan.TicksPerSecond / vsc.MinFrameInterval);
            var capability = new Capability(mt.subType, maxFramRate, vih.BmiHeader.Width,
                                                       vih.BmiHeader.Height, vih.BmiHeader.BitCount,i, CameraFrameFormat.YUY2);
            ret.Add(capability);
        }
        else if (mt.subType == MediaSubType.MJPG)
        {
            var maxFramRate = (int)(TimeSpan.TicksPerSecond / vsc.MinFrameInterval);
            var capability = new Capability(mt.subType, maxFramRate, vih.BmiHeader.Width,
                                                 vih.BmiHeader.Height, vih.BmiHeader.BitCount, i, CameraFrameFormat.MJPG);
            ret.Add(capability);
        }
    }
    

    Using this format system, I can successfully change formats with an RGB24
    capture source. It only fails when I need to go to an MJpeg format that is not
    640x480.

    Regards,
    Steve

     
  • Steve

    Steve - 2012-05-19

    To be clear, when I want to use the YUY2 or RGB24 feeds (both of which are
    working), I don't connect the MJpegDec.
    Also, if I set the samplegrabber media format to MJPG instead of RGB24 and
    don't connect the MJpegDec, then the system also works (although I can't
    actually do anything with the compressed MJPG data).

    Regards,
    Steve

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks