背景:去掉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 DecoderKlass                    Codec/Decoder/Video/HardwareDescription              Decodes MPEG4 streams via V4L2 APIAuthor                   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 DecoderKlass                    Codec/Decoder/Video/HardwareDescription              Decodes MPEG4 streams via V4L2 APIAuthor                   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 video4linux2GST_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                     video4linux2Description              elements for Video 4 LinuxFilename                 /usr/lib/gstreamer-1.0/libgstvideo4linux2.soVersion                  1.16.3License                  LGPLSource module            gst-plugins-goodBinary package           GStreamer Good Plug-ins source releaseOrigin URL               Unknown package originv4l2src: Video (video4linux2) Sourcev4l2sink: Video (video4linux2) Sinkv4l2radio: Radio (video4linux2) Tunerv4l2deviceprovider: Video (video4linux2) Device Providerv4l2jpegdec: V4L2 JPEG Decoderv4l2mpeg4dec: V4L2 MPEG4 Decoderv4l2video26mpeg4dec: V4L2 MPEG4 Decoderv4l2h264dec: V4L2 H264 Decoderv4l2h265dec: V4L2 H265 Decoderv4l2vp9dec: V4L2 VP9 Decoder10 features:+-- 9 elements+-- 1 device providers

增加log输出v4l2dec注册的type_name

+GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
+#define GST_CAT_DEFAULT v4l2_debug
+voidgst_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_MPEG4PART2structure = 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

去掉v4l2mpeg4dec插件的mpeg4解码能力相关推荐

  1. linux mpeg-4,嵌入式MPEG-4解码系统的设计与实现,嵌入式MPEG-4解码系统,嵌入式Linux,视频码流,P...

    介绍了一种嵌入式高图像质量的MPEC-4视频流解码系统.该系统以嵌入式Linux作为操作系统,采用硬解码方式,把IDE接口设备或网络端口输入的MPEC-4视频码流(ES.PS和TS)转换成PAL/NT ...

  2. WebRTC 中收集音视频编解码能力

    在 WebRTC 中,交互的两端在建立连接过程中,需要通过 ICE 协议,交换各自的音视频编解码能力,如编解码器和编解码器的一些参数配置,并协商出一组配置和参数,用于后续的音视频传输过程. 对于音频, ...

  3. 订阅内容解码失败(非base64码)_【火眼金睛】超强解码能力——邦纳全新ABR系列读码器来袭!...

    点击关注▲ "邦纳",开启智造之旅 邦纳全新ABR系列读码器具有超强的解码能力,两种不同子系列产品,具有多重分辨率和镜头配置.从此读码不再是难题! 产品特点 超强的解码能力使其可以 ...

  4. 英伟达Tesla T4 显卡编解码能力测试

    显卡基本参数: Timestamp : Fri Aug 27 10:04:12 2021 Driver Version : 460.32.03 CUDA Version 11.2 Attached G ...

  5. RK3399实际解码能力测试

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.什么是MPP? 二.开始测试 总结 前言 最近在做一个基于RK3399的项目,要用到硬解码能力.RK3399的硬解 ...

  6. rt1052 usb速率_如何才能赋予RT1052超级视频编解码能力?

    本文导读 Cortex-M7处理器的核心本质为微控制器,却拥有高达600MHz的主频,高密度的512KB TCM SRAM和16MB的高速SDRAM,超快的实时响应,超强处理性能赋予了RT1052视频 ...

  7. nvidia 专业显卡解码能力

    专业显卡问题 p620 解码:有时我们经常遇到专业显卡,专业显卡和非专业显卡在使用opengl 等底层调用时表现不一样,值得注意的是:专业显卡解码能力到了p400 以上才有显著的提升,p620 家族为 ...

  8. 分贝测试软件哪个好 家庭影院,家庭影院DIY攻略 攻略篇 – 5.2 音频解码能力

    ○ 音频解码能力越强,声音越好听. 音频解码,就是将数字音频信号还原成模拟音频信号,但声音看不见摸不着,所以举大家都很熟悉的数码照片为例,可能会更好理解. 数码照片文件越大,图像越真实,比如像素越多. ...

  9. 海思3531DV200-强编解码能力解决方案

    DEC3531D_C是广州英码信息科技有限公司推出的一款以海思Hi3531DV200处理器为核心而设计的编解码一体板.Hi3531DV200内置 ARM Cortex A53 四核@1.15GHz处理 ...

最新文章

  1. 如何做一次有效的绩效考核面谈?
  2. java 查询表 并返回数据_ajax与java前后台传值及数据表查询解决一个bug的问题
  3. jquery 控制CSS属性display 实现元素的显示、隐藏
  4. FFmpeg 4.0版发布
  5. 代码敲慢一点,学得会快一点
  6. python执行命令不阻塞_Python 命令行非阻塞输入
  7. 万里汇WorldFirst支持从PayPal提现美元(实战教程)
  8. 解决 Elasticsearch 查询时 Fielddata is disabled on text fields by default 错误
  9. 使用电脑过程中突然无法复制粘贴了
  10. OpenERP QWeb模板标签笔记
  11. C/C++实现matlab的imfill()函数
  12. 如何在表格里做计算机统计表,(excel怎么做统计表)excel表格如何制作数据表
  13. 计算机输入d为啥返回桌面,电脑进入游戏怎么返回桌面
  14. python字符串两个冒号_Python 数组字符串 冒号 用法
  15. linux CentOS7安装VCS、Verdi、SCL
  16. 音频特效生成与算法 1
  17. 共享经济app开发方案
  18. 东方通中间件弱密码漏洞检测方法
  19. 惊天揭密!一直以来中本聪的发言并非全部真实!
  20. 理光有邮件服务器吗,理光Ricoh设置扫描PDF到PC和邮件教程

热门文章

  1. 基于GAN框架的时间序列异常检测研究综述
  2. 安卓声卡驱动:2.Machine驱动与声卡
  3. jstack -l pid:查看线程状态,使用的垃圾回收算法,死锁检测
  4. 什么是java方法的重载?
  5. 2021年机修钳工(高级)找解析及机修钳工(高级)操作证考试
  6. 趣说西门子的经济型PLC S7-200SMART和S7-1200
  7. 法宣在线积分小程序获取积分数以源码python技巧
  8. 【算法设计与分析】—— n的阶乘问题(eg:求100的阶乘 结果中的所有位数都精确输出)
  9. 电脑运行linux虚拟盘闪退,Linux 系统下启动Android模拟器报错闪退
  10. sed搜索某行在行末追加_Linux的Shell--Sed操作(指定行增加删除内容)