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.
This commit is contained in:
Philippe Normand 2019-03-04 11:05:29 +00:00
parent 7bd1909f4f
commit 6ce195e9d1
32 changed files with 1166 additions and 544 deletions

View file

@ -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 \

View file

@ -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);

125
sys/v4l2/gstv4l2codec.c Normal file
View file

@ -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;
}

48
sys/v4l2/gstv4l2codec.h Normal file
View file

@ -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__ */

View file

@ -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);
}

View file

@ -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);
}

226
sys/v4l2/gstv4l2h264codec.c Normal file
View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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__ */

158
sys/v4l2/gstv4l2h265codec.c Normal file
View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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));

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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',