locked
Extract all the Frames from a Video- without missing any frame RRS feed

  • Question

  • I am developing a utility which can extract all the frames from a video file that can be played using direct show.

    IMediaDet::GetBitmapBits() method takes first argument time in seconds which implies I will miss the remaining 24 frames per second.

    Is there any method like IMediaDet::GetBitmapBits() which takes the time in REFERENCE_TIME such that I don't miss any frame.
    Wednesday, March 17, 2010 6:44 AM

Answers

  • Using IMediaDet will be inefficient.

    Use the Dump filter sample in the Windows SDK as a starting point.

    Then build a graph.  Source [ -> Demux -> Decoder ] -> Dump.

    Add a custom interface to Dump if you need to specify the name of the output file, format, etc.  The EzRGB24 sample has an example of a custom interface and so does the SDK docs.

    You can also use the Sample Grabber but, IMO, the Dump method is more elegant.

    Source [ -> Demux -> Decoder ] -> Sample Grabber -> Null Renderer.

    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Proposed as answer by micha137 Wednesday, March 17, 2010 8:35 AM
    • Marked as answer by The March Hare Thursday, March 18, 2010 5:54 PM
    Wednesday, March 17, 2010 7:45 AM
  • The file written by the dump filter does no contain garbage, it contains the raw bitmap data for all the frames of the video in the connection format you specified (between the decoder and dump) : if you specified MEDIASUBTYPE_RGB32, then you get the pixels in RGB32 format.
    If you want bitmaps, you need to package each frame pixels into a bitmap by adding the correct bitmap header.
    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Thursday, March 18, 2010 5:32 AM
    Wednesday, March 17, 2010 12:59 PM
  • You would get the mediatype only on the first sample. And none afterwards.

    To get the mediatype, use the input pin's ConnectionMediatype.

    Each sample contains exactly one frame (one bitmap).

    You could also post-process offline the dump file (extract each bitmaps's data and put it in a bitmap file).


    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Monday, March 22, 2010 7:32 AM
    Friday, March 19, 2010 10:46 AM
  • In the sample, you get only the bitmap bits, not the headers.

    So the

    pSample->GetPointer(&pbBmpData);

    gives you pbBmpData as a pointer to the pixels.

    Using GDI+, I use the bitmap constructor that takes a pointer to the pixels array, passing pbBmpData.


    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Monday, March 22, 2010 7:31 AM
    Sunday, March 21, 2010 4:22 PM
  • bmi.bmiHeader.biCompression = 844715353  is hex 0x32595559 which is YUY2.  See http://fourcc.org for a description of the different YUV and RGB types.

    You can convert the YUY2 to RGB yourself.  Here is some info:

    http://www.fourcc.org/fccyvrgb.php

    More can be found by googling or binging.


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Marked as answer by subhanshoo Monday, March 22, 2010 7:32 AM
    Monday, March 22, 2010 7:07 AM
  • Modify CDumpInputPin

    CheckMediaType() 

    return S_FALSE except if Mediatype is RGB in which case return S_OK

    This way the filer will accept to connect only with RGB.


    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Monday, March 22, 2010 9:18 AM
    Monday, March 22, 2010 8:09 AM
  • Below is the info from "Top-Down vs. Bottom-Up DIBs" in the SDK docs.  See if it is useful for solving your issue.  It's always possible for a decoder to ignore this (in which case I would say the decoder has a bug):

    For RGB DIBs, the image orientation is indicated by the biHeight member of the BITMAPINFOHEADER structure. If biHeight is positive, the image is bottom-up. If biHeight is negative, the image is top-down.

    DIBs in YUV formats are always top-down, and the sign of the biHeight member is ignored. Decoders should offer YUV formats with positive biHeight, but they should also accept YUV formats with negative biHeight and ignore the sign.

    Also, any DIB type that uses a FOURCC in the biCompression member, should express its biHeight as a positive number no matter what its orientation is, since the FOURCC itself identifies a compression scheme whose image orientation should be understood by any compatible filter.



    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Marked as answer by subhanshoo Monday, March 22, 2010 2:47 PM
    Monday, March 22, 2010 12:52 PM
  • Okay, this is odd because it has not come up much.  I use the STL in my filters.  However, all of my custom filters are compiled into my executable.  This is simpler in terms of installing an app because there is no registration needed.  The only reason I can see to not do this is if you have a filter shared between apps or you expect other apps to use the filter.

    So, my recommendation is to compile the filter into your app if that is possible.  See Geraint's AppFilter sample on his download page here:

    http://www.gdcl.co.uk/downloads.htm

    You can probably even use MFC containers this way :)


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Marked as answer by subhanshoo Wednesday, March 24, 2010 4:49 AM
    Tuesday, March 23, 2010 2:08 PM

