一、概述

​ 因为gstreamer没有提供qnx系统的支持, 因此这里要实现音频和视频的播放,就必须自己实现最终的音视频输出的元件,即sink元件,一开始,我的想法是,可否移植开源的音视频输出库,比如sdl,alsa等等, 但是发现有些麻烦, 反而把事情弄的更复杂了。 最终还是踏踏实实的两个gstreamer的sink元件,用来输出音频和视频。

​ 要编写gstreamer的插件有很多方式, 比如直接“继承”实现GstElementClass和GstElement,使用gst-template工具创建一个插件模板,然后去实现。 我这里使用的另一种方式, 既然是实现sink类型的元件。 那么就直接找gstreamer已有的sink元件作为模板,将他们复制过来,删除原有的接口实现代码,换上自己的实现。

注意, 输出的plugin动态库名称以 libpluginname.so 的形式, 而这个pluginname就是 编写插件时,定义插件的宏GST_PLUGIN_DEFINE 的参数中的name, 如果不匹配,就会出现插件无法是使用,被gstreamer将插件加入黑名单

二、实现QNX audio sink插件

其实gstreamer有sink插件的“基类”:GstAudioSinkClass, 我们要做的就是继承和override一些接口。GstAudioSinkClass的全部接口如下:

struct _GstAudioSinkClass {/**基类,其完成的继承路径是 GSTAudioSinkClass ——> GstAudioBaseSinkClass ——>GstBaseSinkClass ——> GstElementClass ,再向上就是和gobject相关的东西了,这里不涉及 */  GstAudioBaseSinkClass parent_class; /* vtable, 接口定义 *//* open the device with given specs, 打开设备*/gboolean (*open)      (GstAudioSink *sink);/* prepare resources and state to operate with the given specs, 进行prepare操作 */gboolean (*prepare)   (GstAudioSink *sink, GstAudioRingBufferSpec *spec);/* undo anything that was done in prepare(), 回退到prepare之前 */gboolean (*unprepare) (GstAudioSink *sink);/* close the device, 关闭设备 */gboolean (*close)     (GstAudioSink *sink);/* write samples to the device, 向音频设备写数据 */gint     (*write)     (GstAudioSink *sink, gpointer data, guint length);/* get number of frames queued in the device,获取设备队列里面有多少帧没有输出(即缓存) */guint    (*delay)     (GstAudioSink *sink);/* reset the audio device, unblock from a write,重置设备 */void     (*reset)     (GstAudioSink *sink);/*< private >*/gpointer _gst_reserved[GST_PADDING];
};

​ 我这里就是以oss音频 sink插件作为模板,将其源码复制出来,删除基于oss接口实现的 gstreamer audio sink接口的代码,然后再填充自己的代码, 其中 头文件 gstQnxAudioSink.h, 其内容如下:

/* GStreamer* Copyright (C) gu.wen <454727014@qq.com>** gstqnxaudiosink.h: **/#ifndef __GST_QNXAUDIO_H__
#define __GST_QNXAUDIO_H__#include <gst/gst.h>
#include <gst/audio/gstaudiosink.h>
#include <glib/gtypes.h>
#include <sys/asoundlib.h> /** 包含qnx audio接口的头文件 */G_BEGIN_DECLS
/** 定义方面操作的工具宏 */
#define GST_TYPE_QNXAUDIOSINK (gst_qnxaudio_sink_get_type())#define GST_QNXAUDIOSINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \GST_TYPE_QNXAUDIOSINK, \GstQnxAudioSink))#define GST_QNXAUDIOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \GST_TYPE_QNXAUDIOSINK, \GstQnxAudioSinkClass))#define GST_IS_QNXAUDIOSINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \GST_TYPE_QNXAUDIOSINK))#define GST_IS_QNXAUDIOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \GST_TYPE_QNXAUDIOSINK))typedef struct _GstQnxAudioSink GstQnxAudioSink;
typedef struct _GstQnxAudioSinkClass GstQnxAudioSinkClass;struct _GstQnxAudioSink
{GstAudioSink sink; /** 继承audio sink, 这个成员变量必须放在首位 */gchar *device;  /** qnx audio 设备节点的路径 */gint audioCard; /** 声卡id */gint bytes_per_sample; GstCaps *probed_caps;  /** 存放检索到的caps信息 *//** qnx audio 相关的 数据结构 */snd_pcm_info_t info; snd_pcm_t *pcm_handle;snd_pcm_channel_info_t channelInfo;snd_mixer_t *mixer_handle;snd_mixer_group_t mixerGroup;snd_pcm_channel_params_t channelParam;snd_pcm_channel_setup_t channelSetup;
};struct _GstQnxAudioSinkClass
{/**类,用于定义接口,其完成的继承路径是 * _GstQnxAudioSinkClass ——> GSTAudioSinkClass ——> GstAudioBaseSinkClass * ——> GstBaseSinkClass ——> GstElementClass* 再向上就是和gobject相关的东西了,这里不涉及 */GstAudioSinkClass parent_class;
};/** 获取GType,具体的参考 gobject/glib相关的信息 */
GType gst_qnxaudio_sink_get_type(void);G_END_DECLS#endif /* __GST_QNXAUDIO_H__ */

接下来再试重点, qnx audio sink 的实现源文件, 如下所示:

