From 15429ee4113a1f2c3943eba2125d8f9f3a9bbe6a Mon Sep 17 00:00:00 2001 From: Amit Pandya Date: Thu, 18 Oct 2018 12:29:00 +0530 Subject: [PATCH] v4l2videoenc: Add HEVC support Add HEVC encoder support. https://bugzilla.gnome.org/show_bug.cgi?id=797141 --- sys/v4l2/Makefile.am | 2 + sys/v4l2/gstv4l2.c | 5 + sys/v4l2/gstv4l2h265enc.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++ sys/v4l2/gstv4l2h265enc.h | 60 ++++++++++++ sys/v4l2/meson.build | 1 + 5 files changed, 303 insertions(+) create mode 100644 sys/v4l2/gstv4l2h265enc.c create mode 100644 sys/v4l2/gstv4l2h265enc.h diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index b1c899b..e4099bc 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -18,6 +18,7 @@ libgstvideo4linux2_la_SOURCES = gstv4l2.c \ gstv4l2fwhtenc.c \ gstv4l2h263enc.c \ gstv4l2h264enc.c \ + gstv4l2h265enc.c \ gstv4l2jpegenc.c \ gstv4l2mpeg4enc.c \ gstv4l2vidorient.c \ @@ -66,6 +67,7 @@ noinst_HEADERS = \ gstv4l2fwhtenc.h \ gstv4l2h263enc.h \ gstv4l2h264enc.h \ + gstv4l2h265enc.h \ gstv4l2jpegenc.h \ gstv4l2mpeg4enc.h \ gstv4l2vidorient.h \ diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c index e6a10e8..56d2e71 100644 --- a/sys/v4l2/gstv4l2.c +++ b/sys/v4l2/gstv4l2.c @@ -50,6 +50,7 @@ #include "gstv4l2fwhtenc.h" #include "gstv4l2h263enc.h" #include "gstv4l2h264enc.h" +#include "gstv4l2h265enc.h" #include "gstv4l2jpegenc.h" #include "gstv4l2mpeg4enc.h" #include "gstv4l2vp8enc.h" @@ -197,6 +198,10 @@ gst_v4l2_probe_and_register (GstPlugin * plugin) gst_v4l2_h264_enc_register (plugin, basename, it->device_path, 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); + if (gst_v4l2_is_mpeg4_enc (sink_caps, src_caps)) gst_v4l2_mpeg4_enc_register (plugin, basename, it->device_path, sink_caps, src_caps); diff --git a/sys/v4l2/gstv4l2h265enc.c b/sys/v4l2/gstv4l2h265enc.c new file mode 100644 index 0000000..d3ef657 --- /dev/null +++ b/sys/v4l2/gstv4l2h265enc.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2018 NVIDIA CORPORATION. + * Author: Amit Pandya + * + * 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 +#include +#include +#include +#include + +#include "gstv4l2object.h" +#include "gstv4l2h265enc.h" + +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_v4l2_h265_enc_debug); +#define GST_CAT_DEFAULT gst_v4l2_h265_enc_debug + +static GstStaticCaps src_template_caps = +GST_STATIC_CAPS ("video/x-h265, stream-format=(string) byte-stream, " + "alignment=(string) au"); + +enum +{ + PROP_0, + V4L2_STD_OBJECT_PROPS, +/* TODO add H265 controls */ +}; + +#define gst_v4l2_h265_enc_parent_class parent_class +G_DEFINE_TYPE (GstV4l2H265Enc, gst_v4l2_h265_enc, GST_TYPE_V4L2_VIDEO_ENC); + +static void +gst_v4l2_h265_enc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + /* TODO */ +} + +static void +gst_v4l2_h265_enc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + /* 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) +{ +} + +static void +gst_v4l2_h265_enc_class_init (GstV4l2H265EncClass * klass) +{ + GstElementClass *element_class; + GObjectClass *gobject_class; + GstV4l2VideoEncClass *baseclass; + + parent_class = g_type_class_peek_parent (klass); + + element_class = (GstElementClass *) klass; + gobject_class = (GObjectClass *) klass; + baseclass = (GstV4l2VideoEncClass *) (klass); + + GST_DEBUG_CATEGORY_INIT (gst_v4l2_h265_enc_debug, "v4l2h265enc", 0, + "V4L2 H.265 Encoder"); + + gst_element_class_set_static_metadata (element_class, + "V4L2 H.265 Encoder", + "Codec/Encoder/Video", + "Encode H.265 video streams via V4L2 API", + "Amit Pandya "); + + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_v4l2_h265_enc_set_property); + gobject_class->get_property = + 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 */ +gboolean +gst_v4l2_is_h265_enc (GstCaps * sink_caps, GstCaps * src_caps) +{ + return gst_v4l2_is_video_enc (sink_caps, src_caps, + gst_static_caps_get (&src_template_caps)); +} + +void +gst_v4l2_h265_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_H265_ENC, + "h265", basename, device_path, sink_caps, + gst_static_caps_get (&src_template_caps), src_caps); +} diff --git a/sys/v4l2/gstv4l2h265enc.h b/sys/v4l2/gstv4l2h265enc.h new file mode 100644 index 0000000..6ead493 --- /dev/null +++ b/sys/v4l2/gstv4l2h265enc.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 NVIDIA CORPORATION. + * Author: Amit Pandya + * + * 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_ENC_H__ +#define __GST_V4L2_H265_ENC_H__ + +#include +#include "gstv4l2videoenc.h" + +G_BEGIN_DECLS +#define GST_TYPE_V4L2_H265_ENC \ + (gst_v4l2_h265_enc_get_type()) +#define GST_V4L2_H265_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2_H265_ENC,GstV4l2H265Enc)) +#define GST_V4L2_H265_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2_H265_ENC,GstV4l2H265EncClass)) +#define GST_IS_V4L2_H265_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2_H265_ENC)) +#define GST_IS_V4L2_H265_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2_H265_ENC)) +typedef struct _GstV4l2H265Enc GstV4l2H265Enc; +typedef struct _GstV4l2H265EncClass GstV4l2H265EncClass; + +struct _GstV4l2H265Enc +{ + GstV4l2VideoEnc parent; +}; + +struct _GstV4l2H265EncClass +{ + GstV4l2VideoEncClass parent_class; +}; + +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); + +G_END_DECLS +#endif /* __GST_V4L2_H265_ENC_H__ */ diff --git a/sys/v4l2/meson.build b/sys/v4l2/meson.build index 71dbd50..ce591b3 100644 --- a/sys/v4l2/meson.build +++ b/sys/v4l2/meson.build @@ -15,6 +15,7 @@ v4l2_sources = [ 'gstv4l2fwhtenc.c', 'gstv4l2h263enc.c', 'gstv4l2h264enc.c', + 'gstv4l2h265enc.c', 'gstv4l2jpegenc.c', 'gstv4l2mpeg4enc.c', 'gstv4l2vidorient.c', -- 2.7.4