去掉v4l2mpeg4dec插件的mpeg4解码能力

背景:去掉v4l2videodec的MPEG4的caps

MPEG4 caps的初始化调用栈

plugin_init在gst-plugins-good/sys/v4l2/gstv4l2.c文件中,是v4l2相关plugin的init函数,通过gst-inspect可以看到video4linux2对应一系列插件

video4linux2:  v4l2src: Video (video4linux2) Source
video4linux2:  v4l2sink: Video (video4linux2) Sink
video4linux2:  v4l2radio: Radio (video4linux2) Tuner
video4linux2:  v4l2deviceprovider (GstDeviceProviderFactory)
video4linux2:  v4l2jpegdec: V4L2 JPEG Decoder
video4linux2:  v4l2mpeg4dec: V4L2 MPEG4 Decoder
video4linux2:  v4l2h264dec: V4L2 H264 Decoder
video4linux2:  v4l2h265dec: V4L2 H265 Decoder
video4linux2:  v4l2vp9dec: V4L2 VP9 Decoder

plugin_init函数,v4l2videodec的调用栈:

plugin_init
	- gst_v4l2_probe_and_register
		- gst_v4l2_video_dec_register
			- gst_v4l2_probe_template_caps
				- gst_v4l2_object_v4l2fourcc_to_structure
					- gst_v4l2_object_v4l2fourcc_to_bare_struct

在gst_v4l2_object_v4l2fourcc_to_bare_struct中可以看到MPEG4的caps定义:

    case V4L2_PIX_FMT_MPEG4:
    case V4L2_PIX_FMT_XVID:
      structure = gst_structure_new ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, "systemstream",
          G_TYPE_BOOLEAN, FALSE, NULL);
      break;

分析

gst_caps_merge调用gst_v4l2_probe_template_caps生成cpas

    sink_caps = gst_caps_merge (gst_v4l2_probe_template_caps (it->device_path,
            video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT),
        gst_v4l2_probe_template_caps (it->device_path, video_fd,
            V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE));

gst_v4l2_probe_template_caps中,通过ioctl查询支持的format,format是多个,format的原型定义如下:

struct v4l2_fmtdesc {
	__u32		    index;             /* Format number      */
	__u32		    type;              /* enum v4l2_buf_type */
	__u32           flags;
	__u8		    description[32];   /* Description string */
	__u32		    pixelformat;       /* Format fourcc      */
	__u32		    reserved[4];
};

ioctl查询支持的format

    if (ioctl (video_fd, VIDIOC_ENUM_FMT, &format) < 0)
      break;                    /* end of enumeration */

然后根据format.pixelformat创建template

template = gst_v4l2_object_v4l2fourcc_to_structure (format.pixelformat);

可以看到V4L2_PIX_FMT_MPEG4部分创建template