/* GStreamer* Copyright (C) gu.wen <454727014@qq.com>** gstqnxaudiosink.c: **//*** SECTION:element-qnxaudio** This element lets you output sound using the qnx audio system (QNXAUDIO).** Note that you should almost always use generic audio conversion elements* like audioconvert and audioresample in front of an audiosink to make sure* your pipeline works under all circumstances (those conversion elements will* act in passthrough-mode if no conversion is necessary).** <refsect2>* <title>Example pipelines</title>* |[* gst-launch-1.0 -v audiotestsrc ! audioconvert ! volume volume=0.1 ! qnxaudio* ]| will output a sine wave (continuous beep sound) to your sound card (with* a very low volume as precaution).* |[* gst-launch-1.0 -v filesrc location=music.ogg ! decodebin ! audioconvert ! * audioresample ! qnxaudio ]| * will play an Ogg/Vorbis audio file and output it using the Open Sound System.* </refsect2>*/#ifdef HAVE_CONFIG_H
#include "config.h"
#endif#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>#include "gstQnxAudioSink.h"#define PLUGIN_VERSION "00.01.00"
#define PACKAGE "gst-plugins-qnx"
#define GST_LICENSE "LGPL"
#define GST_PACKAGE_NAME "GStreamer qnx Plug-ins source release"
#define GST_PACKAGE_ORIGIN "Unknown package origin"GST_DEBUG_CATEGORY_EXTERN(qnxaudio_debug);
#define GST_CAT_DEFAULT qnxaudio_debugstatic void gst_qnxaudio_sink_dispose(GObject *object);
static void gst_qnxaudio_sink_finalise(GObject *object);static void gst_qnxaudio_sink_get_property(GObject *object, guint prop_id,GValue *value, GParamSpec *pspec);static void gst_qnxaudio_sink_set_property(GObject *object, guint prop_id,const GValue *value, GParamSpec *pspec);static GstCaps *gst_qnxaudio_sink_getcaps(GstBaseSink *bsink, GstCaps *filter);static gboolean gst_qnxaudio_sink_open(GstAudioSink *asink);
static gboolean gst_qnxaudio_sink_close(GstAudioSink *asink);
static gboolean gst_qnxaudio_sink_prepare(GstAudioSink *asink,GstAudioRingBufferSpec *spec);
static gboolean gst_qnxaudio_sink_unprepare(GstAudioSink *asink);
static gint gst_qnxaudio_sink_write(GstAudioSink *asink, gpointer data,guint length);
static guint gst_qnxaudio_sink_delay(GstAudioSink *asink);
static void gst_qnxaudio_sink_reset(GstAudioSink *asink);/* QnxAudioSink signals and args */
enum
{LAST_SIGNAL
};#define DEFAULT_DEVICE "/dev/snd/pcmPreferredp"enum
{PROP_0,PROP_DEVICE,
};#define FORMATS "{" GST_AUDIO_NE(S16) "," GST_AUDIO_NE(U16) ", S8, U8 }"/** 定义 固定pad的工厂 */
static GstStaticPadTemplate qnxaudio_sink_factory =GST_STATIC_PAD_TEMPLATE("sink",GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS("audio/x-raw, ""format = (string) " FORMATS ", ""layout = (string) interleaved, ""rate = (int) [ 1, MAX ], ""channels = (int) 1; ""audio/x-raw, ""format = (string) " FORMATS ", ""layout = (string) interleaved, ""rate = (int) [ 1, MAX ], ""channels = (int) 2, ""channel-mask = (bitmask) 0x3"));/* static guint gst_qnxaudio_sink_signals[LAST_SIGNAL] = { 0 }; */#define gst_qnxaudio_sink_parent_class parent_classG_DEFINE_TYPE(GstQnxAudioSink, gst_qnxaudio_sink, GST_TYPE_AUDIO_SINK);static void gst_qnxaudio_sink_dispose(GObject *object)
{   /** override GObjectClass 的dispose接口 */GstQnxAudioSink *qnxaudio = GST_QNXAUDIOSINK(object);if (qnxaudio->probed_caps){/**如果已经索引过qnx audio sink 的能力, 就是放已有的caps信息 */gst_caps_unref(qnxaudio->probed_caps);qnxaudio->probed_caps = NULL;}/** 再调用父类的dispose接口 */G_OBJECT_CLASS(parent_class)->dispose(object);
}static GstStructure *
gst_qnxaudio_helper_get_format_structure(unsigned int format_bit)
{/** 根据qnx audio的类型生成caps信息的结构体 */GstStructure *structure;//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);const gchar *format;switch (format_bit){case SND_PCM_SFMT_U8:format = "U8";break;case SND_PCM_SFMT_S16_LE:format = "S16LE";break;case SND_PCM_SFMT_S16_BE:format = "S16BE";break;case SND_PCM_SFMT_S8:format = "S8";break;case SND_PCM_SFMT_U16_LE:format = "U16LE";break;case SND_PCM_SFMT_U16_BE:format = "U16BE";break;default:g_assert_not_reached();//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return NULL;}printf("[%s.%d]===>:format: %s\n", __FUNCTION__, __LINE__, format);structure = gst_structure_new("audio/x-raw","format", G_TYPE_STRING, format,"layout", G_TYPE_STRING, "interleaved", NULL);return structure;
}static GstCaps *
gst_qnxaudio_helper_probe_caps(snd_pcm_channel_info_t *channelInfo)
{/** 索引qnx audio的能力信息 *///printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
#if G_BYTE_ORDER == G_LITTLE_ENDIANconst guint probe_formats[] = {SND_PCM_SFMT_S16_LE, SND_PCM_SFMT_U16_LE, SND_PCM_SFMT_U8, SND_PCM_SFMT_S8};
#elseconst guint probe_formats[] = {SND_PCM_SFMT_S16_BE, SND_PCM_SFMT_U16_BE, SND_PCM_SFMT_U8, SND_PCM_SFMT_S8};
#endifGstStructure *structure;GstCaps *caps;int f;/* FIXME test make sure we're not currently playing *//* FIXME test both mono and stereo */caps = gst_caps_new_empty();/* assume that the most significant bit of format_mask is 0 */for (f = 0; f < G_N_ELEMENTS(probe_formats); ++f){printf("[%s.%d]===>:idx:%d, rate range(%d - %d)\n", __FUNCTION__, __LINE__, f, channelInfo->min_rate, channelInfo->max_rate);GValue rate_value = {0};/* one big range */g_value_init(&rate_value, GST_TYPE_INT_RANGE);gst_value_set_int_range(&rate_value, channelInfo->min_rate,(channelInfo->max_rate == -1) ? channelInfo->min_rate : channelInfo->max_rate);structure = gst_qnxaudio_helper_get_format_structure(probe_formats[f]);gst_structure_set(structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);gst_structure_set_value(structure, "rate", &rate_value);g_value_unset(&rate_value);gst_caps_append_structure(caps, structure);}if (gst_caps_is_empty(caps)){/* fixme: make user-visible */GST_WARNING("Your qnx audio device could not be probed correctly");}else{caps = gst_caps_simplify(caps);}printf("[%s.%d]===>:probed caps: %p\n", __FUNCTION__, __LINE__, caps);GST_DEBUG("probed caps: %" GST_PTR_FORMAT, caps);return caps;
}static void gst_qnxaudio_sink_class_init(GstQnxAudioSinkClass *klass)
{/** 类初始化接口 *///printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);GObjectClass *gobject_class;GstElementClass *gstelement_class;GstBaseSinkClass *gstbasesink_class;GstAudioSinkClass *gstaudiosink_class;gobject_class = (GObjectClass *)klass;gstelement_class = (GstElementClass *)klass;gstbasesink_class = (GstBaseSinkClass *)klass;gstaudiosink_class = (GstAudioSinkClass *)klass;parent_class = g_type_class_peek_parent(klass);/** override 父类接口 */gobject_class->dispose = gst_qnxaudio_sink_dispose;gobject_class->finalize = gst_qnxaudio_sink_finalise;gobject_class->get_property = gst_qnxaudio_sink_get_property;gobject_class->set_property = gst_qnxaudio_sink_set_property;/** 安装属性接口 */g_object_class_install_property(gobject_class, PROP_DEVICE,g_param_spec_string("device", "Device","QNXAUDIO device (usually /dev/dspN)", DEFAULT_DEVICE,G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));/** override 父类接口 */gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_getcaps);gstaudiosink_class->open = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_open);gstaudiosink_class->close = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_close);gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_prepare);gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_unprepare);gstaudiosink_class->write = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_write);gstaudiosink_class->delay = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_delay);gstaudiosink_class->reset = GST_DEBUG_FUNCPTR(gst_qnxaudio_sink_reset);/** 设置qnx  audio sink 元件的meta信息 */gst_element_class_set_static_metadata(gstelement_class, "Audio Sink (QNXAUDIO)","Sink/Audio","Output to a sound card via QNXAUDIO","guwen <454727014@qq.com>");/** 添加固定pad工厂 */gst_element_class_add_static_pad_template(gstelement_class,&qnxaudio_sink_factory);//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);                                              
}static void gst_qnxaudio_sink_init(GstQnxAudioSink *qnxaudio)
{/** qnx audio sink数据结构初始化 */GST_DEBUG_OBJECT(qnxaudio, "initializing qnxaudio");//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);qnxaudio->pcm_handle = NULL;qnxaudio->mixer_handle = NULL;qnxaudio->audioCard = -1;qnxaudio->probed_caps = NULL;qnxaudio->device = strdup(DEFAULT_DEVICE);memset(&qnxaudio->channelInfo, 0, sizeof(qnxaudio->channelInfo));memset(&qnxaudio->channelParam, 0, sizeof(qnxaudio->channelParam));memset(&qnxaudio->channelSetup, 0, sizeof(qnxaudio->channelSetup));memset(&qnxaudio->mixerGroup, 0, sizeof(qnxaudio->mixerGroup));//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
}static void gst_qnxaudio_sink_finalise(GObject *object)
{/** override finalise接口 *///printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);GstQnxAudioSink *qnxaudio = GST_QNXAUDIOSINK(object);g_free(qnxaudio->device);G_OBJECT_CLASS(parent_class)->finalize((GObject *)(object));
}static void 
gst_qnxaudio_sink_set_property(GObject *object, guint prop_id,const GValue *value, GParamSpec *pspec)
{/** 设置属性 *///printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);GstQnxAudioSink *sink;sink = GST_QNXAUDIOSINK(object);switch (prop_id){case PROP_DEVICE://printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);g_free(sink->device);sink->device = g_value_dup_string(value);if (sink->probed_caps){gst_caps_unref(sink->probed_caps);sink->probed_caps = NULL;}break;default:G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);break;}
}static void gst_qnxaudio_sink_get_property(GObject *object, guint prop_id,GValue *value, GParamSpec *pspec)
{GstQnxAudioSink *sink;//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);sink = GST_QNXAUDIOSINK(object);switch (prop_id){case PROP_DEVICE:g_value_set_string(value, sink->device);break;default:G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);break;}
}static GstCaps *gst_qnxaudio_sink_getcaps(GstBaseSink *bsink, GstCaps *filter)
{GstQnxAudioSink *qnxaudio;    GstCaps *caps;qnxaudio = GST_QNXAUDIOSINK(bsink);// printf("[%s.%d]===>:pcm_handle: %p\n", // __FUNCTION__, __LINE__, qnxaudio->pcm_handle);if (qnxaudio->pcm_handle == NULL){////printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);caps = gst_pad_get_pad_template_caps(GST_BASE_SINK_PAD(bsink));}else if (qnxaudio->probed_caps){////printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);caps = gst_caps_ref(qnxaudio->probed_caps);}else{//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);caps = gst_qnxaudio_helper_probe_caps(&qnxaudio->channelInfo);if (caps && !gst_caps_is_empty(caps)){qnxaudio->probed_caps = gst_caps_ref(caps);}}if (filter && caps){//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);GstCaps *intersection;intersection =gst_caps_intersect_full(filter, caps, GST_CAPS_INTERSECT_FIRST);gst_caps_unref(caps);return intersection;}else{////printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return caps;}
}static gint ilog2(gint x)
{/* well... hacker's delight explains... */x = x | (x >> 1);x = x | (x >> 2);x = x | (x >> 4);x = x | (x >> 8);x = x | (x >> 16);x = x - ((x >> 1) & 0x55555555);x = (x & 0x33333333) + ((x >> 2) & 0x33333333);x = (x + (x >> 4)) & 0x0f0f0f0f;x = x + (x >> 8);x = x + (x >> 16);return (x & 0x0000003f) - 1;
}static gint 
gst_qnxaudio_sink_get_format(GstAudioRingBufferFormatType fmt, GstAudioFormat rfmt)
{gint result = -1;switch (fmt){case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:result = SND_PCM_SFMT_MU_LAW;break;case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:result = SND_PCM_SFMT_A_LAW;break;case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IMA_ADPCM:result = SND_PCM_SFMT_IMA_ADPCM;break;case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:result = SND_PCM_SFMT_MPEG;break;case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:{switch (rfmt){case GST_AUDIO_FORMAT_U8:result = SND_PCM_SFMT_U8;break;case GST_AUDIO_FORMAT_S16LE:result = SND_PCM_SFMT_S16_LE;break;case GST_AUDIO_FORMAT_S16BE:result = SND_PCM_SFMT_S16_BE;break;case GST_AUDIO_FORMAT_S8:result = SND_PCM_SFMT_S8;break;case GST_AUDIO_FORMAT_U16LE:result = SND_PCM_SFMT_U16_LE;break;case GST_AUDIO_FORMAT_U16BE:result = SND_PCM_SFMT_U16_BE;break;default:result = -1;break;}break;}default:result = -1;break;}return result;
}static gboolean gst_qnxaudio_sink_open(GstAudioSink *asink)
{//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);GstQnxAudioSink *qnxaudio;qnxaudio = GST_QNXAUDIOSINK(asink);int rtn = snd_pcm_open_name(&qnxaudio->pcm_handle, qnxaudio->device, SND_PCM_OPEN_PLAYBACK);if (rtn == EOK){rtn = snd_pcm_info(qnxaudio->pcm_handle, &qnxaudio->info);if (rtn == 0){qnxaudio->channelInfo.channel = SND_PCM_CHANNEL_PLAYBACK;rtn = snd_pcm_plugin_info(qnxaudio->pcm_handle, &qnxaudio->channelInfo);if (rtn == 0){qnxaudio->audioCard = qnxaudio->info.card;//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;}else{GST_ELEMENT_ERROR(qnxaudio, RESOURCE, OPEN_WRITE, (NULL),("Could not open audio device for playback." "snd_pcm_plugin_info failed: %s\n", snd_strerror(rtn)));}/** todo something */}else{GST_ELEMENT_ERROR(qnxaudio, RESOURCE, OPEN_WRITE,(("Could not open audio device for playback. ""get qnx audio pcm info failedd")),(NULL));}rtn = snd_pcm_close(qnxaudio->pcm_handle);}else{GST_ERROR_OBJECT(qnxaudio, "open qnx audio output device: %s failed\n", qnxaudio->device);/** Errors */if (rtn == -EINVAL){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, OPEN_WRITE,(("Could not open audio device for playback. ""The mode is invalid")),(NULL));}else if (rtn == -ENOENT){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, NOT_FOUND,(("Could not open audio device for playback. ""The named device doesn't exist.")),(NULL));}else if (rtn == -ENOMEM){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, NO_SPACE_LEFT,(("Could not open audio device for playback. ""Not enough memory is available to allocate the""control structures")),(NULL));}else if (rtn == -SND_ERROR_INCOMPATIBLE_VERSION){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, OPEN_WRITE,(("Could not open audio device for playback. ""The audio driver version is incompatible ""with the client library that the application""is using.")),(NULL));}}qnxaudio->pcm_handle = NULL;qnxaudio->mixer_handle = NULL;//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;
}static gboolean gst_qnxaudio_sink_close(GstAudioSink *asink)
{GstQnxAudioSink *qnxaudio;int rtn;qnxaudio = GST_QNXAUDIOSINK(asink);//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);if (qnxaudio->pcm_handle){rtn = snd_pcm_plugin_flush(qnxaudio->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);       }if (qnxaudio->mixer_handle){rtn = snd_mixer_close(qnxaudio->mixer_handle);if (rtn != 0){GST_ERROR_OBJECT(qnxaudio, "close mixer failed: %d\n", rtn);return FALSE;}  qnxaudio->mixer_handle = NULL;      }if (qnxaudio->pcm_handle){rtn = snd_pcm_close(qnxaudio->pcm_handle);if (rtn != 0){GST_ERROR_OBJECT(qnxaudio, "close qnx audio device failed: %d\n", rtn);return FALSE;}qnxaudio->pcm_handle = NULL;        }//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;
}static gboolean 
gst_qnxaudio_sink_prepare(GstAudioSink *asink, GstAudioRingBufferSpec *spec)
{GstQnxAudioSink *qnxaudio;int tmp;guint mSampleBits, mSampleRate, mSampleChannels;gint fragSize;snd_pcm_channel_params_t* pChParam;qnxaudio = GST_QNXAUDIOSINK(asink);//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);tmp = gst_qnxaudio_sink_get_format(spec->type,GST_AUDIO_INFO_FORMAT(&spec->info));if (tmp == -1){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("Unable to get format (%d, %d)", spec->type,GST_AUDIO_INFO_FORMAT(&spec->info)));return FALSE;}mSampleBits = GST_AUDIO_INFO_WIDTH(&spec->info);mSampleRate = GST_AUDIO_INFO_RATE(&spec->info);mSampleChannels = GST_AUDIO_INFO_CHANNELS(&spec->info);if (mSampleBits != 16 && mSampleBits != 8){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("unexpected width %d", mSampleBits));return FALSE;}tmp = ilog2(spec->segsize);tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;GST_DEBUG_OBJECT(qnxaudio, "set segsize: %d, segtotal: %d, value: %08x",spec->segsize, spec->segtotal, tmp);fragSize = 0;pChParam = &qnxaudio->channelParam;pChParam->mode = SND_PCM_MODE_BLOCK;pChParam->channel = SND_PCM_CHANNEL_PLAYBACK;pChParam->start_mode = SND_PCM_START_FULL;pChParam->stop_mode = SND_PCM_STOP_STOP;pChParam->buf.block.frag_size = qnxaudio->channelInfo.max_fragment_size;if (fragSize != -1){pChParam->buf.block.frag_size = fragSize;}pChParam->buf.block.frags_max = -1; //num_frags;pChParam->buf.block.frags_min = 1;pChParam->format.interleave = 1;pChParam->format.rate = mSampleRate;pChParam->format.voices = mSampleChannels;if (mSampleBits == 8){pChParam->format.format = SND_PCM_SFMT_U8;}else if (mSampleBits == 16){pChParam->format.format = SND_PCM_SFMT_S16_LE;}else{pChParam->format.format = SND_PCM_SFMT_S16_LE;}strcpy(pChParam->sw_mixer_subchn_name, "Wave playback channel");tmp = snd_pcm_plugin_params(qnxaudio->pcm_handle, &qnxaudio->channelParam);if (tmp < 0){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("snd_pcm_plugin_params failed: %s\n",snd_strerror(tmp)));return FALSE;}tmp = snd_pcm_plugin_prepare(qnxaudio->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);if (tmp < 0){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("snd_pcm_plugin_prepare failed: %s\n",snd_strerror(tmp)));return FALSE;}qnxaudio->channelSetup.channel = SND_PCM_CHANNEL_PLAYBACK;qnxaudio->channelSetup.mixer_gid = &qnxaudio->mixerGroup.gid;tmp = snd_pcm_plugin_setup(qnxaudio->pcm_handle, &qnxaudio->channelSetup);if (tmp < 0){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("snd_pcm_plugin_setup failed: %s\n",snd_strerror(tmp)));return FALSE;}GST_INFO_OBJECT(qnxaudio, "Format %s \n", snd_pcm_get_format_name(qnxaudio->channelSetup.format.format));GST_INFO_OBJECT(qnxaudio, "Frag Size %d \n", qnxaudio->channelSetup.buf.block.frag_size);GST_INFO_OBJECT(qnxaudio, "Total Frags %d \n", qnxaudio->channelSetup.buf.block.frags);GST_INFO_OBJECT(qnxaudio, "Rate %d \n", qnxaudio->channelSetup.format.rate);GST_INFO_OBJECT(qnxaudio, "Voices %d \n", qnxaudio->channelSetup.format.voices);if (qnxaudio->mixerGroup.gid.name[0] == 0){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("Mixer Pcm Group [%s] Not Set \n",qnxaudio->mixerGroup.gid.name));return FALSE;}tmp = snd_mixer_open(&qnxaudio->mixer_handle, qnxaudio->audioCard, qnxaudio->channelSetup.mixer_device);if (tmp < 0){GST_ELEMENT_ERROR(qnxaudio, RESOURCE, SETTINGS, (NULL),("snd_mixer_open failed: %s\n",snd_strerror(tmp)));return FALSE;}spec->segsize = pChParam->buf.block.frag_size;//spec->segtotal = info.fragstotal;qnxaudio->bytes_per_sample = GST_AUDIO_INFO_BPF(&spec->info);GST_DEBUG_OBJECT(qnxaudio, "got segsize: %d, segtotal: %d, value: %08x",spec->segsize, spec->segtotal, tmp);//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;
}static gboolean gst_qnxaudio_sink_unprepare(GstAudioSink *asink)
{//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);if (!gst_qnxaudio_sink_close(asink)){GST_ERROR_OBJECT(asink, "Could not close the audio device");return FALSE;}if (!gst_qnxaudio_sink_open(asink)){GST_ERROR_OBJECT(asink, "Could not reopen the audio device");return FALSE;}//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;
}static gint gst_qnxaudio_sink_write(GstAudioSink *asink, gpointer data, guint length)
{////printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return snd_pcm_plugin_write(GST_QNXAUDIOSINK(asink)->pcm_handle, data, length);
}static guint gst_qnxaudio_sink_delay(GstAudioSink *asink)
{GstQnxAudioSink *qnxaudio;////printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);snd_pcm_channel_status_t status;memset(&status, 0, sizeof(status));status.channel = SND_PCM_CHANNEL_PLAYBACK;qnxaudio = GST_QNXAUDIOSINK(asink);if (snd_pcm_plugin_status(qnxaudio->pcm_handle, &status) < 0){GST_ERROR_OBJECT(asink, "underrun: playback channel status error\n");return 0;}return status.count / qnxaudio->bytes_per_sample;
}static void gst_qnxaudio_sink_reset(GstAudioSink *asink)
{//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);/* There's nothing we can do here really, * 对于qnx audio这里没有实现这个接口 **/
}//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////GST_DEBUG_CATEGORY (qnxaudio_debug);
#define GST_CAT_DEFAULT qnxaudio_debugstatic gboolean
plugin_init (GstPlugin * plugin)
{//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);/** 注册 qnxaudiosink这个元件 */if (!gst_element_register(plugin, "qnxaudiosink", GST_RANK_SECONDARY,GST_TYPE_QNXAUDIOSINK)){return FALSE;}GST_DEBUG_CATEGORY_INIT(qnxaudio_debug, "qnxaudio",0, "QNX audio elements");#ifdef ENABLE_NLSGST_DEBUG("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,LOCALEDIR);bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
#endif /* ENABLE_NLS *///printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;
}GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,GST_VERSION_MINOR,qnxaudio,"Qnx Audio support for GStreamer",plugin_init, PLUGIN_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

