none
Need help on video in portrait mode.

    Question

  • Hi,

    Can some one give me some links or tips on developing filters or application that captures video in portrait mode ?
    Mahantesh Ganamukhi
    Monday, April 20, 2009 4:07 PM

Answers

  • Most devices only present in landscape mode so you will likely need a rotate filter in your graph.

    Some third-parties, LeadTools, for example, offer commercial rotate filters.  See my Links page.

    You could also develop your own rotate filter.  The resize filter by Vivek on my Downloads page could be a good starting point.

    Here is some previous discussion:

    http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/search?group=microsoft.public.win32.programmer.directx.video&q=rotate+filter&qt_g=Search+this+group


    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Monday, April 20, 2009 4:28 PM
  • For rotating, the math is simple.  For example, a 90 degree clockwise rotation is:

    Source

    A B C D
    E F G H
    I J K L

    Dest

    I E A   (2,0) (1,0) (0,0)
    J F B   (2,1) (1,1) (0,1)
    K G C   (2,2) (1,2) (0,2)
    L H D   (2,3) (1,3) (0,3)

    Assuming you have RGB32 each pixel is one RGBQUAD (32 bits), assume <src> and <dest> are RGBQUAD pointers to the beginning of the image data.  If RGB24, RGBTRIPLE pointers, if 16 bit, USHORT pointers.

    In this case <src_rows> is 3 and <src_cols> is 4.

    So the rotation can be done with this nested loop. Something like:

    for (col = 0; col < src_cols; col++) {
       for (row = src_rows - 1; row >= 0; row--)
         *dest++ = src[row * src_cols + col];
    }

    No need to create bitmaps and use GetPixel and SetPixel.

    For information on stride, type:

        stride renderer

    In the search box in the top of this page.  The article you want about the video renderer is about four down from the top.  Alternatively, download the DirectX 2004 SDK, as recommended on my site.  This has a standalone CHM file for dshow which can be easily searched.  If the output destination has stride, you need to make an easy modification to the loop as each row in the destination is completed.  I'll leave that one for you to figure out.

     

     

     

     

     


    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Tuesday, April 28, 2009 4:24 PM
  • Mahantesh, I've made a minor fix, you can get the latest version on SF. Mine seems to be working fine in most cases.
    I've only tested using RGB24 and 32 CIF inputs. What input are you using?
    In the meanwhile I suggest you substitute my overly complex 90 deg rotation with The March Hare's suggestion.

    Have found a bug though: in the case of an RGB32 288x351 input my stride/padding calculation seems incorrect, it looks like
    stride = (biWidth * (biBitCount / 8) + 3) & ~3;
    padding = stride - (biBitCount / 8 * biWidth);
    isn't sufficient to calculate the correct padding, from reading The March Hare's post I'm guessing that I need to align the data on a 64 bit boundary.
    The resulting image is skewed along the diagonal. I'll fix that as soon as I get a chance.

    http://sourceforge.net/projects/videoprocessing/
    Thursday, April 30, 2009 6:06 AM
  • Thanks for the vote of confidence, Ralf.  I think all that is needed if there is stride on the output pin is:

      dest += dest_stride - dest_cols;

    after the inner loop.  Adding a statement like this is one reason I always put a brace around an outer loop :)
    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Thursday, April 30, 2009 8:02 AM