static GstStructure *
gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
{
  GstStructure *structure = NULL;

  switch (fourcc) {
    case V4L2_PIX_FMT_MJPEG:   /* Motion-JPEG */
    case V4L2_PIX_FMT_PJPG:    /* Progressive-JPEG */
    case V4L2_PIX_FMT_JPEG:    /* JFIF JPEG */
      structure = gst_structure_new_empty ("image/jpeg");
      break;
    case V4L2_PIX_FMT_MPEG4:
    case V4L2_PIX_FMT_XVID:
      structure = gst_structure_new ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, "systemstream",
          G_TYPE_BOOLEAN, FALSE, NULL);
      break;      

ERROR1

sh-5.0# GST_DEBUG=5 gst-inspect v4l2mpeg4dec               
westeros-sink: discover decoder: /dev/video26

(gst-plugin-scanner:9700): GStreamer-CRITICAL **: 14:47:48.527: gst_debug_log_valist: assertion 'category != NULL' failed
(gst-plugin-scanner:9708): GStreamer-CRITICAL **: 14:47:48.930: gst_debug_log_valist: assertion 'category != NULL' failed

这个错误是因为加了一句log输出导致:

+++ b/sys/v4l2/gstv4l2videodec.c
@@ -1183,6 +1183,7 @@ G_STMT_START { \
   }
 
   if (codec_name) {
+    GST_WARNING ("plugin '%s'", codec_name);
     type_name = g_strdup_printf ("v4l2%sdec", codec_name);
     if (g_type_from_name (type_name) != 0) {
       g_free (type_name);

正确的做法应该是定义default category,不然GST_WARNING用的时候发现category为null,就报前面的错了。GST_WARNING在有些地方可以直接用,有些地方不可以,原因取决于有没有有效的GST_CAT_DEFAULT定义。

这个地方也可以用g_warning增加调试信息:

g_warning ("plugin codec name-: '%s'", codec_name);
$ gst-inspect v4l2mpeg4dec 

 plugin codec name: 'jpeg'
 plugin codec name: 'mpeg4'
 plugin codec name: 'h264'
 plugin codec name: 'h265'
 plugin codec name: 'vp9'

v4l2mpeg4dec

Factory Details:
  Rank                     primary + 1 (257)
  Long-name                V4L2 MPEG4 Decoder
  Klass                    Codec/Decoder/Video/Hardware
  Description              Decodes MPEG4 streams via V4L2 API
  Author                   Nicolas Dufresne <nicolas.dufresne@collabora.com>

对应代码:

  cdata->longname = "V4L2 " codec " Decoder"; \
  cdata->description = "Decodes " codec " streams via V4L2 API"; \
  codec_name = g_ascii_strdown (codec, -1); \

这部分是和v4l2video26mpeg4dec共用的。

继承关系:

GObject
 +----GInitiallyUnowned
       +----GstObject
             +----GstElement
                   +----GstVideoDecoder
                         +----GstV4l2VideoDec
                               +----v4l2mpeg4dec

v4l2video26mpeg4dec

Factory Details:
  Rank                     primary + 1 (257)
  Long-name                V4L2 MPEG4 Decoder
  Klass                    Codec/Decoder/Video/Hardware
  Description              Decodes MPEG4 streams via V4L2 API
  Author                   Nicolas Dufresne <nicolas.dufresne@collabora.com>

继承关系:

GObject
 +----GInitiallyUnowned
       +----GstObject
             +----GstElement
                   +----GstVideoDecoder
                         +----GstV4l2VideoDec
                               +----v4l2video26mpeg4dec
v4l2video26mpeg4dec为什么加了就不见了?

v4l2video26mpeg4dec是video4linux2的一个feature

GST_REGISTRY gstregistrychunks.c:729:gst_registry_chunks_load_feature:
 Added feature v4l2mpeg4dec, plugin 0x1b23008 video4linux2

GST_REGISTRY gstregistrychunks.c:571:gst_registry_chunks_load_feature:
 Plugin 'video4linux2' feature 'v4l2video26mpeg4dec' typename : 'GstElementFactory'

上面打印log的地方:

  GST_DEBUG ("Plugin '%s' feature '%s' typename : '%s'", plugin_name, feature_name, type_name);
registry里面对应的代码

gstreamer/gst/gstregistrychunks.c

_priv_gst_registry_chunks_load_plugin中load插件的feature

  /* Load plugin features */
  for (i = 0; i < n; i++) {
    if (G_UNLIKELY (!gst_registry_chunks_load_feature (registry, in, end,
                plugin))) {
      GST_ERROR ("Error while loading binary feature for plugin '%s'",
          GST_STR_NULL (plugin->desc.name));
      gst_registry_remove_plugin (registry, plugin);
      goto fail;
    }
  }

ERROR2

如果代码有错误,后面是0 features

gstregistrychunks.c:850:_priv_gst_registry_chunks_load_plugin: read strings for name='libgstvideo4linux2.so'
gstregistrychunks.c:851:_priv_gst_registry_chunks_load_plugin:   desc.description='Plugin for blacklisted file'
gstregistrychunks.c:852:_priv_gst_registry_chunks_load_plugin:   filename='/usr/lib/gstreamer-1.0/libgstvideo4linux2.so'
gstregistrychunks.c:853:_priv_gst_registry_chunks_load_plugin:   desc.version='0.0.0'
gstregistrychunks.c:854:_priv_gst_registry_chunks_load_plugin:   desc.license='BLACKLIST'
gstregistrychunks.c:855:_priv_gst_registry_chunks_load_plugin:   desc.source='BLACKLIST'
gstregistrychunks.c:856:_priv_gst_registry_chunks_load_plugin:   desc.package='BLACKLIST'
gstregistrychunks.c:857:_priv_gst_registry_chunks_load_plugin:   desc.origin='BLACKLIST'
gstregistrychunks.c:858:_priv_gst_registry_chunks_load_plugin:   desc.datetime=
gstregistry.c:474:gst_registry_add_plugin:<registry0> adding plugin 0xf46008 for filename "/usr/lib/gstreamer-1.0/libgstvideo4linux2.so"
gstregistry.c:487:gst_registry_add_plugin:<registry0> emitting plugin-added for filename "/usr/lib/gstreamer-1.0/libgstvideo4linux2.so"
gstregistrychunks.c:878:_priv_gst_registry_chunks_load_plugin: Added plugin 'libgstvideo4linux2.so' plugin with 0 features from binary regis

video4linux2

gst-inspect video4linux2
WARNING: terminal is not fully functional
Plugin Details:N)
  Name                     video4linux2
  Description              elements for Video 4 Linux
  Filename                 /usr/lib/gstreamer-1.0/libgstvideo4linux2.so
  Version                  1.16.3
  License                  LGPL
  Source module            gst-plugins-good
  Binary package           GStreamer Good Plug-ins source release
  Origin URL               Unknown package origin

  v4l2src: Video (video4linux2) Source
  v4l2sink: Video (video4linux2) Sink
  v4l2radio: Radio (video4linux2) Tuner
  v4l2deviceprovider: Video (video4linux2) Device Provider
  v4l2jpegdec: V4L2 JPEG Decoder
  v4l2mpeg4dec: V4L2 MPEG4 Decoder
  v4l2video26mpeg4dec: V4L2 MPEG4 Decoder
  v4l2h264dec: V4L2 H264 Decoder
  v4l2h265dec: V4L2 H265 Decoder
  v4l2vp9dec: V4L2 VP9 Decoder
  
  10 features:
  +-- 9 elements
  +-- 1 device providers
增加log输出v4l2dec注册的type_name
+GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
+#define GST_CAT_DEFAULT v4l2_debug
+
 void
 gst_v4l2_video_dec_register (GstPlugin * plugin, const gchar * basename,
     const gchar * device_path, GstCaps * sink_caps, GstCaps * src_caps)
@@ -1210,6 +1214,7 @@ gst_v4l2_video_dec_register (GstPlugin * plugin, const gchar * basename,
     GType type, subtype;
     gchar *type_name;
 
+    
     s = gst_caps_get_structure (sink_caps, i);
 
     cdata = g_new0 (GstV4l2VideoDecCData, 1);
@@ -1222,7 +1227,7 @@ gst_v4l2_video_dec_register (GstPlugin * plugin, const gchar * basename,
     gst_caps_set_features_simple(cdata->src_caps, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_DMABUF));
     gst_caps_append(cdata->src_caps, gst_caps_copy (src_caps));
     type_name = gst_v4l2_video_dec_set_metadata (s, cdata, basename);
-
+    GST_CAT_WARNING (GST_CAT_DEFAULT, "shizh: type_name: %s, caps size: %d", type_name, gst_caps_get_size (sink_caps));

去掉mpeg4的caps
v4l2 gstv4l2videodec.c:1230:gst_v4l2_video_dec_register: type_name: v4l2jpegdec, caps size: 5
v4l2 gstv4l2videodec.c:1230:gst_v4l2_video_dec_register: type_name: v4l2mpeg4dec, caps size: 5
v4l2 gstv4l2videodec.c:1230:gst_v4l2_video_dec_register: type_name: v4l2h264dec, caps size: 5
v4l2 gstv4l2videodec.c:1230:gst_v4l2_video_dec_register: type_name: v4l2h265dec, caps size: 5
v4l2 gstv4l2videodec.c:1230:gst_v4l2_video_dec_register: type_name: v4l2vp9dec, caps size: 5

所以通过ENABLE_MPEG4PART2去掉mpeg4的caps是可行的:

#ifdef ENABLE_MPEG4PART2
      structure = gst_structure_new ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, "systemstream",
          G_TYPE_BOOLEAN, FALSE, NULL);
#endif
v4l2video26mpeg4dec的出处

因为g_type_from_name通过mpeg4的name去取,发现已经有了,所以又用basename和codec_name组合了一个新的name,basename为video26。codec_name为mpeg4,即新的名字v4l2+video26+mpeg4dec,就是v4l2video26mpeg4dec,去掉mpeg4的caps之后,就不会有v4l2video26mpeg4dec。

  if (codec_name) {
    type_name = g_strdup_printf ("v4l2%sdec", codec_name);
    if (g_type_from_name (type_name) != 0) {
      g_free (type_name);
      GST_WARNING ("plugin codec name: v4l2 %s %s dec'", basename, codec_name);
      type_name = g_strdup_printf ("v4l2%s%sdec", basename, codec_name);
    }

加上前面的log会输出:

gst_v4l2_video_dec_set_metadata: plugin codec name: v4l2 video26 mpeg4 dec'
mpeg1和mpeg2

V4L2_PIX_FMT_MPEG1和V4L2_PIX_FMT_MPEG2应该merge caps的时候被merge到一块了:

    case V4L2_PIX_FMT_MPEG1:
      structure = gst_structure_new ("video/mpeg",
          "mpegversion", G_TYPE_INT, 1, NULL);
      break;
    case V4L2_PIX_FMT_MPEG2:
      structure = gst_structure_new ("video/mpeg",
          "mpegversion", G_TYPE_INT, 2, NULL);
v4l2通过ioctl查询format信息

在gst-plugins-good/sys/v4l2/gstv4l2.c的gst_v4l2_probe_template_caps函数中,通过ioctl调用得到format:

    if (ioctl (video_fd, VIDIOC_ENUM_FMT, &format) < 0)
      break;                    /* end of enumeration */

    GST_LOG ("index:       %u", format.index);
    GST_LOG ("type:        %d", format.type);
    GST_LOG ("flags:       %08x", format.flags);
    GST_LOG ("description: '%s'", format.description);
    GST_LOG ("pixelformat: %" GST_FOURCC_FORMAT,
        GST_FOURCC_ARGS (format.pixelformat));

输出log如下:

v4l2 gstv4l2.c:75:gst_v4l2_probe_template_caps: Getting /dev/video26 format enumerations
v4l2 gstv4l2.c:75:gst_v4l2_probe_template_caps: Getting /dev/video26 format enumerations
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       0
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'H.264'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: H264
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       1
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'HEVC'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: HEVC
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       2
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'VP9'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: VP90
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       3
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'MPEG-1 ES'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: MPG1
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       4
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'MPEG-2 ES'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: MPG2
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       5
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'MPEG-4 Part 2 ES'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: MPG4
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       6
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'Motion-JPEG'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: MJPG
v4l2 gstv4l2.c:89:gst_v4l2_probe_template_caps: index:       7
v4l2 gstv4l2.c:90:gst_v4l2_probe_template_caps: type:        10
v4l2 gstv4l2.c:91:gst_v4l2_probe_template_caps: flags:       00000001
v4l2 gstv4l2.c:92:gst_v4l2_probe_template_caps: description: 'AV1'
v4l2 gstv4l2.c:93:gst_v4l2_probe_template_caps: pixelformat: AV10
v4l2 gstv4l2object.c:1573:gst_v4l2_object_v4l2fourcc_to_bare_struct: Unsupported fourcc 0x30315641 AV10

通过v4l2插件播放

GST_DEBUG=v4l2*:5 gst-launch-1.0 filesrc location=/data/hbc9_h264.avi ! avidemux ! h264parse ! v4l2h264dec ! autovideosink

通过property控制

想了下如果通过property控制不可行,因为caps已经关掉了,没法在通过property增加caps,需要重新registry。

void gst_v4l2_object_install_properties_helper (
    GObjectClass * gobject_class, const char *default_device)
{
  g_object_class_install_property (gobject_class, PROP_DEVICE,
      g_param_spec_string ("device", "Device", "Device location",
          default_device, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
      g_param_spec_string ("device-name", "Device name",
          "Name of the device", DEFAULT_PROP_DEVICE_NAME,
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
添加property

在gst-plugins-good/sys/v4l2/gstv4l2object.c中搜索g_object_class_install_property函数,可以参考添加property的代码

  g_object_class_install_property (gobject_class, PROP_FLAGS,
      g_param_spec_flags ("flags", "Flags", "Device type flags",
          GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS,
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

测试播放命令:

 DISABLE_MPEG4_DECODE=1 gst-play-1.0 /data/mpeg4.ts
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值