三、 实现QNX video sink 插件

和audio sink一样,gstreamer也提供了video sink的“基类”GstVideoSinkClass, 其内容就相对比较简单:

/*** GstVideoSinkClass:* @parent_class: the parent class structure* @show_frame: render a video frame. Maps to #GstBaseSinkClass.render() and*     #GstBaseSinkClass.preroll() vfuncs. Rendering during preroll will be*     suppressed if the #GstVideoSink:show-preroll-frame property is set to*     %FALSE.** The video sink class structure. Derived classes should override the* @show_frame virtual function.*/
struct _GstVideoSinkClass {GstBaseSinkClass parent_class;GstFlowReturn  (*show_frame) (GstVideoSink *video_sink, GstBuffer *buf);/*< private >*/gpointer _gst_reserved[GST_PADDING];
};

一样的参考现有的视频输出元件的模板,定义头文件如下:

/* GStreamer* Copyright (C) gu.wen <454727014@qq.com>** gstqnxvideosink.h: **/#ifndef __GST_QNX_VIDEO_SINK_H__
#define __GST_QNX_VIDEO_SINK_H__#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideosink.h>//for qnx screen api
#include <screen/screen.h>//#include <aalib.h>#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */#define GST_TYPE_QNXVIDEOSINK \(gst_qnxvideo_sink_get_type())
#define GST_QNXVIDEOSINK(obj) \(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_QNXVIDEOSINK, GstQnxVideoSink))
#define GST_QNXVIDEOSINK_CLASS(klass) \(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_QNXVIDEOSINK, GstQnxVideoSinkClass))
#define GST_IS_QNXVIDEOSINK(obj) \(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_QNXVIDEOSINK))
#define GST_IS_QNXVIDEOSINK_CLASS(klass) \(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_QNXVIDEOSINK))typedef struct _GstQnxVideoSink GstQnxVideoSink;typedef struct _GstQnxVideoSinkClass GstQnxVideoSinkClass;struct _GstQnxVideoSink
{/** qnx video sink 继承 自  GstVideoSink */GstVideoSink parent;GstVideoInfo info;gint frames_displayed;guint64 frame_time;screen_context_t screen_ctx;screen_window_t screen_win;gboolean isOpened;screen_buffer_t dispBuf[2];gint dispRect[4]; /** dsiaply rect size */gint startX;gint startY;gint width;gint height;
};struct _GstQnxVideoSinkClass
{/** qnx video sink class 继承自 GstVideoSinkClass */GstVideoSinkClass parent_class;
};GType gst_qnxvideo_sink_get_type(void);#ifdef __cplusplus
}
#endif /* __cplusplus */#endif /* __GST_QNXVIDEOSINKE_H__ */

