summaryrefslogtreecommitdiff
path: root/src/multimedia/video/qabstractvideobuffer.cpp
blob: 50e38a98cc67263dda73b96b74606a1ff00d8eb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qabstractvideobuffer_p.h"

#include <qvariant.h>

#include <QDebug>


QT_BEGIN_NAMESPACE

static void qRegisterAbstractVideoBufferMetaTypes()
{
    qRegisterMetaType<QAbstractVideoBuffer::HandleType>();
    qRegisterMetaType<QAbstractVideoBuffer::MapMode>();
}

Q_CONSTRUCTOR_FUNCTION(qRegisterAbstractVideoBufferMetaTypes)

int QAbstractVideoBufferPrivate::map(
            QAbstractVideoBuffer::MapMode mode,
            int *numBytes,
            int bytesPerLine[4],
            uchar *data[4])
{
    data[0] = q_ptr->map(mode, numBytes, bytesPerLine);
    return data[0] ? 1 : 0;
}

/*!
    \class QAbstractVideoBuffer
    \brief The QAbstractVideoBuffer class is an abstraction for video data.
    \inmodule QtMultimedia
    \ingroup multimedia
    \ingroup multimedia_video

    The QVideoFrame class makes use of a QAbstractVideoBuffer internally to reference a buffer of
    video data.  Quite often video data buffers may reside in video memory rather than system
    memory, and this class provides an abstraction of the location.

    In addition, creating a subclass of QAbstractVideoBuffer will allow you to construct video
    frames from preallocated or static buffers, in cases where the QVideoFrame constructors
    taking a QByteArray or a QImage do not suffice.  This may be necessary when implementing
    a new hardware accelerated video system, for example.

    The contents of a buffer can be accessed by mapping the buffer to memory using the map()
    function, which returns a pointer to memory containing the contents of the video buffer.
    The memory returned by map() is released by calling the unmap() function.

    The handle() of a buffer may also be used to manipulate its contents using type specific APIs.
    The type of a buffer's handle is given by the handleType() function.

    \sa QVideoFrame
*/

/*!
    \enum QAbstractVideoBuffer::HandleType

    Identifies the type of a video buffers handle.

    \value NoHandle The buffer has no handle, its data can only be accessed by mapping the buffer.
    \value GLTextureHandle The handle of the buffer is an OpenGL texture ID.
    \value XvShmImageHandle The handle contains pointer to shared memory XVideo image.
    \value CoreImageHandle The handle contains pointer to \macos CIImage.
    \value QPixmapHandle The handle of the buffer is a QPixmap.
    \value EGLImageHandle The handle of the buffer is an EGLImageKHR.
    \value UserHandle Start value for user defined handle types.

    \sa handleType()
*/

/*!
    \enum QAbstractVideoBuffer::MapMode

    Enumerates how a video buffer's data is mapped to system memory.

    \value NotMapped The video buffer is not mapped to memory.
    \value ReadOnly The mapped memory is populated with data from the video buffer when mapped, but
    the content of the mapped memory may be discarded when unmapped.
    \value WriteOnly The mapped memory is uninitialized when mapped, but the possibly modified content
    will be used to populate the video buffer when unmapped.
    \value ReadWrite The mapped memory is populated with data from the video buffer, and the
    video buffer is repopulated with the content of the mapped memory when it is unmapped.

    \sa mapMode(), map()
*/

/*!
    Constructs an abstract video buffer of the given \a type.
*/
QAbstractVideoBuffer::QAbstractVideoBuffer(HandleType type)
    : d_ptr(0)
    , m_type(type)
{
}

/*!
    \internal
*/
QAbstractVideoBuffer::QAbstractVideoBuffer(QAbstractVideoBufferPrivate &dd, HandleType type)
    : d_ptr(&dd)
    , m_type(type)
{
    d_ptr->q_ptr = this;
}

/*!
    Destroys an abstract video buffer.
*/
QAbstractVideoBuffer::~QAbstractVideoBuffer()
{
    delete d_ptr;
}