All replies

  • Using IMediaDet will be inefficient.

    Use the Dump filter sample in the Windows SDK as a starting point.

    Then build a graph.  Source [ -> Demux -> Decoder ] -> Dump.

    Add a custom interface to Dump if you need to specify the name of the output file, format, etc.  The EzRGB24 sample has an example of a custom interface and so does the SDK docs.

    You can also use the Sample Grabber but, IMO, the Dump method is more elegant.

    Source [ -> Demux -> Decoder ] -> Sample Grabber -> Null Renderer.

    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Proposed as answer by micha137 Wednesday, March 17, 2010 8:35 AM
    • Marked as answer by The March Hare Thursday, March 18, 2010 5:54 PM
    Wednesday, March 17, 2010 7:45 AM
  • I tried using your solution but the file generated by the Dump Filter is garbage.

    I didn't understand what you meant by the custom interface,

    I am new to Direct Show, all I want is to extract all the frames from the video in a CList without rendering.

    Also let me know that where should the FrameList be places, 

    I guess the Dump Filter which I need to querry for the pointer for the Frame List.

    Anyways I felt good to see a quick response on the forum, thanx a lot.
    Wednesday, March 17, 2010 11:41 AM
  • The file written by the dump filter does no contain garbage, it contains the raw bitmap data for all the frames of the video in the connection format you specified (between the decoder and dump) : if you specified MEDIASUBTYPE_RGB32, then you get the pixels in RGB32 format.
    If you want bitmaps, you need to package each frame pixels into a bitmap by adding the correct bitmap header.
    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Thursday, March 18, 2010 5:32 AM
    Wednesday, March 17, 2010 12:59 PM
  • 1.  You have the source code to the Dump filter.  Look at it and understand what it does.  As Michel pointed out, it is the raw data.  You need to understand what is in the media sample before modify Dump to you put that data you need in your CList.

    2.  You have the documentation for DirectShow on MSDN.  It covers what a custom interface is, what media types are, how filters negotiate their connections, etc.

    3.  Dshow isn't trivial to use.  Look at my site (Help, FAQs, Links).  There are a lot of resources available to you and your question is not new.  Search the forums and the newsgroups for more information.

    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Wednesday, March 17, 2010 1:51 PM

  • Your DShow Tutorials really helped me a lot on

    http://tmhare.mvps.org

    As you mentioned that my Question is not new, 

    can you provide some links where they have reference implementation.

    Currently I am trying to Modify the Dump Filter, 
    trying to add a std::list<Frames>, also a custom interface to access the list.
    the idea is to Play the video using Dump filter instead of renderer and Wait for the Video to complete using WaitForSingleObject() method, 
    then using the Custom Interface access the Populated Frame List for further processing.
    I guess turning the internal clock will also speedup the process.

    Some how I am getting error when I try to make the std::list<> member in the CDump Class, what is the issue.

    Thanx a lot to again "The March Hare" & "Michel Roujansky"<abbr class="affil" style="font-weight: inherit; font-style: inherit; font-family: inherit; outline-width: 0px; outline-style: initial; outline-color: initial; vertical-align: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">.</abbr>
    Thursday, March 18, 2010 5:12 PM
  • I don't know of a sample that implements exactly what you want.  However, there is enough information in this thread and the docs to get this done.  See the three points above.

    "Some how I am getting error when I try to make the std::list<> member in the CDump Class, what is the issue."  That's hard to answer without knowing what problem you're are having.  Look at what I wrote above again.  You need to understand what the media samples the Dump filter receives consist of in order to work with the data.  It's not hard but you have to do some reading.

    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Thursday, March 18, 2010 5:54 PM
  • I am trying to Extract the Bitmap Headers from the Video itself in 

    CDumpInputPin::Receive(IMediaSample *pSample)

     

    but unable to get the AM_MEDIA_TYPE, the following code always returns null in pMediaType;

    AM_MEDIA_TYPE* pMediaType;

     

    pSample->GetMediaType(&pMediaType);

     

    The MSDN Docs says null is returned when AM_MEDIA_TYPE is unchanged however in my case its always NULL.

    I am trying the following

     

     

    if (pMediaType)// If MediaType has not changed since last sample then it is NULL.

    {

    if ((pMediaType->formattype == FORMAT_VideoInfo) && 

    (pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER)))

    {

    VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pMediaType->pbFormat);

    BITMAPINFOHEADER bmih;

    ZeroMemory(&bmih, sizeof(BITMAPINFOHEADER));

    if (pVih)

    {

    lVideoWidth = pVih->bmiHeader.biWidth;

    lVideoHeight = pVih->bmiHeader.biHeight;

    if (lVideoHeight < 0) 

    lVideoHeight *= -1;


    bmih= pVih->bmiHeader;

    m_pDump->ComposeFrameBitmap(pbData, pSample->GetActualDataLength(), bmih);

    //I doubt  that pbData will contain data for more than 1 frame.

    }

    }

     

    }

     

    Also please let me know know the precise readings I need to undergo to get this work ASAP,  I need to meet the deadline.

     

    Thanx.

    Friday, March 19, 2010 7:26 AM
  • I am always getting pMediaType as NULL and HRESULT value S_FALSE

     

    AM_MEDIA_TYPE* pMediaType;

    pSample->GetMediaType(&pMediaType);

     

    I tried to debug with multiple videos mpg, wmv, avi, vob but the method always failed

    i.e. it detected no change in the media type.

     

    Is there any other way to fetch the MEDIA_TYPE also I figured out that the  MediaSample contains whole video,

    Which means I will require some way to extract the Frames from the MediaSample again.

    I have extracted one Frame from MediaSample using IMediaDet now what about the other frames.

     

    Friday, March 19, 2010 10:31 AM
  • You would get the mediatype only on the first sample. And none afterwards.

    To get the mediatype, use the input pin's ConnectionMediatype.

    Each sample contains exactly one frame (one bitmap).

    You could also post-process offline the dump file (extract each bitmaps's data and put it in a bitmap file).


    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Monday, March 22, 2010 7:32 AM
    Friday, March 19, 2010 10:46 AM
  • I was not at all getting the MEDIA_TYPE earlier, I did felt the same.


    Now I am able to get the MEDIA_TYPE using ConnectionMediaType().

    I wander the method  CDumpInputPin::Receive() is being called only once when I Play or on Play\Pause.


    I suppose it must be called continuously for Each Frame as you said "Each sample contains exactly one frame".


    Also the MEDIA_TYPE is not equal FORMAT_VideoInfo.


    Some header values seems correct but some not.

    I got VIDEOINFOHEADER->BITMAPINFOHEADER.biHeight == 22000 which does not makes sense.

    Friday, March 19, 2010 12:08 PM
  • If the data is encoded you need to have the decoder in your graph (see my first post).

    What are the media type and subtype?


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Friday, March 19, 2010 1:35 PM
  • Thanx,

     

    I figured out, I am not building the graph programatically instead using graph builder which is  using ffdshow video decoder.

     

    The media formattype is FORMAT_VideoInfo2 instead of earlier assumed FORMAT_VideoInfo this the video header now is also 

    VIDEOINFOHEADER2 instead of assumed VIDEOINFOHEADER due to which I was getting garbage values in BITMAPINFOHEADER.

     

    Now I am successfully decoding the HEADERS but the issue remains of the Raw Bitmap Data, I am assuming the Raw Bitmap Data to immediately follow the  AM_MEDIA_TYPE + VIDEOINFOHEADER but I am getting Black Bitmaps.

     

     

     

     

    AM_MEDIA_TYPE MediaType;

    hr= ConnectionMediaType(&MediaType);


     

    if ((MediaType.formattype == FORMAT_VideoInfo2) &&

    (MediaType.cbFormat >= sizeof(VIDEOINFOHEADER2)))

    {

    VIDEOINFOHEADER2* pVih = (VIDEOINFOHEADER2*)(MediaType.pbFormat);

    if (pVih)

    {


    lVideoWidth = pVih->bmiHeader.biWidth;

    lVideoHeight= pVih->bmiHeader.biHeight;

    if (lVideoHeight < 0) 

    lVideoHeight *= -1;


     

    BITMAPINFOHEADER bmih;

    ZeroMemory(&bmih, sizeof(BITMAPINFOHEADER));

     

    bmih= pVih->bmiHeader;


    long lSampleLength= pSample->GetActualDataLength();

    HRESULT hr2 = pSample->GetPointer(&pbBmpData);


    int nSizeVIH= sizeof(VIDEOINFOHEADER2);

    int nSizeBIH= sizeof(BITMAPINFOHEADER);

    //int nSizeFormat= MediaType.cbFormat;

    int nSizeMT= sizeof(AM_MEDIA_TYPE);


    int nRawBmpDataIndex= nSizeMT + nSizeVIH;// - nSizeBIH ;


    PBYTE pBmpData= (PBYTE)pbBmpData[nRawBmpDataIndex];

    m_pDump->WriteBitmapData2File(pBmpData, lSampleLength, bmih);


    }

    }

     

     

     

    Please let me know the exact position of the Bitmap Data.

     

    I am using the following code to generate a Bitmap using GDI+

     

     

    HBITMAP hBitmap = CreateDIBitmap (GetDC(NULL), &bmih, CBM_INIT, (void*)pbBmpData, &bmi, DIB_RGB_COLORS);


    //Create a GDI+ Bitmap and Assign as a Current Frame

    HPALETTE hPalette = (HPALETTE)/*GetCurrentObject(, OBJ_PAL);*/GetStockObject(DEFAULT_PALETTE); 


    Bitmap* pCurrentFrame= new Bitmap (hBitmap, hPalette); 

    //

     

    What is the Structure of Media Sample Buffer, Or it directly points to the Raw Frame Bitmap Data ??

    • Edited by subhanshoo Sunday, March 21, 2010 5:00 PM Addition
    Sunday, March 21, 2010 9:41 AM
  • In the sample, you get only the bitmap bits, not the headers.

    So the

    pSample->GetPointer(&pbBmpData);

    gives you pbBmpData as a pointer to the pixels.

    Using GDI+, I use the bitmap constructor that takes a pointer to the pixels array, passing pbBmpData.


    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Monday, March 22, 2010 7:31 AM
    Sunday, March 21, 2010 4:22 PM
  • Thanx a lot for earlier replies especially Michel for his last post,

     

    Now I have managed to get the Bitmap however not what I am expecting for the following reasons.

     

    The BitmapInfo Header Dump:

     

    bmi.bmiHeader.biSize = 40;

    bmi.bmiHeader.biWidth = 352;

    bmi.bmiHeader.biHeight = 288;

    bmi.bmiHeader.biPlanes = 1;

    bmi.bmiHeader.biBitCount = 16;

    bmi.bmiHeader.biCompression = 844715353;

    bmi.bmiHeader.biSizeImage = 202752;

    bmi.bmiHeader.biXPelsPerMeter = 0;

    bmi.bmiHeader.biYPelsPerMeter = 0;

    bmi.bmiHeader.biClrUsed = 0;

    bmi.bmiHeader.biClrImportant = 0;


    The Problem is with bmi.bmiHeader.biCompression = 844715353 this value is none of the values in MSDN, 

    Digging on Media Type and Subtype I found that I am getting 

    MediaType.majortype == MEDIATYPE_Video

    MediaType.subtype == MEDIASUBTYPE_YUY2

     

    Now the issue remains of the YUV2 to RGB ColorSpace Conversion

     

    I tried using ColorSpace Conversion Filter for this Pupose, I placed the Filter right between the "ffdshow Video Decoder" and "Dump Filter"

    but the Filters fail to connect the color space filter either connects to the "ffdshow Video Decoder" or "Dump Filter" but not both as I need.

     

    I tried Setting the Media Subtype too but there is no change in the Output.

     

    AM_MEDIA_TYPE MediaType;

    hr= ConnectionMediaType(&MediaType);

    MediaType.subtype = MEDIASUBTYPE_RGB32;

    pSample->SetMediaType(&MediaType);


    let me know the other options.

    Monday, March 22, 2010 6:53 AM
  • bmi.bmiHeader.biCompression = 844715353  is hex 0x32595559 which is YUY2.  See http://fourcc.org for a description of the different YUV and RGB types.

    You can convert the YUY2 to RGB yourself.  Here is some info:

    http://www.fourcc.org/fccyvrgb.php

    More can be found by googling or binging.


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Monday, March 22, 2010 7:07 AM
  • bmi.bmiHeader.biCompression = 844715353  is hex 0x32595559 which is YUY2.  See http://fourcc.org for a description of the different YUV and RGB types.

    You can convert the YUY2 to RGB yourself.  Here is some info:

    http://www.fourcc.org/fccyvrgb.php

    More can be found by googling or binging.


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Marked as answer by subhanshoo Monday, March 22, 2010 7:32 AM
    Monday, March 22, 2010 7:07 AM
  • I already have a method for YUV2 for RGB Conversion but I am not sure of its performance for processing 25 Frames per-second,

    I have figured out that ffdShow Filter Supports the following Output Formats

     

    Major Type:  Video - Sub Type:  YUY2 - Format:  YUY2 352x288, 16 bits

    Major Type:  Video - Sub Type:  UYVY - Format:  UYVY 352x288, 16 bits

    Major Type:  Video - Sub Type:  YVYU - Format:  YVYU 352x288, 16 bits

    Major Type:  Video - Sub Type:  YV12 - Format:  YV12 352x288, 12 bits

    Major Type:  Video - Sub Type:  RGB32 - Format:   RGB 352x288, 32 bits

    Major Type:  Video - Sub Type:  RGB24 - Format:   RGB 352x288, 24 bits

    Major Type:  Video - Sub Type:  RGB565 - Format:   RGB 352x288, 16 bits

    Major Type:  Video - Sub Type:  RGB555 - Format:   RGB 352x288, 16 bits

     

    The Idea behind is to configure the output Media Sample to RGB so that the ffdShow ouputs in RGB, eliminating the need of manual conversions.

    I also figured out DShow Color Space Conversion Filter does only RGB->RGB Conversions.

     

    Now how can I Modify the Dump Filter to Request the Media Sample in RGB Format from ffdShow.

    Monday, March 22, 2010 7:31 AM
  • Modify CDumpInputPin

    CheckMediaType() 

    return S_FALSE except if Mediatype is RGB in which case return S_OK

    This way the filer will accept to connect only with RGB.


    Michel Roujansky, http://www.roujansky.com
    • Marked as answer by subhanshoo Monday, March 22, 2010 9:18 AM
    Monday, March 22, 2010 8:09 AM
  • Thanx a lot I finally got the Bitmap on Disk however the Bitmaps are Inverted which I fixed using 

     

    Bitmap::RotateFlip(Gdiplus::Rotate180FlipX);

     

    But is it normally the case or It's due to any error.

    Monday, March 22, 2010 10:38 AM
  • You have to check the sample's height to see if it is negative.

    Some media have naturally inverted frames (e.g. DV).


    Michel Roujansky, http://www.roujansky.com
    Monday, March 22, 2010 10:46 AM

  • You have to check the sample's height to see if it is negative.

    Some media have naturally inverted frames (e.g. DV).


    Michel Roujansky, http://www.roujansky.com

     

    I have already checked them they are +ve in my case.

    Monday, March 22, 2010 11:37 AM
  • Below is the info from "Top-Down vs. Bottom-Up DIBs" in the SDK docs.  See if it is useful for solving your issue.  It's always possible for a decoder to ignore this (in which case I would say the decoder has a bug):

    For RGB DIBs, the image orientation is indicated by the biHeight member of the BITMAPINFOHEADER structure. If biHeight is positive, the image is bottom-up. If biHeight is negative, the image is top-down.

    DIBs in YUV formats are always top-down, and the sign of the biHeight member is ignored. Decoders should offer YUV formats with positive biHeight, but they should also accept YUV formats with negative biHeight and ignore the sign.

    Also, any DIB type that uses a FOURCC in the biCompression member, should express its biHeight as a positive number no matter what its orientation is, since the FOURCC itself identifies a compression scheme whose image orientation should be understood by any compatible filter.



    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Marked as answer by subhanshoo Monday, March 22, 2010 2:47 PM
    Monday, March 22, 2010 12:52 PM
  • 1.  You have the source code to the Dump filter.  Look at it and understand what it does.  As Michel pointed out, it is the raw data.  You need to understand what is in the media sample before modify Dump to you put that data you need in your CList.

     

    I am trying March Hare's suggestion to put the data in CList or std::<list> but I am getting linking error when I instantiate the std::list<> in

    CDump class.

     

     

    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::~_Container_base(void)" (__imp_??1_Container_base@std@@QAE@XZ) referenced in function "public: __thiscall std::_Vector_val<int,class std::allocator<int> >::~_Vector_val<int,class std::allocator<int> >(void)" (??1?$_Vector_val@HV?$allocator@H@std@@@std@@QAE@XZ)
    
    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __thiscall std::_Container_base::_Orphan_all(void)const " (__imp_?_Orphan_all@_Container_base@std@@QBEXXZ) referenced in function "protected: void __thiscall std::vector<int,class std::allocator<int> >::_Tidy(void)" (?_Tidy@?$vector@HV?$allocator@H@std@@@std@@IAEXXZ)
    
    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::_Container_base::_Container_base(void)" (__imp_??0_Container_base@std@@QAE@XZ) referenced in function "protected: __thiscall std::_Vector_val<int,class std::allocator<int> >::_Vector_val<int,class std::allocator<int> >(class std::allocator<int>)" (??0?$_Vector_val@HV?$allocator@H@std@@@std@@IAE@V?$allocator@H@1@@Z)
    
    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (__imp_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) referenced in function "protected: static void __stdcall std::vector<int,class std::allocator<int> >::_Xlen(void)" (?_Xlen@?$vector@HV?$allocator@H@std@@@std@@KGXXZ)
    
    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (__imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) referenced in function "protected: static void __stdcall std::vector<int,class std::allocator<int> >::_Xlen(void)" (?_Xlen@?$vector@HV?$allocator@H@std@@@std@@KGXXZ)
    
    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (__imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@ABV01@@Z) referenced in function "public: __thiscall std::logic_error::logic_error(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0logic_error@std@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z)
    
    1>dump.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: char const * __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::c_str(void)const " (__imp_?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) referenced in function "public: virtual char const * __thiscall std::logic_error::what(void)const " (?what@logic_error@std@@UBEPBDXZ)

     

    I googled for the creating and STL Template instantiation a member of a DLL class but the solutions seems to be not working.

    I also tried it using CList but the issue is Dump Project is not a MFC Project, I set the Project to use MFC as a shared DLL then I get lots of linking errors.

     

    Just let me know which will be a better idea to use STL vector or CList considering the programming issues.

     

     

    Thanx in Advance.

     

     

     

    • Edited by subhanshoo Tuesday, March 23, 2010 6:17 AM Update
    Tuesday, March 23, 2010 5:33 AM
  • Make sure for the baseclasses and the dump filter:

    1.  They are compiled with the same version of Visual Studio.

    2.  The compiler and linker/library options are the same for both projects (threading/dll type, wchar_t, Unicode, etc.).


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Tuesday, March 23, 2010 6:09 AM
  • Make sure for the baseclasses and the dump filter:

    1.  They are compiled with the same version of Visual Studio.

    2.  The compiler and linker/library options are the same for both projects (threading/dll type, wchar_t, Unicode, etc.).


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.

     

    Already Checked Ok.

    Actually the issues are in exporting the STL from a DLL, the only STL that can be exported from a DLL is vector,

    as per the following Article

    http://support.microsoft.com/default.aspx/kb/168958?p=1

     

    Now I am struggling to create a pointer member like 

     

    std::vector<Bitmap*>*		m_plistFrames;

     

    which I want to populate with the extracted frames and access using a custom interface to it.

     

    I have still to get the list thing working, I am getting the following linking errors with std::vector<>.

     

    1>dump.obj : error LNK2019: unresolved external symbol "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) referenced in function "public: void __thiscall std::_Container_base::_Orphan_all(void)const " (?_Orphan_all@_Container_base@std@@QBEXXZ)
    1>dump.obj : error LNK2019: unresolved external symbol "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) referenced in function "public: void __thiscall std::_Container_base::_Orphan_all(void)const " (?_Orphan_all@_Container_base@std@@QBEXXZ)
    1>dump.obj : error LNK2019: unresolved external symbol "public: static void __cdecl std::_String_base::_Xran(void)" (?_Xran@_String_base@std@@SAXXZ) referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::assign(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned int,unsigned int)" (?assign@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@ABV12@II@Z)
    1>dump.obj : error LNK2019: unresolved external symbol "public: static void __cdecl std::_String_base::_Xlen(void)" (?_Xlen@_String_base@std@@SAXXZ) referenced in function "protected: bool __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Grow(unsigned int,bool)" (?_Grow@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@IAE_NI_N@Z)
    1>dump.obj : error LNK2019: unresolved external symbol "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) referenced in function "void __cdecl std::_Debug_pointer<char>(char const *,wchar_t const *,unsigned int)" (??$_Debug_pointer@D@std@@YAXPBDPB_WI@Z)
    

    hope I will be able to figure out soon.

     

    Please do suggest alternatives, if any.

    Tuesday, March 23, 2010 6:45 AM
  • What type of container can be used in filters,

    I need a container like CList to keep all the extracted frames in the Container.

    I was trying with std::vector<> but seems to be not working with COM DLL as

    how to Export COM interfaces as well as vector template classes.

    now trying out IList COM's interface.

    Tuesday, March 23, 2010 1:20 PM
  • Okay, this is odd because it has not come up much.  I use the STL in my filters.  However, all of my custom filters are compiled into my executable.  This is simpler in terms of installing an app because there is no registration needed.  The only reason I can see to not do this is if you have a filter shared between apps or you expect other apps to use the filter.

    So, my recommendation is to compile the filter into your app if that is possible.  See Geraint's AppFilter sample on his download page here:

    http://www.gdcl.co.uk/downloads.htm

    You can probably even use MFC containers this way :)


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Tuesday, March 23, 2010 2:08 PM
  • Okay, this is odd because it has not come up much.  I use the STL in my filters.  However, all of my custom filters are compiled into my executable.  This is simpler in terms of installing an app because there is no registration needed.  The only reason I can see to not do this is if you have a filter shared between apps or you expect other apps to use the filter.

    So, my recommendation is to compile the filter into your app if that is possible.  See Geraint's AppFilter sample on his download page here:

    http://www.gdcl.co.uk/downloads.htm

    You can probably even use MFC containers this way :)


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    • Marked as answer by subhanshoo Wednesday, March 24, 2010 4:49 AM
    Tuesday, March 23, 2010 2:08 PM
  • I am trying to use the Modified Dump Filter in a MFC Based Caller Program, I am creating a default graph for the input video file,

    Now instead of the default renderer I want to put my Modified Dump Filter, This is the same I have been doing so far with Graph Builder. 

    The issues is accessing the Modified Dump Filter there

     

    I have made the following registry entries to register my Filter for COM.

    REGEDIT4 
    [HKEY_CLASSES_ROOT\CLSID\{36A5F770-FE4C-11CE-A8ED-00AA002FEAB5}]
    @="Dump"
    [HKEY_CLASSES_ROOT\CLSID\{36A5F770-FE4C-11CE-A8ED-00AA002FEAB5}\InprocServer32]
    @="C:\\~DirectShowSDK_All\\DirectShow\\filters\\Dump\\Debug\\Dump.dll"

     

    I am unable to access CLSID_Dump to access by COM and get a reference to the Filter.

     

    I get the following error when I try to create a COM instance to the Filter

    error C2065: 'CLSID_Dump' : undeclared identifier 

     

    Thanx.

    Wednesday, March 24, 2010 8:42 AM
  • Did you include dumpuids.h in your program?

    did you run

    regsvr32 "C:\\~DirectShowSDK_All\\DirectShow\\filters\\Dump\\Debug\\Dump.dll"

     

    Why don't you try to use the filter's (C++)  class directly in your program as suggested by TMH above? This way you avoid registration and have directly access to the filter's members.


    Michel Roujansky, http://www.roujansky.com
    Wednesday, March 24, 2010 1:04 PM
  • Also note that you should create your own GUID for your filter.  If you re-use the one for the Dump filter it will cause conflicts with any other filter that uses the same CLSID (GUID).

    VS has a tool built-in:

    http://msdn.microsoft.com/en-us/library/ms241442(VS.80).aspx

    The same applies to your GUID for your custom interface.

    Also, see my FAQs page for an easier way to do filter registration, if you decide to stick with the external filter.


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Wednesday, March 24, 2010 2:05 PM
  • Thanks March and Michel,

     

    I had already registered my filter using

    regsvr32 "C:\\~DirectShowSDK_All\\DirectShow\\filters\\Dump\\Debug\\Dump.dll"

    otherwise how could I use it with GraphEdit anyways.

     

    I have no plans to stick with external filter as the type of app I am building is more suited with internal filter.

     

    The GUID issues are not of GUID conflicts, I am using the default GUID provided in the Dump Filter Sample Project,

    What else is required to make them available in other projects.

     

    anyways I don't need them now with the internal filter.

     

    The internal filter is working fine for me except in CAppSinkBuilder::Run()

     

    IMediaEvent            *pEvent;
    HRESULT hr = m_pGraph->QueryInterface (IID_IMediaEvent, (void **)&pEvent);
    assert (SUCCEEDED(hr));
    
    
    
    // Wait for completion.
    
    long evCode;
    hr= pEvent->WaitForCompletion(INFINITE, &evCode);

    the hr is always VFW_E_WRONG_STATE which fails to wait for the decoding to finish.

     

    In my app I have some other methods to call after the Frame List is fully Populated.

    Thursday, March 25, 2010 5:12 AM
  • 1.  Using regsvr32 is antiquated.  See my FAQs page for how to do this automatically.

    2.  Michel already pointed out that you can use the CLSID by dumpuids.h.  See my FAQs page for how to correct an undefined CLSID.

    3.  VFW_E_WRONG_STATE means the graph is not running according to the remarks section for IMediaEvent::WaitForCompletion.  Is your graph processing any frames? (see my FAQs page for information on how to debug a filter)


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Thursday, March 25, 2010 5:55 AM
  • VFW_E_WRONG_STATE means the graph is not running according to the remarks section for IMediaEvent::WaitForCompletion.  Is your graph processing any frames? (see my FAQs page for information on how to debug a filter)

     

    I already know that VFW_E_WRONG_STATE means that the graph is stopped but in my case the graph is working fine,

    I am getting the bitmaps decoded and saved on the Disk, all I am unable to do is to wait till all the frames are processed.

    Thursday, March 25, 2010 6:37 AM
  • If you call WaitForCompletion right after running the graph, which probably returns S_FALSE (not yet running), then

    A better method for checking is to set up a timer in your message loop and periodically call WaitForCompletion with no timeout (0).


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Thursday, March 25, 2010 2:53 PM
  • Okay, this is odd because it has not come up much.  I use the STL in my filters.  However, all of my custom filters are compiled into my executable.  This is simpler in terms of installing an app because there is no registration needed.  The only reason I can see to not do this is if you have a filter shared between apps or you expect other apps to use the filter.

    So, my recommendation is to compile the filter into your app if that is possible.  See Geraint's AppFilter sample on his download page here:

    http://www.gdcl.co.uk/downloads.htm

    You can probably even use MFC containers this way :)


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.

    I am exploring more on the Internal Filter sample, I found out that when 

    CAppSinkBuilder m_Graph;

    is the member of the Application Dialog everything works fine. {except WaitForCompletion()}

    but when I use 

    CAppSinkBuilder m_Graph;

    as a local variable in a Method the Filter is not being Called  I mean 

    CSinkInput::Receive(IMediaSample *pSample)

    is not getting called at all.

    Although HRESULT is SUCCESS everywhere.

    Monday, March 29, 2010 9:17 AM
  • If you are expecting to create and run the graph from a method on your application, that's generally a bad idea.  You should create the graph let it run and return to your Windows processing loop either:

    - Setting a windows timer in your message loop to check the status of the graph using WaitForCompletion with a 0 timeout.

    - Waiting for EC_COMPLETE (after using IMediaEventSink::SetNotifyWindow, several of the samples illustrate this including the Watermark sample)

     


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Monday, March 29, 2010 5:06 PM
  • I have tried an alternate,

     

    CAppSink  :: HANDLE m_hEndOfStream;

     

    which I set the Event in 


    HRESULT CAppSink :: EndOfStream();

    and use


    ::WaitForSingleObject(m_hEndOfStream, INFINITE);

     

    once the stream is completed the wait is finished.

     

    Will there be any issue in this approach,

     

    this seems to be working fine for me.

     

    Thanx.

    Tuesday, March 30, 2010 2:41 PM
  • If it's working then I don't see a problem.  Usually though, you want to still update your UI and perhaps offer other features to the user while the frame capture is working.  That is why it is more typical to handle the check for end of stream in your main message loop.
    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Tuesday, March 30, 2010 7:23 PM