summaryrefslogtreecommitdiff
path: root/sys/v4l2
diff options
context:
space:
mode:
authorPhilippe Normand <philn@igalia.com>2019-03-04 11:05:29 +0000
committerPhilippe Normand <philn@igalia.com>2019-06-05 10:23:40 +0100
commit6ce195e9d1139d109b4301812221dc74f986909b (patch)
treede491db3c2bd370805ec332e5ce9ce7806958ac0 /sys/v4l2
parent7bd1909f4fc4763a2e55ccbc0b1fdbc5795f6452 (diff)
v4l2: Profile and level probing support for encoders and decoders
There used to be some profile/level support in encoders. This code was moved to GstV4l2Codecs and is now also used for decoders. The caps templates for the H.264, H.265, MPEG4, VP8 and VP9 encoders and decoders should now reflect the profiles and levels advertised by the kernel.
Diffstat (limited to 'sys/v4l2')
-rw-r--r--sys/v4l2/Makefile.am12
-rw-r--r--sys/v4l2/gstv4l2.c12
-rw-r--r--sys/v4l2/gstv4l2codec.c125
-rw-r--r--sys/v4l2/gstv4l2codec.h48
-rw-r--r--sys/v4l2/gstv4l2fwhtenc.c2
-rw-r--r--sys/v4l2/gstv4l2h263enc.c2
-rw-r--r--sys/v4l2/gstv4l2h264codec.c226
-rw-r--r--sys/v4l2/gstv4l2h264codec.h34
-rw-r--r--sys/v4l2/gstv4l2h264enc.c192
-rw-r--r--sys/v4l2/gstv4l2h264enc.h2
-rw-r--r--sys/v4l2/gstv4l2h265codec.c158
-rw-r--r--sys/v4l2/gstv4l2h265codec.h34
-rw-r--r--sys/v4l2/gstv4l2h265enc.c123
-rw-r--r--sys/v4l2/gstv4l2h265enc.h2
-rw-r--r--sys/v4l2/gstv4l2jpegenc.c2
-rw-r--r--sys/v4l2/gstv4l2mpeg4codec.c141
-rw-r--r--sys/v4l2/gstv4l2mpeg4codec.h34
-rw-r--r--sys/v4l2/gstv4l2mpeg4enc.c111
-rw-r--r--sys/v4l2/gstv4l2mpeg4enc.h2
-rw-r--r--sys/v4l2/gstv4l2videodec.c29
-rw-r--r--sys/v4l2/gstv4l2videodec.h2
-rw-r--r--sys/v4l2/gstv4l2videoenc.c61
-rw-r--r--sys/v4l2/gstv4l2videoenc.h13
-rw-r--r--sys/v4l2/gstv4l2vp8codec.c83
-rw-r--r--sys/v4l2/gstv4l2vp8codec.h34
-rw-r--r--sys/v4l2/gstv4l2vp8enc.c49
-rw-r--r--sys/v4l2/gstv4l2vp8enc.h2
-rw-r--r--sys/v4l2/gstv4l2vp9codec.c84
-rw-r--r--sys/v4l2/gstv4l2vp9codec.h34
-rw-r--r--sys/v4l2/gstv4l2vp9enc.c49
-rw-r--r--sys/v4l2/gstv4l2vp9enc.h2
-rw-r--r--sys/v4l2/meson.build6
32 files changed, 1166 insertions, 544 deletions
diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am
index e4099bc4a..1c311018b 100644
--- a/sys/v4l2/Makefile.am
+++ b/sys/v4l2/Makefile.am
@@ -5,6 +5,7 @@ include $(top_srcdir)/common/gst-glib-gen.mak
libgstvideo4linux2_la_SOURCES = gstv4l2.c \
gstv4l2allocator.c \
gstv4l2colorbalance.c \
+ gstv4l2codec.c \
gstv4l2deviceprovider.c \
gstv4l2object.c \
gstv4l2bufferpool.c \
@@ -18,11 +19,16 @@ libgstvideo4linux2_la_SOURCES = gstv4l2.c \
gstv4l2fwhtenc.c \
gstv4l2h263enc.c \
gstv4l2h264enc.c \
+ gstv4l2h264codec.c \
+ gstv4l2h265codec.c \
gstv4l2h265enc.c \
gstv4l2jpegenc.c \
gstv4l2mpeg4enc.c \
+ gstv4l2mpeg4codec.c \
gstv4l2vidorient.c \
+ gstv4l2vp8codec.c \
gstv4l2vp8enc.c \
+ gstv4l2vp9codec.c \
gstv4l2vp9enc.c \
v4l2_calls.c \
v4l2-utils.c \
@@ -64,14 +70,20 @@ noinst_HEADERS = \
gstv4l2transform.h \
gstv4l2videodec.h \
gstv4l2videoenc.h \
+ gstv4l2codec.h \
gstv4l2fwhtenc.h \
+ gstv4l2h264codec.h \
gstv4l2h263enc.h \
gstv4l2h264enc.h \
+ gstv4l2h265codec.h \
gstv4l2h265enc.h \
gstv4l2jpegenc.h \
gstv4l2mpeg4enc.h \
+ gstv4l2mpeg4codec.h \
gstv4l2vidorient.h \
+ gstv4l2vp8codec.h \
gstv4l2vp8enc.h \
+ gstv4l2vp9codec.h \
gstv4l2vp9enc.h \
v4l2-utils.h \
tuner.h \
diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c
index c2c1d21b2..e1888804d 100644
--- a/sys/v4l2/gstv4l2.c
+++ b/sys/v4l2/gstv4l2.c
@@ -192,7 +192,7 @@ gst_v4l2_probe_and_register (GstPlugin * plugin)
if (gst_v4l2_is_video_dec (sink_caps, src_caps)) {
gst_v4l2_video_dec_register (plugin, basename, it->device_path,
- sink_caps, src_caps);
+ video_fd, sink_caps, src_caps);
} else if (gst_v4l2_is_video_enc (sink_caps, src_caps, NULL)) {
if (gst_v4l2_is_fwht_enc (sink_caps, src_caps))
gst_v4l2_fwht_enc_register (plugin, basename, it->device_path,
@@ -200,15 +200,15 @@ gst_v4l2_probe_and_register (GstPlugin * plugin)
if (gst_v4l2_is_h264_enc (sink_caps, src_caps))
gst_v4l2_h264_enc_register (plugin, basename, it->device_path,
- sink_caps, src_caps);
+ video_fd, sink_caps, src_caps);
if (gst_v4l2_is_h265_enc (sink_caps, src_caps))
gst_v4l2_h265_enc_register (plugin, basename, it->device_path,
- sink_caps, src_caps);
+ video_fd, sink_caps, src_caps);
if (gst_v4l2_is_mpeg4_enc (sink_caps, src_caps))
gst_v4l2_mpeg4_enc_register (plugin, basename, it->device_path,
- sink_caps, src_caps);
+ video_fd, sink_caps, src_caps);
if (gst_v4l2_is_h263_enc (sink_caps, src_caps))
gst_v4l2_h263_enc_register (plugin, basename, it->device_path,
@@ -220,11 +220,11 @@ gst_v4l2_probe_and_register (GstPlugin * plugin)
if (gst_v4l2_is_vp8_enc (sink_caps, src_caps))
gst_v4l2_vp8_enc_register (plugin, basename, it->device_path,
- sink_caps, src_caps);
+ video_fd, sink_caps, src_caps);
if (gst_v4l2_is_vp9_enc (sink_caps, src_caps))
gst_v4l2_vp9_enc_register (plugin, basename, it->device_path,
- sink_caps, src_caps);
+ video_fd, sink_caps, src_caps);
} else if (gst_v4l2_is_transform (sink_caps, src_caps)) {
gst_v4l2_transform_register (plugin, basename, it->device_path,
sink_caps, src_caps);
diff --git a/sys/v4l2/gstv4l2codec.c b/sys/v4l2/gstv4l2codec.c
new file mode 100644
index 000000000..696ba3c05
--- /dev/null
+++ b/sys/v4l2/gstv4l2codec.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ * Author: Philippe Normand <philn@igalia.com>
+ *
+ * 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
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "gstv4l2codec.h"
+#include "ext/videodev2.h"
+
+#include <gst/gst.h>
+
+static GValue *
+probe_controls (gint video_fd, guint32 cid,
+ const gchar * (transform_control) (gint))
+{
+ GValue *controls = NULL;
+ struct v4l2_queryctrl query_ctrl;
+
+ memset (&query_ctrl, 0, sizeof (query_ctrl));
+ query_ctrl.id = cid;
+
+ if (ioctl (video_fd, VIDIOC_QUERYCTRL, &query_ctrl) == 0) {
+ if (query_ctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ return NULL;
+ }
+
+ if (query_ctrl.type == V4L2_CTRL_TYPE_MENU) {
+ struct v4l2_querymenu query_menu;
+
+ memset (&query_menu, 0, sizeof (query_menu));
+ query_menu.id = query_ctrl.id;
+
+ controls = g_new0 (GValue, 1);
+ g_value_init (controls, GST_TYPE_LIST);
+ for (query_menu.index = query_ctrl.minimum;
+ query_menu.index <= query_ctrl.maximum; query_menu.index++) {
+ if (ioctl (video_fd, VIDIOC_QUERYMENU, &query_menu) >= 0) {
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, transform_control (query_menu.index));
+ gst_value_list_append_and_take_value (controls, &value);
+ }
+ }
+ if (gst_value_list_get_size (controls) == 0) {
+ g_value_unset (controls);
+ controls = NULL;
+ }
+ }
+ }
+
+ return controls;
+}
+
+GValue *
+gst_v4l2_codec_probe_profiles (const GstV4l2Codec * codec, gint video_fd)
+{
+ return probe_controls (video_fd, codec->profile_cid,
+ codec->profile_to_string);
+}
+
+GValue *
+gst_v4l2_codec_probe_levels (const GstV4l2Codec * codec, gint video_fd)
+{
+ GValue *controls = NULL;
+ struct v4l2_queryctrl query_ctrl;
+
+ memset (&query_ctrl, 0, sizeof (query_ctrl));
+ query_ctrl.id = codec->level_cid;
+
+ if (ioctl (video_fd, VIDIOC_QUERYCTRL, &query_ctrl) == 0) {
+ if (query_ctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ return NULL;
+ }
+
+ if (query_ctrl.type == V4L2_CTRL_TYPE_MENU) {
+ struct v4l2_querymenu query_menu;
+
+ memset (&query_menu, 0, sizeof (query_menu));
+ query_menu.id = query_ctrl.id;
+ query_menu.index = query_ctrl.maximum;
+
+ if (ioctl (video_fd, VIDIOC_QUERYMENU, &query_menu) >= 0) {
+ controls = g_new0 (GValue, 1);
+ g_value_init (controls, GST_TYPE_LIST);
+
+ /* Assume that all levels below the highest one reported by the driver are supported. */
+ for (gint32 i = query_ctrl.minimum; i <= query_ctrl.maximum; i++) {
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, codec->level_to_string (i));
+ gst_value_list_append_and_take_value (controls, &value);
+ }
+ }
+ }
+ }
+
+ return controls;
+}
diff --git a/sys/v4l2/gstv4l2codec.h b/sys/v4l2/gstv4l2codec.h
new file mode 100644
index 000000000..47161dc9c
--- /dev/null
+++ b/sys/v4l2/gstv4l2codec.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GST_V4L2_CODEC_H__
+#define __GST_V4L2_CODEC_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstV4l2Codec GstV4l2Codec;
+
+struct _GstV4l2Codec {
+ guint32 profile_cid;
+ const gchar * (*profile_to_string) (gint v4l2_profile);
+ gint (*profile_from_string) (const gchar * profile);
+
+ guint32 level_cid;
+ const gchar * (*level_to_string) (gint v4l2_level);
+ gint (*level_from_string) (const gchar * level);
+
+};
+
+GValue * gst_v4l2_codec_probe_profiles(const GstV4l2Codec * codec, gint video_fd);
+GValue * gst_v4l2_codec_probe_levels(const GstV4l2Codec * codec, gint video_fd);
+
+G_END_DECLS
+
+#endif /* __GST_V4L2_CODEC_H__ */
diff --git a/sys/v4l2/gstv4l2fwhtenc.c b/sys/v4l2/gstv4l2fwhtenc.c
index 9be9eca2f..973993ec4 100644
--- a/sys/v4l2/gstv4l2fwhtenc.c
+++ b/sys/v4l2/gstv4l2fwhtenc.c
@@ -114,6 +114,6 @@ gst_v4l2_fwht_enc_register (GstPlugin * plugin, const gchar * basename,
const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
{
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_FWHT_ENC,
- "fwht", basename, device_path, sink_caps,
+ "fwht", basename, device_path, NULL, -1, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2h263enc.c b/sys/v4l2/gstv4l2h263enc.c
index e29fa648f..b930986ea 100644
--- a/sys/v4l2/gstv4l2h263enc.c
+++ b/sys/v4l2/gstv4l2h263enc.c
@@ -111,6 +111,6 @@ gst_v4l2_h263_enc_register (GstPlugin * plugin, const gchar * basename,
const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
{
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_H263_ENC,
- "h263", basename, device_path, sink_caps,
+ "h263", basename, device_path, NULL, -1, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2h264codec.c b/sys/v4l2/gstv4l2h264codec.c
new file mode 100644
index 000000000..020c64c60
--- /dev/null
+++ b/sys/v4l2/gstv4l2h264codec.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ *
+ * 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
+
+#include "gstv4l2h264codec.h"
+
+#include <gst/gst.h>
+#include "ext/v4l2-controls.h"
+
+
+static gint
+v4l2_profile_from_string (const gchar * profile)
+{
+ gint v4l2_profile = -1;
+
+ if (g_str_equal (profile, "baseline")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
+ } else if (g_str_equal (profile, "constrained-baseline")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE;
+ } else if (g_str_equal (profile, "main")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
+ } else if (g_str_equal (profile, "extended")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
+ } else if (g_str_equal (profile, "high")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
+ } else if (g_str_equal (profile, "high-10")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10;
+ } else if (g_str_equal (profile, "high-4:2:2")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422;
+ } else if (g_str_equal (profile, "high-4:4:4")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE;
+ } else if (g_str_equal (profile, "high-10-intra")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA;
+ } else if (g_str_equal (profile, "high-4:2:2-intra")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA;
+ } else if (g_str_equal (profile, "high-4:4:4-intra")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA;
+ } else if (g_str_equal (profile, "cavlc-4:4:4-intra")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA;
+ } else if (g_str_equal (profile, "scalable-baseline")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE;
+ } else if (g_str_equal (profile, "scalable-high")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH;
+ } else if (g_str_equal (profile, "scalable-high-intra")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA;
+ } else if (g_str_equal (profile, "stereo-high")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
+ } else if (g_str_equal (profile, "multiview-high")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
+ } else {
+ GST_WARNING ("Unsupported profile string '%s'", profile);
+ }
+
+ return v4l2_profile;
+}
+
+static const gchar *
+v4l2_profile_to_string (gint v4l2_profile)
+{
+ switch (v4l2_profile) {
+ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+ return "baseline";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+ return "constrained-baseline";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+ return "main";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
+ return "extended";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+ return "high";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
+ return "high-10";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
+ return "high-4:2:2";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
+ return "high-4:4:4";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
+ return "high-10-intra";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
+ return "high-4:2:2-intra";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
+ return "high-4:4:4-intra";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
+ return "cavlc-4:4:4-intra";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
+ return "scalable-baseline";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
+ return "scalable-high";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
+ return "scalable-high-intra";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
+ return "stereo-high";
+ case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
+ return "multiview-high";
+ default:
+ GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
+ break;
+ }
+
+ return NULL;
+}
+
+static gint
+v4l2_level_from_string (const gchar * level)
+{
+ gint v4l2_level = -1;
+
+ if (g_str_equal (level, "1"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
+ else if (g_str_equal (level, "1b"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1B;
+ else if (g_str_equal (level, "1.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
+ else if (g_str_equal (level, "1.2"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
+ else if (g_str_equal (level, "1.3"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
+ else if (g_str_equal (level, "2"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
+ else if (g_str_equal (level, "2.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
+ else if (g_str_equal (level, "2.2"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
+ else if (g_str_equal (level, "3"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
+ else if (g_str_equal (level, "3.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
+ else if (g_str_equal (level, "3.2"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
+ else if (g_str_equal (level, "4"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+ else if (g_str_equal (level, "4.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
+ else if (g_str_equal (level, "4.2"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
+ else if (g_str_equal (level, "5"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
+ else if (g_str_equal (level, "5.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
+ else
+ GST_WARNING ("Unsupported level '%s'", level);
+
+ return v4l2_level;
+}
+
+static const gchar *
+v4l2_level_to_string (gint v4l2_level)
+{
+ switch (v4l2_level) {
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+ return "1";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+ return "1b";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+ return "1.1";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+ return "1.2";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+ return "1.3";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+ return "2";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+ return "2.1";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+ return "2.2";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+ return "3.0";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+ return "3.1";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+ return "3.2";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+ return "4";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+ return "4.1";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
+ return "4.2";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
+ return "5";
+ case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
+ return "5.1";
+ default:
+ GST_WARNING ("Unsupported V4L2 level %i", v4l2_level);
+ break;
+ }
+
+ return NULL;
+}
+
+const GstV4l2Codec *
+gst_v4l2_h264_get_codec (void)
+{
+ static GstV4l2Codec *codec = NULL;
+ if (g_once_init_enter (&codec)) {
+ static GstV4l2Codec c;
+ c.profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
+ c.profile_to_string = v4l2_profile_to_string;
+ c.profile_from_string = v4l2_profile_from_string;
+ c.level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
+ c.level_to_string = v4l2_level_to_string;
+ c.level_from_string = v4l2_level_from_string;
+ g_once_init_leave (&codec, &c);
+ }
+ return codec;
+}
diff --git a/sys/v4l2/gstv4l2h264codec.h b/sys/v4l2/gstv4l2h264codec.h
new file mode 100644
index 000000000..001ac4005
--- /dev/null
+++ b/sys/v4l2/gstv4l2h264codec.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 SUMOMO Computer Association.
+ * Author: ayaka <ayaka@soulik.info>
+ * Factored out from gstv4l2h264enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GST_V4L2_H264_CODEC_H__
+#define __GST_V4L2_H264_CODEC_H__
+
+#include "gstv4l2codec.h"
+
+G_BEGIN_DECLS
+
+const GstV4l2Codec * gst_v4l2_h264_get_codec (void);
+
+G_END_DECLS
+
+#endif
diff --git a/sys/v4l2/gstv4l2h264enc.c b/sys/v4l2/gstv4l2h264enc.c
index ee160b3a0..535725ba4 100644
--- a/sys/v4l2/gstv4l2h264enc.c
+++ b/sys/v4l2/gstv4l2h264enc.c
@@ -31,6 +31,7 @@
#include "gstv4l2object.h"
#include "gstv4l2h264enc.h"
+#include "gstv4l2h264codec.h"
#include <string.h>
#include <gst/gst-i18n-plugin.h>
@@ -88,185 +89,6 @@ gst_v4l2_h264_enc_get_property (GObject * object,
/* TODO */
}
-static gint
-v4l2_profile_from_string (const gchar * profile)
-{
- gint v4l2_profile = -1;
-
- if (g_str_equal (profile, "baseline")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
- } else if (g_str_equal (profile, "constrained-baseline")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE;
- } else if (g_str_equal (profile, "main")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
- } else if (g_str_equal (profile, "extended")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
- } else if (g_str_equal (profile, "high")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
- } else if (g_str_equal (profile, "high-10")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10;
- } else if (g_str_equal (profile, "high-4:2:2")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422;
- } else if (g_str_equal (profile, "high-4:4:4")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE;
- } else if (g_str_equal (profile, "high-10-intra")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA;
- } else if (g_str_equal (profile, "high-4:2:2-intra")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA;
- } else if (g_str_equal (profile, "high-4:4:4-intra")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA;
- } else if (g_str_equal (profile, "cavlc-4:4:4-intra")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA;
- } else if (g_str_equal (profile, "scalable-baseline")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE;
- } else if (g_str_equal (profile, "scalable-high")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH;
- } else if (g_str_equal (profile, "scalable-high-intra")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA;
- } else if (g_str_equal (profile, "stereo-high")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
- } else if (g_str_equal (profile, "multiview-high")) {
- v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
- } else {
- GST_WARNING ("Unsupported profile string '%s'", profile);
- }
-
- return v4l2_profile;
-}
-
-static const gchar *
-v4l2_profile_to_string (gint v4l2_profile)
-{
- switch (v4l2_profile) {
- case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
- return "baseline";
- case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
- return "constrained-baseline";
- case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
- return "main";
- case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
- return "extended";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
- return "high";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
- return "high-10";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
- return "high-4:2:2";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
- return "high-4:4:4";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
- return "high-10-intra";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
- return "high-4:2:2-intra";
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
- return "high-4:4:4-intra";
- case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
- return "cavlc-4:4:4-intra";
- case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
- return "scalable-baseline";
- case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
- return "scalable-high";
- case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
- return "scalable-high-intra";
- case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
- return "stereo-high";
- case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
- return "multiview-high";
- default:
- GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
- break;
- }
-
- return NULL;
-}
-
-static gint
-v4l2_level_from_string (const gchar * level)
-{
- gint v4l2_level = -1;
-
- if (g_str_equal (level, "1"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
- else if (g_str_equal (level, "1b"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1B;
- else if (g_str_equal (level, "1.1"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
- else if (g_str_equal (level, "1.2"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
- else if (g_str_equal (level, "1.3"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
- else if (g_str_equal (level, "2"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
- else if (g_str_equal (level, "2.1"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
- else if (g_str_equal (level, "2.2"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
- else if (g_str_equal (level, "3"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
- else if (g_str_equal (level, "3.1"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
- else if (g_str_equal (level, "3.2"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
- else if (g_str_equal (level, "4"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
- else if (g_str_equal (level, "4.1"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
- else if (g_str_equal (level, "4.2"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
- else if (g_str_equal (level, "5"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
- else if (g_str_equal (level, "5.1"))
- v4l2_level = V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
- else
- GST_WARNING ("Unsupported level '%s'", level);
-
- return v4l2_level;
-}
-
-static const gchar *
-v4l2_level_to_string (gint v4l2_level)
-{
- switch (v4l2_level) {
- case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
- return "1";
- case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
- return "1b";
- case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
- return "1.1";
- case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
- return "1.2";
- case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
- return "1.3";
- case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
- return "2";
- case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
- return "2.1";
- case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
- return "2.2";
- case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
- return "3.0";
- case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
- return "3.1";
- case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
- return "3.2";
- case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
- return "4";
- case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
- return "4.1";
- case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
- return "4.2";
- case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
- return "5";
- case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
- return "5.1";
- default:
- GST_WARNING ("Unsupported V4L2 level %i", v4l2_level);
- break;
- }
-
- return NULL;
-}
-
static void
gst_v4l2_h264_enc_init (GstV4l2H264Enc * self)
{
@@ -299,12 +121,6 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
GST_DEBUG_FUNCPTR (gst_v4l2_h264_enc_get_property);
baseclass->codec_name = "H264";
- baseclass->profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
- baseclass->profile_to_string = v4l2_profile_to_string;
- baseclass->profile_from_string = v4l2_profile_from_string;
- baseclass->level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
- baseclass->level_to_string = v4l2_level_to_string;
- baseclass->level_from_string = v4l2_level_from_string;
}
/* Probing functions */
@@ -317,9 +133,11 @@ gst_v4l2_is_h264_enc (GstCaps * sink_caps, GstCaps * src_caps)
void
gst_v4l2_h264_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps,
+ GstCaps * src_caps)
{
+ const GstV4l2Codec *codec = gst_v4l2_h264_get_codec ();
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_H264_ENC,
- "h264", basename, device_path, sink_caps,
+ "h264", basename, device_path, codec, video_fd, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2h264enc.h b/sys/v4l2/gstv4l2h264enc.h
index 3bfa34346..269028049 100644
--- a/sys/v4l2/gstv4l2h264enc.h
+++ b/sys/v4l2/gstv4l2h264enc.h
@@ -54,7 +54,7 @@ GType gst_v4l2_h264_enc_get_type (void);
gboolean gst_v4l2_is_h264_enc (GstCaps * sink_caps, GstCaps * src_caps);
void gst_v4l2_h264_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps);
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps, GstCaps * src_caps);
G_END_DECLS
#endif /* __GST_V4L2_H264_ENC_H__ */
diff --git a/sys/v4l2/gstv4l2h265codec.c b/sys/v4l2/gstv4l2h265codec.c
new file mode 100644
index 000000000..7186da8cd
--- /dev/null
+++ b/sys/v4l2/gstv4l2h265codec.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 NVIDIA CORPORATION.
+ * Author: Amit Pandya <apandya@nvidia.com>
+ * Factored out from gstv4l2h264enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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
+
+#include "gstv4l2h265codec.h"
+
+#include <gst/gst.h>
+#include "ext/v4l2-controls.h"
+
+
+static gint
+v4l2_profile_from_string (const gchar * profile)
+{
+ gint v4l2_profile = -1;
+
+ if (g_str_equal (profile, "main")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN;
+ } else if (g_str_equal (profile, "mainstillpicture")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE;
+ } else if (g_str_equal (profile, "main10")) {
+ v4l2_profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10;
+ } else {
+ GST_WARNING ("Unsupported profile string '%s'", profile);
+ }
+
+ return v4l2_profile;
+}
+
+static const gchar *
+v4l2_profile_to_string (gint v4l2_profile)
+{
+ switch (v4l2_profile) {
+ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
+ return "main";
+ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
+ return "mainstillpicture";
+ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10:
+ return "main10";
+ default:
+ GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
+ break;
+ }
+ return NULL;
+}
+
+static gint
+v4l2_level_from_string (const gchar * level)
+{
+ gint v4l2_level = -1;
+
+ if (g_str_equal (level, "1"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_1;
+ else if (g_str_equal (level, "2"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_2;
+ else if (g_str_equal (level, "2.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1;
+ else if (g_str_equal (level, "3"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_3;
+ else if (g_str_equal (level, "3.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1;
+ else if (g_str_equal (level, "4"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4;
+ else if (g_str_equal (level, "4.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1;
+ else if (g_str_equal (level, "5"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5;
+ else if (g_str_equal (level, "5.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1;
+ else if (g_str_equal (level, "5.2"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2;
+ else if (g_str_equal (level, "6"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6;
+ else if (g_str_equal (level, "6.1"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1;
+ else if (g_str_equal (level, "6.2"))
+ v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2;
+ else
+ GST_WARNING ("Unsupported level '%s'", level);
+
+ return v4l2_level;
+}
+
+static const gchar *
+v4l2_level_to_string (gint v4l2_level)
+{
+ switch (v4l2_level) {
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
+ return "1";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
+ return "2";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
+ return "2.1";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
+ return "3";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
+ return "3.1";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
+ return "4";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
+ return "4.1";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
+ return "5";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
+ return "5.1";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2:
+ return "5.2";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_6:
+ return "6";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1:
+ return "6.1";
+ case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2:
+ return "6.2";
+ default:
+ GST_WARNING ("Unsupported V4L2 level %i", v4l2_level);
+ break;
+ }
+
+ return NULL;
+}
+
+const GstV4l2Codec *
+gst_v4l2_h265_get_codec (void)
+{
+ static GstV4l2Codec *codec = NULL;
+ if (g_once_init_enter (&codec)) {
+ static GstV4l2Codec c;
+ c.profile_cid = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE;
+ c.profile_to_string = v4l2_profile_to_string;
+ c.profile_from_string = v4l2_profile_from_string;
+ c.level_cid = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL;
+ c.level_to_string = v4l2_level_to_string;
+ c.level_from_string = v4l2_level_from_string;
+ g_once_init_leave (&codec, &c);
+ }
+ return codec;
+}
diff --git a/sys/v4l2/gstv4l2h265codec.h b/sys/v4l2/gstv4l2h265codec.h
new file mode 100644
index 000000000..78d91c51e
--- /dev/null
+++ b/sys/v4l2/gstv4l2h265codec.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 NVIDIA CORPORATION.
+ * Author: Amit Pandya <apandya@nvidia.com>
+ * Factored out from gstv4l2h264enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GST_V4L2_H265_CODEC_H__
+#define __GST_V4L2_H265_CODEC_H__
+
+#include "gstv4l2codec.h"
+
+G_BEGIN_DECLS
+
+const GstV4l2Codec * gst_v4l2_h265_get_codec (void);
+
+G_END_DECLS
+
+#endif
diff --git a/sys/v4l2/gstv4l2h265enc.c b/sys/v4l2/gstv4l2h265enc.c
index 763f0bf32..4e4797bf8 100644
--- a/sys/v4l2/gstv4l2h265enc.c
+++ b/sys/v4l2/gstv4l2h265enc.c
@@ -31,6 +31,7 @@
#include "gstv4l2object.h"
#include "gstv4l2h265enc.h"
+#include "gstv4l2h265codec.h"
#include <string.h>
#include <gst/gst-i18n-plugin.h>
@@ -66,116 +67,6 @@ gst_v4l2_h265_enc_get_property (GObject * object,
/* TODO */
}
-static gint
-v4l2_profile_from_string (const gchar * profile)
-{
- gint v4l2_profile = -1;
-
- if (g_str_equal (profile, "main")) {
- v4l2_profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN;
- } else if (g_str_equal (profile, "mainstillpicture")) {
- v4l2_profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE;
- } else if (g_str_equal (profile, "main10")) {
- v4l2_profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10;
- } else {
- GST_WARNING ("Unsupported profile string '%s'", profile);
- }
-
- return v4l2_profile;
-}
-
-static const gchar *
-v4l2_profile_to_string (gint v4l2_profile)
-{
- switch (v4l2_profile) {
- case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
- return "main";
- case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
- return "mainstillpicture";
- case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10:
- return "main10";
- default:
- GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
- break;
- }
- return NULL;
-}
-
-static gint
-v4l2_level_from_string (const gchar * level)
-{
- gint v4l2_level = -1;
-
- if (g_str_equal (level, "1"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_1;
- else if (g_str_equal (level, "2"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_2;
- else if (g_str_equal (level, "2.1"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1;
- else if (g_str_equal (level, "3"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_3;
- else if (g_str_equal (level, "3.1"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1;
- else if (g_str_equal (level, "4"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4;
- else if (g_str_equal (level, "4.1"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1;
- else if (g_str_equal (level, "5"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5;
- else if (g_str_equal (level, "5.1"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1;
- else if (g_str_equal (level, "5.2"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2;
- else if (g_str_equal (level, "6"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6;
- else if (g_str_equal (level, "6.1"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1;
- else if (g_str_equal (level, "6.2"))
- v4l2_level = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2;
- else
- GST_WARNING ("Unsupported level '%s'", level);
-
- return v4l2_level;
-}
-
-static const gchar *
-v4l2_level_to_string (gint v4l2_level)
-{
- switch (v4l2_level) {
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
- return "1";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
- return "2";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
- return "2.1";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
- return "3";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
- return "3.1";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
- return "4";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
- return "4.1";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
- return "5";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
- return "5.1";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2:
- return "5.2";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_6:
- return "6";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1:
- return "6.1";
- case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2:
- return "6.2";
- default:
- GST_WARNING ("Unsupported V4L2 level %i", v4l2_level);
- break;
- }
-
- return NULL;
-}
-
static void
gst_v4l2_h265_enc_init (GstV4l2H265Enc * self)
{
@@ -209,12 +100,6 @@ gst_v4l2_h265_enc_class_init (GstV4l2H265EncClass * klass)
GST_DEBUG_FUNCPTR (gst_v4l2_h265_enc_get_property);
baseclass->codec_name = "H265";
- baseclass->profile_cid = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE;
- baseclass->profile_to_string = v4l2_profile_to_string;
- baseclass->profile_from_string = v4l2_profile_from_string;
- baseclass->level_cid = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL;
- baseclass->level_to_string = v4l2_level_to_string;
- baseclass->level_from_string = v4l2_level_from_string;
}
/* Probing functions */
@@ -227,9 +112,11 @@ gst_v4l2_is_h265_enc (GstCaps * sink_caps, GstCaps * src_caps)
void
gst_v4l2_h265_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps,
+ GstCaps * src_caps)
{
+ const GstV4l2Codec *codec = gst_v4l2_h265_get_codec ();
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_H265_ENC,
- "h265", basename, device_path, sink_caps,
+ "h265", basename, device_path, codec, video_fd, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2h265enc.h b/sys/v4l2/gstv4l2h265enc.h
index 6ead49393..a8d7824b6 100644
--- a/sys/v4l2/gstv4l2h265enc.h
+++ b/sys/v4l2/gstv4l2h265enc.h
@@ -54,7 +54,7 @@ GType gst_v4l2_h265_enc_get_type (void);
gboolean gst_v4l2_is_h265_enc (GstCaps * sink_caps, GstCaps * src_caps);
void gst_v4l2_h265_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps);
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps, GstCaps * src_caps);
G_END_DECLS
#endif /* __GST_V4L2_H265_ENC_H__ */
diff --git a/sys/v4l2/gstv4l2jpegenc.c b/sys/v4l2/gstv4l2jpegenc.c
index 6ed3e7229..f99218a8a 100644
--- a/sys/v4l2/gstv4l2jpegenc.c
+++ b/sys/v4l2/gstv4l2jpegenc.c
@@ -114,6 +114,6 @@ gst_v4l2_jpeg_enc_register (GstPlugin * plugin, const gchar * basename,
const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
{
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_JPEG_ENC,
- "jpeg", basename, device_path, sink_caps,
+ "jpeg", basename, device_path, NULL, -1, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2mpeg4codec.c b/sys/v4l2/gstv4l2mpeg4codec.c
new file mode 100644
index 000000000..34ba3af20
--- /dev/null
+++ b/sys/v4l2/gstv4l2mpeg4codec.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ * Factored out from gstv4l2mpeg4enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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.
+ *
+ */
+
+#include "gstv4l2mpeg4codec.h"
+
+#include <gst/gst.h>
+#include "ext/v4l2-controls.h"
+
+static gint
+v4l2_profile_from_string (const gchar * profile)
+{
+ gint v4l2_profile = -1;
+
+ if (g_str_equal (profile, "simple"))
+ v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE;
+ else if (g_str_equal (profile, "advanced-simple"))
+ v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE;
+ else if (g_str_equal (profile, "core"))
+ v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE;
+ else if (g_str_equal (profile, "simple-scalable"))
+ v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE;
+ else if (g_str_equal (profile, "advanced-coding-efficiency"))
+ v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY;
+ else
+ GST_WARNING ("Unsupported profile string '%s'", profile);
+
+ return v4l2_profile;
+}
+
+static const gchar *
+v4l2_profile_to_string (gint v4l2_profile)
+{
+ switch (v4l2_profile) {
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
+ return "simple";
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
+ return "advanced-simple";
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE:
+ return "core";
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE:
+ return "simple-scalable";
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY:
+ return "advanced-coding-efficiency";
+ default:
+ GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
+ break;
+ }
+
+ return NULL;
+}
+
+static gint
+v4l2_level_from_string (const gchar * level)
+{
+ gint v4l2_level = -1;
+
+ if (g_str_equal (level, "0"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0;
+ else if (g_str_equal (level, "0b"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B;
+ else if (g_str_equal (level, "1"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_1;
+ else if (g_str_equal (level, "2"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_2;
+ else if (g_str_equal (level, "3"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_3;
+ else if (g_str_equal (level, "3b"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B;
+ else if (g_str_equal (level, "4"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_4;
+ else if (g_str_equal (level, "5"))
+ v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5;
+ else
+ GST_WARNING ("Unsupported level '%s'", level);
+
+ return v4l2_level;
+}
+
+static const gchar *
+v4l2_level_to_string (gint v4l2_level)
+{
+ switch (v4l2_level) {
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0:
+ return "0";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B:
+ return "0b";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1:
+ return "1";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2:
+ return "2";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3:
+ return "3";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B:
+ return "3b";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4:
+ return "4";
+ case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5:
+ return "5";
+ default:
+ GST_WARNING ("Unsupported V4L2 level %i", v4l2_level);
+ break;
+ }
+
+ return NULL;
+}
+
+const GstV4l2Codec *
+gst_v4l2_mpeg4_get_codec (void)
+{
+ static GstV4l2Codec *codec = NULL;
+ if (g_once_init_enter (&codec)) {
+ static GstV4l2Codec c;
+ c.profile_cid = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
+ c.profile_to_string = v4l2_profile_to_string;
+ c.profile_from_string = v4l2_profile_from_string;
+ c.level_cid = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL;
+ c.level_to_string = v4l2_level_to_string;
+ c.level_from_string = v4l2_level_from_string;
+ g_once_init_leave (&codec, &c);
+ }
+ return codec;
+}
diff --git a/sys/v4l2/gstv4l2mpeg4codec.h b/sys/v4l2/gstv4l2mpeg4codec.h
new file mode 100644
index 000000000..e003c4293
--- /dev/null
+++ b/sys/v4l2/gstv4l2mpeg4codec.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ * Factored out from gstv4l2mpeg4enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GST_V4L2_MPEG4_CODEC_H__
+#define __GST_V4L2_MPEG4_CODEC_H__
+
+#include "gstv4l2codec.h"
+
+G_BEGIN_DECLS
+
+const GstV4l2Codec * gst_v4l2_mpeg4_get_codec (void);
+
+G_END_DECLS
+
+#endif
diff --git a/sys/v4l2/gstv4l2mpeg4enc.c b/sys/v4l2/gstv4l2mpeg4enc.c
index 9333fd0f0..af18688af 100644
--- a/sys/v4l2/gstv4l2mpeg4enc.c
+++ b/sys/v4l2/gstv4l2mpeg4enc.c
@@ -31,6 +31,7 @@
#include "gstv4l2object.h"
#include "gstv4l2mpeg4enc.h"
+#include "gstv4l2mpeg4codec.h"
#include <string.h>
#include <gst/gst-i18n-plugin.h>
@@ -65,104 +66,6 @@ gst_v4l2_mpeg4_enc_get_property (GObject * object,
/* TODO */
}
-static gint
-v4l2_profile_from_string (const gchar * profile)
-{
- gint v4l2_profile = -1;
-
- if (g_str_equal (profile, "simple"))
- v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE;
- else if (g_str_equal (profile, "advanced-simple"))
- v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE;
- else if (g_str_equal (profile, "core"))
- v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE;
- else if (g_str_equal (profile, "simple-scalable"))
- v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE;
- else if (g_str_equal (profile, "advanced-coding-efficiency"))
- v4l2_profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY;
- else
- GST_WARNING ("Unsupported profile string '%s'", profile);
-
- return v4l2_profile;
-}
-
-static const gchar *
-v4l2_profile_to_string (gint v4l2_profile)
-{
- switch (v4l2_profile) {
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
- return "simple";
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
- return "advanced-simple";
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE:
- return "core";
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE:
- return "simple-scalable";
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY:
- return "advanced-coding-efficiency";
- default:
- GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
- break;
- }
-
- return NULL;
-}
-
-static gint
-v4l2_level_from_string (const gchar * level)
-{
- gint v4l2_level = -1;
-
- if (g_str_equal (level, "0"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0;
- else if (g_str_equal (level, "0b"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B;
- else if (g_str_equal (level, "1"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_1;
- else if (g_str_equal (level, "2"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_2;
- else if (g_str_equal (level, "3"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_3;
- else if (g_str_equal (level, "3b"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B;
- else if (g_str_equal (level, "4"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_4;
- else if (g_str_equal (level, "5"))
- v4l2_level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5;
- else
- GST_WARNING ("Unsupported level '%s'", level);
-
- return v4l2_level;
-}
-
-static const gchar *
-v4l2_level_to_string (gint v4l2_level)
-{
- switch (v4l2_level) {
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0:
- return "0";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B:
- return "0b";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1:
- return "1";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2:
- return "2";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3:
- return "3";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B:
- return "3b";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4:
- return "4";
- case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5:
- return "5";
- default:
- GST_WARNING ("Unsupported V4L2 level %i", v4l2_level);
- break;
- }
-
- return NULL;
-}
-
static void
gst_v4l2_mpeg4_enc_init (GstV4l2Mpeg4Enc * self)
{
@@ -196,12 +99,6 @@ gst_v4l2_mpeg4_enc_class_init (GstV4l2Mpeg4EncClass * klass)
GST_DEBUG_FUNCPTR (gst_v4l2_mpeg4_enc_get_property);
baseclass->codec_name = "MPEG4";
- baseclass->profile_cid = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
- baseclass->profile_to_string = v4l2_profile_to_string;
- baseclass->profile_from_string = v4l2_profile_from_string;
- baseclass->level_cid = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL;
- baseclass->level_to_string = v4l2_level_to_string;
- baseclass->level_from_string = v4l2_level_from_string;
}
/* Probing functions */
@@ -214,9 +111,11 @@ gst_v4l2_is_mpeg4_enc (GstCaps * sink_caps, GstCaps * src_caps)
void
gst_v4l2_mpeg4_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps,
+ GstCaps * src_caps)
{
+ const GstV4l2Codec *codec = gst_v4l2_mpeg4_get_codec ();
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_MPEG4_ENC,
- "mpeg4", basename, device_path, sink_caps,
+ "mpeg4", basename, device_path, codec, video_fd, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2mpeg4enc.h b/sys/v4l2/gstv4l2mpeg4enc.h
index 84941037f..9e4c884b7 100644
--- a/sys/v4l2/gstv4l2mpeg4enc.h
+++ b/sys/v4l2/gstv4l2mpeg4enc.h
@@ -54,7 +54,7 @@ GType gst_v4l2_mpeg4_enc_get_type (void);
gboolean gst_v4l2_is_mpeg4_enc (GstCaps * sink_caps, GstCaps * src_caps);
void gst_v4l2_mpeg4_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps);
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps, GstCaps * src_caps);
G_END_DECLS
#endif /* __GST_V4L2_MPEG4_ENC_H__ */
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 6338884e8..99a04e303 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -32,6 +32,12 @@
#include "gstv4l2object.h"
#include "gstv4l2videodec.h"
+#include "gstv4l2h264codec.h"
+#include "gstv4l2h265codec.h"
+#include "gstv4l2mpeg4codec.h"
+#include "gstv4l2vp8codec.h"
+#include "gstv4l2vp9codec.h"
+
#include <string.h>
#include <gst/gst-i18n-plugin.h>
@@ -45,6 +51,7 @@ typedef struct
GstCaps *src_caps;
const gchar *longname;
const gchar *description;
+ const GstV4l2Codec *codec;
} GstV4l2VideoDecCData;
enum
@@ -1081,6 +1088,7 @@ G_STMT_START { \
SET_META ("MPEG2");
} else {
SET_META ("MPEG4");
+ cdata->codec = gst_v4l2_mpeg4_get_codec ();
}
} else if (gst_structure_has_name (s, "video/x-h263")) {
SET_META ("H263");
@@ -1088,14 +1096,18 @@ G_STMT_START { \
SET_META ("FWHT");
} else if (gst_structure_has_name (s, "video/x-h264")) {
SET_META ("H264");
+ cdata->codec = gst_v4l2_h264_get_codec ();
} else if (gst_structure_has_name (s, "video/x-h265")) {
SET_META ("H265");
+ cdata->codec = gst_v4l2_h265_get_codec ();
} else if (gst_structure_has_name (s, "video/x-wmv")) {
SET_META ("VC1");
} else if (gst_structure_has_name (s, "video/x-vp8")) {
SET_META ("VP8");
+ cdata->codec = gst_v4l2_vp8_get_codec ();
} else if (gst_structure_has_name (s, "video/x-vp9")) {
SET_META ("VP9");
+ cdata->codec = gst_v4l2_vp9_get_codec ();
} else if (gst_structure_has_name (s, "video/x-bayer")) {
SET_META ("BAYER");
} else if (gst_structure_has_name (s, "video/x-sonix")) {
@@ -1130,7 +1142,8 @@ G_STMT_START { \
void
gst_v4l2_video_dec_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps,
+ GstCaps * src_caps)
{
gint i;
@@ -1157,6 +1170,20 @@ gst_v4l2_video_dec_register (GstPlugin * plugin, const gchar * basename,
continue;
}
+ if (cdata->codec != NULL) {
+ GValue *value = gst_v4l2_codec_probe_levels (cdata->codec, video_fd);
+ if (value != NULL) {
+ gst_caps_set_value (cdata->sink_caps, "level", value);
+ g_value_unset (value);
+ }
+
+ value = gst_v4l2_codec_probe_profiles (cdata->codec, video_fd);
+ if (value != NULL) {
+ gst_caps_set_value (cdata->sink_caps, "profile", value);
+ g_value_unset (value);
+ }
+ }
+
type = gst_v4l2_video_dec_get_type ();
g_type_query (type, &type_query);
memset (&type_info, 0, sizeof (type_info));
diff --git a/sys/v4l2/gstv4l2videodec.h b/sys/v4l2/gstv4l2videodec.h
index be97d10aa..6696fcb35 100644
--- a/sys/v4l2/gstv4l2videodec.h
+++ b/sys/v4l2/gstv4l2videodec.h
@@ -76,7 +76,7 @@ GType gst_v4l2_video_dec_get_type (void);
gboolean gst_v4l2_is_video_dec (GstCaps * sink_caps, GstCaps * src_caps);
void gst_v4l2_video_dec_register (GstPlugin * plugin,
const gchar *basename,
- const gchar *device_path,
+ const gchar *device_path, gint video_fd,
GstCaps * sink_caps, GstCaps * src_caps);
G_END_DECLS
diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index 8a86e4af0..e0b015086 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -45,6 +45,7 @@ typedef struct
gchar *device;
GstCaps *sink_caps;
GstCaps *src_caps;
+ const GstV4l2Codec *codec;
} GstV4l2VideoEncCData;
enum
@@ -419,8 +420,9 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
GQueue profiles = G_QUEUE_INIT;
GQueue levels = G_QUEUE_INIT;
gboolean failed = FALSE;
+ const GstV4l2Codec *codec = klass->codec;
- if (klass->profile_cid && get_string_list (s, "profile", &profiles)) {
+ if (codec->profile_cid && get_string_list (s, "profile", &profiles)) {
GList *l;
for (l = profiles.head; l; l = l->next) {
@@ -430,8 +432,9 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
GST_TRACE_OBJECT (ctx->self, "Trying profile %s", profile);
- control.id = klass->profile_cid;
- control.value = v4l2_profile = klass->profile_from_string (profile);
+ control.id = codec->profile_cid;
+
+ control.value = v4l2_profile = codec->profile_from_string (profile);
if (control.value < 0)
continue;
@@ -442,7 +445,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
break;
}
- profile = klass->profile_to_string (control.value);
+ profile = codec->profile_to_string (control.value);
if (control.value == v4l2_profile) {
ctx->profile = profile;
@@ -462,7 +465,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
g_queue_clear (&profiles);
}
- if (!failed && klass->level_cid && get_string_list (s, "level", &levels)) {
+ if (!failed && codec->level_cid && get_string_list (s, "level", &levels)) {
GList *l;
for (l = levels.head; l; l = l->next) {
@@ -472,8 +475,8 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
GST_TRACE_OBJECT (ctx->self, "Trying level %s", level);
- control.id = klass->level_cid;
- control.value = v4l2_level = klass->level_from_string (level);
+ control.id = codec->level_cid;
+ control.value = v4l2_level = codec->level_from_string (level);
if (control.value < 0)
continue;
@@ -484,7 +487,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
break;
}
- level = klass->level_to_string (control.value);
+ level = codec->level_to_string (control.value);
if (control.value == v4l2_level) {
ctx->level = level;
@@ -518,6 +521,7 @@ gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
struct ProfileLevelCtx ctx = { self, NULL, NULL };
GstVideoCodecState *state;
GstStructure *s;
+ const GstV4l2Codec *codec = klass->codec;
GST_DEBUG_OBJECT (self, "Negotiating %s profile and level.",
klass->codec_name);
@@ -543,26 +547,26 @@ gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
}
}
- if (klass->profile_cid && !ctx.profile) {
+ if (codec->profile_cid && !ctx.profile) {
struct v4l2_control control = { 0, };
- control.id = klass->profile_cid;
+ control.id = codec->profile_cid;
if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto g_ctrl_failed;
- ctx.profile = klass->profile_to_string (control.value);
+ ctx.profile = codec->profile_to_string (control.value);
}
- if (klass->level_cid && !ctx.level) {
+ if (codec->level_cid && !ctx.level) {
struct v4l2_control control = { 0, };
- control.id = klass->level_cid;
+ control.id = codec->level_cid;
if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto g_ctrl_failed;
- ctx.level = klass->level_to_string (control.value);
+ ctx.level = codec->level_to_string (control.value);
}
GST_DEBUG_OBJECT (self, "Selected %s profile %s at level %s",
@@ -571,10 +575,10 @@ gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
state = gst_video_encoder_get_output_state (encoder);
s = gst_caps_get_structure (state->caps, 0);
- if (klass->profile_cid)
+ if (codec->profile_cid)
gst_structure_set (s, "profile", G_TYPE_STRING, ctx.profile, NULL);
- if (klass->level_cid)
+ if (codec->level_cid)
gst_structure_set (s, "level", G_TYPE_STRING, ctx.level, NULL);
if (!GST_VIDEO_ENCODER_CLASS (parent_class)->negotiate (encoder))
@@ -1122,6 +1126,7 @@ gst_v4l2_video_enc_subclass_init (gpointer g_class, gpointer data)
GstV4l2VideoEncCData *cdata = data;
klass->default_device = cdata->device;
+ klass->codec = cdata->codec;
/* Note: gst_pad_template_new() take the floating ref from the caps */
gst_element_class_add_pad_template (element_class,
@@ -1160,8 +1165,9 @@ gst_v4l2_is_video_enc (GstCaps * sink_caps, GstCaps * src_caps,
void
gst_v4l2_video_enc_register (GstPlugin * plugin, GType type,
- const char *codec, const gchar * basename, const gchar * device_path,
- GstCaps * sink_caps, GstCaps * codec_caps, GstCaps * src_caps)
+ const char *codec_name, const gchar * basename, const gchar * device_path,
+ const GstV4l2Codec * codec, gint video_fd, GstCaps * sink_caps,
+ GstCaps * codec_caps, GstCaps * src_caps)
{
GstCaps *filtered_caps;
GTypeQuery type_query;
@@ -1170,12 +1176,27 @@ gst_v4l2_video_enc_register (GstPlugin * plugin, GType type,
gchar *type_name;
GstV4l2VideoEncCData *cdata;
+ if (codec != NULL && video_fd != -1) {
+ GValue *value = gst_v4l2_codec_probe_levels (codec, video_fd);
+ if (value != NULL) {
+ gst_caps_set_value (src_caps, "level", value);
+ g_value_unset (value);
+ }
+
+ value = gst_v4l2_codec_probe_profiles (codec, video_fd);
+ if (value != NULL) {
+ gst_caps_set_value (src_caps, "profile", value);
+ g_value_unset (value);
+ }
+ }
+
filtered_caps = gst_caps_intersect (src_caps, codec_caps);
cdata = g_new0 (GstV4l2VideoEncCData, 1);
cdata->device = g_strdup (device_path);
cdata->sink_caps = gst_caps_ref (sink_caps);
cdata->src_caps = gst_caps_ref (filtered_caps);
+ cdata->codec = codec;
g_type_query (type, &type_query);
memset (&type_info, 0, sizeof (type_info));
@@ -1189,11 +1210,11 @@ gst_v4l2_video_enc_register (GstPlugin * plugin, GType type,
* v4l2h264enc, for any additional encoders, we create unique names. Encoder
* names may change between boots, so this should help gain stable names for
* the most common use cases. */
- type_name = g_strdup_printf ("v4l2%senc", codec);
+ type_name = g_strdup_printf ("v4l2%senc", codec_name);
if (g_type_from_name (type_name) != 0) {
g_free (type_name);
- type_name = g_strdup_printf ("v4l2%s%senc", basename, codec);
+ type_name = g_strdup_printf ("v4l2%s%senc", basename, codec_name);
}
subtype = g_type_register_static (type, type_name, &type_info, 0);
diff --git a/sys/v4l2/gstv4l2videoenc.h b/sys/v4l2/gstv4l2videoenc.h
index f03acd523..3659cb51d 100644
--- a/sys/v4l2/gstv4l2videoenc.h
+++ b/sys/v4l2/gstv4l2videoenc.h
@@ -29,6 +29,7 @@
#include <gstv4l2object.h>
#include <gstv4l2bufferpool.h>
+#include <gstv4l2codec.h>
G_BEGIN_DECLS
#define GST_TYPE_V4L2_VIDEO_ENC \
@@ -73,14 +74,7 @@ struct _GstV4l2VideoEncClass
gchar *default_device;
const char *codec_name;
-
- guint32 profile_cid;
- const gchar * (*profile_to_string) (gint v4l2_profile);
- gint (*profile_from_string) (const gchar * profile);
-
- guint32 level_cid;
- const gchar * (*level_to_string) (gint v4l2_level);
- gint (*level_from_string) (const gchar * level);
+ const GstV4l2Codec *codec;
};
GType gst_v4l2_video_enc_get_type (void);
@@ -90,7 +84,8 @@ gboolean gst_v4l2_is_video_enc (GstCaps * sink_caps, GstCaps * src_caps,
GstCaps * codec_caps);
void gst_v4l2_video_enc_register (GstPlugin * plugin, GType type,
- const char *codec, const gchar * basename, const gchar * device_path,
+ const char *codec_name, const gchar * basename, const gchar * device_path,
+ const GstV4l2Codec * codec, gint video_fd,
GstCaps * sink_caps, GstCaps *codec_caps, GstCaps * src_caps);
G_END_DECLS
diff --git a/sys/v4l2/gstv4l2vp8codec.c b/sys/v4l2/gstv4l2vp8codec.c
new file mode 100644
index 000000000..7181af6d9
--- /dev/null
+++ b/sys/v4l2/gstv4l2vp8codec.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ * Factored out from gstv4l2vp8enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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
+
+#include "gstv4l2vp8codec.h"
+
+#include <gst/gst.h>
+#include "ext/v4l2-controls.h"
+
+static gint
+v4l2_profile_from_string (const gchar * profile)
+{
+ gint v4l2_profile = -1;
+
+ if (g_str_equal (profile, "0"))
+ v4l2_profile = 0;
+ else if (g_str_equal (profile, "1"))
+ v4l2_profile = 1;
+ else if (g_str_equal (profile, "2"))
+ v4l2_profile = 2;
+ else if (g_str_equal (profile, "3"))
+ v4l2_profile = 3;
+ else
+ GST_WARNING ("Unsupported profile string '%s'", profile);
+
+ return v4l2_profile;
+}
+
+static const gchar *
+v4l2_profile_to_string (gint v4l2_profile)
+{
+ switch (v4l2_profile) {
+ case 0:
+ return "0";
+ case 1:
+ return "1";
+ case 2:
+ return "2";
+ case 3:
+ return "3";
+ default:
+ GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
+ break;
+ }
+
+ return NULL;
+}
+
+const GstV4l2Codec *
+gst_v4l2_vp8_get_codec (void)
+{
+ static GstV4l2Codec *codec = NULL;
+ if (g_once_init_enter (&codec)) {
+ static GstV4l2Codec c;
+ c.profile_cid = V4L2_CID_MPEG_VIDEO_VPX_PROFILE;
+ c.profile_to_string = v4l2_profile_to_string;
+ c.profile_from_string = v4l2_profile_from_string;
+ g_once_init_leave (&codec, &c);
+ }
+ return codec;
+}
diff --git a/sys/v4l2/gstv4l2vp8codec.h b/sys/v4l2/gstv4l2vp8codec.h
new file mode 100644
index 000000000..42c23be26
--- /dev/null
+++ b/sys/v4l2/gstv4l2vp8codec.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ * Factored out from gstv4l2vp8enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GST_V4L2_VP8_CODEC_H__
+#define __GST_V4L2_VP8_CODEC_H__
+
+#include "gstv4l2codec.h"
+
+G_BEGIN_DECLS
+
+const GstV4l2Codec * gst_v4l2_vp8_get_codec (void);
+
+G_END_DECLS
+
+#endif
diff --git a/sys/v4l2/gstv4l2vp8enc.c b/sys/v4l2/gstv4l2vp8enc.c
index eadac8ff5..8bf908672 100644
--- a/sys/v4l2/gstv4l2vp8enc.c
+++ b/sys/v4l2/gstv4l2vp8enc.c
@@ -31,6 +31,7 @@
#include "gstv4l2object.h"
#include "gstv4l2vp8enc.h"
+#include "gstv4l2vp8codec.h"
#include <string.h>
#include <gst/gst-i18n-plugin.h>
@@ -65,45 +66,6 @@ gst_v4l2_vp8_enc_get_property (GObject * object,
/* TODO */
}
-static gint
-v4l2_profile_from_string (const gchar * profile)
-{
- gint v4l2_profile = -1;
-
- if (g_str_equal (profile, "0"))
- v4l2_profile = 0;
- else if (g_str_equal (profile, "1"))
- v4l2_profile = 1;
- else if (g_str_equal (profile, "2"))
- v4l2_profile = 2;
- else if (g_str_equal (profile, "3"))
- v4l2_profile = 3;
- else
- GST_WARNING ("Unsupported profile string '%s'", profile);
-
- return v4l2_profile;
-}
-
-static const gchar *
-v4l2_profile_to_string (gint v4l2_profile)
-{
- switch (v4l2_profile) {
- case 0:
- return "0";
- case 1:
- return "1";
- case 2:
- return "2";
- case 3:
- return "3";
- default:
- GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
- break;
- }
-
- return NULL;
-}
-
static void
gst_v4l2_vp8_enc_init (GstV4l2Vp8Enc * self)
{
@@ -138,9 +100,6 @@ gst_v4l2_vp8_enc_class_init (GstV4l2Vp8EncClass * klass)
GST_DEBUG_FUNCPTR (gst_v4l2_vp8_enc_get_property);
baseclass->codec_name = "VP8";
- baseclass->profile_cid = V4L2_CID_MPEG_VIDEO_VPX_PROFILE;
- baseclass->profile_to_string = v4l2_profile_to_string;
- baseclass->profile_from_string = v4l2_profile_from_string;
}
/* Probing functions */
@@ -153,9 +112,11 @@ gst_v4l2_is_vp8_enc (GstCaps * sink_caps, GstCaps * src_caps)
void
gst_v4l2_vp8_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps,
+ GstCaps * src_caps)
{
+ const GstV4l2Codec *codec = gst_v4l2_vp8_get_codec ();
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_VP8_ENC,
- "vp8", basename, device_path, sink_caps,
+ "vp8", basename, device_path, codec, video_fd, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2vp8enc.h b/sys/v4l2/gstv4l2vp8enc.h
index 3e82b4b79..41a6cdaad 100644
--- a/sys/v4l2/gstv4l2vp8enc.h
+++ b/sys/v4l2/gstv4l2vp8enc.h
@@ -54,7 +54,7 @@ GType gst_v4l2_vp8_enc_get_type (void);
gboolean gst_v4l2_is_vp8_enc (GstCaps * sink_caps, GstCaps * src_caps);
void gst_v4l2_vp8_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps);
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps, GstCaps * src_caps);
G_END_DECLS
#endif /* __GST_V4L2_VP8_ENC_H__ */
diff --git a/sys/v4l2/gstv4l2vp9codec.c b/sys/v4l2/gstv4l2vp9codec.c
new file mode 100644
index 000000000..b4f2d5cf0
--- /dev/null
+++ b/sys/v4l2/gstv4l2vp9codec.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ * Factored out from gstv4l2vp9enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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
+
+#include "gstv4l2vp9codec.h"
+
+#include <gst/gst.h>
+#include "ext/v4l2-controls.h"
+
+
+static gint
+v4l2_profile_from_string (const gchar * profile)
+{
+ gint v4l2_profile = -1;
+
+ if (g_str_equal (profile, "0"))
+ v4l2_profile = 0;
+ else if (g_str_equal (profile, "1"))
+ v4l2_profile = 1;
+ else if (g_str_equal (profile, "2"))
+ v4l2_profile = 2;
+ else if (g_str_equal (profile, "3"))
+ v4l2_profile = 3;
+ else
+ GST_WARNING ("Unsupported profile string '%s'", profile);
+
+ return v4l2_profile;
+}
+
+static const gchar *
+v4l2_profile_to_string (gint v4l2_profile)
+{
+ switch (v4l2_profile) {
+ case 0:
+ return "0";
+ case 1:
+ return "1";
+ case 2:
+ return "2";
+ case 3:
+ return "3";
+ default:
+ GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
+ break;
+ }
+
+ return NULL;
+}
+
+const GstV4l2Codec *
+gst_v4l2_vp9_get_codec (void)
+{
+ static GstV4l2Codec *codec = NULL;
+ if (g_once_init_enter (&codec)) {
+ static GstV4l2Codec c;
+ c.profile_cid = V4L2_CID_MPEG_VIDEO_VPX_PROFILE;
+ c.profile_to_string = v4l2_profile_to_string;
+ c.profile_from_string = v4l2_profile_from_string;
+ g_once_init_leave (&codec, &c);
+ }
+ return codec;
+}
diff --git a/sys/v4l2/gstv4l2vp9codec.h b/sys/v4l2/gstv4l2vp9codec.h
new file mode 100644
index 000000000..84a54ef8f
--- /dev/null
+++ b/sys/v4l2/gstv4l2vp9codec.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 Collabora Inc.
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ * Factored out from gstv4l2vp9enc by Philippe Normand <philn@igalia.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GST_V4L2_VP9_CODEC_H__
+#define __GST_V4L2_VP9_CODEC_H__
+
+#include "gstv4l2codec.h"
+
+G_BEGIN_DECLS
+
+const GstV4l2Codec * gst_v4l2_vp9_get_codec (void);
+
+G_END_DECLS
+
+#endif
diff --git a/sys/v4l2/gstv4l2vp9enc.c b/sys/v4l2/gstv4l2vp9enc.c
index 69eedca8d..f26a2ebc7 100644
--- a/sys/v4l2/gstv4l2vp9enc.c
+++ b/sys/v4l2/gstv4l2vp9enc.c
@@ -31,6 +31,7 @@
#include "gstv4l2object.h"
#include "gstv4l2vp9enc.h"
+#include "gstv4l2vp9codec.h"
#include <string.h>
#include <gst/gst-i18n-plugin.h>
@@ -65,45 +66,6 @@ gst_v4l2_vp9_enc_get_property (GObject * object,
/* TODO */
}
-static gint
-v4l2_profile_from_string (const gchar * profile)
-{
- gint v4l2_profile = -1;
-
- if (g_str_equal (profile, "0"))
- v4l2_profile = 0;
- else if (g_str_equal (profile, "1"))
- v4l2_profile = 1;
- else if (g_str_equal (profile, "2"))
- v4l2_profile = 2;
- else if (g_str_equal (profile, "3"))
- v4l2_profile = 3;
- else
- GST_WARNING ("Unsupported profile string '%s'", profile);
-
- return v4l2_profile;
-}
-
-static const gchar *
-v4l2_profile_to_string (gint v4l2_profile)
-{
- switch (v4l2_profile) {
- case 0:
- return "0";
- case 1:
- return "1";
- case 2:
- return "2";
- case 3:
- return "3";
- default:
- GST_WARNING ("Unsupported V4L2 profile %i", v4l2_profile);
- break;
- }
-
- return NULL;
-}
-
static void
gst_v4l2_vp9_enc_init (GstV4l2Vp9Enc * self)
{
@@ -137,9 +99,6 @@ gst_v4l2_vp9_enc_class_init (GstV4l2Vp9EncClass * klass)
GST_DEBUG_FUNCPTR (gst_v4l2_vp9_enc_get_property);
baseclass->codec_name = "VP9";
- baseclass->profile_cid = V4L2_CID_MPEG_VIDEO_VPX_PROFILE;
- baseclass->profile_to_string = v4l2_profile_to_string;
- baseclass->profile_from_string = v4l2_profile_from_string;
}
/* Probing functions */
@@ -152,9 +111,11 @@ gst_v4l2_is_vp9_enc (GstCaps * sink_caps, GstCaps * src_caps)
void
gst_v4l2_vp9_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps,
+ GstCaps * src_caps)
{
+ const GstV4l2Codec *codec = gst_v4l2_vp9_get_codec ();
gst_v4l2_video_enc_register (plugin, GST_TYPE_V4L2_VP9_ENC,
- "vp9", basename, device_path, sink_caps,
+ "vp9", basename, device_path, codec, video_fd, sink_caps,
gst_static_caps_get (&src_template_caps), src_caps);
}
diff --git a/sys/v4l2/gstv4l2vp9enc.h b/sys/v4l2/gstv4l2vp9enc.h
index b768cced2..f9b8ad768 100644
--- a/sys/v4l2/gstv4l2vp9enc.h
+++ b/sys/v4l2/gstv4l2vp9enc.h
@@ -54,7 +54,7 @@ GType gst_v4l2_vp9_enc_get_type (void);
gboolean gst_v4l2_is_vp9_enc (GstCaps * sink_caps, GstCaps * src_caps);
void gst_v4l2_vp9_enc_register (GstPlugin * plugin, const gchar * basename,
- const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps);
+ const gchar * device_path, gint video_fd, GstCaps * sink_caps, GstCaps * src_caps);
G_END_DECLS
#endif /* __GST_V4L2_VP9_ENC_H__ */
diff --git a/sys/v4l2/meson.build b/sys/v4l2/meson.build
index 61cd618c2..bae955a3d 100644
--- a/sys/v4l2/meson.build
+++ b/sys/v4l2/meson.build
@@ -1,6 +1,7 @@
v4l2_sources = [
'gstv4l2.c',
'gstv4l2allocator.c',
+ 'gstv4l2codec.c',
'gstv4l2colorbalance.c',
'gstv4l2deviceprovider.c',
'gstv4l2object.c',
@@ -14,12 +15,17 @@ v4l2_sources = [
'gstv4l2videoenc.c',
'gstv4l2fwhtenc.c',
'gstv4l2h263enc.c',
+ 'gstv4l2h264codec.c',
'gstv4l2h264enc.c',
+ 'gstv4l2h265codec.c',
'gstv4l2h265enc.c',
'gstv4l2jpegenc.c',
+ 'gstv4l2mpeg4codec.c',
'gstv4l2mpeg4enc.c',
'gstv4l2vidorient.c',
+ 'gstv4l2vp8codec.c',
'gstv4l2vp8enc.c',
+ 'gstv4l2vp9codec.c',
'gstv4l2vp9enc.c',
'v4l2_calls.c',
'v4l2-utils.c',