接下来就是重点,具体的video sink元件的实现,其代码稍微有点多,具体如下所示。

/* GStreamer* Copyright (C) gu.wen <454727014@qq.com>** gstqnxvideosink.c: **//*** SECTION:element-qnxvideosink* @see_also: #GstQnxVideoSink** Displays video on qnx.** <refsect2>* <title>Example launch line</title>* |[* gst-launch-1.0 filesrc location=test.avi ! decodebin ! videoconvert * ! qnxvideosink ]| This pipeline renders a video to ascii art into*  a separate window. |[* gst-launch-1.0 filesrc location=test.avi ! decodebin ! videoconvert * ! qnxvideosink driver=curses ]| * This pipeline renders a video to ascii art into the current terminal.* </refsect2>*/#ifdef HAVE_CONFIG_H
#include "config.h"
#endif#include <string.h>
#include <sys/time.h>#include <gst/video/gstvideometa.h>
#include "gstQnxVideoSink.h"///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////#define PLUGIN_VERSION "00.01.00"
#define PACKAGE "gst-plugins-qnx"
#define GST_LICENSE "LGPL"
#define GST_PACKAGE_NAME "GStreamer qnx Plug-ins source release"
#define GST_PACKAGE_ORIGIN "Unknown package origin"#define GST_DEFAULT_FRAME_BUF_CNT 4
#define GST_DISP_BUF_CNT 4
#define GST_DISP_USAGE SCREEN_USAGE_NATIVE|SCREEN_USAGE_WRITE
/* qnxvideosink signals and args */
enum
{LAST_SIGNAL
};enum
{PROP_0,PROP_WIDTH,PROP_HEIGHT,
#if 0PROP_DRIVER,PROP_DITHER,PROP_BRIGHTNESS,PROP_CONTRAST,PROP_GAMMA,PROP_INVERSION,PROP_RANDOMVAL,
#endifPROP_FRAMES_DISPLAYED,PROP_FRAME_TIME
};static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS(GST_VIDEO_CAPS_MAKE("NV12")));static GstCaps *gst_qnxvideo_sink_fixate(GstBaseSink *bsink, GstCaps *caps);
static gboolean gst_qnxvideo_sink_setcaps(GstBaseSink *bsink, GstCaps *caps);
static void gst_qnxvideo_sink_get_times(GstBaseSink *bsink, GstBuffer *buffer,GstClockTime *start, GstClockTime *end);static gboolean gst_qnxvideo_sink_propose_allocation(GstBaseSink *bsink,GstQuery *query);
static GstFlowReturn gst_qnxvideo_sink_show_frame(GstVideoSink *videosink,GstBuffer *buffer);static void gst_qnxvideo_sink_set_property(GObject *object, guint prop_id,const GValue *value, GParamSpec *pspec);static void gst_qnxvideo_sink_get_property(GObject *object, guint prop_id,GValue *value, GParamSpec *pspec);static GstStateChangeReturn gst_qnxvideo_sink_change_state(GstElement *element,GstStateChange transition);#define gst_qnxvideo_sink_parent_class parent_class
G_DEFINE_TYPE(GstQnxVideoSink, gst_qnxvideo_sink, GST_TYPE_VIDEO_SINK);#if 0
#define GST_TYPE_QNXVIDEODRIVERS (gst_qnxvideo_sink_drivers_get_type())
static GType gst_qnxvideo_sink_drivers_get_type(void)
{static GType driver_type = 0;if (!driver_type){GEnumValue *drivers;const struct aa_driver *driver;gint n_drivers;gint i;for (n_drivers = 0; aa_drivers[n_drivers]; n_drivers++){/* count number of drivers */}drivers = g_new0(GEnumValue, n_drivers + 1);for (i = 0; i < n_drivers; i++){driver = aa_drivers[i];drivers[i].value = i;drivers[i].value_name = g_strdup(driver->name);drivers[i].value_nick = g_utf8_strdown(driver->shortname, -1);}drivers[i].value = 0;drivers[i].value_name = NULL;drivers[i].value_nick = NULL;driver_type = g_enum_register_static("GstQnxVideoSinkDrivers", drivers);}return driver_type;
}#define GST_TYPE_AADITHER (gst_qnxvideo_sink_dither_get_type())
static GType gst_qnxvideo_sink_dither_get_type(void)
{static GType dither_type = 0;if (!dither_type){GEnumValue *ditherers;gint n_ditherers;gint i;for (n_ditherers = 0; aa_dithernames[n_ditherers]; n_ditherers++){/* count number of ditherers */}ditherers = g_new0(GEnumValue, n_ditherers + 1);for (i = 0; i < n_ditherers; i++){ditherers[i].value = i;ditherers[i].value_name = g_strdup(aa_dithernames[i]);ditherers[i].value_nick =g_strdelimit(g_strdup(aa_dithernames[i]), " _", '-');}ditherers[i].value = 0;ditherers[i].value_name = NULL;ditherers[i].value_nick = NULL;dither_type = g_enum_register_static("GstQnxVideoSinkDitherers", ditherers);}return dither_type;
}
#endifstatic void gst_qnxvideo_sink_class_init(GstQnxVideoSinkClass *klass)
{GObjectClass *gobject_class;GstElementClass *gstelement_class;GstBaseSinkClass *gstbasesink_class;GstVideoSinkClass *gstvideosink_class;printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);gobject_class = (GObjectClass *)klass;gstelement_class = (GstElementClass *)klass;gstbasesink_class = (GstBaseSinkClass *)klass;gstvideosink_class = (GstVideoSinkClass *)klass;gobject_class->set_property = gst_qnxvideo_sink_set_property;gobject_class->get_property = gst_qnxvideo_sink_get_property;/* FIXME: add long property descriptions */g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_WIDTH,g_param_spec_int("width", "width", "width", G_MININT, G_MAXINT, 0,G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_HEIGHT,g_param_spec_int("height", "height", "height", G_MININT, G_MAXINT, 0,G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#if 0  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DRIVER,g_param_spec_enum ("driver", "driver", "driver", GST_TYPE_QNXVIDEODRIVERS, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DITHER,g_param_spec_enum ("dither", "dither", "dither", GST_TYPE_AADITHER, 0,G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BRIGHTNESS,g_param_spec_int ("brightness", "brightness", "brightness", G_MININT,G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CONTRAST,g_param_spec_int ("contrast", "contrast", "contrast", G_MININT, G_MAXINT,0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GAMMA,g_param_spec_float ("gamma", "gamma", "gamma", 0.0, 5.0, 1.0,G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERSION,g_param_spec_boolean ("inversion", "inversion", "inversion", TRUE,G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_RANDOMVAL,g_param_spec_int ("randomval", "randomval", "randomval", G_MININT,G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));g_object_class_install_property(G_OBJECT_CLASS(klass),PROP_FRAMES_DISPLAYED, g_param_spec_int("frames-displayed", "frames displayed", "frames displayed", G_MININT, G_MAXINT, 0, G_PARAM_READABLE |G_PARAM_STATIC_STRINGS));g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_FRAME_TIME,g_param_spec_int("frame-time", "frame time", "frame time", G_MININT,G_MAXINT, 0, G_PARAM_READABLE |G_PARAM_STATIC_STRINGS));
#endifgst_element_class_add_static_pad_template(gstelement_class, &sink_template);gst_element_class_set_static_metadata(gstelement_class,"Qnx video sink", "Sink/Video", "An Qnx videosink","guwen <454727014@qq.com>");gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_qnxvideo_sink_change_state);gstbasesink_class->fixate = GST_DEBUG_FUNCPTR(gst_qnxvideo_sink_fixate);gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_qnxvideo_sink_setcaps);gstbasesink_class->get_times = GST_DEBUG_FUNCPTR(gst_qnxvideo_sink_get_times);gstbasesink_class->propose_allocation =GST_DEBUG_FUNCPTR(gst_qnxvideo_sink_propose_allocation);gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR(gst_qnxvideo_sink_show_frame);printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
}static GstCaps* gst_qnxvideo_sink_fixate(GstBaseSink *bsink, GstCaps *caps)
{GstStructure *structure;printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);caps = gst_caps_make_writable(caps);structure = gst_caps_get_structure(caps, 0);gst_structure_fixate_field_nearest_int(structure, "width", 1920);gst_structure_fixate_field_nearest_int(structure, "height", 720);gst_structure_fixate_field_nearest_fraction(structure, "framerate", 30, 1);caps = GST_BASE_SINK_CLASS(parent_class)->fixate(bsink, caps);printf("[%s.%d]===>:caps: %p\n", __FUNCTION__, __LINE__, caps);return caps;
}static gboolean gst_qnxvideo_sink_setcaps(GstBaseSink *basesink, GstCaps *caps)
{GstQnxVideoSink *qnxvideosink;GstVideoInfo info;printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);qnxvideosink = GST_QNXVIDEOSINK(basesink);if (!gst_video_info_from_caps(&info, caps))goto invalid_caps;qnxvideosink->info = info;qnxvideosink->width = info.width;qnxvideosink->height = info.height;printf("[%s.%d]===>:witdh: %d, height:%d\n", __FUNCTION__, __LINE__, info.width, info.height);if (qnxvideosink->screen_win){memset(&(qnxvideosink->dispRect), 0, sizeof(qnxvideosink->dispRect));qnxvideosink->dispRect[2] = qnxvideosink->width;qnxvideosink->dispRect[3] = qnxvideosink->height;screen_create_window_buffers(qnxvideosink->screen_win, GST_DISP_BUF_CNT);//screen_get_window_property_iv(qnxvideosink->screen_win,//                              SCREEN_PROPERTY_BUFFER_SIZE,//                              qnxvideosink->dispRect + 2);screen_set_window_property_iv(qnxvideosink->screen_win, SCREEN_PROPERTY_SIZE, qnxvideosink->dispRect + 2);screen_set_window_property_iv(qnxvideosink->screen_win, SCREEN_PROPERTY_BUFFER_SIZE, qnxvideosink->dispRect + 2);}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;/* ERRORS */
invalid_caps:
{GST_ERROR_OBJECT(qnxvideosink, "invalid caps");printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;
}
}static void
gst_qnxvideo_sink_init(GstQnxVideoSink *qnxvideosink)
{
#if 0    memcpy(&qnxvideosink->ascii_surf, &aa_defparams,sizeof(struct aa_hardware_params));qnxvideosink->ascii_parms.bright = 0;qnxvideosink->ascii_parms.contrast = 16;qnxvideosink->ascii_parms.gamma = 1.0;qnxvideosink->ascii_parms.dither = 0;qnxvideosink->ascii_parms.inversion = 0;qnxvideosink->ascii_parms.randomval = 0;qnxvideosink->aa_driver = 0;
#elseprintf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);qnxvideosink->screen_win = NULL;qnxvideosink->screen_ctx = NULL;qnxvideosink->isOpened = FALSE;memset(&(qnxvideosink->dispRect), 0, sizeof(qnxvideosink->dispRect));printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
#endif
}static void gst_qnxvideo_sink_scale(GstQnxVideoSink *qnxvideosink, guchar *src, guchar *dest,gint sw, gint sh, gint ss, gint dw, gint dh)
{gint ypos, yinc, y;gint xpos, xinc, x;g_return_if_fail((dw != 0) && (dh != 0));ypos = 0x10000;yinc = (sh << 16) / dh;xinc = (sw << 16) / dw;for (y = dh; y; y--){while (ypos > 0x10000){ypos -= 0x10000;src += ss;}xpos = 0x10000;{guchar *destp = dest;guchar *srcp = src;for (x = dw; x; x--){while (xpos >= 0x10000L){srcp++;xpos -= 0x10000L;}*destp++ = *srcp;xpos += xinc;}}dest += dw;ypos += yinc;}
}static void
gst_qnxvideo_sink_get_times(GstBaseSink *sink, GstBuffer *buffer,GstClockTime *start, GstClockTime *end)
{//printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);*start = GST_BUFFER_TIMESTAMP(buffer);if (GST_BUFFER_DURATION_IS_VALID(buffer))*end = *start + GST_BUFFER_DURATION(buffer);
}static gboolean gst_qnxvideo_sink_propose_allocation(GstBaseSink *bsink, GstQuery *query)
{GstCaps *caps;GstVideoInfo info;guint size;printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);gst_query_parse_allocation(query, &caps, NULL);if (caps == NULL)goto no_caps;if (!gst_video_info_from_caps(&info, caps))goto invalid_caps;size = GST_VIDEO_INFO_SIZE(&info);/* we need at least 2 buffer because we hold on to the last one */gst_query_add_allocation_pool(query, NULL, size, GST_DEFAULT_FRAME_BUF_CNT, 0);/* we support various metadata */gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;/* ERRORS */
no_caps:
{GST_ERROR_OBJECT(bsink, "no caps specified");printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;
}
invalid_caps:
{GST_ERROR_OBJECT(bsink, "invalid caps specified");printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;
}
}static GstFlowReturn gst_qnxvideo_sink_show_frame(GstVideoSink *videosink, GstBuffer *buffer)
{GstQnxVideoSink *qnxvideosink;GstVideoFrame frame;//  printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);qnxvideosink = GST_QNXVIDEOSINK(videosink);GST_DEBUG("show frame");if (!gst_video_frame_map(&frame, &qnxvideosink->info, buffer, GST_MAP_READ))goto invalid_frame;#if 0screen_pixmap_t pixmapInfo;screen_create_pixmap(&pixmapInfo, qnxvideosink->screen_ctx);int format = SCREEN_FORMAT_NV12;screen_set_pixmap_property_iv(pixmapInfo, SCREEN_PROPERTY_FORMAT, &format);gint usage = SCREEN_USAGE_WRITE | SCREEN_USAGE_NATIVE;screen_set_pixmap_property_iv(pixmapInfo, SCREEN_PROPERTY_USAGE, &usage);int size[2] = { qnxvideosink->width, qnxvideosink->height };screen_set_pixmap_property_iv(pixmapInfo, SCREEN_PROPERTY_BUFFER_SIZE, size);screen_buffer_t pixmapBuf;screen_create_pixmap_buffer(pixmapInfo);screen_get_pixmap_property_pv(pixmapInfo, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&pixmapBuf);unsigned char *pBuf = NULL;screen_get_buffer_property_pv(pixmapBuf, SCREEN_PROPERTY_POINTER, (void **)&pBuf);int stride = 0;screen_get_buffer_property_iv(pixmapBuf, SCREEN_PROPERTY_STRIDE, &stride);
#if 0for (i = 0; i < size[1]; i++, ptr += stride) {for (j = 0; j < size[0]; j++) {ptr[j*4] = 0xa0;ptr[j*4+1] = 0xa0;ptr[j*4+2] = 0xa0;ptr[j*4+3] = ((j >= i && j <= size[1]-i) || (j <= i && j >= size[1]-i)) ? 0xff : 0;}}
#endif#if 0gst_qnxvideo_sink_scale(qnxvideosink, GST_VIDEO_FRAME_PLANE_DATA(&frame, 0), /* src */pBuf,                     /* dest */GST_VIDEO_INFO_WIDTH(&qnxvideosink->info),  /* sw */GST_VIDEO_INFO_HEIGHT(&qnxvideosink->info), /* sh */GST_VIDEO_FRAME_PLANE_STRIDE(&frame, 0),    /* ss */qnxvideosink->width,                  /* dw */qnxvideosink->height);                /* dh */#elsememcpy(pBuf, GST_VIDEO_FRAME_PLANE_DATA(&frame, 0), qnxvideosink->width * qnxvideosink->height * 3 / 2);
#endifscreen_buffer_t render_buf[2];screen_get_window_property_pv(qnxvideosink->screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)render_buf);int hg[] = {SCREEN_BLIT_SOURCE_WIDTH, qnxvideosink->width,SCREEN_BLIT_SOURCE_HEIGHT, qnxvideosink->height,SCREEN_BLIT_DESTINATION_X, 0,SCREEN_BLIT_DESTINATION_Y, 0,SCREEN_BLIT_DESTINATION_WIDTH, qnxvideosink->width,SCREEN_BLIT_DESTINATION_HEIGHT, qnxvideosink->height,SCREEN_BLIT_TRANSPARENCY, SCREEN_TRANSPARENCY_SOURCE_OVER,SCREEN_BLIT_END};screen_blit(qnxvideosink->screen_ctx, render_buf[0], pixmapBuf, hg);screen_post_window(qnxvideosink->screen_win, render_buf[0], 1, qnxvideosink->dispRect, 0);    screen_destroy_pixmap(pixmapInfo);
#elsescreen_buffer_t render_buf[GST_DISP_BUF_CNT];screen_get_window_property_pv(qnxvideosink->screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&render_buf);   char *pBuf = NULL;screen_get_buffer_property_pv(render_buf[0], SCREEN_PROPERTY_POINTER, (void **)&pBuf); memcpy(pBuf, GST_VIDEO_FRAME_PLANE_DATA(&frame, 0), qnxvideosink->width * qnxvideosink->height * 3 / 2);screen_post_window(qnxvideosink->screen_win, render_buf[0], 1, qnxvideosink->dispRect, 0);
#endifgst_video_frame_unmap(&frame);qnxvideosink->frames_displayed++;//  printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return GST_FLOW_OK;/* ERRORS */
invalid_frame:
{GST_ERROR_OBJECT(qnxvideosink, "invalid frame");printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return GST_FLOW_ERROR;
}
}static void
gst_qnxvideo_sink_set_property(GObject *object, guint prop_id, const GValue *value,GParamSpec *pspec)
{GstQnxVideoSink *qnxvideosink;printf("[%s.%d]===>: prop_id:%d\n", __FUNCTION__, __LINE__, prop_id);qnxvideosink = GST_QNXVIDEOSINK(object);switch (prop_id){case PROP_WIDTH:qnxvideosink->width = g_value_get_int(value);break;case PROP_HEIGHT:qnxvideosink->height = g_value_get_int(value);break;
#if 0case PROP_DRIVER:{qnxvideosink->aa_driver = g_value_get_enum(value);break;}case PROP_DITHER:{qnxvideosink->ascii_parms.dither = g_value_get_enum(value);break;}case PROP_BRIGHTNESS:{qnxvideosink->ascii_parms.bright = g_value_get_int(value);break;}case PROP_CONTRAST:{qnxvideosink->ascii_parms.contrast = g_value_get_int(value);break;}case PROP_GAMMA:{qnxvideosink->ascii_parms.gamma = g_value_get_float(value);break;}case PROP_INVERSION:{qnxvideosink->ascii_parms.inversion = g_value_get_boolean(value);break;}case PROP_RANDOMVAL:{qnxvideosink->ascii_parms.randomval = g_value_get_int(value);break;}
#endifdefault:break;}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
}static void
gst_qnxvideo_sink_get_property(GObject *object, guint prop_id, GValue *value,GParamSpec *pspec)
{GstQnxVideoSink *qnxvideosink;printf("[%s.%d]===>:, prop_id: %d\n", __FUNCTION__, __LINE__, prop_id);qnxvideosink = GST_QNXVIDEOSINK(object);switch (prop_id){case PROP_WIDTH:{g_value_set_int(value, qnxvideosink->width);break;}case PROP_HEIGHT:{g_value_set_int(value, qnxvideosink->height);break;}
#if 0case PROP_DRIVER:{g_value_set_enum(value, qnxvideosink->aa_driver);break;}case PROP_DITHER:{g_value_set_enum(value, qnxvideosink->ascii_parms.dither);break;}case PROP_BRIGHTNESS:{g_value_set_int(value, qnxvideosink->ascii_parms.bright);break;}case PROP_CONTRAST:{g_value_set_int(value, qnxvideosink->ascii_parms.contrast);break;}case PROP_GAMMA:{g_value_set_float(value, qnxvideosink->ascii_parms.gamma);break;}case PROP_INVERSION:{g_value_set_boolean(value, qnxvideosink->ascii_parms.inversion);break;}case PROP_RANDOMVAL:{g_value_set_int(value, qnxvideosink->ascii_parms.randomval);break;}case PROP_FRAMES_DISPLAYED:{g_value_set_int(value, qnxvideosink->frames_displayed);break;}case PROP_FRAME_TIME:{g_value_set_int(value, qnxvideosink->frame_time / 1000000);break;}
#endifdefault:{G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);break;}}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
}static gboolean
gst_qnxvideo_sink_open(GstQnxVideoSink *qnxvideosink)
{printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);if (qnxvideosink->isOpened == FALSE){screen_create_context(&qnxvideosink->screen_ctx, SCREEN_APPLICATION_CONTEXT);screen_create_window(&qnxvideosink->screen_win, qnxvideosink->screen_ctx);int usage = GST_DISP_USAGE;screen_set_window_property_iv(qnxvideosink->screen_win, SCREEN_PROPERTY_USAGE, &usage);int format = SCREEN_FORMAT_NV12;screen_set_window_property_iv(qnxvideosink->screen_win, SCREEN_PROPERTY_FORMAT, &format);qnxvideosink->isOpened = TRUE;printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;
}static gboolean gst_qnxvideo_sink_close(GstQnxVideoSink *qnxvideosink)
{printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);if (qnxvideosink->isOpened == TRUE){if (qnxvideosink->screen_win){screen_destroy_window(qnxvideosink->screen_win);qnxvideosink->screen_win = NULL;}    if (qnxvideosink->screen_ctx){screen_destroy_context(qnxvideosink->screen_ctx);qnxvideosink->screen_ctx = NULL;    }printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;
}static GstStateChangeReturn
gst_qnxvideo_sink_change_state(GstElement *element, GstStateChange transition)
{printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);GstStateChangeReturn ret;switch (transition){case GST_STATE_CHANGE_NULL_TO_READY:break;case GST_STATE_CHANGE_READY_TO_PAUSED:if (!gst_qnxvideo_sink_open(GST_QNXVIDEOSINK(element)))goto open_failed;break;case GST_STATE_CHANGE_PAUSED_TO_PLAYING:break;default:break;}ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);switch (transition){case GST_STATE_CHANGE_PLAYING_TO_PAUSED:break;case GST_STATE_CHANGE_PAUSED_TO_READY:break;case GST_STATE_CHANGE_READY_TO_NULL:gst_qnxvideo_sink_close(GST_QNXVIDEOSINK(element));break;default:break;}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return ret;open_failed:
{printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return GST_STATE_CHANGE_FAILURE;
}
}static gboolean plugin_init(GstPlugin *plugin)
{printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);if (!gst_element_register(plugin, "qnxvideosink", GST_RANK_SECONDARY, GST_TYPE_QNXVIDEOSINK)){printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return FALSE;}printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);return TRUE;
}GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,GST_VERSION_MINOR,qnxvideo,"Qnx video sink",plugin_init, PLUGIN_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);

