Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

How to add video rotation?

Help
2010-01-01
2013-01-10
  • hosentraeger
    hosentraeger
    2010-01-01

    Hi,

    I tried to add the rotate filter to the direct show sample "PlayCap". I added this code to the file, right before RenderStream():
       

    // Add rotate filter
    IBaseFilter * pRotateFilter = NULL;
    CoCreateInstance ( CLSID_RotateFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, ( void** ) &pRotateFilter );
    ISettingsInterface * pSettingsInterface = NULL;
    pRotateFilter->QueryInterface ( IID_ISettingsInterface, ( void ** ) &pSettingsInterface );
    hr = pSettingsInterface->SetParameter ( "rotationmode", "3" );
    hr = g_pGraph->AddFilter ( pRotateFilter, L"RotateFilter" );
        …

    It didn't work :-( What is the right way to add the filter? Any help is appreciated!

     
  • Ralf Globisch
    Ralf Globisch
    2010-01-04

    Hi, the sample code looks fine.
    Did you check the HRESULT after each step? If any of the steps failed that will give you a clue as to what's gone wrong.

    I tried a quick modify of PlayCap and the one thing I did differently is to render the graph. Instead of

        hr = g_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
                                       pSrcFilter, NULL, NULL);

    try something like

        IBaseFilter * pRotateFilter = NULL;
    CoCreateInstance ( CLSID_RotateFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, ( void** ) &pRotateFilter );
    ISettingsInterface * pSettingsInterface = NULL;
    pRotateFilter->QueryInterface ( IID_ISettingsInterface, ( void ** ) &pSettingsInterface );
    hr = pSettingsInterface->SetParameter ( "rotationmode", "3" );
    hr = g_pGraph->AddFilter ( pRotateFilter, L"RotateFilter" );
    hr = CDirectShowHelper::ConnectFilters(g_pGraph, pSrcFilter, pRotateFilter );
    hr = CDirectShowHelper::Render(g_pGraph, pRotateFilter);

    This worked ok for me.
    If you need the implementation of CDirectShowHelper::ConnectFilters and CDirectShowHelper::Render I've updated the svn repository: you can copy it from the
    <<project_root>>/SourceRtvcLibDirectShow/DirectShowHelper.h & cpp files to avoid having to link to an extra lib (I'll make them inline in the near future). The code is taken from/based on some of the sample code somewhere in the DS SDK.

    Let us know If you have any further problems and please report any bugs you might discover ;)

     
  • hosentraeger
    hosentraeger
    2010-01-05

    Hi,

    thanks a lot for adding the helper functions! I checked out the files, re-compiled the video processing dll's from trunk and added DirectShowHelper.c to my project. Now I can use the RotateFilter using ConnectFilters() and Render().

    There's also another approach I had learned. It uses two times Render():

    static const GUID CLSID_RotateFilter = { 0x66888cff, 0x359b, 0x414b, { 0xbc, 0x20, 0xcf, 0xd6, 0xd8, 0x11, 0x20, 0x9b } };
    #include "RtvcLib/DirectShow/SettingsInterface.h"
    #include "RtvcLib/DirectShow/DirectShowHelper.h"
       

       
    // Add rotate filter
    IBaseFilter * pRotateFilter = NULL;
    CoCreateInstance ( CLSID_RotateFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, ( void** ) &pRotateFilter );
    ISettingsInterface * pSettingsInterface = NULL;
    pRotateFilter->QueryInterface ( IID_ISettingsInterface, ( void ** ) &pSettingsInterface );
    hr = pSettingsInterface->SetParameter ( "rotationmode", "2" );
    hr = g_pGraph->AddFilter ( pRotateFilter, L"RotateFilter" );
    hr = g_pCapture->RenderStream ( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pSrcFilter, NULL, pRotateFilter );
    hr = g_pCapture->RenderStream ( NULL, &MEDIATYPE_Video, pRotateFilter, NULL, NULL );

    The Rotate Filter does a transformation, but it doesn't work quite correctly with my web cam. It seems to flip the image vertically before applying the transformation. If you for example set rotation_mode to "0", you'll get a vertically flipped image. Mode "2" gives a horizontally flipped image.

    So I modified RtvcLib/image/PicRotateRGBBase.cpp as follows:

      

         …
          case ROTATE_180_DEGREES_CLOCKWISE:
            {
            BYTE* pSrc = (BYTE*)pInImg;
            int nTotalPixels = m_nWidth * m_nHeight;
            int nLastIndex = (nTotalPixels - 1) * nBytesPerPixel;
            BYTE* pDest = (BYTE*)pOutImg + nLastIndex;
           
            for ( int y = 0; y < m_nHeight; y++ )
            {
            for ( int x = 0; x < m_nWidth; x++ )
            {
            unsigned long * pSrcPixel = ( unsigned long * ) pInImg + y * m_nWidth + x;
            unsigned long * pDestPixel = ( unsigned long * ) pOutImg + y * m_nWidth + ( m_nWidth - x - 1 );
            *pDestPixel = *pSrcPixel;
            }
            }
            /*
            for (int i = 0; i < nTotalPixels; ++i, pSrc += nBytesPerPixel, pDest -= nBytesPerPixel)
            {
            memcpy(pDest, pSrc, sizeof(BYTE) *nBytesPerPixel);
            }
            */
            return true;
        }

    This is not a pretty hack but after all it works for me:-)

    If I can help with the issue, please let me know! I'll submit some screenshots (if I figure out how:-) )

     
  • Ralf Globisch
    Ralf Globisch
    2010-01-05

    Hi, I'm glad you came right ;)

    It could also be that your webcam src filter is flipping the image. My webcam at work exhibits that behaviour, whereas my webcam on my laptop works correctly.

    If you look at the code for mode "0" it does a straight memcpy into the output buffer so mode "0" should really do nothing. If that isn't the case, let me know…

    Thanks for pointing that out though! Your comment about the flipping made me test all the rotations again and I picked up that the CC rotate by 270 was flipping the image, which I've fixed now. I also added a slightly modified version of your code to implement the Flip horizontal.

    Thanks for the help and pls let me know if you discover any other bugs/funnies.

    Cheers,
    Ralf

     
  • Fenis
    Fenis
    2010-11-28

    Hi!
    I would make the same thing: to add filter rotate to playcap. I want to rotate a video 90 degrees.
    I downloaded Filter Rotate by this site and compiled it,  but I didn't find librtvcimaged.lib . Is it necessary this .lib to add filter rotate to playcap? If yes, where can I find this .lib?
    Have I to add the directory "Filter Rotate" into directory "PlayCap"  to add the filter rotate to playcap?
    I know that writing this lines of code, I add a filter to playcap:

    … // Add rotate filter IBaseFilter * pRotateFilter = NULL; CoCreateInstance ( CLSID_RotateFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, ( void** ) &pRotateFilter ); ISettingsInterface * pSettingsInterface = NULL; pRotateFilter->QueryInterface ( IID_ISettingsInterface, ( void ** ) &pSettingsInterface );
    hr = pSettingsInterface->SetParameter ( "rotationmode", "1" );
    hr = g_pGraph->AddFilter ( pRotateFilter, L"RotateFilter" );

    This line generate 2 files: RotateFilter.cpp an RotateFilter.h
    These files have only constructor and destructor.
    Is that right?

    Thanks for your help.
    Fenis

     
  • Ralf Globisch
    Ralf Globisch
    2010-11-29

    Hi Fenis,

    Replies inline:

    > I would make the same thing: to add filter rotate to playcap. I want to rotate a video 90 degrees.
    > I downloaded Filter Rotate by this site and compiled it,  but I didn't find librtvcimaged.lib . Is it necessary this .lib to add filter rotate to playcap? If yes, where can I find this .lib?

    Did you download the entire trunk? There are instructions in the README.txt on how to start up the Visual Studio solution using a batch file. If you open the solution in the way specified, you should see all video processing project projects in the VS IDE. The RotateFilter has a dependency on the Image project. That project should be built automatically as it is a dependency of the RotateFilter. This lib is necessary as it contains the rotation implementations PicRotateRGB24Impl and PicRotateRGB24Impl .h & .cpp.

    > Have I to add the directory "Filter Rotate" into directory "PlayCap"  to add the filter rotate to playcap?
    > I know that writing this lines of code, I add a filter to playcap:
    … // Add rotate filter IBaseFilter * pRotateFilter = NULL; CoCreateInstance ( CLSID_RotateFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, ( void** ) &pRotateFilter ); ISettingsInterface * pSettingsInterface = NULL; pRotateFilter->QueryInterface ( IID_ISettingsInterface, ( void ** ) &pSettingsInterface );
    hr = pSettingsInterface->SetParameter ( "rotationmode", "1" );
    hr = g_pGraph->AddFilter ( pRotateFilter, L"RotateFilter" );

    You shouldn't have to copy any directories around. The RotateFilter is COM registered in the custom build event step of the project. If the regsvr32 command succeeds you can create an instance of the filter using it's GUID CLSID_RotateFilter. You can modify your project's include path to find the RotateFilter header and dependencies. Alternatively, just redeclare the GUID.

    This line generate 2 files: RotateFilter.cpp an RotateFilter.h
    These files have only constructor and destructor.
    Is that right?

    I don't understand what you mean here. The RotateFilter files contain more than just constructor and destructor. And they aren't generated by the lines above?

     
  • Fenis
    Fenis
    2010-11-30

    Hi!
    Now I understand tha I had wrong.
    So.. I have playcap project that works fine.
    I want to add the filter rotate to this playcap. How can I do it?
    How can I redeclare the GUID?

    I thought that I could add only filter rotate to playcap, including the filter rotate directory into playcap directory and writing in VS2010 some lines of code ( for example those line I wrote above.).

    I would understand how to work with these projects.
    I'm sorry but I'm new in programming directshow and VS2010 too..

    Thanks.
    Fenis

     
  • Fenis
    Fenis
    2010-12-01

    ..
    I try to modify playcap adding this line in play.cpp


    ICaptureGraphBuilder2 * g_pRotateFilter = NULL;
    IBaseFilter *pRotateFilter = NULL;
    hr = CoCreateInstance ( CLSID_CaptureGraphBuilder2,
    NULL,
    CLSCTX_INPROC,
    IID_ICaptureGraphBuilder2,
    (void **) &g_pRotateFilter);

    if (FAILED(hr))
    return hr;

    //Add my rotate filter to filter graph
    hr= g_pGraph->AddFilter(pRotateFilter, L"Rotate Filter"); //ERROR
        if (FAILED(hr))
        {
            Msg(TEXT("Couldn't add the rotate filter to the graph!  hr=0x%x\r\n\r\n")
                TEXT("If you have a working video capture device, please make sure\r\n")
                TEXT("that it is connected and is not being used by another application.\r\n\r\n")
                TEXT("The sample will now close."), hr);
            pRotateFilter->Release();//Rilascia il filtro
            return hr;
        }
    ….

    Compile is fine, but debug no. I have the error (see the line and comment above //ERROR): here I have hr=E_POINTER.
    Why?

    I think that I didn't correctly connect filter rotate to filter playcap.
    First, do I have to query interface with
    ISettingsInterface * pSettingsInterface = NULL;
    pRotateFilter->QueryInterface ( IID_ISettingsInterface, ( void ** ) &pSettingsInterface );

    ?

    Why in the precedent post he used CLSCTX_INPROC_SERVER and not CLSCTX_INPROC, used in playcap example?

    In another example I saw that it used the function AddFilterByCLSID

    hr = g_pGraph->AddFilterByCLSID (g_pGraph, CLSID_RotateFilter, L"Rotate Filter", &pRotateFilter);

    What's the different?

    Thanks.