From d11f13f476411b828387c3c26619bc77c255affb Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 17 Apr 2020 15:23:03 -0400 Subject: [PATCH] Introduce the videocolorscale element Now that videoconvert and videoscale's are both based on GstVideoConverter and are using the exact same code, it makes much more sense to have one element doing the two operation, and it can be more efficient in some cases (one single path for both operations). This removes the `videoscale` and `videoconvert` plugins but keeps the element but makes them also do both operations (adding some APIs to each element). There is a small change in API for the `videoscale:dither` property which was previously a totally unused boolean, it is now an enum and is used. Part-of: --- .../docs/plugins/gst_plugins_cache.json | 420 ++++--- subprojects/gst-plugins-base/gst/meson.build | 2 +- .../gst/videoconvert/gstvideoconvert.c | 870 -------------- .../gst/videoconvert/meson.build | 14 - .../gst/videoconvertscale/README | 5 + .../gst/videoconvertscale/gstvideoconvert.c | 59 + .../gstvideoconvert.h | 35 +- .../gstvideoconvertscale.c} | 1018 ++++++++++++----- .../gstvideoconvertscale.h} | 45 +- .../gstvideoconvertscaleplugin.c | 51 + .../gst/videoconvertscale/gstvideoscale.c | 125 ++ .../gst/videoconvertscale/gstvideoscale.h | 36 + .../gst/videoconvertscale/meson.build | 18 + .../gst-plugins-base/gst/videoscale/README | 5 - .../gst/videoscale/meson.build | 14 - .../gst-plugins-base/meson_options.txt | 3 +- 16 files changed, 1282 insertions(+), 1438 deletions(-) delete mode 100644 subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.c delete mode 100644 subprojects/gst-plugins-base/gst/videoconvert/meson.build create mode 100644 subprojects/gst-plugins-base/gst/videoconvertscale/README create mode 100644 subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c rename subprojects/gst-plugins-base/gst/{videoconvert => videoconvertscale}/gstvideoconvert.h (57%) rename subprojects/gst-plugins-base/gst/{videoscale/gstvideoscale.c => videoconvertscale/gstvideoconvertscale.c} (54%) rename subprojects/gst-plugins-base/gst/{videoscale/gstvideoscale.h => videoconvertscale/gstvideoconvertscale.h} (74%) create mode 100644 subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscaleplugin.c create mode 100644 subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c create mode 100644 subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.h create mode 100644 subprojects/gst-plugins-base/gst/videoconvertscale/meson.build delete mode 100644 subprojects/gst-plugins-base/gst/videoscale/README delete mode 100644 subprojects/gst-plugins-base/gst/videoscale/meson.build diff --git a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json index 52cc0fc30e..6827f94171 100644 --- a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json @@ -13609,14 +13609,15 @@ "tracers": {}, "url": "Unknown package origin" }, - "videoconvert": { - "description": "Colorspace conversion", + "videoconvertscale": { + "description": "Convert video colorspaces and resizes video frames", "elements": { "videoconvert": { - "author": "GStreamer maintainers ", - "description": "Converts video from one colorspace to another", + "author": "Wim Taymans ", + "description": "Resizes video and allow color conversion", "hierarchy": [ "GstVideoConvert", + "GstVideoConvertScale", "GstVideoFilter", "GstBaseTransform", "GstElement", @@ -13624,21 +13625,61 @@ "GInitiallyUnowned", "GObject" ], - "klass": "Filter/Converter/Video", - "long-name": "Colorspace converter", + "klass": "Filter/Converter/Video/Scaler/Colorspace", + "long-name": "Video colorspace converter and scaler", "pad-templates": { "sink": { - "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n", + "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", "direction": "sink", "presence": "always" }, "src": { - "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n", + "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", + "direction": "src", + "presence": "always" + } + }, + "rank": "marginal" + }, + "videoconvertscale": { + "author": "Wim Taymans ", + "description": "Resizes video and allow color conversion", + "hierarchy": [ + "GstVideoConvertScale", + "GstVideoFilter", + "GstBaseTransform", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Filter/Converter/Video/Scaler/Colorspace", + "long-name": "Video colorspace converter and scaler", + "pad-templates": { + "sink": { + "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", "direction": "src", "presence": "always" } }, "properties": { + "add-borders": { + "blurb": "Add black borders if necessary to keep the display aspect ratio", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "true", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, "alpha-mode": { "blurb": "Alpha Mode to use", "conditionally-available": false, @@ -13715,6 +13756,20 @@ "type": "guint", "writable": true }, + "envelope": { + "blurb": "Size of filter envelope", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "2", + "max": "5", + "min": "1", + "mutable": "null", + "readable": true, + "type": "gdouble", + "writable": true + }, "gamma-mode": { "blurb": "Gamma Conversion Mode", "conditionally-available": false, @@ -13739,10 +13794,22 @@ "type": "GstVideoMatrixMode", "writable": true }, + "method": { + "blurb": "method", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "bilinear (1)", + "mutable": "null", + "readable": true, + "type": "GstVideoScaleMethod", + "writable": true + }, "n-threads": { "blurb": "Maximum number of threads to use", "conditionally-available": false, - "construct": false, + "construct": true, "construct-only": false, "controllable": false, "default": "1", @@ -13764,14 +13831,141 @@ "readable": true, "type": "GstVideoPrimariesMode", "writable": true + }, + "sharpen": { + "blurb": "Sharpening", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "1", + "min": "0", + "mutable": "null", + "readable": true, + "type": "gdouble", + "writable": true + }, + "sharpness": { + "blurb": "Sharpness of filter", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "1", + "max": "1.5", + "min": "0.5", + "mutable": "null", + "readable": true, + "type": "gdouble", + "writable": true } }, - "rank": "none" + "rank": "secondary" + }, + "videoscale": { + "author": "Wim Taymans ", + "description": "Resizes video and allow color conversion", + "hierarchy": [ + "GstVideoScale", + "GstVideoConvertScale", + "GstVideoFilter", + "GstBaseTransform", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Filter/Converter/Video/Scaler/Colorspace", + "long-name": "Video colorspace converter and scaler", + "pad-templates": { + "sink": { + "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", + "direction": "src", + "presence": "always" + } + }, + "properties": { + "gamma-decode": { + "blurb": "Decode gamma before scaling", + "conditionally-available": false, + "construct": true, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + } + }, + "rank": "marginal" } }, - "filename": "gstvideoconvert", + "filename": "gstvideoconvertscale", "license": "LGPL", - "other-types": {}, + "other-types": { + "GstVideoScaleMethod": { + "kind": "enum", + "values": [ + { + "desc": "Nearest Neighbour", + "name": "nearest-neighbour", + "value": "0" + }, + { + "desc": "Bilinear (2-tap)", + "name": "bilinear", + "value": "1" + }, + { + "desc": "4-tap Sinc", + "name": "4-tap", + "value": "2" + }, + { + "desc": "Lanczos", + "name": "lanczos", + "value": "3" + }, + { + "desc": "Bilinear (multi-tap)", + "name": "bilinear2", + "value": "4" + }, + { + "desc": "Sinc (multi-tap)", + "name": "sinc", + "value": "5" + }, + { + "desc": "Hermite (multi-tap)", + "name": "hermite", + "value": "6" + }, + { + "desc": "Spline (multi-tap)", + "name": "spline", + "value": "7" + }, + { + "desc": "Catmull-Rom (multi-tap)", + "name": "catrom", + "value": "8" + }, + { + "desc": "Mitchell (multi-tap)", + "name": "mitchell", + "value": "9" + } + ] + } + }, "package": "GStreamer Base Plug-ins", "source": "gst-plugins-base", "tracers": {}, @@ -13980,208 +14174,6 @@ "tracers": {}, "url": "Unknown package origin" }, - "videoscale": { - "description": "Resizes video", - "elements": { - "videoscale": { - "author": "Wim Taymans ", - "description": "Resizes video", - "hierarchy": [ - "GstVideoScale", - "GstVideoFilter", - "GstBaseTransform", - "GstElement", - "GstObject", - "GInitiallyUnowned", - "GObject" - ], - "klass": "Filter/Converter/Video/Scaler", - "long-name": "Video scaler", - "pad-templates": { - "sink": { - "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", - "direction": "sink", - "presence": "always" - }, - "src": { - "caps": "video/x-raw:\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n\nvideo/x-raw(ANY):\n format: { ABGR64_LE, BGRA64_LE, AYUV64, ARGB64_LE, ARGB64, RGBA64_LE, ABGR64_BE, BGRA64_BE, ARGB64_BE, RGBA64_BE, GBRA_12LE, GBRA_12BE, Y412_LE, Y412_BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, RGB10A2_LE, BGR10A2_LE, Y410, GBRA, ABGR, VUYA, BGRA, AYUV, ARGB, RGBA, A420, AV12, Y444_16LE, Y444_16BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, r210, I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, NV12_10BE_8L128, Y444, RGBP, GBR, BGRP, NV24, xBGR, BGRx, xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, YV12, NV21, NV12, NV12_8L128, NV12_64Z32, NV12_4L4, NV12_32L32, NV12_16L32S, Y41B, IYU1, YVU9, YUV9, RGB16, BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }\n width: [ 1, 32767 ]\n height: [ 1, 32767 ]\n framerate: [ 0/1, 2147483647/1 ]\n", - "direction": "src", - "presence": "always" - } - }, - "properties": { - "add-borders": { - "blurb": "Add black borders if necessary to keep the display aspect ratio", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "true", - "mutable": "null", - "readable": true, - "type": "gboolean", - "writable": true - }, - "dither": { - "blurb": "Add dither (only used for Lanczos method)", - "conditionally-available": false, - "construct": true, - "construct-only": false, - "controllable": false, - "default": "false", - "mutable": "null", - "readable": true, - "type": "gboolean", - "writable": true - }, - "envelope": { - "blurb": "Size of filter envelope", - "conditionally-available": false, - "construct": true, - "construct-only": false, - "controllable": false, - "default": "2", - "max": "5", - "min": "1", - "mutable": "null", - "readable": true, - "type": "gdouble", - "writable": true - }, - "gamma-decode": { - "blurb": "Decode gamma before scaling", - "conditionally-available": false, - "construct": true, - "construct-only": false, - "controllable": false, - "default": "false", - "mutable": "null", - "readable": true, - "type": "gboolean", - "writable": true - }, - "method": { - "blurb": "method", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "bilinear (1)", - "mutable": "null", - "readable": true, - "type": "GstVideoScaleMethod", - "writable": true - }, - "n-threads": { - "blurb": "Maximum number of threads to use", - "conditionally-available": false, - "construct": true, - "construct-only": false, - "controllable": false, - "default": "1", - "max": "-1", - "min": "0", - "mutable": "null", - "readable": true, - "type": "guint", - "writable": true - }, - "sharpen": { - "blurb": "Sharpening", - "conditionally-available": false, - "construct": true, - "construct-only": false, - "controllable": false, - "default": "0", - "max": "1", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gdouble", - "writable": true - }, - "sharpness": { - "blurb": "Sharpness of filter", - "conditionally-available": false, - "construct": true, - "construct-only": false, - "controllable": false, - "default": "1", - "max": "1.5", - "min": "0.5", - "mutable": "null", - "readable": true, - "type": "gdouble", - "writable": true - } - }, - "rank": "none" - } - }, - "filename": "gstvideoscale", - "license": "LGPL", - "other-types": { - "GstVideoScaleMethod": { - "kind": "enum", - "values": [ - { - "desc": "Nearest Neighbour", - "name": "nearest-neighbour", - "value": "0" - }, - { - "desc": "Bilinear (2-tap)", - "name": "bilinear", - "value": "1" - }, - { - "desc": "4-tap Sinc", - "name": "4-tap", - "value": "2" - }, - { - "desc": "Lanczos", - "name": "lanczos", - "value": "3" - }, - { - "desc": "Bilinear (multi-tap)", - "name": "bilinear2", - "value": "4" - }, - { - "desc": "Sinc (multi-tap)", - "name": "sinc", - "value": "5" - }, - { - "desc": "Hermite (multi-tap)", - "name": "hermite", - "value": "6" - }, - { - "desc": "Spline (multi-tap)", - "name": "spline", - "value": "7" - }, - { - "desc": "Catmull-Rom (multi-tap)", - "name": "catrom", - "value": "8" - }, - { - "desc": "Mitchell (multi-tap)", - "name": "mitchell", - "value": "9" - } - ] - } - }, - "package": "GStreamer Base Plug-ins", - "source": "gst-plugins-base", - "tracers": {}, - "url": "Unknown package origin" - }, "videotestsrc": { "description": "Creates a test video stream", "elements": { diff --git a/subprojects/gst-plugins-base/gst/meson.build b/subprojects/gst-plugins-base/gst/meson.build index 91be2a00b7..2d14191ce9 100644 --- a/subprojects/gst-plugins-base/gst/meson.build +++ b/subprojects/gst-plugins-base/gst/meson.build @@ -1,6 +1,6 @@ foreach plugin : ['adder', 'app', 'audioconvert', 'audiomixer', 'audiorate', 'audioresample', 'audiotestsrc', 'compositor', 'encoding', 'gio', 'overlaycomposition', 'pbtypes', 'playback', - 'rawparse', 'subparse', 'tcp', 'typefind', 'videoconvert', 'videorate', 'videoscale', + 'rawparse', 'subparse', 'tcp', 'typefind', 'videoconvertscale', 'videorate', 'videotestsrc', 'volume'] if not get_option(plugin).disabled() subdir(plugin) diff --git a/subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.c b/subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.c deleted file mode 100644 index 0f65ee2db8..0000000000 --- a/subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.c +++ /dev/null @@ -1,870 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * This file: - * Copyright (C) 2003 Ronald Bultje - * Copyright (C) 2010 David Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-videoconvert - * @title: videoconvert - * - * Convert video frames between a great variety of video formats. - * - * ## Example launch line - * |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw,format=YUY2 ! videoconvert ! autovideosink - * ]| - * This will output a test video (generated in YUY2 format) in a video - * window. If the video sink selected does not support YUY2 videoconvert will - * automatically convert the video to a format understood by the video sink. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "gstvideoconvert.h" - -#include -#include -#include - -#include - -GST_DEBUG_CATEGORY (videoconvert_debug); -#define GST_CAT_DEFAULT videoconvert_debug -GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE); - -static GQuark _colorspace_quark; - -#define gst_video_convert_parent_class parent_class -G_DEFINE_TYPE (GstVideoConvert, gst_video_convert, GST_TYPE_VIDEO_FILTER); -GST_ELEMENT_REGISTER_DEFINE (videoconvert, "videoconvert", - GST_RANK_NONE, GST_TYPE_VIDEO_CONVERT); - -#define DEFAULT_PROP_DITHER GST_VIDEO_DITHER_BAYER -#define DEFAULT_PROP_DITHER_QUANTIZATION 1 -#define DEFAULT_PROP_CHROMA_RESAMPLER GST_VIDEO_RESAMPLER_METHOD_LINEAR -#define DEFAULT_PROP_ALPHA_MODE GST_VIDEO_ALPHA_MODE_COPY -#define DEFAULT_PROP_ALPHA_VALUE 1.0 -#define DEFAULT_PROP_CHROMA_MODE GST_VIDEO_CHROMA_MODE_FULL -#define DEFAULT_PROP_MATRIX_MODE GST_VIDEO_MATRIX_MODE_FULL -#define DEFAULT_PROP_GAMMA_MODE GST_VIDEO_GAMMA_MODE_NONE -#define DEFAULT_PROP_PRIMARIES_MODE GST_VIDEO_PRIMARIES_MODE_NONE -#define DEFAULT_PROP_N_THREADS 1 - -enum -{ - PROP_0, - PROP_DITHER, - PROP_DITHER_QUANTIZATION, - PROP_CHROMA_RESAMPLER, - PROP_ALPHA_MODE, - PROP_ALPHA_VALUE, - PROP_CHROMA_MODE, - PROP_MATRIX_MODE, - PROP_GAMMA_MODE, - PROP_PRIMARIES_MODE, - PROP_N_THREADS -}; - -#define CSP_VIDEO_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \ - GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS_ALL) - -static GstStaticPadTemplate gst_video_convert_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (CSP_VIDEO_CAPS) - ); - -static GstStaticPadTemplate gst_video_convert_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (CSP_VIDEO_CAPS) - ); - -static void gst_video_convert_set_property (GObject * object, - guint property_id, const GValue * value, GParamSpec * pspec); -static void gst_video_convert_get_property (GObject * object, - guint property_id, GValue * value, GParamSpec * pspec); - -static gboolean gst_video_convert_set_info (GstVideoFilter * filter, - GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps, - GstVideoInfo * out_info); -static GstFlowReturn gst_video_convert_transform_frame (GstVideoFilter * filter, - GstVideoFrame * in_frame, GstVideoFrame * out_frame); - -static GstCapsFeatures *features_format_interlaced, - *features_format_interlaced_sysmem; - -/* copies the given caps */ -static GstCaps * -gst_video_convert_caps_remove_format_info (GstCaps * caps) -{ - GstStructure *st; - GstCapsFeatures *f; - gint i, n; - GstCaps *res; - - res = gst_caps_new_empty (); - - n = gst_caps_get_size (caps); - for (i = 0; i < n; i++) { - st = gst_caps_get_structure (caps, i); - f = gst_caps_get_features (caps, i); - - /* If this is already expressed by the existing caps - * skip this structure */ - if (i > 0 && gst_caps_is_subset_structure_full (res, st, f)) - continue; - - st = gst_structure_copy (st); - /* Only remove format info for the cases when we can actually convert */ - if (!gst_caps_features_is_any (f) - && (gst_caps_features_is_equal (f, - GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY) - || gst_caps_features_is_equal (f, features_format_interlaced) - || gst_caps_features_is_equal (f, - features_format_interlaced_sysmem))) { - gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site", - NULL); - } - - gst_caps_append_structure_full (res, st, gst_caps_features_copy (f)); - } - - return res; -} - -/* - * This is an incomplete matrix of in formats and a score for the preferred output - * format. - * - * out: RGB24 RGB16 ARGB AYUV YUV444 YUV422 YUV420 YUV411 YUV410 PAL GRAY - * in - * RGB24 0 2 1 2 2 3 4 5 6 7 8 - * RGB16 1 0 1 2 2 3 4 5 6 7 8 - * ARGB 2 3 0 1 4 5 6 7 8 9 10 - * AYUV 3 4 1 0 2 5 6 7 8 9 10 - * YUV444 2 4 3 1 0 5 6 7 8 9 10 - * YUV422 3 5 4 2 1 0 6 7 8 9 10 - * YUV420 4 6 5 3 2 1 0 7 8 9 10 - * YUV411 4 6 5 3 2 1 7 0 8 9 10 - * YUV410 6 8 7 5 4 3 2 1 0 9 10 - * PAL 1 3 2 6 4 6 7 8 9 0 10 - * GRAY 1 4 3 2 1 5 6 7 8 9 0 - * - * PAL or GRAY are never preferred, if we can we would convert to PAL instead - * of GRAY, though - * less subsampling is preferred and if any, preferably horizontal - * We would like to keep the alpha, even if we would need to to colorspace conversion - * or lose depth. - */ -#define SCORE_FORMAT_CHANGE 1 -#define SCORE_DEPTH_CHANGE 1 -#define SCORE_ALPHA_CHANGE 1 -#define SCORE_CHROMA_W_CHANGE 1 -#define SCORE_CHROMA_H_CHANGE 1 -#define SCORE_PALETTE_CHANGE 1 - -#define SCORE_COLORSPACE_LOSS 2 /* RGB <-> YUV */ -#define SCORE_DEPTH_LOSS 4 /* change bit depth */ -#define SCORE_ALPHA_LOSS 8 /* lose the alpha channel */ -#define SCORE_CHROMA_W_LOSS 16 /* vertical subsample */ -#define SCORE_CHROMA_H_LOSS 32 /* horizontal subsample */ -#define SCORE_PALETTE_LOSS 64 /* convert to palette format */ -#define SCORE_COLOR_LOSS 128 /* convert to GRAY */ - -#define COLORSPACE_MASK (GST_VIDEO_FORMAT_FLAG_YUV | \ - GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_GRAY) -#define ALPHA_MASK (GST_VIDEO_FORMAT_FLAG_ALPHA) -#define PALETTE_MASK (GST_VIDEO_FORMAT_FLAG_PALETTE) - -/* calculate how much loss a conversion would be */ -static void -score_value (GstBaseTransform * base, const GstVideoFormatInfo * in_info, - const GValue * val, gint * min_loss, const GstVideoFormatInfo ** out_info) -{ - const gchar *fname; - const GstVideoFormatInfo *t_info; - GstVideoFormatFlags in_flags, t_flags; - gint loss; - - fname = g_value_get_string (val); - t_info = gst_video_format_get_info (gst_video_format_from_string (fname)); - if (!t_info) - return; - - /* accept input format immediately without loss */ - if (in_info == t_info) { - *min_loss = 0; - *out_info = t_info; - return; - } - - loss = SCORE_FORMAT_CHANGE; - - in_flags = GST_VIDEO_FORMAT_INFO_FLAGS (in_info); - in_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; - in_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; - in_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; - - t_flags = GST_VIDEO_FORMAT_INFO_FLAGS (t_info); - t_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; - t_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; - t_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; - - if ((t_flags & PALETTE_MASK) != (in_flags & PALETTE_MASK)) { - loss += SCORE_PALETTE_CHANGE; - if (t_flags & PALETTE_MASK) - loss += SCORE_PALETTE_LOSS; - } - - if ((t_flags & COLORSPACE_MASK) != (in_flags & COLORSPACE_MASK)) { - loss += SCORE_COLORSPACE_LOSS; - if (t_flags & GST_VIDEO_FORMAT_FLAG_GRAY) - loss += SCORE_COLOR_LOSS; - } - - if ((t_flags & ALPHA_MASK) != (in_flags & ALPHA_MASK)) { - loss += SCORE_ALPHA_CHANGE; - if (in_flags & ALPHA_MASK) - loss += SCORE_ALPHA_LOSS; - } - - if ((in_info->h_sub[1]) != (t_info->h_sub[1])) { - loss += SCORE_CHROMA_H_CHANGE; - if ((in_info->h_sub[1]) < (t_info->h_sub[1])) - loss += SCORE_CHROMA_H_LOSS; - } - if ((in_info->w_sub[1]) != (t_info->w_sub[1])) { - loss += SCORE_CHROMA_W_CHANGE; - if ((in_info->w_sub[1]) < (t_info->w_sub[1])) - loss += SCORE_CHROMA_W_LOSS; - } - - if ((in_info->bits) != (t_info->bits)) { - loss += SCORE_DEPTH_CHANGE; - if ((in_info->bits) > (t_info->bits)) - loss += SCORE_DEPTH_LOSS; - } - - GST_DEBUG_OBJECT (base, "score %s -> %s = %d", - GST_VIDEO_FORMAT_INFO_NAME (in_info), - GST_VIDEO_FORMAT_INFO_NAME (t_info), loss); - - if (loss < *min_loss) { - GST_DEBUG_OBJECT (base, "found new best %d", loss); - *out_info = t_info; - *min_loss = loss; - } -} - -static void -gst_video_convert_fixate_format (GstBaseTransform * base, GstCaps * caps, - GstCaps * result) -{ - GstStructure *ins, *outs; - const gchar *in_format; - const GstVideoFormatInfo *in_info, *out_info = NULL; - gint min_loss = G_MAXINT; - guint i, capslen; - - ins = gst_caps_get_structure (caps, 0); - in_format = gst_structure_get_string (ins, "format"); - if (!in_format) - return; - - GST_DEBUG_OBJECT (base, "source format %s", in_format); - - in_info = - gst_video_format_get_info (gst_video_format_from_string (in_format)); - if (!in_info) - return; - - outs = gst_caps_get_structure (result, 0); - - capslen = gst_caps_get_size (result); - GST_DEBUG_OBJECT (base, "iterate %d structures", capslen); - for (i = 0; i < capslen; i++) { - GstStructure *tests; - const GValue *format; - - tests = gst_caps_get_structure (result, i); - format = gst_structure_get_value (tests, "format"); - /* should not happen */ - if (format == NULL) - continue; - - if (GST_VALUE_HOLDS_LIST (format)) { - gint j, len; - - len = gst_value_list_get_size (format); - GST_DEBUG_OBJECT (base, "have %d formats", len); - for (j = 0; j < len; j++) { - const GValue *val; - - val = gst_value_list_get_value (format, j); - if (G_VALUE_HOLDS_STRING (val)) { - score_value (base, in_info, val, &min_loss, &out_info); - if (min_loss == 0) - break; - } - } - } else if (G_VALUE_HOLDS_STRING (format)) { - score_value (base, in_info, format, &min_loss, &out_info); - } - } - if (out_info) - gst_structure_set (outs, "format", G_TYPE_STRING, - GST_VIDEO_FORMAT_INFO_NAME (out_info), NULL); -} - -static gboolean -subsampling_unchanged (GstVideoInfo * in_info, GstVideoInfo * out_info) -{ - gint i; - const GstVideoFormatInfo *in_format, *out_format; - - if (GST_VIDEO_INFO_N_COMPONENTS (in_info) != - GST_VIDEO_INFO_N_COMPONENTS (out_info)) - return FALSE; - - in_format = in_info->finfo; - out_format = out_info->finfo; - - for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (in_info); i++) { - if (GST_VIDEO_FORMAT_INFO_W_SUB (in_format, - i) != GST_VIDEO_FORMAT_INFO_W_SUB (out_format, i)) - return FALSE; - if (GST_VIDEO_FORMAT_INFO_H_SUB (in_format, - i) != GST_VIDEO_FORMAT_INFO_H_SUB (out_format, i)) - return FALSE; - } - - return TRUE; -} - -static void -transfer_colorimetry_from_input (GstBaseTransform * trans, GstCaps * in_caps, - GstCaps * out_caps) -{ - GstStructure *out_caps_s = gst_caps_get_structure (out_caps, 0); - GstStructure *in_caps_s = gst_caps_get_structure (in_caps, 0); - gboolean have_colorimetry = - gst_structure_has_field (out_caps_s, "colorimetry"); - gboolean have_chroma_site = - gst_structure_has_field (out_caps_s, "chroma-site"); - - /* If the output already has colorimetry and chroma-site, stop, - * otherwise try and transfer what we can from the input caps */ - if (have_colorimetry && have_chroma_site) - return; - - { - GstVideoInfo in_info, out_info; - const GValue *in_colorimetry = - gst_structure_get_value (in_caps_s, "colorimetry"); - - if (!gst_video_info_from_caps (&in_info, in_caps)) { - GST_WARNING_OBJECT (trans, - "Failed to convert sink pad caps to video info"); - return; - } - if (!gst_video_info_from_caps (&out_info, out_caps)) { - GST_WARNING_OBJECT (trans, - "Failed to convert src pad caps to video info"); - return; - } - - if (!have_colorimetry && in_colorimetry != NULL) { - if ((GST_VIDEO_INFO_IS_YUV (&out_info) - && GST_VIDEO_INFO_IS_YUV (&in_info)) - || (GST_VIDEO_INFO_IS_RGB (&out_info) - && GST_VIDEO_INFO_IS_RGB (&in_info)) - || (GST_VIDEO_INFO_IS_GRAY (&out_info) - && GST_VIDEO_INFO_IS_GRAY (&in_info))) { - /* Can transfer the colorimetry intact from the input if it has it */ - gst_structure_set_value (out_caps_s, "colorimetry", in_colorimetry); - } else { - gchar *colorimetry_str; - - /* Changing between YUV/RGB - forward primaries and transfer function, but use - * default range and matrix. - * the primaries is used for conversion between RGB and XYZ (CIE 1931 coordinate). - * the transfer function could be another reference (e.g., HDR) - */ - out_info.colorimetry.primaries = in_info.colorimetry.primaries; - out_info.colorimetry.transfer = in_info.colorimetry.transfer; - - colorimetry_str = - gst_video_colorimetry_to_string (&out_info.colorimetry); - gst_caps_set_simple (out_caps, "colorimetry", G_TYPE_STRING, - colorimetry_str, NULL); - g_free (colorimetry_str); - } - } - - /* Only YUV output needs chroma-site. If the input was also YUV and had the same chroma - * subsampling, transfer the siting. If the sub-sampling is changing, then the planes get - * scaled anyway so there's no real reason to prefer the input siting. */ - if (!have_chroma_site && GST_VIDEO_INFO_IS_YUV (&out_info)) { - if (GST_VIDEO_INFO_IS_YUV (&in_info)) { - const GValue *in_chroma_site = - gst_structure_get_value (in_caps_s, "chroma-site"); - if (in_chroma_site != NULL - && subsampling_unchanged (&in_info, &out_info)) - gst_structure_set_value (out_caps_s, "chroma-site", in_chroma_site); - } - } - } -} - -static GstCaps * -gst_video_convert_fixate_caps (GstBaseTransform * trans, - GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) -{ - GstCaps *result; - - GST_DEBUG_OBJECT (trans, "trying to fixate othercaps %" GST_PTR_FORMAT - " based on caps %" GST_PTR_FORMAT, othercaps, caps); - - result = gst_caps_intersect (othercaps, caps); - if (gst_caps_is_empty (result)) { - gst_caps_unref (result); - result = othercaps; - } else { - gst_caps_unref (othercaps); - } - - GST_DEBUG_OBJECT (trans, "now fixating %" GST_PTR_FORMAT, result); - - result = gst_caps_make_writable (result); - gst_video_convert_fixate_format (trans, caps, result); - - /* fixate remaining fields */ - result = gst_caps_fixate (result); - - if (direction == GST_PAD_SINK) { - if (gst_caps_is_subset (caps, result)) { - gst_caps_replace (&result, caps); - } else { - /* Try and preserve input colorimetry / chroma information */ - transfer_colorimetry_from_input (trans, caps, result); - } - } - - return result; -} - -static gboolean -gst_video_convert_filter_meta (GstBaseTransform * trans, GstQuery * query, - GType api, const GstStructure * params) -{ - /* This element cannot passthrough the crop meta, because it would convert the - * wrong sub-region of the image, and worst, our output image may not be large - * enough for the crop to be applied later */ - if (api == GST_VIDEO_CROP_META_API_TYPE) - return FALSE; - - /* propose all other metadata upstream */ - return TRUE; -} - -/* The caps can be transformed into any other caps with format info removed. - * However, we should prefer passthrough, so if passthrough is possible, - * put it first in the list. */ -static GstCaps * -gst_video_convert_transform_caps (GstBaseTransform * btrans, - GstPadDirection direction, GstCaps * caps, GstCaps * filter) -{ - GstCaps *tmp, *tmp2; - GstCaps *result; - - /* Get all possible caps that we can transform to */ - tmp = gst_video_convert_caps_remove_format_info (caps); - - if (filter) { - tmp2 = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (tmp); - tmp = tmp2; - } - - result = tmp; - - GST_DEBUG_OBJECT (btrans, "transformed %" GST_PTR_FORMAT " into %" - GST_PTR_FORMAT, caps, result); - - return result; -} - -static gboolean -gst_video_convert_transform_meta (GstBaseTransform * trans, GstBuffer * outbuf, - GstMeta * meta, GstBuffer * inbuf) -{ - const GstMetaInfo *info = meta->info; - gboolean ret; - - if (gst_meta_api_type_has_tag (info->api, _colorspace_quark)) { - /* don't copy colorspace specific metadata, FIXME, we need a MetaTransform - * for the colorspace metadata. */ - ret = FALSE; - } else { - /* copy other metadata */ - ret = TRUE; - } - return ret; -} - -static gboolean -gst_video_convert_set_info (GstVideoFilter * filter, - GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps, - GstVideoInfo * out_info) -{ - GstVideoConvert *space; - GstBaseTransformClass *gstbasetransform_class = - GST_BASE_TRANSFORM_GET_CLASS (filter); - GstVideoInfo tmp_info; - - space = GST_VIDEO_CONVERT_CAST (filter); - - if (space->convert) { - gst_video_converter_free (space->convert); - space->convert = NULL; - } - - /* these must match */ - if (in_info->width != out_info->width || in_info->height != out_info->height - || in_info->fps_n != out_info->fps_n || in_info->fps_d != out_info->fps_d) - goto format_mismatch; - - /* if present, these must match too */ - if (in_info->par_n != out_info->par_n || in_info->par_d != out_info->par_d) - goto format_mismatch; - - /* if present, these must match too */ - if (in_info->interlace_mode != out_info->interlace_mode) - goto format_mismatch; - - /* if the only thing different in the caps is the transfer function, and - * we're converting between equivalent transfer functions, do passthrough */ - tmp_info = *in_info; - tmp_info.colorimetry.transfer = out_info->colorimetry.transfer; - if (gst_video_info_is_equal (&tmp_info, out_info)) { - if (gst_video_transfer_function_is_equivalent (in_info-> - colorimetry.transfer, in_info->finfo->bits, - out_info->colorimetry.transfer, out_info->finfo->bits)) { - gstbasetransform_class->passthrough_on_same_caps = FALSE; - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE); - return TRUE; - } - } - gstbasetransform_class->passthrough_on_same_caps = TRUE; - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), FALSE); - - space->convert = gst_video_converter_new (in_info, out_info, - gst_structure_new ("GstVideoConvertConfig", - GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, - space->dither, - GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION, G_TYPE_UINT, - space->dither_quantization, - GST_VIDEO_CONVERTER_OPT_CHROMA_RESAMPLER_METHOD, - GST_TYPE_VIDEO_RESAMPLER_METHOD, space->chroma_resampler, - GST_VIDEO_CONVERTER_OPT_ALPHA_MODE, - GST_TYPE_VIDEO_ALPHA_MODE, space->alpha_mode, - GST_VIDEO_CONVERTER_OPT_ALPHA_VALUE, - G_TYPE_DOUBLE, space->alpha_value, - GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, - GST_TYPE_VIDEO_CHROMA_MODE, space->chroma_mode, - GST_VIDEO_CONVERTER_OPT_MATRIX_MODE, - GST_TYPE_VIDEO_MATRIX_MODE, space->matrix_mode, - GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, - GST_TYPE_VIDEO_GAMMA_MODE, space->gamma_mode, - GST_VIDEO_CONVERTER_OPT_PRIMARIES_MODE, - GST_TYPE_VIDEO_PRIMARIES_MODE, space->primaries_mode, - GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT, - space->n_threads, NULL)); - if (space->convert == NULL) - goto no_convert; - - GST_DEBUG_OBJECT (filter, "converting format %s -> %s", - gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)), - gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info))); - - return TRUE; - - /* ERRORS */ -format_mismatch: - { - GST_ERROR_OBJECT (space, "input and output formats do not match"); - return FALSE; - } -no_convert: - { - GST_ERROR_OBJECT (space, "could not create converter"); - return FALSE; - } -} - -static void -gst_video_convert_finalize (GObject * obj) -{ - GstVideoConvert *space = GST_VIDEO_CONVERT (obj); - - if (space->convert) { - gst_video_converter_free (space->convert); - } - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -gst_video_convert_class_init (GstVideoConvertClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; - GstBaseTransformClass *gstbasetransform_class = - (GstBaseTransformClass *) klass; - GstVideoFilterClass *gstvideofilter_class = (GstVideoFilterClass *) klass; - - gobject_class->set_property = gst_video_convert_set_property; - gobject_class->get_property = gst_video_convert_get_property; - gobject_class->finalize = gst_video_convert_finalize; - - gst_element_class_add_static_pad_template (gstelement_class, - &gst_video_convert_src_template); - gst_element_class_add_static_pad_template (gstelement_class, - &gst_video_convert_sink_template); - - gst_element_class_set_static_metadata (gstelement_class, - "Colorspace converter", "Filter/Converter/Video", - "Converts video from one colorspace to another", - "GStreamer maintainers "); - - gstbasetransform_class->transform_caps = - GST_DEBUG_FUNCPTR (gst_video_convert_transform_caps); - gstbasetransform_class->fixate_caps = - GST_DEBUG_FUNCPTR (gst_video_convert_fixate_caps); - gstbasetransform_class->filter_meta = - GST_DEBUG_FUNCPTR (gst_video_convert_filter_meta); - gstbasetransform_class->transform_meta = - GST_DEBUG_FUNCPTR (gst_video_convert_transform_meta); - - gstbasetransform_class->passthrough_on_same_caps = TRUE; - - gstvideofilter_class->set_info = - GST_DEBUG_FUNCPTR (gst_video_convert_set_info); - gstvideofilter_class->transform_frame = - GST_DEBUG_FUNCPTR (gst_video_convert_transform_frame); - - g_object_class_install_property (gobject_class, PROP_DITHER, - g_param_spec_enum ("dither", "Dither", "Apply dithering while converting", - gst_video_dither_method_get_type (), DEFAULT_PROP_DITHER, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_DITHER_QUANTIZATION, - g_param_spec_uint ("dither-quantization", "Dither Quantize", - "Quantizer to use", 0, G_MAXUINT, DEFAULT_PROP_DITHER_QUANTIZATION, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_CHROMA_RESAMPLER, - g_param_spec_enum ("chroma-resampler", "Chroma resampler", - "Chroma resampler method", gst_video_resampler_method_get_type (), - DEFAULT_PROP_CHROMA_RESAMPLER, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_ALPHA_MODE, - g_param_spec_enum ("alpha-mode", "Alpha Mode", - "Alpha Mode to use", gst_video_alpha_mode_get_type (), - DEFAULT_PROP_ALPHA_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_ALPHA_VALUE, - g_param_spec_double ("alpha-value", "Alpha Value", - "Alpha Value to use", 0.0, 1.0, - DEFAULT_PROP_ALPHA_VALUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_CHROMA_MODE, - g_param_spec_enum ("chroma-mode", "Chroma Mode", "Chroma Resampling Mode", - gst_video_chroma_mode_get_type (), DEFAULT_PROP_CHROMA_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_MATRIX_MODE, - g_param_spec_enum ("matrix-mode", "Matrix Mode", "Matrix Conversion Mode", - gst_video_matrix_mode_get_type (), DEFAULT_PROP_MATRIX_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_GAMMA_MODE, - g_param_spec_enum ("gamma-mode", "Gamma Mode", "Gamma Conversion Mode", - gst_video_gamma_mode_get_type (), DEFAULT_PROP_GAMMA_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_PRIMARIES_MODE, - g_param_spec_enum ("primaries-mode", "Primaries Mode", - "Primaries Conversion Mode", gst_video_primaries_mode_get_type (), - DEFAULT_PROP_PRIMARIES_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_N_THREADS, - g_param_spec_uint ("n-threads", "Threads", - "Maximum number of threads to use", 0, G_MAXUINT, - DEFAULT_PROP_N_THREADS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_video_convert_init (GstVideoConvert * space) -{ - space->dither = DEFAULT_PROP_DITHER; - space->dither_quantization = DEFAULT_PROP_DITHER_QUANTIZATION; - space->chroma_resampler = DEFAULT_PROP_CHROMA_RESAMPLER; - space->alpha_mode = DEFAULT_PROP_ALPHA_MODE; - space->alpha_value = DEFAULT_PROP_ALPHA_VALUE; - space->chroma_mode = DEFAULT_PROP_CHROMA_MODE; - space->matrix_mode = DEFAULT_PROP_MATRIX_MODE; - space->gamma_mode = DEFAULT_PROP_GAMMA_MODE; - space->primaries_mode = DEFAULT_PROP_PRIMARIES_MODE; - space->n_threads = DEFAULT_PROP_N_THREADS; -} - -void -gst_video_convert_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - GstVideoConvert *csp; - - csp = GST_VIDEO_CONVERT (object); - - switch (property_id) { - case PROP_DITHER: - csp->dither = g_value_get_enum (value); - break; - case PROP_CHROMA_RESAMPLER: - csp->chroma_resampler = g_value_get_enum (value); - break; - case PROP_ALPHA_MODE: - csp->alpha_mode = g_value_get_enum (value); - break; - case PROP_ALPHA_VALUE: - csp->alpha_value = g_value_get_double (value); - break; - case PROP_CHROMA_MODE: - csp->chroma_mode = g_value_get_enum (value); - break; - case PROP_MATRIX_MODE: - csp->matrix_mode = g_value_get_enum (value); - break; - case PROP_GAMMA_MODE: - csp->gamma_mode = g_value_get_enum (value); - break; - case PROP_PRIMARIES_MODE: - csp->primaries_mode = g_value_get_enum (value); - break; - case PROP_DITHER_QUANTIZATION: - csp->dither_quantization = g_value_get_uint (value); - break; - case PROP_N_THREADS: - csp->n_threads = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_video_convert_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - GstVideoConvert *csp; - - csp = GST_VIDEO_CONVERT (object); - - switch (property_id) { - case PROP_DITHER: - g_value_set_enum (value, csp->dither); - break; - case PROP_CHROMA_RESAMPLER: - g_value_set_enum (value, csp->chroma_resampler); - break; - case PROP_ALPHA_MODE: - g_value_set_enum (value, csp->alpha_mode); - break; - case PROP_ALPHA_VALUE: - g_value_set_double (value, csp->alpha_value); - break; - case PROP_CHROMA_MODE: - g_value_set_enum (value, csp->chroma_mode); - break; - case PROP_MATRIX_MODE: - g_value_set_enum (value, csp->matrix_mode); - break; - case PROP_GAMMA_MODE: - g_value_set_enum (value, csp->gamma_mode); - break; - case PROP_PRIMARIES_MODE: - g_value_set_enum (value, csp->primaries_mode); - break; - case PROP_DITHER_QUANTIZATION: - g_value_set_uint (value, csp->dither_quantization); - break; - case PROP_N_THREADS: - g_value_set_uint (value, csp->n_threads); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static GstFlowReturn -gst_video_convert_transform_frame (GstVideoFilter * filter, - GstVideoFrame * in_frame, GstVideoFrame * out_frame) -{ - GstVideoConvert *space; - - space = GST_VIDEO_CONVERT_CAST (filter); - - GST_CAT_DEBUG_OBJECT (CAT_PERFORMANCE, filter, - "doing colorspace conversion from %s -> to %s", - GST_VIDEO_INFO_NAME (&filter->in_info), - GST_VIDEO_INFO_NAME (&filter->out_info)); - - gst_video_converter_frame (space->convert, in_frame, out_frame); - - return GST_FLOW_OK; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - GST_DEBUG_CATEGORY_INIT (videoconvert_debug, "videoconvert", 0, - "Colorspace Converter"); - - GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE"); - - _colorspace_quark = g_quark_from_static_string ("colorspace"); - - features_format_interlaced = - gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL); - features_format_interlaced_sysmem = - gst_caps_features_copy (features_format_interlaced); - gst_caps_features_add (features_format_interlaced_sysmem, - GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); - - return GST_ELEMENT_REGISTER (videoconvert, plugin); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - videoconvert, "Colorspace conversion", plugin_init, VERSION, GST_LICENSE, - GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/subprojects/gst-plugins-base/gst/videoconvert/meson.build b/subprojects/gst-plugins-base/gst/videoconvert/meson.build deleted file mode 100644 index 2798f8d018..0000000000 --- a/subprojects/gst-plugins-base/gst/videoconvert/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -vconvert_sources = [ - 'gstvideoconvert.c', -] - -gstvideoconvert = library('gstvideoconvert', - vconvert_sources, - c_args : gst_plugins_base_args, - include_directories: [configinc, libsinc], - dependencies : [video_dep], - install : true, - install_dir : plugins_install_dir, -) -pkgconfig.generate(gstvideoconvert, install_dir : plugins_pkgconfig_install_dir) -plugins += [gstvideoconvert] diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/README b/subprojects/gst-plugins-base/gst/videoconvertscale/README new file mode 100644 index 0000000000..731f17db3a --- /dev/null +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/README @@ -0,0 +1,5 @@ +- test different strides using +gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoconvertscale ! video/x-raw,width=328,height=240 ! xvimagesink +gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoconvertscale ! video/x-raw,width=324,height=240 ! xvimagesink +gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoconvertscale ! video/x-raw,width=322,height=240 ! xvimagesink +gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoconvertscale ! video/x-raw,width=321,height=240 ! xvimagesink diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c new file mode 100644 index 0000000000..8424bbfe2b --- /dev/null +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.c @@ -0,0 +1,59 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * This file: + * Copyright (C) 2003 Ronald Bultje + * Copyright (C) 2010 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-videoconvert + * @title: videoconvert + * + * Convert video frames between a great variety of video formats. + * + * ## Example launch line + * |[ + * gst-launch-1.0 -v videotestsrc ! video/x-raw,format=YUY2 ! videoconvert ! autovideosink + * ]| + * This will output a test video (generated in YUY2 format) in a video + * window. If the video sink selected does not support YUY2 videoconvert will + * automatically convert the video to a format understood by the video sink. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvideoconvert.h" + +G_DEFINE_TYPE (GstVideoConvert, gst_video_convert, + GST_TYPE_VIDEO_CONVERT_SCALE); +GST_ELEMENT_REGISTER_DEFINE (videoconvert, "videoconvert", + GST_RANK_MARGINAL, gst_video_convert_get_type ()); + +static void +gst_video_convert_class_init (GstVideoConvertClass * klass) +{ + +} + +static void +gst_video_convert_init (GstVideoConvert * self) +{ + +} diff --git a/subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.h b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.h similarity index 57% rename from subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.h rename to subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.h index 0f093f4f7d..143b6d4265 100644 --- a/subprojects/gst-plugins-base/gst/videoconvert/gstvideoconvert.h +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvert.h @@ -19,43 +19,20 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GST_VIDEOCONVERT_H__ -#define __GST_VIDEOCONVERT_H__ +#pragma once -#include -#include -#include +#include "gstvideoconvertscale.h" G_BEGIN_DECLS -#define GST_TYPE_VIDEO_CONVERT (gst_video_convert_get_type()) -#define GST_VIDEO_CONVERT_CAST(obj) ((GstVideoConvert *)(obj)) G_DECLARE_FINAL_TYPE (GstVideoConvert, gst_video_convert, GST, VIDEO_CONVERT, - GstVideoFilter) + GstVideoConvertScale); -/** - * GstVideoConvert: - * - * Opaque object data structure. - */ -struct _GstVideoConvert { - GstVideoFilter element; - - GstVideoConverter *convert; - GstVideoDitherMethod dither; - guint dither_quantization; - GstVideoResamplerMethod chroma_resampler; - GstVideoAlphaMode alpha_mode; - GstVideoChromaMode chroma_mode; - GstVideoMatrixMode matrix_mode; - GstVideoGammaMode gamma_mode; - GstVideoPrimariesMode primaries_mode; - gdouble alpha_value; - gint n_threads; +struct _GstVideoConvert +{ + GstVideoConvertScale parent; }; GST_ELEMENT_REGISTER_DECLARE (videoconvert); G_END_DECLS - -#endif /* __GST_VIDEOCONVERT_H__ */ diff --git a/subprojects/gst-plugins-base/gst/videoscale/gstvideoscale.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c similarity index 54% rename from subprojects/gst-plugins-base/gst/videoscale/gstvideoscale.c rename to subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c index 1b20c7311b..df168caf82 100644 --- a/subprojects/gst-plugins-base/gst/videoscale/gstvideoscale.c +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.c @@ -1,6 +1,8 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) 2003 Ronald Bultje * Copyright (C) 2005-2012 David Schleef + * Copyright (C) 2022 Thibault Saunier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -19,14 +21,14 @@ */ /** - * SECTION:element-videoscale - * @title: videoscale - * @see_also: videorate, videoconvert + * SECTION:element-videoconvertscale + * @title: videoconvertscale * - * This element resizes video frames. By default the element will try to - * negotiate to the same size on the source and sinkpad so that no scaling - * is needed. It is therefore safe to insert this element in a pipeline to - * get more robust behaviour without any cost if no scaling is needed. + * This element resizes video frames and allows changing colorspace. By default + * the element will try to negotiate to the same size on the source and sinkpad + * so that no scaling is needed. It is therefore safe to insert this element in + * a pipeline to get more robust behaviour without any cost if no scaling is + * needed. * * This element supports a wide range of color spaces including various YUV and * RGB formats and is therefore generally able to operate anywhere in a @@ -34,17 +36,18 @@ * * ## Example pipelines * |[ - * gst-launch-1.0 -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoconvert ! videoscale ! autovideosink + * gst-launch-1.0 -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoconvertscale ! autovideosink * ]| * Decode an Ogg/Theora and display the video. If the video sink chosen - * cannot perform scaling, the video scaling will be performed by videoscale + * cannot perform scaling, the video scaling will be performed by videoconvertscale * when you resize the video window. * To create the test Ogg/Theora file refer to the documentation of theoraenc. * |[ - * gst-launch-1.0 -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoconvert ! videoscale ! video/x-raw,width=100 ! autovideosink + * gst-launch-1.0 -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoconvertscale ! video/x-raw,width=100 ! autovideosink * ]| * Decode an Ogg/Theora and display the video with a width of 100. * + * Since: 1.22 */ /* @@ -78,21 +81,63 @@ #include #include -#include "gstvideoscale.h" +#include "gstvideoconvertscale.h" -#define GST_CAT_DEFAULT video_scale_debug -GST_DEBUG_CATEGORY_STATIC (video_scale_debug); +typedef struct +{ + /* properties */ + GstVideoScaleMethod method; + gboolean add_borders; + double sharpness; + double sharpen; + int submethod; + double envelope; + gint n_threads; + GstVideoDitherMethod dither; + guint dither_quantization; + GstVideoResamplerMethod chroma_resampler; + GstVideoAlphaMode alpha_mode; + GstVideoChromaMode chroma_mode; + GstVideoMatrixMode matrix_mode; + GstVideoGammaMode gamma_mode; + GstVideoPrimariesMode primaries_mode; + gdouble alpha_value; + + GstVideoConverter *convert; + + gint borders_h; + gint borders_w; +} GstVideoConvertScalePrivate; + +#define gst_video_convert_scale_parent_class parent_class +G_DEFINE_TYPE_WITH_PRIVATE (GstVideoConvertScale, gst_video_convert_scale, + GST_TYPE_VIDEO_FILTER); +GST_ELEMENT_REGISTER_DEFINE (videoconvertscale, "videoconvertscale", + GST_RANK_SECONDARY, GST_TYPE_VIDEO_CONVERT_SCALE); + +#define PRIV(self) gst_video_convert_scale_get_instance_private(((GstVideoConvertScale*) self)) + +#define GST_CAT_DEFAULT video_convertscale_debug +GST_DEBUG_CATEGORY_STATIC (video_convertscale_debug); GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE); #define DEFAULT_PROP_METHOD GST_VIDEO_SCALE_BILINEAR #define DEFAULT_PROP_ADD_BORDERS TRUE #define DEFAULT_PROP_SHARPNESS 1.0 #define DEFAULT_PROP_SHARPEN 0.0 -#define DEFAULT_PROP_DITHER FALSE -#define DEFAULT_PROP_SUBMETHOD 1 +#define DEFAULT_PROP_DITHER GST_VIDEO_DITHER_BAYER #define DEFAULT_PROP_ENVELOPE 2.0 -#define DEFAULT_PROP_GAMMA_DECODE FALSE -#define DEFAULT_PROP_N_THREADS 1 +#define DEFAULT_PROP_DITHER_QUANTIZATION 1 +#define DEFAULT_PROP_CHROMA_RESAMPLER GST_VIDEO_RESAMPLER_METHOD_LINEAR +#define DEFAULT_PROP_ALPHA_MODE GST_VIDEO_ALPHA_MODE_COPY +#define DEFAULT_PROP_ALPHA_VALUE 1.0 +#define DEFAULT_PROP_CHROMA_MODE GST_VIDEO_CHROMA_MODE_FULL +#define DEFAULT_PROP_MATRIX_MODE GST_VIDEO_MATRIX_MODE_FULL +#define DEFAULT_PROP_GAMMA_MODE GST_VIDEO_GAMMA_MODE_NONE +#define DEFAULT_PROP_PRIMARIES_MODE GST_VIDEO_PRIMARIES_MODE_NONE +#define DEFAULT_PROP_N_THREADS 1 + +static GQuark _colorspace_quark; enum { @@ -104,8 +149,15 @@ enum PROP_DITHER, PROP_SUBMETHOD, PROP_ENVELOPE, - PROP_GAMMA_DECODE, - PROP_N_THREADS + PROP_N_THREADS, + PROP_DITHER_QUANTIZATION, + PROP_CHROMA_RESAMPLER, + PROP_ALPHA_MODE, + PROP_ALPHA_VALUE, + PROP_CHROMA_MODE, + PROP_MATRIX_MODE, + PROP_GAMMA_MODE, + PROP_PRIMARIES_MODE, }; #undef GST_VIDEO_SIZE_RANGE @@ -123,7 +175,7 @@ enum #define GST_VIDEO_FORMATS GST_VIDEO_FORMATS_ALL -static GstStaticCaps gst_video_scale_format_caps = +static GstStaticCaps gst_video_convert_scale_format_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS) ";" GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS)); @@ -158,75 +210,98 @@ gst_video_scale_method_get_type (void) } static GstCaps * -gst_video_scale_get_capslist (void) +gst_video_convert_scale_get_capslist (void) { static GstCaps *caps = NULL; static gsize inited = 0; if (g_once_init_enter (&inited)) { - caps = gst_static_caps_get (&gst_video_scale_format_caps); + caps = gst_static_caps_get (&gst_video_convert_scale_format_caps); g_once_init_leave (&inited, 1); } return caps; } static GstPadTemplate * -gst_video_scale_src_template_factory (void) +gst_video_convert_scale_src_template_factory (void) { return gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - gst_video_scale_get_capslist ()); + gst_video_convert_scale_get_capslist ()); } static GstPadTemplate * -gst_video_scale_sink_template_factory (void) +gst_video_convert_scale_sink_template_factory (void) { return gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - gst_video_scale_get_capslist ()); + gst_video_convert_scale_get_capslist ()); } -static void gst_video_scale_finalize (GstVideoScale * videoscale); -static gboolean gst_video_scale_src_event (GstBaseTransform * trans, +static void gst_video_convert_scale_finalize (GstVideoConvertScale * self); +static gboolean gst_video_convert_scale_src_event (GstBaseTransform * trans, GstEvent * event); /* base transform vmethods */ -static GstCaps *gst_video_scale_transform_caps (GstBaseTransform * trans, - GstPadDirection direction, GstCaps * caps, GstCaps * filter); -static GstCaps *gst_video_scale_fixate_caps (GstBaseTransform * base, +static GstCaps *gst_video_convert_scale_transform_caps (GstBaseTransform * + trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter); +static GstCaps *gst_video_convert_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); -static gboolean gst_video_scale_transform_meta (GstBaseTransform * trans, - GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf); +static gboolean gst_video_convert_scale_transform_meta (GstBaseTransform * + trans, GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf); -static gboolean gst_video_scale_set_info (GstVideoFilter * filter, +static gboolean gst_video_convert_scale_set_info (GstVideoFilter * filter, GstCaps * in, GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info); -static GstFlowReturn gst_video_scale_transform_frame (GstVideoFilter * filter, - GstVideoFrame * in, GstVideoFrame * out); +static GstFlowReturn gst_video_convert_scale_transform_frame (GstVideoFilter * + filter, GstVideoFrame * in, GstVideoFrame * out); -static void gst_video_scale_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_video_scale_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -#define gst_video_scale_parent_class parent_class -G_DEFINE_TYPE (GstVideoScale, gst_video_scale, GST_TYPE_VIDEO_FILTER); -GST_ELEMENT_REGISTER_DEFINE (videoscale, "videoscale", - GST_RANK_NONE, GST_TYPE_VIDEO_SCALE); +static void gst_video_convert_scale_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_video_convert_scale_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); static GstCapsFeatures *features_format_interlaced, *features_format_interlaced_sysmem; +static gboolean +gst_video_convert_scale_filter_meta (GstBaseTransform * trans, GstQuery * query, + GType api, const GstStructure * params) +{ + /* This element cannot passthrough the crop meta, because it would convert the + * wrong sub-region of the image, and worst, our output image may not be large + * enough for the crop to be applied later */ + if (api == GST_VIDEO_CROP_META_API_TYPE) + return FALSE; + + /* propose all other metadata upstream */ + return TRUE; +} + static void -gst_video_scale_class_init (GstVideoScaleClass * klass) +gst_video_convert_scale_class_init (GstVideoConvertScaleClass * klass) { GObjectClass *gobject_class = (GObjectClass *) klass; GstElementClass *element_class = (GstElementClass *) klass; GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass; GstVideoFilterClass *filter_class = (GstVideoFilterClass *) klass; - gobject_class->finalize = (GObjectFinalizeFunc) gst_video_scale_finalize; - gobject_class->set_property = gst_video_scale_set_property; - gobject_class->get_property = gst_video_scale_get_property; + GST_DEBUG_CATEGORY_INIT (video_convertscale_debug, "videoconvertscale", 0, + "videoconvertscale element"); + GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE"); + + features_format_interlaced = + gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL); + features_format_interlaced_sysmem = + gst_caps_features_copy (features_format_interlaced); + gst_caps_features_add (features_format_interlaced_sysmem, + GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); + + _colorspace_quark = g_quark_from_static_string ("colorspace"); + + gobject_class->finalize = + (GObjectFinalizeFunc) gst_video_convert_scale_finalize; + gobject_class->set_property = gst_video_convert_scale_set_property; + gobject_class->get_property = gst_video_convert_scale_get_property; g_object_class_install_property (gobject_class, PROP_METHOD, g_param_spec_enum ("method", "method", "method", @@ -250,216 +325,259 @@ gst_video_scale_class_init (GstVideoScaleClass * klass) G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DITHER, - g_param_spec_boolean ("dither", "Dither", - "Add dither (only used for Lanczos method)", - DEFAULT_PROP_DITHER, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - -#if 0 - /* I am hiding submethod for now, since it's poorly named, poorly - * documented, and will probably just get people into trouble. */ - g_object_class_install_property (gobject_class, PROP_SUBMETHOD, - g_param_spec_int ("submethod", "submethod", - "submethod", 0, 3, DEFAULT_PROP_SUBMETHOD, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -#endif - + g_param_spec_enum ("dither", "Dither", "Apply dithering while converting", + gst_video_dither_method_get_type (), DEFAULT_PROP_DITHER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_ENVELOPE, g_param_spec_double ("envelope", "Envelope", "Size of filter envelope", 1.0, 5.0, DEFAULT_PROP_ENVELOPE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_GAMMA_DECODE, - g_param_spec_boolean ("gamma-decode", "Gamma Decode", - "Decode gamma before scaling", DEFAULT_PROP_GAMMA_DECODE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_N_THREADS, g_param_spec_uint ("n-threads", "Threads", "Maximum number of threads to use", 0, G_MAXUINT, DEFAULT_PROP_N_THREADS, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DITHER_QUANTIZATION, + g_param_spec_uint ("dither-quantization", "Dither Quantize", + "Quantizer to use", 0, G_MAXUINT, DEFAULT_PROP_DITHER_QUANTIZATION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CHROMA_RESAMPLER, + g_param_spec_enum ("chroma-resampler", "Chroma resampler", + "Chroma resampler method", gst_video_resampler_method_get_type (), + DEFAULT_PROP_CHROMA_RESAMPLER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ALPHA_MODE, + g_param_spec_enum ("alpha-mode", "Alpha Mode", + "Alpha Mode to use", gst_video_alpha_mode_get_type (), + DEFAULT_PROP_ALPHA_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ALPHA_VALUE, + g_param_spec_double ("alpha-value", "Alpha Value", + "Alpha Value to use", 0.0, 1.0, + DEFAULT_PROP_ALPHA_VALUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CHROMA_MODE, + g_param_spec_enum ("chroma-mode", "Chroma Mode", "Chroma Resampling Mode", + gst_video_chroma_mode_get_type (), DEFAULT_PROP_CHROMA_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MATRIX_MODE, + g_param_spec_enum ("matrix-mode", "Matrix Mode", "Matrix Conversion Mode", + gst_video_matrix_mode_get_type (), DEFAULT_PROP_MATRIX_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_GAMMA_MODE, + g_param_spec_enum ("gamma-mode", "Gamma Mode", "Gamma Conversion Mode", + gst_video_gamma_mode_get_type (), DEFAULT_PROP_GAMMA_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PRIMARIES_MODE, + g_param_spec_enum ("primaries-mode", "Primaries Mode", + "Primaries Conversion Mode", gst_video_primaries_mode_get_type (), + DEFAULT_PROP_PRIMARIES_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gst_element_class_set_static_metadata (element_class, - "Video scaler", "Filter/Converter/Video/Scaler", - "Resizes video", "Wim Taymans "); + "Video colorspace converter and scaler", + "Filter/Converter/Video/Scaler/Colorspace", + "Resizes video and allow color conversion", + "Wim Taymans "); gst_element_class_add_pad_template (element_class, - gst_video_scale_sink_template_factory ()); + gst_video_convert_scale_sink_template_factory ()); gst_element_class_add_pad_template (element_class, - gst_video_scale_src_template_factory ()); - - trans_class->transform_caps = - GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps); - trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_video_scale_fixate_caps); - trans_class->src_event = GST_DEBUG_FUNCPTR (gst_video_scale_src_event); - trans_class->transform_meta = - GST_DEBUG_FUNCPTR (gst_video_scale_transform_meta); - - filter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_scale_set_info); - filter_class->transform_frame = - GST_DEBUG_FUNCPTR (gst_video_scale_transform_frame); + gst_video_convert_scale_src_template_factory ()); _size_quark = g_quark_from_static_string (GST_META_TAG_VIDEO_SIZE_STR); _scale_quark = gst_video_meta_transform_scale_get_quark (); gst_type_mark_as_plugin_api (GST_TYPE_VIDEO_SCALE_METHOD, 0); + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_video_convert_scale_transform_caps); + trans_class->fixate_caps = + GST_DEBUG_FUNCPTR (gst_video_convert_scale_fixate_caps); + trans_class->filter_meta = + GST_DEBUG_FUNCPTR (gst_video_convert_scale_filter_meta); + trans_class->src_event = + GST_DEBUG_FUNCPTR (gst_video_convert_scale_src_event); + trans_class->transform_meta = + GST_DEBUG_FUNCPTR (gst_video_convert_scale_transform_meta); + + filter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_convert_scale_set_info); + filter_class->transform_frame = + GST_DEBUG_FUNCPTR (gst_video_convert_scale_transform_frame); } static void -gst_video_scale_init (GstVideoScale * videoscale) +gst_video_convert_scale_init (GstVideoConvertScale * self) { - videoscale->method = DEFAULT_PROP_METHOD; - videoscale->add_borders = DEFAULT_PROP_ADD_BORDERS; - videoscale->submethod = DEFAULT_PROP_SUBMETHOD; - videoscale->sharpness = DEFAULT_PROP_SHARPNESS; - videoscale->sharpen = DEFAULT_PROP_SHARPEN; - videoscale->dither = DEFAULT_PROP_DITHER; - videoscale->envelope = DEFAULT_PROP_ENVELOPE; - videoscale->gamma_decode = DEFAULT_PROP_GAMMA_DECODE; - videoscale->n_threads = DEFAULT_PROP_N_THREADS; + GstVideoConvertScalePrivate *priv = PRIV (self); + + priv->method = DEFAULT_PROP_METHOD; + priv->add_borders = DEFAULT_PROP_ADD_BORDERS; + priv->sharpness = DEFAULT_PROP_SHARPNESS; + priv->sharpen = DEFAULT_PROP_SHARPEN; + priv->envelope = DEFAULT_PROP_ENVELOPE; + priv->n_threads = DEFAULT_PROP_N_THREADS; + priv->dither = DEFAULT_PROP_DITHER; + priv->dither_quantization = DEFAULT_PROP_DITHER_QUANTIZATION; + priv->chroma_resampler = DEFAULT_PROP_CHROMA_RESAMPLER; + priv->alpha_mode = DEFAULT_PROP_ALPHA_MODE; + priv->alpha_value = DEFAULT_PROP_ALPHA_VALUE; + priv->chroma_mode = DEFAULT_PROP_CHROMA_MODE; + priv->matrix_mode = DEFAULT_PROP_MATRIX_MODE; + priv->gamma_mode = DEFAULT_PROP_GAMMA_MODE; + priv->primaries_mode = DEFAULT_PROP_PRIMARIES_MODE; } static void -gst_video_scale_finalize (GstVideoScale * videoscale) +gst_video_convert_scale_finalize (GstVideoConvertScale * self) { - if (videoscale->convert) - gst_video_converter_free (videoscale->convert); + GstVideoConvertScalePrivate *priv = PRIV (self); - G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (videoscale)); + if (priv->convert) + gst_video_converter_free (priv->convert); + + G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (self)); } static void -gst_video_scale_set_property (GObject * object, guint prop_id, +gst_video_convert_scale_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVideoScale *vscale = GST_VIDEO_SCALE (object); + GstVideoConvertScalePrivate *priv = PRIV (object); + GST_OBJECT_LOCK (object); switch (prop_id) { case PROP_METHOD: - GST_OBJECT_LOCK (vscale); - vscale->method = g_value_get_enum (value); - GST_OBJECT_UNLOCK (vscale); + priv->method = g_value_get_enum (value); break; case PROP_ADD_BORDERS: - GST_OBJECT_LOCK (vscale); - vscale->add_borders = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (vscale); - gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (vscale)); - break; + priv->add_borders = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (object); + + gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (object)); + return; case PROP_SHARPNESS: - GST_OBJECT_LOCK (vscale); - vscale->sharpness = g_value_get_double (value); - GST_OBJECT_UNLOCK (vscale); + priv->sharpness = g_value_get_double (value); break; case PROP_SHARPEN: - GST_OBJECT_LOCK (vscale); - vscale->sharpen = g_value_get_double (value); - GST_OBJECT_UNLOCK (vscale); - break; - case PROP_DITHER: - GST_OBJECT_LOCK (vscale); - vscale->dither = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (vscale); + priv->sharpen = g_value_get_double (value); break; case PROP_SUBMETHOD: - GST_OBJECT_LOCK (vscale); - vscale->submethod = g_value_get_int (value); - GST_OBJECT_UNLOCK (vscale); + priv->submethod = g_value_get_int (value); break; case PROP_ENVELOPE: - GST_OBJECT_LOCK (vscale); - vscale->envelope = g_value_get_double (value); - GST_OBJECT_UNLOCK (vscale); - break; - case PROP_GAMMA_DECODE: - GST_OBJECT_LOCK (vscale); - vscale->gamma_decode = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (vscale); + priv->envelope = g_value_get_double (value); break; case PROP_N_THREADS: - GST_OBJECT_LOCK (vscale); - vscale->n_threads = g_value_get_uint (value); - GST_OBJECT_UNLOCK (vscale); + priv->n_threads = g_value_get_uint (value); + break; + case PROP_DITHER: + priv->dither = g_value_get_enum (value); + break; + case PROP_CHROMA_RESAMPLER: + priv->chroma_resampler = g_value_get_enum (value); + break; + case PROP_ALPHA_MODE: + priv->alpha_mode = g_value_get_enum (value); + break; + case PROP_ALPHA_VALUE: + priv->alpha_value = g_value_get_double (value); + break; + case PROP_CHROMA_MODE: + priv->chroma_mode = g_value_get_enum (value); + break; + case PROP_MATRIX_MODE: + priv->matrix_mode = g_value_get_enum (value); + break; + case PROP_GAMMA_MODE: + priv->gamma_mode = g_value_get_enum (value); + break; + case PROP_PRIMARIES_MODE: + priv->primaries_mode = g_value_get_enum (value); + break; + case PROP_DITHER_QUANTIZATION: + priv->dither_quantization = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + GST_OBJECT_UNLOCK (object); } static void -gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) +gst_video_convert_scale_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) { - GstVideoScale *vscale = GST_VIDEO_SCALE (object); + GstVideoConvertScalePrivate *priv = PRIV (object); + GST_OBJECT_LOCK (object); switch (prop_id) { case PROP_METHOD: - GST_OBJECT_LOCK (vscale); - g_value_set_enum (value, vscale->method); - GST_OBJECT_UNLOCK (vscale); + g_value_set_enum (value, priv->method); break; case PROP_ADD_BORDERS: - GST_OBJECT_LOCK (vscale); - g_value_set_boolean (value, vscale->add_borders); - GST_OBJECT_UNLOCK (vscale); + g_value_set_boolean (value, priv->add_borders); break; case PROP_SHARPNESS: - GST_OBJECT_LOCK (vscale); - g_value_set_double (value, vscale->sharpness); - GST_OBJECT_UNLOCK (vscale); + g_value_set_double (value, priv->sharpness); break; case PROP_SHARPEN: - GST_OBJECT_LOCK (vscale); - g_value_set_double (value, vscale->sharpen); - GST_OBJECT_UNLOCK (vscale); - break; - case PROP_DITHER: - GST_OBJECT_LOCK (vscale); - g_value_set_boolean (value, vscale->dither); - GST_OBJECT_UNLOCK (vscale); + g_value_set_double (value, priv->sharpen); break; case PROP_SUBMETHOD: - GST_OBJECT_LOCK (vscale); - g_value_set_int (value, vscale->submethod); - GST_OBJECT_UNLOCK (vscale); + g_value_set_int (value, priv->submethod); break; case PROP_ENVELOPE: - GST_OBJECT_LOCK (vscale); - g_value_set_double (value, vscale->envelope); - GST_OBJECT_UNLOCK (vscale); - break; - case PROP_GAMMA_DECODE: - GST_OBJECT_LOCK (vscale); - g_value_set_boolean (value, vscale->gamma_decode); - GST_OBJECT_UNLOCK (vscale); + g_value_set_double (value, priv->envelope); break; case PROP_N_THREADS: - GST_OBJECT_LOCK (vscale); - g_value_set_uint (value, vscale->n_threads); - GST_OBJECT_UNLOCK (vscale); + g_value_set_uint (value, priv->n_threads); + break; + case PROP_DITHER: + g_value_set_enum (value, priv->dither); + break; + case PROP_CHROMA_RESAMPLER: + g_value_set_enum (value, priv->chroma_resampler); + break; + case PROP_ALPHA_MODE: + g_value_set_enum (value, priv->alpha_mode); + break; + case PROP_ALPHA_VALUE: + g_value_set_double (value, priv->alpha_value); + break; + case PROP_CHROMA_MODE: + g_value_set_enum (value, priv->chroma_mode); + break; + case PROP_MATRIX_MODE: + g_value_set_enum (value, priv->matrix_mode); + break; + case PROP_GAMMA_MODE: + g_value_set_enum (value, priv->gamma_mode); + break; + case PROP_PRIMARIES_MODE: + g_value_set_enum (value, priv->primaries_mode); + break; + case PROP_DITHER_QUANTIZATION: + g_value_set_uint (value, priv->dither_quantization); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + GST_OBJECT_UNLOCK (object); } static GstCaps * -gst_video_scale_transform_caps (GstBaseTransform * trans, - GstPadDirection direction, GstCaps * caps, GstCaps * filter) +gst_video_convert_caps_remove_format_and_rangify_size_info (GstCaps * caps) { GstCaps *ret; GstStructure *structure; GstCapsFeatures *features; gint i, n; - GST_DEBUG_OBJECT (trans, - "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, - (direction == GST_PAD_SINK) ? "sink" : "src"); - ret = gst_caps_new_empty (); + n = gst_caps_get_size (caps); for (i = 0; i < n; i++) { structure = gst_caps_get_structure (caps, i); @@ -470,10 +588,8 @@ gst_video_scale_transform_caps (GstBaseTransform * trans, if (i > 0 && gst_caps_is_subset_structure_full (ret, structure, features)) continue; - /* make copy */ structure = gst_structure_copy (structure); - - /* If the features are non-sysmem we can only do passthrough */ + /* Only remove format info for the cases when we can actually convert */ if (!gst_caps_features_is_any (features) && (gst_caps_features_is_equal (features, GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY) @@ -482,17 +598,32 @@ gst_video_scale_transform_caps (GstBaseTransform * trans, features_format_interlaced_sysmem))) { gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - /* if pixel aspect ratio, make a range of it */ if (gst_structure_has_field (structure, "pixel-aspect-ratio")) { gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1, NULL); } + gst_structure_remove_fields (structure, "format", "colorimetry", + "chroma-site", NULL); } gst_caps_append_structure_full (ret, structure, gst_caps_features_copy (features)); } + return ret; +} + +static GstCaps * +gst_video_convert_scale_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) +{ + GstCaps *ret; + + GST_DEBUG_OBJECT (trans, + "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, + (direction == GST_PAD_SINK) ? "sink" : "src"); + + ret = gst_video_convert_caps_remove_format_and_rangify_size_info (caps); if (filter) { GstCaps *intersection; @@ -508,18 +639,18 @@ gst_video_scale_transform_caps (GstBaseTransform * trans, } static gboolean -gst_video_scale_transform_meta (GstBaseTransform * trans, GstBuffer * outbuf, - GstMeta * meta, GstBuffer * inbuf) +gst_video_convert_scale_transform_meta (GstBaseTransform * trans, + GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf) { GstVideoFilter *videofilter = GST_VIDEO_FILTER (trans); const GstMetaInfo *info = meta->info; const gchar *const *tags; const gchar *const *curr = NULL; gboolean should_copy = TRUE; - const gchar *const valid_tags[] = { GST_META_TAG_VIDEO_STR, - GST_META_TAG_VIDEO_COLORSPACE_STR, + const gchar *const valid_tags[] = { + GST_META_TAG_VIDEO_STR, GST_META_TAG_VIDEO_ORIENTATION_STR, - GST_META_TAG_VIDEO_SIZE_STR + GST_META_TAG_VIDEO_SIZE_STR, }; tags = gst_meta_api_type_get_tags (info->api); @@ -529,6 +660,12 @@ gst_video_scale_transform_meta (GstBaseTransform * trans, GstBuffer * outbuf, return TRUE; } + if (gst_meta_api_type_has_tag (info->api, _colorspace_quark)) { + /* don't copy colorspace specific metadata, FIXME, we need a MetaTransform + * for the colorspace metadata. */ + return FALSE; + } + /* We are only changing size, we can preserve other metas tagged as orientation and colorspace */ for (curr = tags; *curr; ++curr) { @@ -561,11 +698,18 @@ gst_video_scale_transform_meta (GstBaseTransform * trans, GstBuffer * outbuf, } static gboolean -gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in, +gst_video_convert_scale_set_info (GstVideoFilter * filter, GstCaps * in, GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info) { - GstVideoScale *videoscale = GST_VIDEO_SCALE (filter); + GstVideoConvertScale *self = GST_VIDEO_CONVERT_SCALE (filter); + GstVideoConvertScalePrivate *priv = PRIV (self); gint from_dar_n, from_dar_d, to_dar_n, to_dar_d; + GstVideoInfo tmp_info; + + if (priv->convert) { + gst_video_converter_free (priv->convert); + priv->convert = NULL; + } if (!gst_util_fraction_multiply (in_info->width, in_info->height, in_info->par_n, in_info->par_d, &from_dar_n, @@ -579,9 +723,9 @@ gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in, to_dar_n = to_dar_d = -1; } - videoscale->borders_w = videoscale->borders_h = 0; + priv->borders_w = priv->borders_h = 0; if (to_dar_n != from_dar_n || to_dar_d != from_dar_d) { - if (videoscale->add_borders) { + if (priv->add_borders) { gint n, d, to_h, to_w; if (from_dar_n != -1 && from_dar_d != -1 @@ -589,33 +733,44 @@ gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in, out_info->par_d, out_info->par_n, &n, &d)) { to_h = gst_util_uint64_scale_int (out_info->width, d, n); if (to_h <= out_info->height) { - videoscale->borders_h = out_info->height - to_h; - videoscale->borders_w = 0; + priv->borders_h = out_info->height - to_h; + priv->borders_w = 0; } else { to_w = gst_util_uint64_scale_int (out_info->height, n, d); g_assert (to_w <= out_info->width); - videoscale->borders_h = 0; - videoscale->borders_w = out_info->width - to_w; + priv->borders_h = 0; + priv->borders_w = out_info->width - to_w; } } else { - GST_WARNING_OBJECT (videoscale, "Can't calculate borders"); + GST_WARNING_OBJECT (self, "Can't calculate borders"); } } else { - GST_WARNING_OBJECT (videoscale, "Can't keep DAR!"); + GST_WARNING_OBJECT (self, "Can't keep DAR!"); } } - if (in_info->width == out_info->width && in_info->height == out_info->height - && videoscale->borders_w == 0 && videoscale->borders_h == 0) { - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE); + /* if present, these must match */ + if (in_info->interlace_mode != out_info->interlace_mode) + goto format_mismatch; + + /* if the only thing different in the caps is the transfer function, and + * we're converting between equivalent transfer functions, do passthrough */ + tmp_info = *in_info; + tmp_info.colorimetry.transfer = out_info->colorimetry.transfer; + if (gst_video_info_is_equal (&tmp_info, out_info)) { + if (gst_video_transfer_function_is_equivalent (in_info-> + colorimetry.transfer, in_info->finfo->bits, + out_info->colorimetry.transfer, out_info->finfo->bits)) { + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE); + } } else { GstStructure *options; GST_CAT_DEBUG_OBJECT (CAT_PERFORMANCE, filter, "setup videoscaling"); gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), FALSE); - options = gst_structure_new_empty ("videoscale"); + options = gst_structure_new_empty ("videoconvertscale"); - switch (videoscale->method) { + switch (priv->method) { case GST_VIDEO_SCALE_NEAREST: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, @@ -686,48 +841,380 @@ gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in, break; } gst_structure_set (options, - GST_VIDEO_RESAMPLER_OPT_ENVELOPE, G_TYPE_DOUBLE, videoscale->envelope, - GST_VIDEO_RESAMPLER_OPT_SHARPNESS, G_TYPE_DOUBLE, videoscale->sharpness, - GST_VIDEO_RESAMPLER_OPT_SHARPEN, G_TYPE_DOUBLE, videoscale->sharpen, - GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, videoscale->borders_w / 2, - GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, videoscale->borders_h / 2, + GST_VIDEO_RESAMPLER_OPT_ENVELOPE, G_TYPE_DOUBLE, priv->envelope, + GST_VIDEO_RESAMPLER_OPT_SHARPNESS, G_TYPE_DOUBLE, priv->sharpness, + GST_VIDEO_RESAMPLER_OPT_SHARPEN, G_TYPE_DOUBLE, priv->sharpen, + GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, priv->borders_w / 2, + GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, priv->borders_h / 2, GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, - out_info->width - videoscale->borders_w, - GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, - out_info->height - videoscale->borders_h, + out_info->width - priv->borders_w, GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, + G_TYPE_INT, out_info->height - priv->borders_h, + GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, + priv->dither, GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION, G_TYPE_UINT, + priv->dither_quantization, + GST_VIDEO_CONVERTER_OPT_CHROMA_RESAMPLER_METHOD, + GST_TYPE_VIDEO_RESAMPLER_METHOD, priv->chroma_resampler, + GST_VIDEO_CONVERTER_OPT_ALPHA_MODE, GST_TYPE_VIDEO_ALPHA_MODE, + priv->alpha_mode, GST_VIDEO_CONVERTER_OPT_ALPHA_VALUE, G_TYPE_DOUBLE, + priv->alpha_value, GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, + GST_TYPE_VIDEO_CHROMA_MODE, priv->chroma_mode, GST_VIDEO_CONVERTER_OPT_MATRIX_MODE, GST_TYPE_VIDEO_MATRIX_MODE, - GST_VIDEO_MATRIX_MODE_NONE, GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, - GST_TYPE_VIDEO_DITHER_METHOD, GST_VIDEO_DITHER_NONE, - GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, GST_TYPE_VIDEO_CHROMA_MODE, - GST_VIDEO_CHROMA_MODE_NONE, - GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT, videoscale->n_threads, - NULL); + priv->matrix_mode, GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, + GST_TYPE_VIDEO_GAMMA_MODE, priv->gamma_mode, + GST_VIDEO_CONVERTER_OPT_PRIMARIES_MODE, GST_TYPE_VIDEO_PRIMARIES_MODE, + priv->primaries_mode, GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT, + priv->n_threads, NULL); - if (videoscale->gamma_decode) { - gst_structure_set (options, - GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, GST_TYPE_VIDEO_GAMMA_MODE, - GST_VIDEO_GAMMA_MODE_REMAP, NULL); - } - - if (videoscale->convert) - gst_video_converter_free (videoscale->convert); - videoscale->convert = gst_video_converter_new (in_info, out_info, options); + priv->convert = gst_video_converter_new (in_info, out_info, options); + if (priv->convert == NULL) + goto no_convert; } - GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %" + GST_DEBUG_OBJECT (filter, "converting format %s -> %s", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)), + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info))); + GST_DEBUG_OBJECT (self, "from=%dx%d (par=%d/%d dar=%d/%d), size %" G_GSIZE_FORMAT " -> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), " "size %" G_GSIZE_FORMAT, in_info->width, in_info->height, in_info->par_n, in_info->par_d, from_dar_n, from_dar_d, in_info->size, out_info->width, out_info->height, out_info->par_n, out_info->par_d, to_dar_n, to_dar_d, - videoscale->borders_w, videoscale->borders_h, out_info->size); + priv->borders_w, priv->borders_h, out_info->size); + + return TRUE; + + /* ERRORS */ +format_mismatch: + { + GST_ERROR_OBJECT (self, "input and output formats do not match"); + return FALSE; + } +no_convert: + { + GST_ERROR_OBJECT (self, "could not create converter"); + return FALSE; + } +} + +/* + * This is an incomplete matrix of in formats and a score for the preferred output + * format. + * + * out: RGB24 RGB16 ARGB AYUV YUV444 YUV422 YUV420 YUV411 YUV410 PAL GRAY + * in + * RGB24 0 2 1 2 2 3 4 5 6 7 8 + * RGB16 1 0 1 2 2 3 4 5 6 7 8 + * ARGB 2 3 0 1 4 5 6 7 8 9 10 + * AYUV 3 4 1 0 2 5 6 7 8 9 10 + * YUV444 2 4 3 1 0 5 6 7 8 9 10 + * YUV422 3 5 4 2 1 0 6 7 8 9 10 + * YUV420 4 6 5 3 2 1 0 7 8 9 10 + * YUV411 4 6 5 3 2 1 7 0 8 9 10 + * YUV410 6 8 7 5 4 3 2 1 0 9 10 + * PAL 1 3 2 6 4 6 7 8 9 0 10 + * GRAY 1 4 3 2 1 5 6 7 8 9 0 + * + * PAL or GRAY are never preferred, if we can we would convert to PAL instead + * of GRAY, though + * less subsampling is preferred and if any, preferably horizontal + * We would like to keep the alpha, even if we would need to to colorspace conversion + * or lose depth. + */ +#define SCORE_FORMAT_CHANGE 1 +#define SCORE_DEPTH_CHANGE 1 +#define SCORE_ALPHA_CHANGE 1 +#define SCORE_CHROMA_W_CHANGE 1 +#define SCORE_CHROMA_H_CHANGE 1 +#define SCORE_PALETTE_CHANGE 1 + +#define SCORE_COLORSPACE_LOSS 2 /* RGB <-> YUV */ +#define SCORE_DEPTH_LOSS 4 /* change bit depth */ +#define SCORE_ALPHA_LOSS 8 /* lose the alpha channel */ +#define SCORE_CHROMA_W_LOSS 16 /* vertical subsample */ +#define SCORE_CHROMA_H_LOSS 32 /* horizontal subsample */ +#define SCORE_PALETTE_LOSS 64 /* convert to palette format */ +#define SCORE_COLOR_LOSS 128 /* convert to GRAY */ + +#define COLORSPACE_MASK (GST_VIDEO_FORMAT_FLAG_YUV | \ + GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_GRAY) +#define ALPHA_MASK (GST_VIDEO_FORMAT_FLAG_ALPHA) +#define PALETTE_MASK (GST_VIDEO_FORMAT_FLAG_PALETTE) + +/* calculate how much loss a conversion would be */ +static void +score_value (GstBaseTransform * base, const GstVideoFormatInfo * in_info, + const GValue * val, gint * min_loss, const GstVideoFormatInfo ** out_info) +{ + const gchar *fname; + const GstVideoFormatInfo *t_info; + GstVideoFormatFlags in_flags, t_flags; + gint loss; + + fname = g_value_get_string (val); + t_info = gst_video_format_get_info (gst_video_format_from_string (fname)); + if (!t_info || t_info->format == GST_VIDEO_FORMAT_UNKNOWN) + return; + + /* accept input format immediately without loss */ + if (in_info == t_info) { + *min_loss = 0; + *out_info = t_info; + return; + } + + loss = SCORE_FORMAT_CHANGE; + + in_flags = GST_VIDEO_FORMAT_INFO_FLAGS (in_info); + in_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; + in_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; + in_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; + + t_flags = GST_VIDEO_FORMAT_INFO_FLAGS (t_info); + t_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; + t_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; + t_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; + + if ((t_flags & PALETTE_MASK) != (in_flags & PALETTE_MASK)) { + loss += SCORE_PALETTE_CHANGE; + if (t_flags & PALETTE_MASK) + loss += SCORE_PALETTE_LOSS; + } + + if ((t_flags & COLORSPACE_MASK) != (in_flags & COLORSPACE_MASK)) { + loss += SCORE_COLORSPACE_LOSS; + if (t_flags & GST_VIDEO_FORMAT_FLAG_GRAY) + loss += SCORE_COLOR_LOSS; + } + + if ((t_flags & ALPHA_MASK) != (in_flags & ALPHA_MASK)) { + loss += SCORE_ALPHA_CHANGE; + if (in_flags & ALPHA_MASK) + loss += SCORE_ALPHA_LOSS; + } + + if ((in_info->h_sub[1]) != (t_info->h_sub[1])) { + loss += SCORE_CHROMA_H_CHANGE; + if ((in_info->h_sub[1]) < (t_info->h_sub[1])) + loss += SCORE_CHROMA_H_LOSS; + } + if ((in_info->w_sub[1]) != (t_info->w_sub[1])) { + loss += SCORE_CHROMA_W_CHANGE; + if ((in_info->w_sub[1]) < (t_info->w_sub[1])) + loss += SCORE_CHROMA_W_LOSS; + } + + if ((in_info->bits) != (t_info->bits)) { + loss += SCORE_DEPTH_CHANGE; + if ((in_info->bits) > (t_info->bits)) + loss += SCORE_DEPTH_LOSS; + } + + GST_DEBUG_OBJECT (base, "score %s -> %s = %d", + GST_VIDEO_FORMAT_INFO_NAME (in_info), + GST_VIDEO_FORMAT_INFO_NAME (t_info), loss); + + if (loss < *min_loss) { + GST_DEBUG_OBJECT (base, "found new best %d", loss); + *out_info = t_info; + *min_loss = loss; + } +} + +static void +gst_video_convert_scale_fixate_format (GstBaseTransform * base, GstCaps * caps, + GstCaps * result) +{ + GstStructure *ins, *outs; + const gchar *in_format; + const GstVideoFormatInfo *in_info, *out_info = NULL; + gint min_loss = G_MAXINT; + guint i, capslen; + + ins = gst_caps_get_structure (caps, 0); + in_format = gst_structure_get_string (ins, "format"); + if (!in_format) + return; + + GST_DEBUG_OBJECT (base, "source format %s", in_format); + + in_info = + gst_video_format_get_info (gst_video_format_from_string (in_format)); + if (!in_info) + return; + + outs = gst_caps_get_structure (result, 0); + + capslen = gst_caps_get_size (result); + GST_DEBUG_OBJECT (base, "iterate %d structures", capslen); + for (i = 0; i < capslen; i++) { + GstStructure *tests; + const GValue *format; + + tests = gst_caps_get_structure (result, i); + format = gst_structure_get_value (tests, "format"); + gst_structure_remove_fields (tests, "height", "width", "pixel-aspect-ratio", + "display-aspect-ratio", NULL); + /* should not happen */ + if (format == NULL) + continue; + + if (GST_VALUE_HOLDS_LIST (format)) { + gint j, len; + + len = gst_value_list_get_size (format); + GST_DEBUG_OBJECT (base, "have %d formats", len); + for (j = 0; j < len; j++) { + const GValue *val; + + val = gst_value_list_get_value (format, j); + if (G_VALUE_HOLDS_STRING (val)) { + score_value (base, in_info, val, &min_loss, &out_info); + if (min_loss == 0) + break; + } + } + } else if (G_VALUE_HOLDS_STRING (format)) { + score_value (base, in_info, format, &min_loss, &out_info); + } + } + if (out_info) + gst_structure_set (outs, "format", G_TYPE_STRING, + GST_VIDEO_FORMAT_INFO_NAME (out_info), NULL); +} + +static gboolean +subsampling_unchanged (GstVideoInfo * in_info, GstVideoInfo * out_info) +{ + gint i; + const GstVideoFormatInfo *in_format, *out_format; + + if (GST_VIDEO_INFO_N_COMPONENTS (in_info) != + GST_VIDEO_INFO_N_COMPONENTS (out_info)) + return FALSE; + + in_format = in_info->finfo; + out_format = out_info->finfo; + + for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (in_info); i++) { + if (GST_VIDEO_FORMAT_INFO_W_SUB (in_format, + i) != GST_VIDEO_FORMAT_INFO_W_SUB (out_format, i)) + return FALSE; + if (GST_VIDEO_FORMAT_INFO_H_SUB (in_format, + i) != GST_VIDEO_FORMAT_INFO_H_SUB (out_format, i)) + return FALSE; + } return TRUE; } +static void +transfer_colorimetry_from_input (GstBaseTransform * trans, GstCaps * in_caps, + GstCaps * out_caps) +{ + GstStructure *out_caps_s = gst_caps_get_structure (out_caps, 0); + GstStructure *in_caps_s = gst_caps_get_structure (in_caps, 0); + gboolean have_colorimetry = + gst_structure_has_field (out_caps_s, "colorimetry"); + gboolean have_chroma_site = + gst_structure_has_field (out_caps_s, "chroma-site"); + + /* If the output already has colorimetry and chroma-site, stop, + * otherwise try and transfer what we can from the input caps */ + if (have_colorimetry && have_chroma_site) + return; + + { + GstVideoInfo in_info, out_info; + const GValue *in_colorimetry = + gst_structure_get_value (in_caps_s, "colorimetry"); + + if (!gst_video_info_from_caps (&in_info, in_caps)) { + GST_WARNING_OBJECT (trans, + "Failed to convert sink pad caps to video info"); + return; + } + if (!gst_video_info_from_caps (&out_info, out_caps)) { + GST_WARNING_OBJECT (trans, + "Failed to convert src pad caps to video info"); + return; + } + + if (!have_colorimetry && in_colorimetry != NULL) { + if ((GST_VIDEO_INFO_IS_YUV (&out_info) + && GST_VIDEO_INFO_IS_YUV (&in_info)) + || (GST_VIDEO_INFO_IS_RGB (&out_info) + && GST_VIDEO_INFO_IS_RGB (&in_info)) + || (GST_VIDEO_INFO_IS_GRAY (&out_info) + && GST_VIDEO_INFO_IS_GRAY (&in_info))) { + /* Can transfer the colorimetry intact from the input if it has it */ + gst_structure_set_value (out_caps_s, "colorimetry", in_colorimetry); + } else { + gchar *colorimetry_str; + + /* Changing between YUV/RGB - forward primaries and transfer function, but use + * default range and matrix. + * the primaries is used for conversion between RGB and XYZ (CIE 1931 coordinate). + * the transfer function could be another reference (e.g., HDR) + */ + out_info.colorimetry.primaries = in_info.colorimetry.primaries; + out_info.colorimetry.transfer = in_info.colorimetry.transfer; + + colorimetry_str = + gst_video_colorimetry_to_string (&out_info.colorimetry); + gst_caps_set_simple (out_caps, "colorimetry", G_TYPE_STRING, + colorimetry_str, NULL); + g_free (colorimetry_str); + } + } + + /* Only YUV output needs chroma-site. If the input was also YUV and had the same chroma + * subsampling, transfer the siting. If the sub-sampling is changing, then the planes get + * scaled anyway so there's no real reason to prefer the input siting. */ + if (!have_chroma_site && GST_VIDEO_INFO_IS_YUV (&out_info)) { + if (GST_VIDEO_INFO_IS_YUV (&in_info)) { + const GValue *in_chroma_site = + gst_structure_get_value (in_caps_s, "chroma-site"); + if (in_chroma_site != NULL + && subsampling_unchanged (&in_info, &out_info)) + gst_structure_set_value (out_caps_s, "chroma-site", in_chroma_site); + } + } + } +} + + static GstCaps * -gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction, - GstCaps * caps, GstCaps * othercaps) +gst_video_convert_scale_get_fixed_format (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + GstCaps *result; + + result = gst_caps_intersect (othercaps, caps); + if (gst_caps_is_empty (result)) { + gst_caps_unref (result); + result = gst_caps_copy (othercaps); + } + + gst_video_convert_scale_fixate_format (trans, caps, result); + + /* fixate remaining fields */ + result = gst_caps_fixate (result); + + if (direction == GST_PAD_SINK) { + if (gst_caps_is_subset (caps, result)) { + gst_caps_replace (&result, caps); + } else { + /* Try and preserve input colorimetry / chroma information */ + transfer_colorimetry_from_input (trans, caps, result); + } + } + + return result; +} + +static GstCaps * +gst_video_convert_scale_fixate_size (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) { GstStructure *ins, *outs; const GValue *from_par, *to_par; @@ -736,10 +1223,6 @@ gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction, othercaps = gst_caps_truncate (othercaps); othercaps = gst_caps_make_writable (othercaps); - - GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT - " based on caps %" GST_PTR_FORMAT, othercaps, caps); - ins = gst_caps_get_structure (caps, 0); outs = gst_caps_get_structure (othercaps, 0); @@ -1169,34 +1652,78 @@ done: return othercaps; } +static GstCaps * +gst_video_convert_scale_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + GstCaps *format; + + GST_DEBUG_OBJECT (base, + "trying to fixate othercaps %" GST_PTR_FORMAT " based on caps %" + GST_PTR_FORMAT, othercaps, caps); + + format = gst_video_convert_scale_get_fixed_format (base, direction, caps, + othercaps); + + if (gst_caps_is_empty (format)) { + GST_ERROR_OBJECT (base, "Could not convert formats"); + return format; + } + + othercaps = + gst_video_convert_scale_fixate_size (base, direction, caps, othercaps); + if (gst_caps_get_size (othercaps) == 1) { + gint i; + const gchar *format_fields[] = { "format", "colorimetry", "chroma-site" }; + GstStructure *format_struct = gst_caps_get_structure (format, 0); + GstStructure *fixated_struct; + + othercaps = gst_caps_make_writable (othercaps); + fixated_struct = gst_caps_get_structure (othercaps, 0); + + for (i = 0; i < G_N_ELEMENTS (format_fields); i++) { + if (gst_structure_has_field (format_struct, format_fields[i])) { + gst_structure_set (fixated_struct, format_fields[i], G_TYPE_STRING, + gst_structure_get_string (format_struct, format_fields[i]), NULL); + } else { + gst_structure_remove_field (fixated_struct, format_fields[i]); + } + } + } + gst_caps_unref (format); + + GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); + + return othercaps; +} + #define GET_LINE(frame, line) \ (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, 0))) + \ GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) * (line)) static GstFlowReturn -gst_video_scale_transform_frame (GstVideoFilter * filter, +gst_video_convert_scale_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame, GstVideoFrame * out_frame) { - GstVideoScale *videoscale = GST_VIDEO_SCALE_CAST (filter); + GstVideoConvertScalePrivate *priv = PRIV (filter); GstFlowReturn ret = GST_FLOW_OK; GST_CAT_DEBUG_OBJECT (CAT_PERFORMANCE, filter, "doing video scaling"); - gst_video_converter_frame (videoscale->convert, in_frame, out_frame); + gst_video_converter_frame (priv->convert, in_frame, out_frame); return ret; } static gboolean -gst_video_scale_src_event (GstBaseTransform * trans, GstEvent * event) +gst_video_convert_scale_src_event (GstBaseTransform * trans, GstEvent * event) { - GstVideoScale *videoscale = GST_VIDEO_SCALE_CAST (trans); + GstVideoConvertScale *self = GST_VIDEO_CONVERT_SCALE_CAST (trans); GstVideoFilter *filter = GST_VIDEO_FILTER_CAST (trans); gboolean ret; gdouble x, y; - GST_DEBUG_OBJECT (videoscale, "handling %s event", - GST_EVENT_TYPE_NAME (event)); + GST_DEBUG_OBJECT (self, "handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NAVIGATION: @@ -1219,26 +1746,3 @@ gst_video_scale_src_event (GstBaseTransform * trans, GstEvent * event) return ret; } - -static gboolean -plugin_init (GstPlugin * plugin) -{ - features_format_interlaced = - gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL); - features_format_interlaced_sysmem = - gst_caps_features_copy (features_format_interlaced); - gst_caps_features_add (features_format_interlaced_sysmem, - GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); - - GST_DEBUG_CATEGORY_INIT (video_scale_debug, "videoscale", 0, - "videoscale element"); - GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE"); - - return GST_ELEMENT_REGISTER (videoscale, plugin); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - videoscale, - "Resizes video", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, - GST_PACKAGE_ORIGIN) diff --git a/subprojects/gst-plugins-base/gst/videoscale/gstvideoscale.h b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h similarity index 74% rename from subprojects/gst-plugins-base/gst/videoscale/gstvideoscale.h rename to subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h index f518d5e797..9d25e039b6 100644 --- a/subprojects/gst-plugins-base/gst/videoscale/gstvideoscale.h +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscale.h @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) 2020 Thibault Saunier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,8 +18,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GST_VIDEO_SCALE_H__ -#define __GST_VIDEO_SCALE_H__ +#ifndef __GST_VIDEO_CONVERT_SCALE_H__ +#define __GST_VIDEO_CONVERT_SCALE_H__ #include #include @@ -26,11 +27,16 @@ G_BEGIN_DECLS -#define GST_TYPE_VIDEO_SCALE (gst_video_scale_get_type()) -#define GST_VIDEO_SCALE_CAST(obj) ((GstVideoScale *)(obj)) -G_DECLARE_FINAL_TYPE (GstVideoScale, gst_video_scale, GST, VIDEO_SCALE, +#define GST_TYPE_VIDEO_CONVERT_SCALE (gst_video_convert_scale_get_type()) +#define GST_VIDEO_CONVERT_SCALE_CAST(obj) ((GstVideoConvertScale *)(obj)) + +G_DECLARE_DERIVABLE_TYPE (GstVideoConvertScale, gst_video_convert_scale, GST, VIDEO_CONVERT_SCALE, GstVideoFilter) +struct _GstVideoConvertScaleClass +{ + GstVideoFilterClass parent; +}; /** * GstVideoScaleMethod: @@ -61,33 +67,8 @@ typedef enum { GST_VIDEO_SCALE_MITCHELL } GstVideoScaleMethod; -/** - * GstVideoScale: - * - * Opaque data structure - */ -struct _GstVideoScale { - GstVideoFilter element; - - /* properties */ - GstVideoScaleMethod method; - gboolean add_borders; - double sharpness; - double sharpen; - gboolean dither; - int submethod; - double envelope; - gboolean gamma_decode; - gint n_threads; - - GstVideoConverter *convert; - - gint borders_h; - gint borders_w; -}; - -GST_ELEMENT_REGISTER_DECLARE (videoscale); +GST_ELEMENT_REGISTER_DECLARE (videoconvertscale); G_END_DECLS -#endif /* __GST_VIDEO_SCALE_H__ */ +#endif /* __GST_VIDEO_CONVERT_SCALE_H__ */ diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscaleplugin.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscaleplugin.c new file mode 100644 index 0000000000..222b6bbd23 --- /dev/null +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoconvertscaleplugin.c @@ -0,0 +1,51 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/** + * plugin-videoconvertscale: + * + * Since: 1.22 + */ + +#include "gstvideoscale.h" +#include "gstvideoconvert.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!GST_ELEMENT_REGISTER (videoscale, plugin)) + return FALSE; + + if (!GST_ELEMENT_REGISTER (videoconvert, plugin)) + return FALSE; + + if (!GST_ELEMENT_REGISTER (videoconvertscale, plugin)) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + videoconvertscale, + "Convert video colorspaces and resizes video frames", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c new file mode 100644 index 0000000000..b246bf97b1 --- /dev/null +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.c @@ -0,0 +1,125 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) 2005-2012 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-videoscale + * @title: videoscale + * @see_also: videorate, videoconvert + * + * This element resizes video frames. By default the element will try to + * negotiate to the same size on the source and sinkpad so that no scaling + * is needed. It is therefore safe to insert this element in a pipeline to + * get more robust behaviour without any cost if no scaling is needed. + * + * This element supports a wide range of color spaces including various YUV and + * RGB formats and is therefore generally able to operate anywhere in a + * pipeline. + * + * ## Example pipelines + * |[ + * gst-launch-1.0 -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoconvert ! videoscale ! autovideosink + * ]| + * Decode an Ogg/Theora and display the video. If the video sink chosen + * cannot perform scaling, the video scaling will be performed by videoscale + * when you resize the video window. + * To create the test Ogg/Theora file refer to the documentation of theoraenc. + * |[ + * gst-launch-1.0 -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoconvert ! videoscale ! video/x-raw,width=100 ! autovideosink + * ]| + * Decode an Ogg/Theora and display the video with a width of 100. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define DEFAULT_PROP_GAMMA_DECODE FALSE + +#include "gstvideoscale.h" + +G_DEFINE_TYPE (GstVideoScale, gst_video_scale, GST_TYPE_VIDEO_CONVERT_SCALE); +GST_ELEMENT_REGISTER_DEFINE (videoscale, "videoscale", + GST_RANK_MARGINAL, gst_video_scale_get_type ()); + +enum +{ + PROP_0, + PROP_GAMMA_DECODE +}; + +static void +gst_video_scale_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case PROP_GAMMA_DECODE: + { + gint mode; + + g_object_get (object, "gamma-mode", &mode, NULL); + g_value_set_boolean (value, mode == GST_VIDEO_GAMMA_MODE_REMAP); + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_scale_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case PROP_GAMMA_DECODE: + { + if (g_value_get_boolean (value)) + g_object_set (object, "gamma-mode", GST_VIDEO_GAMMA_MODE_REMAP, NULL); + else + g_object_set (object, "gamma-mode", GST_VIDEO_GAMMA_MODE_NONE, NULL); + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_scale_class_init (GstVideoScaleClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->set_property = gst_video_scale_set_property; + gobject_class->get_property = gst_video_scale_get_property; + + g_object_class_install_property (gobject_class, PROP_GAMMA_DECODE, + g_param_spec_boolean ("gamma-decode", "Gamma Decode", + "Decode gamma before scaling", DEFAULT_PROP_GAMMA_DECODE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_video_scale_init (GstVideoScale * self) +{ + +} diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.h b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.h new file mode 100644 index 0000000000..c924b0eb5b --- /dev/null +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/gstvideoscale.h @@ -0,0 +1,36 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include "gstvideoconvertscale.h" + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE (GstVideoScale, gst_video_scale, GST, VIDEO_SCALE, + GstVideoConvertScale); + +struct _GstVideoScale +{ + GstVideoConvertScale parent; +}; + +GST_ELEMENT_REGISTER_DECLARE (videoscale); + +G_END_DECLS diff --git a/subprojects/gst-plugins-base/gst/videoconvertscale/meson.build b/subprojects/gst-plugins-base/gst/videoconvertscale/meson.build new file mode 100644 index 0000000000..6c73bf6804 --- /dev/null +++ b/subprojects/gst-plugins-base/gst/videoconvertscale/meson.build @@ -0,0 +1,18 @@ +videoconvertscale_sources = [ + 'gstvideoconvert.c', + 'gstvideoconvertscale.c', + 'gstvideoconvertscaleplugin.c', + 'gstvideoscale.c', +] + +gstvideoconvertscale = library('gstvideoconvertscale', + videoconvertscale_sources, + c_args : gst_plugins_base_args, + include_directories: [configinc, libsinc], + dependencies : [video_dep, gst_dep, gst_base_dep], + install : true, + install_dir : plugins_install_dir, +) + +pkgconfig.generate(gstvideoconvertscale, install_dir : plugins_pkgconfig_install_dir) +plugins += [gstvideoconvertscale] diff --git a/subprojects/gst-plugins-base/gst/videoscale/README b/subprojects/gst-plugins-base/gst/videoscale/README deleted file mode 100644 index 50f1fe2792..0000000000 --- a/subprojects/gst-plugins-base/gst/videoscale/README +++ /dev/null @@ -1,5 +0,0 @@ -- test different strides using -gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoscale ! video/x-raw,width=328,height=240 ! xvimagesink -gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoscale ! video/x-raw,width=324,height=240 ! xvimagesink -gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoscale ! video/x-raw,width=322,height=240 ! xvimagesink -gst-launch -v videotestsrc ! video/x-raw,width=320,height=240,format=UYVY ! videoscale ! video/x-raw,width=321,height=240 ! xvimagesink diff --git a/subprojects/gst-plugins-base/gst/videoscale/meson.build b/subprojects/gst-plugins-base/gst/videoscale/meson.build deleted file mode 100644 index 991fa19797..0000000000 --- a/subprojects/gst-plugins-base/gst/videoscale/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -videoscale_sources = [ - 'gstvideoscale.c', -] - -gstvideoscale = library('gstvideoscale', - videoscale_sources, - c_args : gst_plugins_base_args, - include_directories: [configinc, libsinc], - dependencies : [video_dep, gst_dep, gst_base_dep], - install : true, - install_dir : plugins_install_dir, -) -pkgconfig.generate(gstvideoscale, install_dir : plugins_pkgconfig_install_dir) -plugins += [gstvideoscale] diff --git a/subprojects/gst-plugins-base/meson_options.txt b/subprojects/gst-plugins-base/meson_options.txt index 3c7641cd77..50ec6aae1f 100644 --- a/subprojects/gst-plugins-base/meson_options.txt +++ b/subprojects/gst-plugins-base/meson_options.txt @@ -46,9 +46,8 @@ option('rawparse', type : 'feature', value : 'auto') option('subparse', type : 'feature', value : 'auto') option('tcp', type : 'feature', value : 'auto') option('typefind', type : 'feature', value : 'auto') -option('videoconvert', type : 'feature', value : 'auto') +option('videoconvertscale', type : 'feature', value : 'auto') option('videorate', type : 'feature', value : 'auto') -option('videoscale', type : 'feature', value : 'auto') option('videotestsrc', type : 'feature', value : 'auto') option('volume', type : 'feature', value : 'auto')