1 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
2 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
3 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
4 // PARTICULAR PURPOSE.
5 //
6 // Copyright (c) Microsoft Corporation. All rights reserved
7 
8 
9 #pragma once
10 
11 
12 //////////////////////////////////////////////////////////////////////////
13 //  VideoBufferLock
14 //
15 //  Description:
16 //  Locks a video buffer that might or might not support IMF2DBuffer.
17 //
18 //////////////////////////////////////////////////////////////////////////
19 
20 class VideoBufferLock
21 {
22 public:
VideoBufferLock(IMFMediaBuffer * pBuffer)23     VideoBufferLock(IMFMediaBuffer *pBuffer) : m_p2DBuffer(NULL)
24     {
25         m_pBuffer = pBuffer;
26         m_pBuffer->AddRef();
27 
28         // Query for the 2-D buffer interface. OK if this fails.
29         m_pBuffer->QueryInterface(IID_PPV_ARGS(&m_p2DBuffer));
30     }
31 
~VideoBufferLock()32     ~VideoBufferLock()
33     {
34         UnlockBuffer();
35         SafeRelease(&m_pBuffer);
36         SafeRelease(&m_p2DBuffer);
37     }
38 
39     // LockBuffer:
40     // Locks the buffer. Returns a pointer to scan line 0 and returns the stride.
41 
42     // The caller must provide the default stride as an input parameter, in case
43     // the buffer does not expose IMF2DBuffer. You can calculate the default stride
44     // from the media type.
45 
LockBuffer(LONG lDefaultStride,DWORD dwHeightInPixels,BYTE ** ppbScanLine0,LONG * plStride)46     HRESULT LockBuffer(
47         LONG  lDefaultStride,    // Minimum stride (with no padding).
48         DWORD dwHeightInPixels,  // Height of the image, in pixels.
49         BYTE  **ppbScanLine0,    // Receives a pointer to the start of scan line 0.
50         LONG  *plStride          // Receives the actual stride.
51         )
52     {
53         HRESULT hr = S_OK;
54 
55         // Use the 2-D version if available.
56         if (m_p2DBuffer)
57         {
58             hr = m_p2DBuffer->Lock2D(ppbScanLine0, plStride);
59         }
60         else
61         {
62             // Use non-2D version.
63             BYTE *pData = NULL;
64 
65             hr = m_pBuffer->Lock(&pData, NULL, NULL);
66             if (SUCCEEDED(hr))
67             {
68                 *plStride = lDefaultStride;
69                 if (lDefaultStride < 0)
70                 {
71                     // Bottom-up orientation. Return a pointer to the start of the
72                     // last row *in memory* which is the top row of the image.
73                     *ppbScanLine0 = pData + abs(lDefaultStride) * (dwHeightInPixels - 1);
74                 }
75                 else
76                 {
77                     // Top-down orientation. Return a pointer to the start of the
78                     // buffer.
79                     *ppbScanLine0 = pData;
80                 }
81             }
82         }
83         return hr;
84     }
85 
UnlockBuffer()86     HRESULT UnlockBuffer()
87     {
88         if (m_p2DBuffer)
89         {
90             return m_p2DBuffer->Unlock2D();
91         }
92         else
93         {
94             return m_pBuffer->Unlock();
95         }
96     }
97 
98 private:
99     IMFMediaBuffer  *m_pBuffer;
100     IMF2DBuffer     *m_p2DBuffer;
101 };
102