注意, 输出的plugin动态库名称以 libpluginname.so 的形式, 而这个pluginname就是 编写插件时,定义插件的宏GST_PLUGIN_DEFINE 的参数中的name, 如果不匹配,就会出现插件无法是使用,被gstreamer将插件加入黑名单

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 蓝桥杯ALGO-148 算法训练 5-1最小公倍数

    蓝桥杯ALGO-148 算法训练 5-1最小公倍数 问题描述编写一函数lcm,求两个正整数的最小公倍数。 样例输入一个满足题目要求的输入范例。例:3 5 样例输出与上面的样例输入对应的输出。15 数据规模和约定输入数据中每一个数的范围。例:两个数都小于65536。 好多都忘记了,记一下…...

    2024/4/28 6:59:25
  2. 山东大学 人机交互复习提纲

    人机交互是关于设计、评价和实现供人们使用的交互式计算机系统,且围绕这些方面主要现象进行研究的科学。人机交互经历了命令行、图形用户界面、自然和谐的交互等三个重要历史发展阶段。完整的人机系统中由人机共同作用来完成如下的功能:信息接受(收集)、信息加工、信息存储…...

    2024/3/29 13:08:28
  3. 解决 reactnative 报错 Error: Failed to load plugin '@react-native-community' declared

    react native 报错 Error: Failed to load plugin @react-native-community declared in .eslintrc.js @react-native-community/eslint-config: Cannot find module @react-native-community/eslint-plugin Require stack:解决:yarn add --dev eslint @react-native-commun…...

    2024/3/29 13:08:29
  4. java-冒泡排序

    一、冒泡排序 基本思想:对比相邻元素值,如果满足条件就交换元素值,把较小(较大)的元素移到数组前面,把大的(小的)元素移动到数组后面,也就是交换两个元素的位置,这样较小的元素就想气泡一样上升到顶部。 二、算法实现(冒泡排序并输出最小元素) public class ButtoS…...

    2024/4/28 13:07:54
  5. C# 面向对象之抽象类抽象方法

    一、抽象类1.1、语法:用abstract修饰类即为抽象类.抽象类中可能包含抽象成员(方法,属性)这些都是共性的【可以为空,可以没有抽象成员,可以有抽象成员】抽象类不能创建对象【不能实例化,不能New】 可以被继承!可以创建数组定义:调用:1.2、语义(了解):抽象类表示一个抽…...

    2024/4/28 7:44:50
  6. Window10下RabbitMQ安装图文教程

    一、erlang下载安装1、下载下载erlang,原因在于RabbitMQ服务端代码是使用并发式语言erlang编写的,下载地址:http://www.erlang.org/downloads,双击.exe文件进行安装就好。百度网盘下载: 链接:https://pan.baidu.com/s/1rOPj2AlxVp1rzEBw7iacGw 密码:9t3j2、安装一直next…...

    2024/3/28 21:14:43
  7. Windows将FRP设置为服务并开机自启

    1.此处需要使用到winsw 下载地址: https://github.com/kohsuke/winsw/releases2.下载解压至任意目录并CD进入;这里将下载WinSw.Net4.exe重命名为winsw.exe了,以方便后面操作;3.创建与winsw同名的配置文件,后缀为xml此处以配置FRP客户端为例:<service><!-- 该服务的唯…...

    2024/4/5 21:15:20
  8. 详解php soap实现web service接口服务

    soap是一种协议,属于web service实现所使用的一种技术规范。 web service的接口实现有两种方式,一种是需要生成wsdl文档的方式,一种是不需要生成wsdl文档的方式。 在实际操作之前,先检查一下自己的环境,是否支持soap,然后修改一下php.ini配置文件,将“soap.wsdl_cache_e…...

    2024/3/29 13:08:21
  9. Unity苹果内购

    Unity内购IAP的二三事Unity端iOS平台进行打包 Unity端 这里需要使用Unity内置的IAP插件,下载IAP插件的方式:Window–>Services–>In-App Purchasing(这个就是unity内置的内购插件),点击把OFF->ON点击之后会有个询问是否是对13岁以下儿童设计的游戏,按照情况勾选,…...

    2024/4/20 5:02:00
  10. 在Hadoop或者Mapreduce 使用压缩或者解压文件的技术研讨

    在Hadoop或者Mapreduce 使用压缩或者解压文件的技术时,都基本会用到CompressionCodecFactory,下面就来浅讨如何使用它。CompressionCodecFactory简介当在读取一个压缩文件的时候,可能并不知道压缩文件用的是哪种压缩算法,那么无法完成解压任务。在Hadoop中,CompressionCod…...

    2024/3/29 7:32:47
  11. 第1期:正向代理和反向代理

    代理只是一种技术,如果在一台服务器上安装了这项技术,则这台服务器就有了代理的功能,它就可以被称为代理服务器。无论是正向代理还是反向代理,它们都是介于客户端和服务端之间的一台服务器。但是由于种种原因,客户端和服务端不能直接通信,例如客户端和服务端的通信链路中…...

    2024/3/29 7:32:46
  12. Spring :Spring Aop 创建代理

    大数据-flinkflink源码专栏九师兄9.90去订阅1.美图2.概述 寻找代理,请参考以前的文章 3.前文概要 /*** Wrap the given bean if necessary, i.e. if it is eligible for being proxied.* @param bean the raw bean instance* @param beanName the name of the bean* @param ca…...

    2024/3/29 7:32:45
  13. 千兆家庭组网方案

    1.前言 这几年网速提升可太快了,当初我刚拥有第一台电脑的时候还是1M网,下一个几百兆的游戏得挂一天才能下完。现在40G的游戏10分钟搞定。目前家里办理的宽带套餐基本都是100M以上,但是很多人都发现自己的网速最多只有9M/S,这是一个很大坑,下面我来介绍一哈如何解决这个问题…...

    2024/3/29 7:32:44
  14. 《惢客创业日记》2019.12.25(周三)传统节日如何浪漫?

    今天的日记说的是昨天的事儿,昨天下班,带着一家人去了市中心的一家相对比较繁华的商场。主要有两个目的,一个是陪家人吃个饭放松一下,另一个是对于中国人过洋节做一个观察和调研,看看有没有联系到惢客的思考点。没想到,所看到的景象却让我大吃一惊。记得往常,虽然从来没…...

    2024/3/29 13:08:20
  15. java.util.concurrent.ExecutorService

    package java.util.concurrent; import java.util.List; import java.util.Collection;/*** 这个一个Executor,提供了一些方法来管理任务终止以及创建一个<Future>对象去追踪一个或多个异步任务的执行过程** 一个ExecutorService对象可以被shut down,这回让它拒绝接收新…...

    2024/4/7 16:19:34
  16. 程序员周末应该干的8件事

    教妹学Java以一种轻松活泼的方式,教同学们学习Java沉默王二9.90去订阅昨天晚上睡觉前,我瞥了一下后台读者的留言,其中有一位叫 abe 的读者说:“二哥,你周末都是怎么度过的呢?我怎么感觉自己好空虚啊,除了打游戏,看奇葩说,偶尔看一下英超,就没有别的事情可以做了。有时…...

    2024/3/29 13:08:17
  17. vue从入门到进阶:指令与事件(二)

    文章目录一.插值v-once v-html 使用 JavaScript 表达式二 v-bind与v-on的缩写v-bind 缩写 v-on 缩写三.条件渲染v-if 在 <template>元素上使用 v-if v-else v-else-if 用 key 管理可复用的元素 v-show v-if vs v-show v-if 与 v-for 一起使用四.列表渲染v-for一个数组的v…...

    2024/3/29 13:08:16
  18. vmware配置管理ubuntu环境

    ubuntu环境下系统开发1.vmware安装1.1网络配置:2.ubuntu安装3.配置管理3.1系统配置3.1.1 /etc/environment3.1.2 /etc/profile3.1.3 /etc/hosts3.1.4 当前工作用户配置3.2网络配置3.2.1 /etc/network/interfaces3.2.2网络配置命令3.3路由配置3.3.1路由表查看3.3.2主机路由3.3.…...

    2024/3/29 13:08:15
  19. 学习python要学哪些内容

    为什么要学习python python现在比较流行,对处理工作上的事情比较有优势,例如如果做财务,或者要到网上爬一些什么信息,为自己所用,都可以利用python。未来是人工智能的时代,需要会编程才能操作机器人为人所用。所以需要学习python。 如何学习python 对于程序员或者计算机科…...

    2024/4/7 20:51:58
  20. day22 Java基础二阶段-Lambda表达式&方法引用的理解和使用

    1.Lambda表达式 1.1体验Lambda表达式【理解】案例需求 启动一个线程,在控制台输出一句话:多线程程序启动了实现方式一实现步骤定义一个类MyRunnable实现Runnable接口,重写run()方法 创建MyRunnable类的对象 创建Thread类的对象,把MyRunnable的对象作为构造参数传递 启动线程…...

    2024/4/25 22:26:07

最新文章

  1. /etc/pam.d/su内容详解

    以下为CentOS Linux release 8.5.2111系统/etc/pam.d/su默认配置。 [root@localhost authselect]# cat /etc/pam.d/su #%PAM-1.0 auth required pam_env.so auth sufficient pam_rootok.so # Uncomment the following line to implicitly t…...

    2024/4/28 13:35:55
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. Vue3学习笔记+报错记录

    文章目录 1.创建Vue3.0工程1.1使用vue-cli创建1.2 使用vite创建工程1.3.分析Vue3工程结构 2.常用Composition2.1 拉开序幕的setup2.2 ref函数_处理基本类型2.3 ref函数_处理对象类型2.4 ref函数使用总结 1.创建Vue3.0工程 1.1使用vue-cli创建 查看vue/cli版本&#xff0c;确保…...

    2024/4/25 2:10:28
  4. k8s_入门_kubelet安装

    安装 在大致了解了一些k8s的基本概念之后&#xff0c;我们实际部署一个k8s集群&#xff0c;做进一步的了解 1. 裸机安装 采用三台机器&#xff0c;一台机器为Master&#xff08;控制面板组件&#xff09;两台机器为Node&#xff08;工作节点&#xff09; 机器的准备有两种方式…...

    2024/4/23 6:23:48
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/26 18:09:39
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/27 4:00:35
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/27 9:01:45
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/28 1:22:35
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57