/*!
    Releases the video buffer.

    QVideoFrame calls QAbstractVideoBuffer::release when the buffer is not used
    any more and can be destroyed or returned to the buffer pool.

    The default implementation deletes the buffer instance.
*/
void QAbstractVideoBuffer::release()
{
    delete this;
}

/*!
    Returns the type of a video buffer's handle.

    \sa handle()
*/
QAbstractVideoBuffer::HandleType QAbstractVideoBuffer::handleType() const
{
    return m_type;
}

/*!
    \fn QAbstractVideoBuffer::mapMode() const

    Returns the mode a video buffer is mapped in.

    \sa map()
*/

/*!
    \fn QAbstractVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)

    Maps the contents of a video buffer to memory.

    In some cases the video buffer might be stored in video memory or otherwise inaccessible
    memory, so it is necessary to map the buffer before accessing the pixel data.  This may involve
    copying the contents around, so avoid mapping and unmapping unless required.

    The map \a mode indicates whether the contents of the mapped memory should be read from and/or
    written to the buffer.  If the map mode includes the \c QAbstractVideoBuffer::ReadOnly flag the
    mapped memory will be populated with the content of the buffer when initially mapped.  If the map
    mode includes the \c QAbstractVideoBuffer::WriteOnly flag the content of the possibly modified
    mapped memory will be written back to the buffer when unmapped.

    When access to the data is no longer needed be sure to call the unmap() function to release the
    mapped memory and possibly update the buffer contents.

    Returns a pointer to the mapped memory region, or a null pointer if the mapping failed.  The
    size in bytes of the mapped memory region is returned in \a numBytes, and the line stride in \a
    bytesPerLine.

    \note Writing to memory that is mapped as read-only is undefined, and may result in changes
    to shared data or crashes.

    \sa unmap(), mapMode()
*/


/*!
    Independently maps the planes of a video buffer to memory.

    The map \a mode indicates whether the contents of the mapped memory should be read from and/or
    written to the buffer.  If the map mode includes the \c QAbstractVideoBuffer::ReadOnly flag the
    mapped memory will be populated with the content of the buffer when initially mapped.  If the map
    mode includes the \c QAbstractVideoBuffer::WriteOnly flag the content of the possibly modified
    mapped memory will be written back to the buffer when unmapped.

    When access to the data is no longer needed be sure to call the unmap() function to release the
    mapped memory and possibly update the buffer contents.

    Returns the number of planes in the mapped video data.  For each plane the line stride of that
    plane will be returned in \a bytesPerLine, and a pointer to the plane data will be returned in
    \a data.  The accumulative size of the mapped data is returned in \a numBytes.

    Not all buffer implementations will map more than the first plane, if this returns a single
    plane for a planar format the additional planes will have to be calculated from the line stride
    of the first plane and the frame height.  Mapping a buffer with QVideoFrame will do this for
    you.

    To implement this function create a derivative of QAbstractPlanarVideoBuffer and implement
    its map function instance instead.

    \since 5.4
*/
int QAbstractVideoBuffer::mapPlanes(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4])
{
    if (d_ptr) {
        return d_ptr->map(mode, numBytes, bytesPerLine, data);
    } else {
        data[0] = map(mode, numBytes, bytesPerLine);

        return data[0] ? 1 : 0;
    }
}

/*!
    \fn QAbstractVideoBuffer::unmap()

    Releases the memory mapped by the map() function.

    If the \l {QAbstractVideoBuffer::MapMode}{MapMode} included the \c QAbstractVideoBuffer::WriteOnly
    flag this will write the current content of the mapped memory back to the video frame.

    \sa map()
*/

/*!
    Returns a type specific handle to the data buffer.

    The type of the handle is given by handleType() function.

    \sa handleType()
*/
QVariant QAbstractVideoBuffer::handle() const
{
    return QVariant();
}


int QAbstractPlanarVideoBufferPrivate::map(
        QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4])
{
    return q_func()->map(mode, numBytes, bytesPerLine, data);
}

