/**************************************************************************** ** ** 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 "qvideoframeconversionhelper_p.h" QT_BEGIN_NAMESPACE #define CLAMP(n) (n > 255 ? 255 : (n < 0 ? 0 : n)) #define EXPAND_UV(u, v) \ int uu = u - 128; \ int vv = v - 128; \ int rv = 409 * vv + 128; \ int guv = 100 * uu + 208 * vv + 128; \ int bu = 516 * uu + 128; \ static inline quint32 qYUVToARGB32(int y, int rv, int guv, int bu, int a = 0xff) { int yy = (y - 16) * 298; return (a << 24) | CLAMP((yy + rv) >> 8) << 16 | CLAMP((yy - guv) >> 8) << 8 | CLAMP((yy + bu) >> 8); } static inline void planarYUV420_to_ARGB32(const uchar *y, int yStride, const uchar *u, int uStride, const uchar *v, int vStride, int uvPixelStride, quint32 *rgb, int width, int height) { quint32 *rgb0 = rgb; quint32 *rgb1 = rgb + width; for (int j = 0; j < height; j += 2) { const uchar *lineY0 = y; const uchar *lineY1 = y + yStride; const uchar *lineU = u; const uchar *lineV = v; for (int i = 0; i < width; i += 2) { EXPAND_UV(*lineU, *lineV); lineU += uvPixelStride; lineV += uvPixelStride; *rgb0++ = qYUVToARGB32(*lineY0++, rv, guv, bu); *rgb0++ = qYUVToARGB32(*lineY0++, rv, guv, bu); *rgb1++ = qYUVToARGB32(*lineY1++, rv, guv, bu); *rgb1++ = qYUVToARGB32(*lineY1++, rv, guv, bu); } y += yStride << 1; // stride * 2 u += uStride; v += vStride; rgb0 += width; rgb1 += width; } } void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_TRIPLANAR(frame) planarYUV420_to_ARGB32(plane1, plane1Stride, plane2, plane2Stride, plane3, plane3Stride, 1, reinterpret_cast(output), width, height); } void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_TRIPLANAR(frame) planarYUV420_to_ARGB32(plane1, plane1Stride, plane3, plane3Stride, plane2, plane2Stride, 1, reinterpret_cast(output), width, height); } void QT_FASTCALL qt_convert_AYUV444_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 4) quint32 *rgb = reinterpret_cast(output); for (int i = 0; i < height; ++i) { const uchar *lineSrc = src; for (int j = 0; j < width; ++j) { int a = *lineSrc++; int y = *lineSrc++; int u = *lineSrc++; int v = *lineSrc++; EXPAND_UV(u, v); *rgb++ = qYUVToARGB32(y, rv, guv, bu, a); } src += stride; } } void QT_FASTCALL qt_convert_YUV444_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 3) quint32 *rgb = reinterpret_cast(output); for (int i = 0; i < height; ++i) { const uchar *lineSrc = src; for (int j = 0; j < width; ++j) { int y = *lineSrc++; int u = *lineSrc++; int v = *lineSrc++; EXPAND_UV(u, v); *rgb++ = qYUVToARGB32(y, rv, guv, bu); } src += stride; } } void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 2) quint32 *rgb = reinterpret_cast(output); for (int i = 0; i < height; ++i) { const uchar *lineSrc = src; for (int j = 0; j < width; j += 2) { int u = *lineSrc++; int y0 = *lineSrc++; int v = *lineSrc++; int y1 = *lineSrc++; EXPAND_UV(u, v); *rgb++ = qYUVToARGB32(y0, rv, guv, bu); *rgb++ = qYUVToARGB32(y1, rv, guv, bu); } src += stride; } } void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 2) quint32 *rgb = reinterpret_cast(output); for (int i = 0; i < height; ++i) { const uchar *lineSrc = src; for (int j = 0; j < width; j += 2) { int y0 = *lineSrc++; int u = *lineSrc++; int y1 = *lineSrc++; int v = *lineSrc++; EXPAND_UV(u, v); *rgb++ = qYUVToARGB32(y0, rv, guv, bu); *rgb++ = qYUVToARGB32(y1, rv, guv, bu); } src += stride; } } void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_BIPLANAR(frame) planarYUV420_to_ARGB32(plane1, plane1Stride, plane2, plane2Stride, plane2 + 1, plane2Stride, 2, reinterpret_cast(output), width, height); } void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_BIPLANAR(frame) planarYUV420_to_ARGB32(plane1, plane1Stride, plane2 + 1, plane2Stride, plane2, plane2Stride, 2, reinterpret_cast(output), width, height); } void QT_FASTCALL qt_convert_BGRA32_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 4) quint32 *argb = reinterpret_cast(output); for (int y = 0; y < height; ++y) { const quint32 *bgra = reinterpret_cast(src); int x = 0; for (; x < width - 3; x += 4) { *argb++ = qConvertBGRA32ToARGB32(*bgra++); *argb++ = qConvertBGRA32ToARGB32(*bgra++); *argb++ = qConvertBGRA32ToARGB32(*bgra++); *argb++ = qConvertBGRA32ToARGB32(*bgra++); } // leftovers for (; x < width; ++x) *argb++ = qConvertBGRA32ToARGB32(*bgra++); src += stride; } } void QT_FASTCALL qt_convert_BGR24_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 3) quint32 *argb = reinterpret_cast(output); for (int y = 0; y < height; ++y) { const uchar *bgr = src; int x = 0; for (; x < width - 3; x += 4) { *argb++ = qConvertBGR24ToARGB32(bgr); bgr += 3; *argb++ = qConvertBGR24ToARGB32(bgr); bgr += 3; *argb++ = qConvertBGR24ToARGB32(bgr); bgr += 3; *argb++ = qConvertBGR24ToARGB32(bgr); bgr += 3; } // leftovers for (; x < width; ++x) { *argb++ = qConvertBGR24ToARGB32(bgr); bgr += 3; } src += stride; } } void QT_FASTCALL qt_convert_BGR565_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 2) quint32 *argb = reinterpret_cast(output); for (int y = 0; y < height; ++y) { const quint16 *bgr = reinterpret_cast(src); int x = 0; for (; x < width - 3; x += 4) { *argb++ = qConvertBGR565ToARGB32(*bgr++); *argb++ = qConvertBGR565ToARGB32(*bgr++); *argb++ = qConvertBGR565ToARGB32(*bgr++); *argb++ = qConvertBGR565ToARGB32(*bgr++); } // leftovers for (; x < width; ++x) *argb++ = qConvertBGR565ToARGB32(*bgr++); src += stride; } } void QT_FASTCALL qt_convert_BGR555_to_ARGB32(const QVideoFrame &frame, uchar *output) { FETCH_INFO_PACKED(frame) MERGE_LOOPS(width, height, stride, 2) quint32 *argb = reinterpret_cast(output); for (int y = 0; y < height; ++y) { const quint16 *bgr = reinterpret_cast(src); int x = 0; for (; x < width - 3; x += 4) { *argb++ = qConvertBGR555ToARGB32(*bgr++); *argb++ = qConvertBGR555ToARGB32(*bgr++); *argb++ = qConvertBGR555ToARGB32(*bgr++); *argb++ = qConvertBGR555ToARGB32(*bgr++); } // leftovers for (; x < width; ++x) *argb++ = qConvertBGR555ToARGB32(*bgr++); src += stride; } } QT_END_NAMESPACE