1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qvideoframe.h"
41
42#include "qvideoframe_p.h"
43#include "qimagevideobuffer_p.h"
44#include "qmemoryvideobuffer_p.h"
45#include "qvideoframeconversionhelper_p.h"
46
47#include <qimage.h>
48#include <qpair.h>
49#include <qsize.h>
50#include <qvariant.h>
51#include <qvector.h>
52#include <qmutex.h>
53
54#include <QDebug>
55
56QT_BEGIN_NAMESPACE
57
58static void qRegisterVideoFrameMetaTypes()
59{
60 qRegisterMetaType<QVideoFrame>();
61 qRegisterMetaType<QVideoFrame::FieldType>();
62 qRegisterMetaType<QVideoFrame::PixelFormat>();
63}
64
65Q_CONSTRUCTOR_FUNCTION(qRegisterVideoFrameMetaTypes)
66
67
68class QVideoFramePrivate : public QSharedData
69{
70public:
71 QVideoFramePrivate()
72 : startTime(-1)
73 , endTime(-1)
74 , mappedBytes(0)
75 , planeCount(0)
76 , pixelFormat(QVideoFrame::Format_Invalid)
77 , fieldType(QVideoFrame::ProgressiveFrame)
78 , buffer(nullptr)
79 , mappedCount(0)
80 {
81 memset(data, 0, sizeof(data));
82 memset(bytesPerLine, 0, sizeof(bytesPerLine));
83 }
84
85 QVideoFramePrivate(const QSize &size, QVideoFrame::PixelFormat format)
86 : size(size)
87 , startTime(-1)
88 , endTime(-1)
89 , mappedBytes(0)
90 , planeCount(0)
91 , pixelFormat(format)
92 , fieldType(QVideoFrame::ProgressiveFrame)
93 , buffer(nullptr)
94 , mappedCount(0)
95 {
96 memset(data, 0, sizeof(data));
97 memset(bytesPerLine, 0, sizeof(bytesPerLine));
98 }
99
100 ~QVideoFramePrivate()
101 {
102 if (buffer)
103 buffer->release();
104 }
105
106 QSize size;
107 qint64 startTime;
108 qint64 endTime;
109 uchar *data[4];
110 int bytesPerLine[4];
111 int mappedBytes;
112 int planeCount;
113 QVideoFrame::PixelFormat pixelFormat;
114 QVideoFrame::FieldType fieldType;
115 QAbstractVideoBuffer *buffer;
116 int mappedCount;
117 QMutex mapMutex;
118 QVariantMap metadata;
119
120private:
121 Q_DISABLE_COPY(QVideoFramePrivate)
122};
123
124/*!
125 \class QVideoFrame
126 \brief The QVideoFrame class represents a frame of video data.
127 \inmodule QtMultimedia
128
129 \ingroup multimedia
130 \ingroup multimedia_video
131
132 A QVideoFrame encapsulates the pixel data of a video frame, and information about the frame.
133
134 Video frames can come from several places - decoded \l {QMediaPlayer}{media}, a
135 \l {QCamera}{camera}, or generated programmatically. The way pixels are described in these
136 frames can vary greatly, and some pixel formats offer greater compression opportunities at
137 the expense of ease of use.
138
139 The pixel contents of a video frame can be mapped to memory using the map() function. While
140 mapped, the video data can accessed using the bits() function, which returns a pointer to a
141 buffer. The total size of this buffer is given by the mappedBytes() function, and the size of
142 each line is given by bytesPerLine(). The return value of the handle() function may also be
143 used to access frame data using the internal buffer's native APIs (for example - an OpenGL
144 texture handle).
145
146 A video frame can also have timestamp information associated with it. These timestamps can be
147 used by an implementation of \l QAbstractVideoSurface to determine when to start and stop
148 displaying the frame, but not all surfaces might respect this setting.
149
150 The video pixel data in a QVideoFrame is encapsulated in a QAbstractVideoBuffer. A QVideoFrame
151 may be constructed from any buffer type by subclassing the QAbstractVideoBuffer class.
152
153 \note Since video frames can be expensive to copy, QVideoFrame is explicitly shared, so any
154 change made to a video frame will also apply to any copies.
155*/
156
157/*!
158 \enum QVideoFrame::PixelFormat
159
160 Enumerates video data types.
161
162 \value Format_Invalid
163 The frame is invalid.
164
165 \value Format_ARGB32
166 The frame is stored using a 32-bit ARGB format (0xAARRGGBB). This is equivalent to
167 QImage::Format_ARGB32.
168
169 \value Format_ARGB32_Premultiplied
170 The frame stored using a premultiplied 32-bit ARGB format (0xAARRGGBB). This is equivalent
171 to QImage::Format_ARGB32_Premultiplied.
172
173 \value Format_RGB32
174 The frame stored using a 32-bit RGB format (0xffRRGGBB). This is equivalent to
175 QImage::Format_RGB32
176
177 \value Format_RGB24
178 The frame is stored using a 24-bit RGB format (8-8-8). This is equivalent to
179 QImage::Format_RGB888
180
181 \value Format_RGB565
182 The frame is stored using a 16-bit RGB format (5-6-5). This is equivalent to
183 QImage::Format_RGB16.
184
185 \value Format_RGB555
186 The frame is stored using a 16-bit RGB format (5-5-5). This is equivalent to
187 QImage::Format_RGB555.
188
189 \value Format_ARGB8565_Premultiplied
190 The frame is stored using a 24-bit premultiplied ARGB format (8-5-6-5).
191
192 \value Format_BGRA32
193 The frame is stored using a 32-bit BGRA format (0xBBGGRRAA).
194
195 \value Format_BGRA32_Premultiplied
196 The frame is stored using a premultiplied 32bit BGRA format.
197
198 \value Format_ABGR32
199 The frame is stored using a 32-bit ABGR format (0xAABBGGRR).
200
201 \value Format_BGR32
202 The frame is stored using a 32-bit BGR format (0xBBGGRRff).
203
204 \value Format_BGR24
205 The frame is stored using a 24-bit BGR format (0xBBGGRR).
206
207 \value Format_BGR565
208 The frame is stored using a 16-bit BGR format (5-6-5).
209
210 \value Format_BGR555
211 The frame is stored using a 16-bit BGR format (5-5-5).
212
213 \value Format_BGRA5658_Premultiplied
214 The frame is stored using a 24-bit premultiplied BGRA format (5-6-5-8).
215
216 \value Format_AYUV444
217 The frame is stored using a packed 32-bit AYUV format (0xAAYYUUVV).
218
219 \value Format_AYUV444_Premultiplied
220 The frame is stored using a packed premultiplied 32-bit AYUV format (0xAAYYUUVV).
221
222 \value Format_YUV444
223 The frame is stored using a 24-bit packed YUV format (8-8-8).
224
225 \value Format_YUV420P
226 The frame is stored using an 8-bit per component planar YUV format with the U and V planes
227 horizontally and vertically sub-sampled, i.e. the height and width of the U and V planes are
228 half that of the Y plane.
229
230 \value Format_YUV422P
231 The frame is stored using an 8-bit per component planar YUV format with the U and V planes
232 horizontally sub-sampled, i.e. the width of the U and V planes are
233 half that of the Y plane, and height of U and V planes is the same as Y.
234
235 \value Format_YV12
236 The frame is stored using an 8-bit per component planar YVU format with the V and U planes
237 horizontally and vertically sub-sampled, i.e. the height and width of the V and U planes are
238 half that of the Y plane.
239
240 \value Format_UYVY
241 The frame is stored using an 8-bit per component packed YUV format with the U and V planes
242 horizontally sub-sampled (U-Y-V-Y), i.e. two horizontally adjacent pixels are stored as a 32-bit
243 macropixel which has a Y value for each pixel and common U and V values.
244
245 \value Format_YUYV
246 The frame is stored using an 8-bit per component packed YUV format with the U and V planes
247 horizontally sub-sampled (Y-U-Y-V), i.e. two horizontally adjacent pixels are stored as a 32-bit
248 macropixel which has a Y value for each pixel and common U and V values.
249
250 \value Format_NV12
251 The frame is stored using an 8-bit per component semi-planar YUV format with a Y plane (Y)
252 followed by a horizontally and vertically sub-sampled, packed UV plane (U-V).
253
254 \value Format_NV21
255 The frame is stored using an 8-bit per component semi-planar YUV format with a Y plane (Y)
256 followed by a horizontally and vertically sub-sampled, packed VU plane (V-U).
257
258 \value Format_IMC1
259 The frame is stored using an 8-bit per component planar YUV format with the U and V planes
260 horizontally and vertically sub-sampled. This is similar to the Format_YUV420P type, except
261 that the bytes per line of the U and V planes are padded out to the same stride as the Y plane.
262
263 \value Format_IMC2
264 The frame is stored using an 8-bit per component planar YUV format with the U and V planes
265 horizontally and vertically sub-sampled. This is similar to the Format_YUV420P type, except
266 that the lines of the U and V planes are interleaved, i.e. each line of U data is followed by a
267 line of V data creating a single line of the same stride as the Y data.
268
269 \value Format_IMC3
270 The frame is stored using an 8-bit per component planar YVU format with the V and U planes
271 horizontally and vertically sub-sampled. This is similar to the Format_YV12 type, except that
272 the bytes per line of the V and U planes are padded out to the same stride as the Y plane.
273
274 \value Format_IMC4
275 The frame is stored using an 8-bit per component planar YVU format with the V and U planes
276 horizontally and vertically sub-sampled. This is similar to the Format_YV12 type, except that
277 the lines of the V and U planes are interleaved, i.e. each line of V data is followed by a line
278 of U data creating a single line of the same stride as the Y data.
279
280 \value Format_Y8
281 The frame is stored using an 8-bit greyscale format.
282
283 \value Format_Y16
284 The frame is stored using a 16-bit linear greyscale format. Little endian.
285
286 \value Format_Jpeg
287 The frame is stored in compressed Jpeg format.
288
289 \value Format_CameraRaw
290 The frame is stored using a device specific camera raw format.
291
292 \value Format_AdobeDng
293 The frame is stored using raw Adobe Digital Negative (DNG) format.
294
295 \value Format_User
296 Start value for user defined pixel formats.
297*/
298
299/*!
300 \enum QVideoFrame::FieldType
301
302 Specifies the field an interlaced video frame belongs to.
303
304 \value ProgressiveFrame The frame is not interlaced.
305 \value TopField The frame contains a top field.
306 \value BottomField The frame contains a bottom field.
307 \value InterlacedFrame The frame contains a merged top and bottom field.
308*/
309
310/*!
311 Constructs a null video frame.
312*/
313QVideoFrame::QVideoFrame()
314 : d(new QVideoFramePrivate)
315{
316}
317
318/*!
319 Constructs a video frame from a \a buffer with the given pixel \a format and \a size in pixels.
320
321 \note This doesn't increment the reference count of the video buffer.
322*/
323QVideoFrame::QVideoFrame(
324 QAbstractVideoBuffer *buffer, const QSize &size, PixelFormat format)
325 : d(new QVideoFramePrivate(size, format))
326{
327 d->buffer = buffer;
328}
329
330/*!
331 Constructs a video frame of the given pixel \a format and \a size in pixels.
332
333 The \a bytesPerLine (stride) is the length of each scan line in bytes, and \a bytes is the total
334 number of bytes that must be allocated for the frame.
335*/
336QVideoFrame::QVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format)
337 : d(new QVideoFramePrivate(size, format))
338{
339 if (bytes > 0) {
340 QByteArray data;
341 data.resize(bytes);
342
343 // Check the memory was successfully allocated.
344 if (!data.isEmpty())
345 d->buffer = new QMemoryVideoBuffer(data, bytesPerLine);
346 }
347}
348
349/*!
350 Constructs a video frame from an \a image.
351
352 \note This will construct an invalid video frame if there is no frame type equivalent to the
353 image format.
354
355 \sa pixelFormatFromImageFormat()
356*/
357QVideoFrame::QVideoFrame(const QImage &image)
358 : d(new QVideoFramePrivate(
359 image.size(), pixelFormatFromImageFormat(image.format())))
360{
361 if (d->pixelFormat != Format_Invalid)
362 d->buffer = new QImageVideoBuffer(image);
363}
364
365/*!
366 Constructs a shallow copy of \a other. Since QVideoFrame is
367 explicitly shared, these two instances will reflect the same frame.
368
369*/
370QVideoFrame::QVideoFrame(const QVideoFrame &other)
371 : d(other.d)
372{
373}
374
375/*!
376 Assigns the contents of \a other to this video frame. Since QVideoFrame is
377 explicitly shared, these two instances will reflect the same frame.
378
379*/
380QVideoFrame &QVideoFrame::operator =(const QVideoFrame &other)
381{
382 d = other.d;
383
384 return *this;
385}
386
387/*!
388 \return \c true if this QVideoFrame and \a other reflect the same frame.
389 */
390bool QVideoFrame::operator==(const QVideoFrame &other) const
391{
392 // Due to explicit sharing we just compare the QSharedData which in turn compares the pointers.
393 return d == other.d;
394}
395
396/*!
397 \return \c true if this QVideoFrame and \a other do not reflect the same frame.
398 */
399bool QVideoFrame::operator!=(const QVideoFrame &other) const
400{
401 return d != other.d;
402}
403
404/*!
405 Destroys a video frame.
406*/
407QVideoFrame::~QVideoFrame()
408{
409}
410
411/*!
412 \return underlying video buffer or \c null if there is none.
413 \since 5.13
414*/
415QAbstractVideoBuffer *QVideoFrame::buffer() const
416{
417 return d->buffer;
418}
419
420/*!
421 Identifies whether a video frame is valid.
422
423 An invalid frame has no video buffer associated with it.
424
425 Returns true if the frame is valid, and false if it is not.
426*/
427bool QVideoFrame::isValid() const
428{
429 return d->buffer != nullptr;
430}
431
432/*!
433 Returns the color format of a video frame.
434*/
435QVideoFrame::PixelFormat QVideoFrame::pixelFormat() const
436{
437 return d->pixelFormat;
438}
439
440/*!
441 Returns the type of a video frame's handle.
442
443*/
444QAbstractVideoBuffer::HandleType QVideoFrame::handleType() const
445{
446 return d->buffer ? d->buffer->handleType() : QAbstractVideoBuffer::NoHandle;
447}
448
449/*!
450 Returns the dimensions of a video frame.
451*/
452QSize QVideoFrame::size() const
453{
454 return d->size;
455}
456
457/*!
458 Returns the width of a video frame.
459*/
460int QVideoFrame::width() const
461{
462 return d->size.width();
463}
464
465/*!
466 Returns the height of a video frame.
467*/
468int QVideoFrame::height() const
469{
470 return d->size.height();
471}
472
473/*!
474 Returns the field an interlaced video frame belongs to.
475
476 If the video is not interlaced this will return WholeFrame.
477*/
478QVideoFrame::FieldType QVideoFrame::fieldType() const
479{
480 return d->fieldType;
481}
482
483/*!
484 Sets the \a field an interlaced video frame belongs to.
485*/
486void QVideoFrame::setFieldType(QVideoFrame::FieldType field)
487{
488 d->fieldType = field;
489}
490
491/*!
492 Identifies if a video frame's contents are currently mapped to system memory.
493
494 This is a convenience function which checks that the \l {QAbstractVideoBuffer::MapMode}{MapMode}
495 of the frame is not equal to QAbstractVideoBuffer::NotMapped.
496
497 Returns true if the contents of the video frame are mapped to system memory, and false
498 otherwise.
499
500 \sa mapMode(), QAbstractVideoBuffer::MapMode
501*/
502
503bool QVideoFrame::isMapped() const
504{
505 return d->buffer != nullptr && d->buffer->mapMode() != QAbstractVideoBuffer::NotMapped;
506}
507
508/*!
509 Identifies if the mapped contents of a video frame will be persisted when the frame is unmapped.
510
511 This is a convenience function which checks if the \l {QAbstractVideoBuffer::MapMode}{MapMode}
512 contains the QAbstractVideoBuffer::WriteOnly flag.
513
514 Returns true if the video frame will be updated when unmapped, and false otherwise.
515
516 \note The result of altering the data of a frame that is mapped in read-only mode is undefined.
517 Depending on the buffer implementation the changes may be persisted, or worse alter a shared
518 buffer.
519
520 \sa mapMode(), QAbstractVideoBuffer::MapMode
521*/
522bool QVideoFrame::isWritable() const
523{
524 return d->buffer != nullptr && (d->buffer->mapMode() & QAbstractVideoBuffer::WriteOnly);
525}
526
527/*!
528 Identifies if the mapped contents of a video frame were read from the frame when it was mapped.
529
530 This is a convenience function which checks if the \l {QAbstractVideoBuffer::MapMode}{MapMode}
531 contains the QAbstractVideoBuffer::WriteOnly flag.
532
533 Returns true if the contents of the mapped memory were read from the video frame, and false
534 otherwise.
535
536 \sa mapMode(), QAbstractVideoBuffer::MapMode
537*/
538bool QVideoFrame::isReadable() const
539{
540 return d->buffer != nullptr && (d->buffer->mapMode() & QAbstractVideoBuffer::ReadOnly);
541}
542
543/*!
544 Returns the mode a video frame was mapped to system memory in.
545
546 \sa map(), QAbstractVideoBuffer::MapMode
547*/
548QAbstractVideoBuffer::MapMode QVideoFrame::mapMode() const
549{
550 return d->buffer != nullptr ? d->buffer->mapMode() : QAbstractVideoBuffer::NotMapped;
551}
552
553/*!
554 Maps the contents of a video frame to system (CPU addressable) memory.
555
556 In some cases the video frame data might be stored in video memory or otherwise inaccessible
557 memory, so it is necessary to map a frame before accessing the pixel data. This may involve
558 copying the contents around, so avoid mapping and unmapping unless required.
559
560 The map \a mode indicates whether the contents of the mapped memory should be read from and/or
561 written to the frame. If the map mode includes the \c QAbstractVideoBuffer::ReadOnly flag the
562 mapped memory will be populated with the content of the video frame when initially mapped. If the map
563 mode includes the \c QAbstractVideoBuffer::WriteOnly flag the content of the possibly modified
564 mapped memory will be written back to the frame when unmapped.
565
566 While mapped the contents of a video frame can be accessed directly through the pointer returned
567 by the bits() function.
568
569 When access to the data is no longer needed, be sure to call the unmap() function to release the
570 mapped memory and possibly update the video frame contents.
571
572 If the video frame has been mapped in read only mode, it is permissible to map it
573 multiple times in read only mode (and unmap it a corresponding number of times). In all
574 other cases it is necessary to unmap the frame first before mapping a second time.
575
576 \note Writing to memory that is mapped as read-only is undefined, and may result in changes
577 to shared data or crashes.
578
579 Returns true if the frame was mapped to memory in the given \a mode and false otherwise.
580
581 \sa unmap(), mapMode(), bits()
582*/
583bool QVideoFrame::map(QAbstractVideoBuffer::MapMode mode)
584{
585 QMutexLocker lock(&d->mapMutex);
586
587 if (!d->buffer)
588 return false;
589
590 if (mode == QAbstractVideoBuffer::NotMapped)
591 return false;
592
593 if (d->mappedCount > 0) {
594 //it's allowed to map the video frame multiple times in read only mode
595 if (d->buffer->mapMode() == QAbstractVideoBuffer::ReadOnly
596 && mode == QAbstractVideoBuffer::ReadOnly) {
597 d->mappedCount++;
598 return true;
599 } else {
600 return false;
601 }
602 }
603
604 Q_ASSERT(d->data[0] == nullptr);
605 Q_ASSERT(d->bytesPerLine[0] == 0);
606 Q_ASSERT(d->planeCount == 0);
607 Q_ASSERT(d->mappedBytes == 0);
608
609 d->planeCount = d->buffer->mapPlanes(mode, &d->mappedBytes, d->bytesPerLine, d->data);
610 if (d->planeCount == 0)
611 return false;
612
613 if (d->planeCount > 1) {
614 // If the plane count is derive the additional planes for planar formats.
615 } else switch (d->pixelFormat) {
616 case Format_Invalid:
617 case Format_ARGB32:
618 case Format_ARGB32_Premultiplied:
619 case Format_RGB32:
620 case Format_RGB24:
621 case Format_RGB565:
622 case Format_RGB555:
623 case Format_ARGB8565_Premultiplied:
624 case Format_BGRA32:
625 case Format_BGRA32_Premultiplied:
626 case Format_ABGR32:
627 case Format_BGR32:
628 case Format_BGR24:
629 case Format_BGR565:
630 case Format_BGR555:
631 case Format_BGRA5658_Premultiplied:
632 case Format_AYUV444:
633 case Format_AYUV444_Premultiplied:
634 case Format_YUV444:
635 case Format_UYVY:
636 case Format_YUYV:
637 case Format_Y8:
638 case Format_Y16:
639 case Format_Jpeg:
640 case Format_CameraRaw:
641 case Format_AdobeDng:
642 case Format_User:
643 // Single plane or opaque format.
644 break;
645 case Format_YUV420P:
646 case Format_YUV422P:
647 case Format_YV12: {
648 // The UV stride is usually half the Y stride and is 32-bit aligned.
649 // However it's not always the case, at least on Windows where the
650 // UV planes are sometimes not aligned.
651 // We calculate the stride using the UV byte count to always
652 // have a correct stride.
653 const int height = d->size.height();
654 const int yStride = d->bytesPerLine[0];
655 const int uvHeight = d->pixelFormat == Format_YUV422P ? height : height / 2;
656 const int uvStride = (d->mappedBytes - (yStride * height)) / uvHeight / 2;
657
658 // Three planes, the second and third vertically (and horizontally for other than Format_YUV422P formats) subsampled.
659 d->planeCount = 3;
660 d->bytesPerLine[2] = d->bytesPerLine[1] = uvStride;
661 d->data[1] = d->data[0] + (yStride * height);
662 d->data[2] = d->data[1] + (uvStride * uvHeight);
663 break;
664 }
665 case Format_NV12:
666 case Format_NV21:
667 case Format_IMC2:
668 case Format_IMC4: {
669 // Semi planar, Full resolution Y plane with interleaved subsampled U and V planes.
670 d->planeCount = 2;
671 d->bytesPerLine[1] = d->bytesPerLine[0];
672 d->data[1] = d->data[0] + (d->bytesPerLine[0] * d->size.height());
673 break;
674 }
675 case Format_IMC1:
676 case Format_IMC3: {
677 // Three planes, the second and third vertically and horizontally subsumpled,
678 // but with lines padded to the width of the first plane.
679 d->planeCount = 3;
680 d->bytesPerLine[2] = d->bytesPerLine[1] = d->bytesPerLine[0];
681 d->data[1] = d->data[0] + (d->bytesPerLine[0] * d->size.height());
682 d->data[2] = d->data[1] + (d->bytesPerLine[1] * d->size.height() / 2);
683 break;
684 }
685 default:
686 break;
687 }
688
689 d->mappedCount++;
690 return true;
691}
692
693/*!
694 Releases the memory mapped by the map() function.
695
696 If the \l {QAbstractVideoBuffer::MapMode}{MapMode} included the QAbstractVideoBuffer::WriteOnly
697 flag this will persist the current content of the mapped memory to the video frame.
698
699 unmap() should not be called if map() function failed.
700
701 \sa map()
702*/
703void QVideoFrame::unmap()
704{
705 QMutexLocker lock(&d->mapMutex);
706
707 if (!d->buffer)
708 return;
709
710 if (d->mappedCount == 0) {
711 qWarning() << "QVideoFrame::unmap() was called more times then QVideoFrame::map()";
712 return;
713 }
714
715 d->mappedCount--;
716
717 if (d->mappedCount == 0) {
718 d->mappedBytes = 0;
719 d->planeCount = 0;
720 memset(d->bytesPerLine, 0, sizeof(d->bytesPerLine));
721 memset(d->data, 0, sizeof(d->data));
722
723 d->buffer->unmap();
724 }
725}
726
727/*!
728 Returns the number of bytes in a scan line.
729
730 \note For planar formats this is the bytes per line of the first plane only. The bytes per line of subsequent
731 planes should be calculated as per the frame \l{QVideoFrame::PixelFormat}{pixel format}.
732
733 This value is only valid while the frame data is \l {map()}{mapped}.
734
735 \sa bits(), map(), mappedBytes()
736*/
737int QVideoFrame::bytesPerLine() const
738{
739 return d->bytesPerLine[0];
740}
741
742/*!
743 Returns the number of bytes in a scan line of a \a plane.
744
745 This value is only valid while the frame data is \l {map()}{mapped}.
746
747 \sa bits(), map(), mappedBytes(), planeCount()
748 \since 5.4
749*/
750
751int QVideoFrame::bytesPerLine(int plane) const
752{
753 return plane >= 0 && plane < d->planeCount ? d->bytesPerLine[plane] : 0;
754}
755
756/*!
757 Returns a pointer to the start of the frame data buffer.
758
759 This value is only valid while the frame data is \l {map()}{mapped}.
760
761 Changes made to data accessed via this pointer (when mapped with write access)
762 are only guaranteed to have been persisted when unmap() is called and when the
763 buffer has been mapped for writing.
764
765 \sa map(), mappedBytes(), bytesPerLine()
766*/
767uchar *QVideoFrame::bits()
768{
769 return d->data[0];
770}
771
772/*!
773 Returns a pointer to the start of the frame data buffer for a \a plane.
774
775 This value is only valid while the frame data is \l {map()}{mapped}.
776
777 Changes made to data accessed via this pointer (when mapped with write access)
778 are only guaranteed to have been persisted when unmap() is called and when the
779 buffer has been mapped for writing.
780
781 \sa map(), mappedBytes(), bytesPerLine(), planeCount()
782 \since 5.4
783*/
784uchar *QVideoFrame::bits(int plane)
785{
786 return plane >= 0 && plane < d->planeCount ? d->data[plane] : nullptr;
787}
788
789/*!
790 Returns a pointer to the start of the frame data buffer.
791
792 This value is only valid while the frame data is \l {map()}{mapped}.
793
794 If the buffer was not mapped with read access, the contents of this
795 buffer will initially be uninitialized.
796
797 \sa map(), mappedBytes(), bytesPerLine()
798*/
799const uchar *QVideoFrame::bits() const
800{
801 return d->data[0];
802}
803
804/*!
805 Returns a pointer to the start of the frame data buffer for a \a plane.
806
807 This value is only valid while the frame data is \l {map()}{mapped}.
808
809 If the buffer was not mapped with read access, the contents of this
810 buffer will initially be uninitialized.
811
812 \sa map(), mappedBytes(), bytesPerLine(), planeCount()
813 \since 5.4
814*/
815const uchar *QVideoFrame::bits(int plane) const
816{
817 return plane >= 0 && plane < d->planeCount ? d->data[plane] : nullptr;
818}
819
820/*!
821 Returns the number of bytes occupied by the mapped frame data.
822
823 This value is only valid while the frame data is \l {map()}{mapped}.
824
825 \sa map()
826*/
827int QVideoFrame::mappedBytes() const
828{
829 return d->mappedBytes;
830}
831
832/*!
833 Returns the number of planes in the video frame.
834
835 This value is only valid while the frame data is \l {map()}{mapped}.
836
837 \sa map()
838 \since 5.4
839*/
840
841int QVideoFrame::planeCount() const
842{
843 return d->planeCount;
844}
845
846/*!
847 Returns a type specific handle to a video frame's buffer.
848
849 For an OpenGL texture this would be the texture ID.
850
851 \sa QAbstractVideoBuffer::handle()
852*/
853QVariant QVideoFrame::handle() const
854{
855 return d->buffer != nullptr ? d->buffer->handle() : QVariant();
856}
857
858/*!
859 Returns the presentation time (in microseconds) when the frame should be displayed.
860
861 An invalid time is represented as -1.
862
863*/
864qint64 QVideoFrame::startTime() const
865{
866 return d->startTime;
867}
868
869/*!
870 Sets the presentation \a time (in microseconds) when the frame should initially be displayed.
871
872 An invalid time is represented as -1.
873
874*/
875void QVideoFrame::setStartTime(qint64 time)
876{
877 d->startTime = time;
878}
879
880/*!
881 Returns the presentation time (in microseconds) when a frame should stop being displayed.
882
883 An invalid time is represented as -1.
884
885*/
886qint64 QVideoFrame::endTime() const
887{
888 return d->endTime;
889}
890
891/*!
892 Sets the presentation \a time (in microseconds) when a frame should stop being displayed.
893
894 An invalid time is represented as -1.
895
896*/
897void QVideoFrame::setEndTime(qint64 time)
898{
899 d->endTime = time;
900}
901
902/*!
903 Returns any extra metadata associated with this frame.
904 */
905QVariantMap QVideoFrame::availableMetaData() const
906{
907 return d->metadata;
908}
909
910/*!
911 Returns any metadata for this frame for the given \a key.
912
913 This might include frame specific information from
914 a camera, or subtitles from a decoded video stream.
915
916 See the documentation for the relevant video frame
917 producer for further information about available metadata.
918 */
919QVariant QVideoFrame::metaData(const QString &key) const
920{
921 return d->metadata.value(key);
922}
923
924/*!
925 Sets the metadata for the given \a key to \a value.
926
927 If \a value is a null variant, any metadata for this key will be removed.
928
929 The producer of the video frame might use this to associate
930 certain data with this frame, or for an intermediate processor
931 to add information for a consumer of this frame.
932 */
933void QVideoFrame::setMetaData(const QString &key, const QVariant &value)
934{
935 if (!value.isNull())
936 d->metadata.insert(key, value);
937 else
938 d->metadata.remove(key);
939}
940
941/*!
942 Returns a video pixel format equivalent to an image \a format. If there is no equivalent
943 format QVideoFrame::InvalidType is returned instead.
944
945 \note In general \l QImage does not handle YUV formats.
946
947*/
948QVideoFrame::PixelFormat QVideoFrame::pixelFormatFromImageFormat(QImage::Format format)
949{
950 switch (format) {
951 case QImage::Format_RGB32:
952 case QImage::Format_RGBX8888:
953 return Format_RGB32;
954 case QImage::Format_ARGB32:
955 case QImage::Format_RGBA8888:
956 return Format_ARGB32;
957 case QImage::Format_ARGB32_Premultiplied:
958 case QImage::Format_RGBA8888_Premultiplied:
959 return Format_ARGB32_Premultiplied;
960 case QImage::Format_RGB16:
961 return Format_RGB565;
962 case QImage::Format_ARGB8565_Premultiplied:
963 return Format_ARGB8565_Premultiplied;
964 case QImage::Format_RGB555:
965 return Format_RGB555;
966 case QImage::Format_RGB888:
967 return Format_RGB24;
968 default:
969 return Format_Invalid;
970 }
971}
972
973/*!
974 Returns an image format equivalent to a video frame pixel \a format. If there is no equivalent
975 format QImage::Format_Invalid is returned instead.
976
977 \note In general \l QImage does not handle YUV formats.
978
979*/
980QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format)
981{
982 switch (format) {
983 case Format_Invalid:
984 return QImage::Format_Invalid;
985 case Format_ARGB32:
986 return QImage::Format_ARGB32;
987 case Format_ARGB32_Premultiplied:
988 return QImage::Format_ARGB32_Premultiplied;
989 case Format_RGB32:
990 return QImage::Format_RGB32;
991 case Format_RGB24:
992 return QImage::Format_RGB888;
993 case Format_RGB565:
994 return QImage::Format_RGB16;
995 case Format_RGB555:
996 return QImage::Format_RGB555;
997 case Format_ARGB8565_Premultiplied:
998 return QImage::Format_ARGB8565_Premultiplied;
999 case Format_BGRA32:
1000 case Format_BGRA32_Premultiplied:
1001 case Format_BGR32:
1002 case Format_BGR24:
1003 return QImage::Format_Invalid;
1004 case Format_BGR565:
1005 case Format_BGR555:
1006 case Format_BGRA5658_Premultiplied:
1007 case Format_AYUV444:
1008 case Format_AYUV444_Premultiplied:
1009 case Format_YUV444:
1010 case Format_YUV420P:
1011 case Format_YUV422P:
1012 case Format_YV12:
1013 case Format_UYVY:
1014 case Format_YUYV:
1015 case Format_NV12:
1016 case Format_NV21:
1017 case Format_IMC1:
1018 case Format_IMC2:
1019 case Format_IMC3:
1020 case Format_IMC4:
1021 case Format_Y8:
1022 case Format_Y16:
1023 case Format_Jpeg:
1024 case Format_CameraRaw:
1025 case Format_AdobeDng:
1026 return QImage::Format_Invalid;
1027 case Format_User:
1028 default:
1029 return QImage::Format_Invalid;
1030 }
1031 return QImage::Format_Invalid;
1032}
1033
1034
1035extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32(const QVideoFrame&, uchar*);
1036extern void QT_FASTCALL qt_convert_BGR24_to_ARGB32(const QVideoFrame&, uchar*);
1037extern void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame&, uchar*);
1038extern void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame&, uchar*);
1039extern void QT_FASTCALL qt_convert_AYUV444_to_ARGB32(const QVideoFrame&, uchar*);
1040extern void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame&, uchar*);
1041extern void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame&, uchar*);
1042extern void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame&, uchar*);
1043extern void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame&, uchar*);
1044extern void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame&, uchar*);
1045extern void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame&, uchar*);
1046extern void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame&, uchar*);
1047
1048static VideoFrameConvertFunc qConvertFuncs[QVideoFrame::NPixelFormats] = {
1049 /* Format_Invalid */ nullptr, // Not needed
1050 /* Format_ARGB32 */ nullptr, // Not needed
1051 /* Format_ARGB32_Premultiplied */ nullptr, // Not needed
1052 /* Format_RGB32 */ nullptr, // Not needed
1053 /* Format_RGB24 */ nullptr, // Not needed
1054 /* Format_RGB565 */ nullptr, // Not needed
1055 /* Format_RGB555 */ nullptr, // Not needed
1056 /* Format_ARGB8565_Premultiplied */ nullptr, // Not needed
1057 /* Format_BGRA32 */ qt_convert_BGRA32_to_ARGB32,
1058 /* Format_BGRA32_Premultiplied */ qt_convert_BGRA32_to_ARGB32,
1059 /* Format_ABGR32 */ nullptr,
1060 /* Format_BGR32 */ qt_convert_BGRA32_to_ARGB32,
1061 /* Format_BGR24 */ qt_convert_BGR24_to_ARGB32,
1062 /* Format_BGR565 */ qt_convert_BGR565_to_ARGB32,
1063 /* Format_BGR555 */ qt_convert_BGR555_to_ARGB32,
1064 /* Format_BGRA5658_Premultiplied */ nullptr,
1065 /* Format_AYUV444 */ qt_convert_AYUV444_to_ARGB32,
1066 /* Format_AYUV444_Premultiplied */ nullptr,
1067 /* Format_YUV444 */ qt_convert_YUV444_to_ARGB32,
1068 /* Format_YUV420P */ qt_convert_YUV420P_to_ARGB32,
1069 /* Format_YUV422P */ nullptr,
1070 /* Format_YV12 */ qt_convert_YV12_to_ARGB32,
1071 /* Format_UYVY */ qt_convert_UYVY_to_ARGB32,
1072 /* Format_YUYV */ qt_convert_YUYV_to_ARGB32,
1073 /* Format_NV12 */ qt_convert_NV12_to_ARGB32,
1074 /* Format_NV21 */ qt_convert_NV21_to_ARGB32,
1075 /* Format_IMC1 */ nullptr,
1076 /* Format_IMC2 */ nullptr,
1077 /* Format_IMC3 */ nullptr,
1078 /* Format_IMC4 */ nullptr,
1079 /* Format_Y8 */ nullptr,
1080 /* Format_Y16 */ nullptr,
1081 /* Format_Jpeg */ nullptr, // Not needed
1082 /* Format_CameraRaw */ nullptr,
1083 /* Format_AdobeDng */ nullptr
1084};
1085
1086static void qInitConvertFuncsAsm()
1087{
1088#ifdef QT_COMPILER_SUPPORTS_SSE2
1089 extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_sse2(const QVideoFrame&, uchar*);
1090 if (qCpuHasFeature(SSE2)){
1091 qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_sse2;
1092 qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_sse2;
1093 qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_sse2;
1094 }
1095#endif
1096#ifdef QT_COMPILER_SUPPORTS_SSSE3
1097 extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_ssse3(const QVideoFrame&, uchar*);
1098 if (qCpuHasFeature(SSSE3)){
1099 qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_ssse3;
1100 qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_ssse3;
1101 qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_ssse3;
1102 }
1103#endif
1104#ifdef QT_COMPILER_SUPPORTS_AVX2
1105 extern void QT_FASTCALL qt_convert_BGRA32_to_ARGB32_avx2(const QVideoFrame&, uchar*);
1106 if (qCpuHasFeature(AVX2)){
1107 qConvertFuncs[QVideoFrame::Format_BGRA32] = qt_convert_BGRA32_to_ARGB32_avx2;
1108 qConvertFuncs[QVideoFrame::Format_BGRA32_Premultiplied] = qt_convert_BGRA32_to_ARGB32_avx2;
1109 qConvertFuncs[QVideoFrame::Format_BGR32] = qt_convert_BGRA32_to_ARGB32_avx2;
1110 }
1111#endif
1112}
1113
1114/*!
1115 \internal
1116*/
1117QImage qt_imageFromVideoFrame(const QVideoFrame &f)
1118{
1119 QVideoFrame &frame = const_cast<QVideoFrame&>(f);
1120 QImage result;
1121
1122 if (!frame.isValid() || !frame.map(QAbstractVideoBuffer::ReadOnly))
1123 return result;
1124
1125 // Formats supported by QImage don't need conversion
1126 QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat());
1127 if (imageFormat != QImage::Format_Invalid) {
1128 result = QImage(frame.bits(), frame.width(), frame.height(), frame.bytesPerLine(), imageFormat).copy();
1129 }
1130
1131 // Load from JPG
1132 else if (frame.pixelFormat() == QVideoFrame::Format_Jpeg) {
1133 result.loadFromData(frame.bits(), frame.mappedBytes(), "JPG");
1134 }
1135
1136 // Need conversion
1137 else {
1138 static bool initAsmFuncsDone = false;
1139 if (!initAsmFuncsDone) {
1140 qInitConvertFuncsAsm();
1141 initAsmFuncsDone = true;
1142 }
1143 VideoFrameConvertFunc convert = qConvertFuncs[frame.pixelFormat()];
1144 if (!convert) {
1145 qWarning() << Q_FUNC_INFO << ": unsupported pixel format" << frame.pixelFormat();
1146 } else {
1147 result = QImage(frame.width(), frame.height(), QImage::Format_ARGB32);
1148 convert(frame, result.bits());
1149 }
1150 }
1151
1152 frame.unmap();
1153
1154 return result;
1155}
1156
1157#ifndef QT_NO_DEBUG_STREAM
1158QDebug operator<<(QDebug dbg, QVideoFrame::PixelFormat pf)
1159{
1160 QDebugStateSaver saver(dbg);
1161 dbg.nospace();
1162 switch (pf) {
1163 case QVideoFrame::Format_Invalid:
1164 return dbg << "Format_Invalid";
1165 case QVideoFrame::Format_ARGB32:
1166 return dbg << "Format_ARGB32";
1167 case QVideoFrame::Format_ARGB32_Premultiplied:
1168 return dbg << "Format_ARGB32_Premultiplied";
1169 case QVideoFrame::Format_RGB32:
1170 return dbg << "Format_RGB32";
1171 case QVideoFrame::Format_RGB24:
1172 return dbg << "Format_RGB24";
1173 case QVideoFrame::Format_RGB565:
1174 return dbg << "Format_RGB565";
1175 case QVideoFrame::Format_RGB555:
1176 return dbg << "Format_RGB555";
1177 case QVideoFrame::Format_ARGB8565_Premultiplied:
1178 return dbg << "Format_ARGB8565_Premultiplied";
1179 case QVideoFrame::Format_BGRA32:
1180 return dbg << "Format_BGRA32";
1181 case QVideoFrame::Format_BGRA32_Premultiplied:
1182 return dbg << "Format_BGRA32_Premultiplied";
1183 case QVideoFrame::Format_ABGR32:
1184 return dbg << "Format_ABGR32";
1185 case QVideoFrame::Format_BGR32:
1186 return dbg << "Format_BGR32";
1187 case QVideoFrame::Format_BGR24:
1188 return dbg << "Format_BGR24";
1189 case QVideoFrame::Format_BGR565:
1190 return dbg << "Format_BGR565";
1191 case QVideoFrame::Format_BGR555:
1192 return dbg << "Format_BGR555";
1193 case QVideoFrame::Format_BGRA5658_Premultiplied:
1194 return dbg << "Format_BGRA5658_Premultiplied";
1195 case QVideoFrame::Format_AYUV444:
1196 return dbg << "Format_AYUV444";
1197 case QVideoFrame::Format_AYUV444_Premultiplied:
1198 return dbg << "Format_AYUV444_Premultiplied";
1199 case QVideoFrame::Format_YUV444:
1200 return dbg << "Format_YUV444";
1201 case QVideoFrame::Format_YUV420P:
1202 return dbg << "Format_YUV420P";
1203 case QVideoFrame::Format_YUV422P:
1204 return dbg << "Format_YUV422P";
1205 case QVideoFrame::Format_YV12:
1206 return dbg << "Format_YV12";
1207 case QVideoFrame::Format_UYVY:
1208 return dbg << "Format_UYVY";
1209 case QVideoFrame::Format_YUYV:
1210 return dbg << "Format_YUYV";
1211 case QVideoFrame::Format_NV12:
1212 return dbg << "Format_NV12";
1213 case QVideoFrame::Format_NV21:
1214 return dbg << "Format_NV21";
1215 case QVideoFrame::Format_IMC1:
1216 return dbg << "Format_IMC1";
1217 case QVideoFrame::Format_IMC2:
1218 return dbg << "Format_IMC2";
1219 case QVideoFrame::Format_IMC3:
1220 return dbg << "Format_IMC3";
1221 case QVideoFrame::Format_IMC4:
1222 return dbg << "Format_IMC4";
1223 case QVideoFrame::Format_Y8:
1224 return dbg << "Format_Y8";
1225 case QVideoFrame::Format_Y16:
1226 return dbg << "Format_Y16";
1227 case QVideoFrame::Format_Jpeg:
1228 return dbg << "Format_Jpeg";
1229 case QVideoFrame::Format_AdobeDng:
1230 return dbg << "Format_AdobeDng";
1231 case QVideoFrame::Format_CameraRaw:
1232 return dbg << "Format_CameraRaw";
1233
1234 default:
1235 return dbg << QString(QLatin1String("UserType(%1)" )).arg(int(pf)).toLatin1().constData();
1236 }
1237}
1238
1239QDebug operator<<(QDebug dbg, QVideoFrame::FieldType f)
1240{
1241 QDebugStateSaver saver(dbg);
1242 dbg.nospace();
1243 switch (f) {
1244 case QVideoFrame::TopField:
1245 return dbg << "TopField";
1246 case QVideoFrame::BottomField:
1247 return dbg << "BottomField";
1248 case QVideoFrame::InterlacedFrame:
1249 return dbg << "InterlacedFrame";
1250 default:
1251 return dbg << "ProgressiveFrame";
1252 }
1253}
1254
1255static QString qFormatTimeStamps(qint64 start, qint64 end)
1256{
1257 // Early out for invalid.
1258 if (start < 0)
1259 return QLatin1String("[no timestamp]");
1260
1261 bool onlyOne = (start == end);
1262
1263 // [hh:]mm:ss.ms
1264 const int s_millis = start % 1000000;
1265 start /= 1000000;
1266 const int s_seconds = start % 60;
1267 start /= 60;
1268 const int s_minutes = start % 60;
1269 start /= 60;
1270
1271 if (onlyOne) {
1272 if (start > 0)
1273 return QString::fromLatin1("@%1:%2:%3.%4")
1274 .arg(start, 1, 10, QLatin1Char('0'))
1275 .arg(s_minutes, 2, 10, QLatin1Char('0'))
1276 .arg(s_seconds, 2, 10, QLatin1Char('0'))
1277 .arg(s_millis, 2, 10, QLatin1Char('0'));
1278 else
1279 return QString::fromLatin1("@%1:%2.%3")
1280 .arg(s_minutes, 2, 10, QLatin1Char('0'))
1281 .arg(s_seconds, 2, 10, QLatin1Char('0'))
1282 .arg(s_millis, 2, 10, QLatin1Char('0'));
1283 } else if (end == -1) {
1284 // Similar to start-start, except it means keep displaying it?
1285 if (start > 0)
1286 return QString::fromLatin1("%1:%2:%3.%4 - forever")
1287 .arg(start, 1, 10, QLatin1Char('0'))
1288 .arg(s_minutes, 2, 10, QLatin1Char('0'))
1289 .arg(s_seconds, 2, 10, QLatin1Char('0'))
1290 .arg(s_millis, 2, 10, QLatin1Char('0'));
1291 else
1292 return QString::fromLatin1("%1:%2.%3 - forever")
1293 .arg(s_minutes, 2, 10, QLatin1Char('0'))
1294 .arg(s_seconds, 2, 10, QLatin1Char('0'))
1295 .arg(s_millis, 2, 10, QLatin1Char('0'));
1296 } else {
1297 const int e_millis = end % 1000000;
1298 end /= 1000000;
1299 const int e_seconds = end % 60;
1300 end /= 60;
1301 const int e_minutes = end % 60;
1302 end /= 60;
1303
1304 if (start > 0 || end > 0)
1305 return QString::fromLatin1("%1:%2:%3.%4 - %5:%6:%7.%8")
1306 .arg(start, 1, 10, QLatin1Char('0'))
1307 .arg(s_minutes, 2, 10, QLatin1Char('0'))
1308 .arg(s_seconds, 2, 10, QLatin1Char('0'))
1309 .arg(s_millis, 2, 10, QLatin1Char('0'))
1310 .arg(end, 1, 10, QLatin1Char('0'))
1311 .arg(e_minutes, 2, 10, QLatin1Char('0'))
1312 .arg(e_seconds, 2, 10, QLatin1Char('0'))
1313 .arg(e_millis, 2, 10, QLatin1Char('0'));
1314 else
1315 return QString::fromLatin1("%1:%2.%3 - %4:%5.%6")
1316 .arg(s_minutes, 2, 10, QLatin1Char('0'))
1317 .arg(s_seconds, 2, 10, QLatin1Char('0'))
1318 .arg(s_millis, 2, 10, QLatin1Char('0'))
1319 .arg(e_minutes, 2, 10, QLatin1Char('0'))
1320 .arg(e_seconds, 2, 10, QLatin1Char('0'))
1321 .arg(e_millis, 2, 10, QLatin1Char('0'));
1322 }
1323}
1324
1325QDebug operator<<(QDebug dbg, const QVideoFrame& f)
1326{
1327 QDebugStateSaver saver(dbg);
1328 dbg.nospace();
1329 dbg << "QVideoFrame(" << f.size() << ", "
1330 << f.pixelFormat() << ", "
1331 << f.handleType() << ", "
1332 << f.mapMode() << ", "
1333 << qFormatTimeStamps(f.startTime(), f.endTime()).toLatin1().constData();
1334 if (f.availableMetaData().count())
1335 dbg << ", metaData: " << f.availableMetaData();
1336 dbg << ')';
1337 return dbg;
1338}
1339#endif
1340
1341QT_END_NAMESPACE
1342
1343