/*!
    \class QAbstractPlanarVideoBuffer
    \brief The QAbstractPlanarVideoBuffer class is an abstraction for planar video data.
    \inmodule QtMultimedia
    \ingroup QtMultimedia
    \ingroup multimedia
    \ingroup multimedia_video

    QAbstractPlanarVideoBuffer extends QAbstractVideoBuffer to support mapping
    non-continuous planar video data.  Implement this instead of QAbstractVideoBuffer when the
    abstracted video data stores planes in separate buffers or includes padding between planes
    which would interfere with calculating offsets from the bytes per line and frame height.

    \sa QAbstractVideoBuffer::mapPlanes()
    \since 5.4
*/

/*!
    Constructs an abstract planar video buffer of the given \a type.
*/
QAbstractPlanarVideoBuffer::QAbstractPlanarVideoBuffer(HandleType type)
    : QAbstractVideoBuffer(*new QAbstractPlanarVideoBufferPrivate, type)
{
}

/*!
    \internal
*/
QAbstractPlanarVideoBuffer::QAbstractPlanarVideoBuffer(
        QAbstractPlanarVideoBufferPrivate &dd, HandleType type)
    : QAbstractVideoBuffer(dd, type)
{
}
/*!
    Destroys an abstract planar video buffer.
*/
QAbstractPlanarVideoBuffer::~QAbstractPlanarVideoBuffer()
{
}

/*!
    \internal
*/
uchar *QAbstractPlanarVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
{
    uchar *data[4];
    int strides[4];
    if (map(mode, numBytes, strides, data) > 0) {
        if (bytesPerLine)
            *bytesPerLine = strides[0];
        return data[0];
    } else {
        return 0;
    }
}

/*!
    \fn int QAbstractPlanarVideoBuffer::map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4])

    Maps the contents of a video buffer to memory.

    The map \a mode indicates whether the contents of the mapped memory should be read from and/or
    written to the buffer.  If the map mode includes the \c QAbstractVideoBuffer::ReadOnly flag the
    mapped memory will be populated with the content of the buffer when initially mapped.  If the map
    mode includes the \c QAbstractVideoBuffer::WriteOnly flag the content of the possibly modified
    mapped memory will be written back to the buffer when unmapped.

    When access to the data is no longer needed be sure to call the unmap() function to release the
    mapped memory and possibly update the buffer contents.

    Returns the number of planes in the mapped video data.  For each plane the line stride of that
    plane will be returned in \a bytesPerLine, and a pointer to the plane data will be returned in
    \a data.  The accumulative size of the mapped data is returned in \a numBytes.

    \sa QAbstractVideoBuffer::map(), QAbstractVideoBuffer::unmap(), QAbstractVideoBuffer::mapMode()
*/

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, QAbstractVideoBuffer::HandleType type)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace();
    switch (type) {
    case QAbstractVideoBuffer::NoHandle:
        return dbg << "NoHandle";
    case QAbstractVideoBuffer::GLTextureHandle:
        return dbg << "GLTextureHandle";
    case QAbstractVideoBuffer::XvShmImageHandle:
        return dbg << "XvShmImageHandle";
    case QAbstractVideoBuffer::CoreImageHandle:
        return dbg << "CoreImageHandle";
    case QAbstractVideoBuffer::QPixmapHandle:
        return dbg << "QPixmapHandle";
    default:
        return dbg << "UserHandle(" << int(type) << ')';
    }
}

QDebug operator<<(QDebug dbg, QAbstractVideoBuffer::MapMode mode)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace();
    switch (mode) {
    case QAbstractVideoBuffer::ReadOnly:
        return dbg << "ReadOnly";
    case QAbstractVideoBuffer::ReadWrite:
        return dbg << "ReadWrite";
    case QAbstractVideoBuffer::WriteOnly:
        return dbg << "WriteOnly";
    default:
        return dbg << "NotMapped";
    }
}
#endif

QT_END_NAMESPACE