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
20class VideoBufferLock
21{
22public:
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
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
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
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
98private:
99    IMFMediaBuffer  *m_pBuffer;
100    IMF2DBuffer     *m_p2DBuffer;
101};
102