All replies

  • Most devices only present in landscape mode so you will likely need a rotate filter in your graph.

    Some third-parties, LeadTools, for example, offer commercial rotate filters.  See my Links page.

    You could also develop your own rotate filter.  The resize filter by Vivek on my Downloads page could be a good starting point.

    Here is some previous discussion:

    http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/search?group=microsoft.public.win32.programmer.directx.video&q=rotate+filter&qt_g=Search+this+group


    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Monday, April 20, 2009 4:28 PM
  • Hi,

    Thanks for the reply. With your help I was able to start on the video rotation filter.  I tried to rotate the image in Transform filter, but its too slow and not accurate.

    Can you please give me some help on what all needs to be taken care in rotating the video?


    Mahantesh Ganamukhi
    Monday, April 27, 2009 3:55 PM
  • What do you mean by not accurate?

    It's hard to say what might be too slow without seeing your Transform method where you rotate the video.


    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Monday, April 27, 2009 4:10 PM
  • Hi,

    Please find the transform function.


    HRESULT CResizer::Transform(IMediaSample *pIn, IMediaSample *pOut)
    {
      
        unsigned char *pDst = 0;
        unsigned char *pSrc = 0;

        pIn->GetPointer((unsigned char **)&pSrc);
        pOut->GetPointer((unsigned char **)&pDst);

        // As given @ http://support.microsoft.com/kb/77127


       HBITMAP hOldSourceBitmap, hOldDestBitmap, hDestBitmap;
       HDC hMemSrc, hMemDest , hDC;
       int height, width;
       int i, j;
       BITMAP SrcBitmap;
       HBITMAP  hSourceBitmap = CreateBitmap(m_inX,m_inY,1,32,pSrc);
     
      hMemSrc = CreateCompatibleDC(0);
      hMemDest= CreateCompatibleDC(0);

     GetObject(hSourceBitmap, sizeof(BITMAP), &SrcBitmap);
        width = SrcBitmap.bmWidth;
        height = SrcBitmap.bmHeight;

     hOldSourceBitmap =  (HBITMAP) SelectObject(hMemSrc, (HGDIOBJ )hSourceBitmap);
        hDestBitmap = CreateBitmap(height, width, SrcBitmap.bmPlanes,
                        SrcBitmap.bmBitsPixel, NULL);
     if (!hDestBitmap)

     {
      // Error return frm here
     }

     hOldDestBitmap = (HBITMAP) SelectObject(hMemDest, hDestBitmap);

     for (int i = 0; i < width; ++i)
     {
      for (int j = 0; j < height; ++j)
      {
       SetPixel(hMemDest, j, width - 1 - i,
       GetPixel(hMemSrc, i, j));
      }
     }

     SelectObject(hMemSrc, hOldSourceBitmap);
     SelectObject(hMemDest, hOldDestBitmap);
     DeleteDC(hMemDest);
     DeleteDC(hMemSrc);


     long cbBuffer = RowWidth(m_inX  ) * m_inY   * m_bytesPerPixel;
     LONG lRes = GetBitmapBits(hDestBitmap,cbBuffer,pDst);

     if ( pSrc != NULL && cbBuffer > 0)
     {
         memcpy(pDst, pSrc, cbBuffer);
     }

        LONGLONG MediaStart, MediaEnd;
        REFERENCE_TIME TimeStart, TimeEnd;

        pIn->GetTime(&TimeStart, &TimeEnd);
        pIn->GetMediaTime(&MediaStart,&MediaEnd);
        pOut->SetActualDataLength( cbBuffer);
        pOut->SetTime(&TimeStart, &TimeEnd);
        pOut->SetMediaTime(&MediaStart,&MediaEnd);
        pOut->SetSyncPoint(pIn->IsSyncPoint() == S_OK);
        pOut->SetPreroll(pIn->IsPreroll() == S_OK);
        pOut->SetDiscontinuity(pIn->IsDiscontinuity() == S_OK);
     
        return NOERROR;
    }


    Please let me know if I am going in correct direction ....


    Mahantesh Ganamukhi
    Monday, April 27, 2009 5:23 PM
  • 1.  You didn't answer my first question in my previous post: What do you mean by not accurate?

    2.  Are you connected to a renderer on the output pin of your transform filter?  If so, you will need to take the stride of the frame into account.  See the docs for an explanation.

    3.  Creating bitmaps as you are doing is going to be quite inefficient.  You should be able to do the transform yourself by using one outer loop to process rows from the source and and an inner loop to process columns.


    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Monday, April 27, 2009 5:31 PM
  • Hi,
    You could get speed improvement by using a temp "local" memory instead of pDst in function GetBitmapBits(hDestBitmap,cbBuffer,pDst);

    do all your calculations locally and then "at the end" copy to pDst.

    try it!!

    regards
    Ashish
    Monday, April 27, 2009 7:28 PM
  • Rotation using DC and GetPixel/SetPixel will be inevitably desperately slow. To perform efficient rotation you need to implement direct buffer access logic and loops. BTW this is mostly a copy of item 3 above by The March Hare.
    http://alax.info/blog/tag/directshow
    Monday, April 27, 2009 8:43 PM
  • Rotation using DC and GetPixel/SetPixel will be inevitably desperately slow.

    Exactly, that's the worst part :)
    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Tuesday, April 28, 2009 7:03 AM
  • Hi,

    1. By not accurate i meant that the preview is rotated and i am able to see some lines on the preview and is out of the renderer window.

    2. Yes I am connected to the a renderer on the output pin of transform filter.

    Graph looks like this

    USB Video device Capture ---> Sample Grabber--->AVI decompressor--->Transform filter --->Video renderer.

    Can you guide me on the documents to refer to know about strides and processing the rows and cloumns?


    Mahantesh Ganamukhi
    Tuesday, April 28, 2009 3:30 PM
  • Hi Ashish,

    I tried your suggestion , it dint help much.


    Mahantesh Ganamukhi
    Tuesday, April 28, 2009 4:18 PM
  • For rotating, the math is simple.  For example, a 90 degree clockwise rotation is:

    Source

    A B C D
    E F G H
    I J K L

    Dest

    I E A   (2,0) (1,0) (0,0)
    J F B   (2,1) (1,1) (0,1)
    K G C   (2,2) (1,2) (0,2)
    L H D   (2,3) (1,3) (0,3)

    Assuming you have RGB32 each pixel is one RGBQUAD (32 bits), assume <src> and <dest> are RGBQUAD pointers to the beginning of the image data.  If RGB24, RGBTRIPLE pointers, if 16 bit, USHORT pointers.

    In this case <src_rows> is 3 and <src_cols> is 4.

    So the rotation can be done with this nested loop. Something like:

    for (col = 0; col < src_cols; col++) {
       for (row = src_rows - 1; row >= 0; row--)
         *dest++ = src[row * src_cols + col];
    }

    No need to create bitmaps and use GetPixel and SetPixel.

    For information on stride, type:

        stride renderer

    In the search box in the top of this page.  The article you want about the video renderer is about four down from the top.  Alternatively, download the DirectX 2004 SDK, as recommended on my site.  This has a standalone CHM file for dshow which can be easily searched.  If the output destination has stride, you need to make an easy modification to the loop as each row in the destination is completed.  I'll leave that one for you to figure out.

     

     

     

     

     


    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Tuesday, April 28, 2009 4:24 PM
  • Mahantesh, I saw your query so I've uploaded a basic rotation filter for RGB24/32 into our source forge project. You can get the source at: http://sourceforge.net/projects/videoprocessing/

    You'll have to build the filter yourself (We provide VS2005 and 2008 solutions) and you can test it using graphedit. Use the filter property page to select the rotation mode. There's still some work to be done with respect to stride and dynamic reconnect, but it should give you a good starting point.

    Hope that helps. Any queries, email me at rglobisch (AT) csir (DOT) co (DOT) za
    http://sourceforge.net/projects/videoprocessing/
    Wednesday, April 29, 2009 6:55 AM
  • Hi Ralf,

    Thanks for sharing the code. I have modified few parts of the code and its working fine for No-rotation,180, flip vertical modes. I am facing problem rotating 90 degree and 270 degree. Image is appearing to be rotated but 4 blurred images are appearing with lesser widths.

    Let me know if you are facing the same problem.
    Mahantesh Ganamukhi
    Wednesday, April 29, 2009 11:11 PM
  • Doesn't the four lines of code I posted above (three lines if you skip the optional braces I put in) do a 90 degree transform for you?
    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Thursday, April 30, 2009 2:22 AM
  • Mahantesh, I've made a minor fix, you can get the latest version on SF. Mine seems to be working fine in most cases.
    I've only tested using RGB24 and 32 CIF inputs. What input are you using?
    In the meanwhile I suggest you substitute my overly complex 90 deg rotation with The March Hare's suggestion.

    Have found a bug though: in the case of an RGB32 288x351 input my stride/padding calculation seems incorrect, it looks like
    stride = (biWidth * (biBitCount / 8) + 3) & ~3;
    padding = stride - (biBitCount / 8 * biWidth);
    isn't sufficient to calculate the correct padding, from reading The March Hare's post I'm guessing that I need to align the data on a 64 bit boundary.
    The resulting image is skewed along the diagonal. I'll fix that as soon as I get a chance.

    http://sourceforge.net/projects/videoprocessing/
    Thursday, April 30, 2009 6:06 AM
  • Thanks for the vote of confidence, Ralf.  I think all that is needed if there is stride on the output pin is:

      dest += dest_stride - dest_cols;

    after the inner loop.  Adding a statement like this is one reason I always put a brace around an outer loop :)
    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Thursday, April 30, 2009 8:02 AM
  • Thanks for the vote of confidence, Ralf.  I think all that is needed if there is stride on the output pin is:

      dest += dest_stride - dest_cols;

    after the inner loop.  Adding a statement like this is one reason I always put a brace around an outer loop :)
    My dshow site is http://tmhare.mvps.org .  Please use Vote As Helpful and Mark As Answer where appropriate.
    Thanks, I'll give that a try :)

    BTW, the vote of confidence is well deserved, I'm grateful to have guys like you and the other experts on this forum.

    http://sourceforge.net/projects/videoprocessing/
    Thursday, April 30, 2009 9:08 AM
  • Thanks, Ralf.  I appreciate your help in the community too :)
    My dshow site is http://tmhare.mvps.org.  Please use Vote As Helpful and Mark As Answer where appropriate.
    Thursday, April 30, 2009 4:43 PM