playbin之Source插件加载流程源码剖析
之前我们有讲解过uridecodebin的setup_source中会创建source插件,关键函数:
/* create and configure an element that can handle the uri */
source = gen_source_element (decoder);
/** Generate and configure a source element.** Returns: (transfer full): a new #GstElement*/
static GstElement *
gen_source_element (GstURIDecodeBin * decoder)
{GObjectClass *source_class;GstElement *source;GParamSpec *pspec;GstQuery *query;GstSchedulingFlags flags;GError *err = NULL;if (!decoder->uri)goto no_uri;GST_LOG_OBJECT (decoder, "finding source for %s", decoder->uri);if (!gst_uri_is_valid (decoder->uri))goto invalid_uri;if (IS_BLACKLISTED_URI (decoder->uri))goto uri_blacklisted;source =gst_element_make_from_uri (GST_URI_SRC, decoder->uri, "source", &err);if (!source)goto no_source;GST_LOG_OBJECT (decoder, "found source type %s", G_OBJECT_TYPE_NAME (source));source_class = G_OBJECT_GET_CLASS (source);pspec = g_object_class_find_property (source_class, "connection-speed");if (pspec != NULL) {guint64 speed = decoder->connection_speed / 1000;gboolean wrong_type = FALSE;if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT) {GParamSpecUInt *pspecuint = G_PARAM_SPEC_UINT (pspec);speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum);} else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT) {GParamSpecInt *pspecint = G_PARAM_SPEC_INT (pspec);speed = CLAMP (speed, pspecint->minimum, pspecint->maximum);} else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT64) {GParamSpecUInt64 *pspecuint = G_PARAM_SPEC_UINT64 (pspec);speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum);} else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT64) {GParamSpecInt64 *pspecint = G_PARAM_SPEC_INT64 (pspec);speed = CLAMP (speed, pspecint->minimum, pspecint->maximum);} else {GST_WARNING_OBJECT (decoder,"The connection speed property %" G_GUINT64_FORMAT" of type %s is not useful not setting it", speed,g_type_name (G_PARAM_SPEC_TYPE (pspec)));wrong_type = TRUE;}if (!wrong_type) {g_object_set (source, "connection-speed", speed, NULL);GST_DEBUG_OBJECT (decoder,"setting connection-speed=%" G_GUINT64_FORMAT " to source element",speed);}}pspec = g_object_class_find_property (source_class, "subtitle-encoding");if (pspec != NULL && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING) {GST_DEBUG_OBJECT (decoder,"setting subtitle-encoding=%s to source element", decoder->encoding);g_object_set (source, "subtitle-encoding", decoder->encoding, NULL);}/* Sink reference before passing it to signal handler.* Language binding might otherwise sink it and then unref.* A floating ref is also tricky for a native signal handler in case* of a "transfer floating" call followed by unref* (e.g. some container_add and then container_remove).* Bottom line; best not have a floating ref boldly going into unknown code.*/g_object_ref_sink (source);g_signal_emit (decoder, gst_uri_decode_bin_signals[SIGNAL_SOURCE_SETUP],0, source);decoder->is_stream = IS_STREAM_URI (decoder->uri);query = gst_query_new_scheduling ();if (gst_element_query (source, query)) {gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL);if ((flags & GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED))decoder->is_stream = TRUE;}gst_query_unref (query);GST_LOG_OBJECT (decoder, "source is stream: %d", decoder->is_stream);decoder->need_queue = IS_QUEUE_URI (decoder->uri);GST_LOG_OBJECT (decoder, "source needs queue: %d", decoder->need_queue);return source;/* ERRORS */
no_uri:{GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND,(_("No URI specified to play from.")), (NULL));return NULL;}
invalid_uri:{GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND,(_("Invalid URI \"%s\"."), decoder->uri), (NULL));g_clear_error (&err);return NULL;}
uri_blacklisted:{GST_ELEMENT_ERROR (decoder, RESOURCE, FAILED,(_("This stream type cannot be played yet.")), (NULL));return NULL;}
no_source:{/* whoops, could not create the source element, dig a little deeper to* figure out what might be wrong. */if (err != NULL && err->code == GST_URI_ERROR_UNSUPPORTED_PROTOCOL) {gchar *prot;prot = gst_uri_get_protocol (decoder->uri);if (prot == NULL)goto invalid_uri;gst_element_post_message (GST_ELEMENT_CAST (decoder),gst_missing_uri_source_message_new (GST_ELEMENT (decoder), prot));GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,(_("No URI handler implemented for \"%s\"."), prot), (NULL));g_free (prot);} else {GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND,("%s", (err) ? err->message : "URI was not accepted by any element"),("No element accepted URI '%s'", decoder->uri));}g_clear_error (&err);return NULL;}
}
关键函数:
(1) gst_uri_is_valid (decoder->uri) 对uri进行校验
static void
gst_uri_protocol_check_internal (const gchar * uri, gchar ** endptr)
{gchar *check = (gchar *) uri;g_assert (uri != NULL);g_assert (endptr != NULL);if (g_ascii_isalpha (*check)) {check++;while (g_ascii_isalnum (*check) || *check == '+'|| *check == '-' || *check == '.')check++;}*endptr = check;
}
(2)IS_BLACKLISTED_URI (decoder->uri)黑名单校验
/* blacklisted URIs, we know they will always fail. */
static const gchar *blacklisted_uris[] = { NULL };
(3)decoder->is_stream = IS_STREAM_URI (decoder->uri);
/* list of URIs that we consider to be streams and that need buffering.* We have no mechanism yet to figure this out with a query. */
static const gchar *stream_uris[] = { "http://", "https://", "mms://","mmsh://", "mmsu://", "mmst://", "fd://", "myth://", "ssh://","ftp://", "sftp://",NULL
};
(4)decoder->need_queue = IS_QUEUE_URI (decoder->uri);
/* list of URIs that need a queue because they are pretty bursty */
static const gchar *queue_uris[] = { "cdda://", NULL };
最关键函数:
source = gst_element_make_from_uri (GST_URI_SRC, decoder->uri, "source", &err);
/*** gst_element_make_from_uri:* @type: Whether to create a source or a sink* @uri: URI to create an element for* @elementname: (allow-none): Name of created element, can be %NULL.* @error: (allow-none): address where to store error information, or %NULL.** Creates an element for handling the given URI.** Returns: (transfer floating): a new element or %NULL if none* could be created*/
GstElement *
gst_element_make_from_uri (const GstURIType type, const gchar * uri,const gchar * elementname, GError ** error)
{GList *possibilities, *walk;gchar *protocol;GstElement *ret = NULL;g_return_val_if_fail (gst_is_initialized (), NULL);g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL);g_return_val_if_fail (error == NULL || *error == NULL, NULL);if (!gst_uri_is_valid (uri)) {g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,_("Invalid URI: %s"), uri);return NULL;}GST_DEBUG ("type:%d, uri:%s, elementname:%s", type, uri, elementname);protocol = gst_uri_get_protocol (uri);possibilities = get_element_factories_from_uri_protocol (type, protocol);if (!possibilities) {GST_DEBUG ("No %s for URI '%s'", type == GST_URI_SINK ? "sink" : "source",uri);/* The error message isn't great, but we don't expect applications to* show that error to users, but call the missing plugins functions */g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_UNSUPPORTED_PROTOCOL,_("No URI handler for the %s protocol found"), protocol);g_free (protocol);return NULL;}g_free (protocol);possibilities = g_list_sort (possibilities, (GCompareFunc) sort_by_rank);walk = possibilities;while (walk) {GstElementFactory *factory = walk->data;GError *uri_err = NULL;ret = gst_element_factory_create (factory, elementname);if (ret != NULL) {GstURIHandler *handler = GST_URI_HANDLER (ret);if (gst_uri_handler_set_uri (handler, uri, &uri_err))break;GST_WARNING ("%s didn't accept URI '%s': %s", GST_OBJECT_NAME (ret), uri,uri_err->message);if (error != NULL && *error == NULL)g_propagate_error (error, uri_err);elseg_error_free (uri_err);gst_object_unref (ret);ret = NULL;}walk = walk->next;}gst_plugin_feature_list_free (possibilities);GST_LOG_OBJECT (ret, "created %s for URL '%s'",type == GST_URI_SINK ? "sink" : "source", uri);/* if the first handler didn't work, but we found another one that works */if (ret != NULL)g_clear_error (error);return ret;
}
(1)protocol = gst_uri_get_protocol (uri) 获取协议,例如http/https/ftp等
(2)possibilities = get_element_factories_from_uri_protocol (type, protocol),从注册表中搜索可匹配上的source的lists
类型:GST_URI_SRC 协议:protocols
static GList *
get_element_factories_from_uri_protocol (const GstURIType type,const gchar * protocol)
{GList *possibilities;SearchEntry entry;g_return_val_if_fail (protocol, NULL);entry.type = type;entry.protocol = protocol;possibilities = gst_registry_feature_filter (gst_registry_get (),search_by_entry, FALSE, &entry);return possibilities;
}
(3)对possibilities排序,从中选择最终匹配的source
possibilities = g_list_sort (possibilities, (GCompareFunc) sort_by_rank);walk = possibilities;while (walk) {GstElementFactory *factory = walk->data;GError *uri_err = NULL;ret = gst_element_factory_create (factory, elementname);if (ret != NULL) {GstURIHandler *handler = GST_URI_HANDLER (ret);if (gst_uri_handler_set_uri (handler, uri, &uri_err))break;GST_WARNING ("%s didn't accept URI '%s': %s", GST_OBJECT_NAME (ret), uri,uri_err->message);if (error != NULL && *error == NULL)g_propagate_error (error, uri_err);elseg_error_free (uri_err);gst_object_unref (ret);ret = NULL;}walk = walk->next;}
a)根据rank排序
b) 对每一个source尝试gst_uri_handler_set_uri ,返回成功则选择该source插件
ret = gst_element_factory_create (factory, elementname);if (ret != NULL) {GstURIHandler *handler = GST_URI_HANDLER (ret);if (gst_uri_handler_set_uri (handler, uri, &uri_err))break;
c) gst_uri_handler_set_uri主要是从,soruce中获取接口iface = GST_URI_HANDLER_GET_INTERFACE (handler),对比source支持的get_protocols是否与当前uri匹配,匹配则成功。
/*** gst_uri_handler_set_uri:* @handler: A #GstURIHandler* @uri: URI to set* @error: (allow-none): address where to store a #GError in case of* an error, or %NULL** Tries to set the URI of the given handler.** Returns: %TRUE if the URI was set successfully, else %FALSE.*/
gboolean
gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri,GError ** error)
{GstURIHandlerInterface *iface;gboolean ret;gchar *protocol;g_return_val_if_fail (GST_IS_URI_HANDLER (handler), FALSE);g_return_val_if_fail (error == NULL || *error == NULL, FALSE);iface = GST_URI_HANDLER_GET_INTERFACE (handler);g_return_val_if_fail (iface != NULL, FALSE);g_return_val_if_fail (iface->set_uri != NULL, FALSE);if (!gst_uri_is_valid (uri)) {g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,_("Invalid URI: %s"), uri);return FALSE;}protocol = gst_uri_get_protocol (uri);if (iface->get_protocols) {const gchar *const *protocols;const gchar *const *p;gboolean found_protocol = FALSE;protocols = iface->get_protocols (G_OBJECT_TYPE (handler));if (protocols != NULL) {for (p = protocols; *p != NULL; ++p) {if (g_ascii_strcasecmp (protocol, *p) == 0) {found_protocol = TRUE;break;}}if (!found_protocol) {g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_UNSUPPORTED_PROTOCOL,_("URI scheme '%s' not supported"), protocol);g_free (protocol);return FALSE;}}}ret = iface->set_uri (handler, uri, error);g_free (protocol);return ret;
}
备注:
Source插件需要实现接口GstURIHandlerInterface
/*** GstURIHandlerInterface:* @parent: The parent interface type* @get_type: Method to tell whether the element handles source or sink URI.* @get_protocols: Method to return the list of protocols handled by the element.* @get_uri: Method to return the URI currently handled by the element.* @set_uri: Method to set a new URI.** Any #GstElement using this interface should implement these methods.*/
struct _GstURIHandlerInterface {GTypeInterface parent;/* vtable *//*< public >*//* querying capabilities */GstURIType (* get_type) (GType type);const gchar * const * (* get_protocols) (GType type);/* using the interface */gchar * (* get_uri) (GstURIHandler * handler);gboolean (* set_uri) (GstURIHandler * handler,const gchar * uri,GError ** error);
};
souphttpsrc的例子:
G_DEFINE_TYPE_WITH_CODE (GstSoupHTTPSrc, gst_soup_http_src, GST_TYPE_PUSH_SRC,G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,gst_soup_http_src_uri_handler_init));static void
gst_soup_http_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
{GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;iface->get_type = gst_soup_http_src_uri_get_type;iface->get_protocols = gst_soup_http_src_uri_get_protocols;iface->get_uri = gst_soup_http_src_uri_get_uri;iface->set_uri = gst_soup_http_src_uri_set_uri;
}
(6)那我们继续看下gst_element_make_from_uri中的关键步骤 possibilities = get_element_factories_from_uri_protocol (type, protocol)->gst_registry_feature_filter
possibilities = gst_registry_feature_filter (gst_registry_get (),search_by_entry, FALSE, &entry);
主要逻辑就是从注册表中匹配对应的source:
static gboolean
search_by_entry (GstPluginFeature * feature, gpointer search_entry)
{const gchar *const *protocols;GstElementFactory *factory;SearchEntry *entry = (SearchEntry *) search_entry;if (!GST_IS_ELEMENT_FACTORY (feature))return FALSE;factory = GST_ELEMENT_FACTORY_CAST (feature);if (factory->uri_type != entry->type)return FALSE;protocols = gst_element_factory_get_uri_protocols (factory);if (protocols == NULL) {g_warning ("Factory '%s' implements GstUriHandler interface but returned ""no supported protocols!", gst_plugin_feature_get_name (feature));return FALSE;}while (*protocols != NULL) {if (g_ascii_strcasecmp (*protocols, entry->protocol) == 0)return TRUE;protocols++;}return FALSE;
}
/*** gst_element_factory_get_uri_protocols:* @factory: a #GstElementFactory** Gets a %NULL-terminated array of protocols this element supports or %NULL if* no protocols are supported. You may not change the contents of the returned* array, as it is still owned by the element factory. Use g_strdupv() to* make a copy of the protocol string array if you need to.** Returns: (transfer none) (array zero-terminated=1): the supported protocols* or %NULL*/
const gchar *const *
gst_element_factory_get_uri_protocols (GstElementFactory * factory)
{g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);return (const gchar * const *) factory->uri_protocols;
}
看下几个常见的source插件的信息:
gst-inspect-1.0 soupsrc
Factory Details:Rank primary (256)Long-name HTTP client sourceKlass Source/NetworkDescription Receive data as a client over the network via HTTP using SOUPAuthor Wouter Cloetens <wouter@mind.be>Plugin Details:Name soupDescription libsoup HTTP client src/sinkFilename /libgstsoup.soVersion 1.20License LGPLSource module gst-plugins-goodBinary package GStreamer Good Plug-ins gitOrigin URL Unknown package originGObject+----GInitiallyUnowned+----GstObject+----GstElement+----GstBaseSrc+----GstPushSrc+----GstSoupHTTPSrcImplemented Interfaces:GstURIHandlerPad Templates:SRC template: 'src'Availability: AlwaysCapabilities:ANYElement has no clocking capabilities.URI handling capabilities:Element can act as source.Supported URI protocols:httphttpsicyicyxPads:SRC: 'src'Pad Template: 'src'Element Properties:automatic-redirect : Automatically follow HTTP redirects (HTTP Status Code 3xx)flags: readable, writableBoolean. Default: trueblocksize : Size in bytes to read per buffer (-1 = default)flags: readable, writableUnsigned Integer. Range: 0 - 4294967295 Default: 4096compress : Allow compressed content encodingsflags: readable, writableBoolean. Default: falsecookies : HTTP request cookiesflags: readable, writableBoxed pointer of type "GStrv"do-timestamp : Apply current stream time to buffersflags: readable, writableBoolean. Default: falseextra-headers : Extra headers to append to the HTTP requestflags: readable, writableBoxed pointer of type "GstStructure"http-log-level : Set log level for soup's HTTP session logflags: readable, writableEnum "SoupLoggerLogLevel" Default: 2, "headers"(0): none - SOUP_LOGGER_LOG_NONE(1): minimal - SOUP_LOGGER_LOG_MINIMAL(2): headers - SOUP_LOGGER_LOG_HEADERS(3): body - SOUP_LOGGER_LOG_BODYiradio-mode : Enable internet radio mode (ask server to send shoutcast/icecast metadata interleaved with the actual stream data)flags: readable, writableBoolean. Default: trueis-live : Act like a live sourceflags: readable, writableBoolean. Default: falsekeep-alive : Use HTTP persistent connectionsflags: readable, writableBoolean. Default: truelocation : Location to read fromflags: readable, writableString. Default: nullmethod : The HTTP method to use (GET, HEAD, OPTIONS, etc)flags: readable, writableString. Default: nullname : The name of the objectflags: readable, writable, 0x2000String. Default: "souphttpsrc0"num-buffers : Number of buffers to output before sending EOS (-1 = unlimited)flags: readable, writableInteger. Range: -1 - 2147483647 Default: -1parent : The parent of the objectflags: readable, writable, 0x2000Object of type "GstObject"proxy : HTTP proxy server URIflags: readable, writableString. Default: ""proxy-id : HTTP proxy URI user id for authenticationflags: readable, writableString. Default: nullproxy-pw : HTTP proxy URI user password for authenticationflags: readable, writableString. Default: nullretries : Maximum number of retries until giving up (-1=infinite)flags: readable, writableInteger. Range: -1 - 2147483647 Default: 3ssl-ca-file : Location of a SSL anchor CA file to useflags: readable, writableString. Default: nullssl-strict : Strict SSL certificate checkingflags: readable, writableBoolean. Default: truessl-use-system-ca-file: Use system CA fileflags: readable, writableBoolean. Default: truetimeout : Value in seconds to timeout a blocking I/O (0 = No timeout).flags: readable, writableUnsigned Integer. Range: 0 - 3600 Default: 15tls-database : TLS database with anchor certificate authorities used to validate the server certificateflags: readable, writableObject of type "GTlsDatabase"tls-interaction : A GTlsInteraction object to be used when the connection or certificate database need to interact with the user.flags: readable, writableObject of type "GTlsInteraction"typefind : Run typefind before negotiating (deprecated, non-functional)flags: readable, writable, deprecatedBoolean. Default: falseuser-agent : Value of the User-Agent HTTP request header fieldflags: readable, writableString. Default: "GStreamer souphttpsrc 1.20.6.1 "user-id : HTTP location URI user id for authenticationflags: readable, writableString. Default: nulluser-pw : HTTP location URI user password for authenticationflags: readable, writableString. Default: null
gst-inspect-1.0 filesrc
Factory Details:Rank primary (256)Long-name File SourceKlass Source/FileDescription Read from arbitrary point in a fileAuthor Erik Walthinsen <omega@cse.ogi.edu>Plugin Details:Name coreelementsDescription GStreamer core elementsFilename /libgstcoreelements.soVersion 1.20License LGPLSource module gstreamerBinary package GStreamer gitOrigin URL Unknown package originGObject+----GInitiallyUnowned+----GstObject+----GstElement+----GstBaseSrc+----GstFileSrcImplemented Interfaces:GstURIHandlerPad Templates:SRC template: 'src'Availability: AlwaysCapabilities:ANYElement has no clocking capabilities.URI handling capabilities:Element can act as source.Supported URI protocols:filePads:SRC: 'src'Pad Template: 'src'Element Properties:blocksize : Size in bytes to read per buffer (-1 = default)flags: readable, writableUnsigned Integer. Range: 0 - 4294967295 Default: 4096do-timestamp : Apply current stream time to buffersflags: readable, writablelocation : Location of the file to readflags: readable, writable, changeable only in NULL or READY stateString. Default: nullname : The name of the objectflags: readable, writable, 0x2000String. Default: "filesrc0"num-buffers : Number of buffers to output before sending EOS (-1 = unlimited)flags: readable, writableInteger. Range: -1 - 2147483647 Default: -1parent : The parent of the objectflags: readable, writable, 0x2000Object of type "GstObject"typefind : Run typefind before negotiating (deprecated, non-functional)flags: readable, writable, deprecatedBoolean. Default: false
相关文章:
playbin之Source插件加载流程源码剖析
之前我们有讲解过uridecodebin的setup_source中会创建source插件,关键函数: /* create and configure an element that can handle the uri */ source gen_source_element (decoder); /** Generate and configure a source element.** Returns: (tra…...
调用的子组件中使用v-model绑定数据以及使用@调用方法
实例: 子组件my-date-picker: <!--* description: 日期组件二次封装* 解决 “日期为区间时,后端不支持传数组,而要传#分割的字符串” --> <template><el-date-pickerclass"comp-my-date-picker"v-mode…...
指纹细节提取(Matlab实现)
指纹细节提取概述指纹作为人体生物特征识别领域中应用最为广泛的特征之一,具有独特性、稳定性和便利性。指纹细节特征对于指纹识别的准确性和可靠性起着关键作用。指纹细节提取,即从指纹图像中精确地提取出能够表征指纹唯一性的关键特征点,是…...
爱普生可编程晶振 SG-8101CE 在智能家居领域展现出的优势
在智能家居的全场景应用中,设备间的协同效率、数据传输的稳定性以及系统运行的可靠性,成为衡量用户体验的核心标准。爱普生 SG-8101CE 可编程晶振以其卓越的性能,为智能门锁、传感器、中控系统等设备提供核心动力,助力厂商打造更可…...
DeepSeek掘金——DeepSeek-R1图形界面Agent指南
DeepSeek掘金——DeepSeek-R1图形界面Agent指南 本文将指导你完成设置 DeepSeek R1 和 Browser Use 的过程,以创建能够执行复杂任务的 AI 代理,包括 Web 自动化、推理和自然语言交互。 开源大型语言模型 (LLM) 的兴起使得创建可与 OpenAI 的 ChatGPT Operator 等专有解决方案…...
Linux知识-第一天
Linux的目录机构为一个树型结构 其没有盘符这个概念,只有一个根目录,所有文件均在其之下 在Linux系统中,路径之间的层级关系 使用 / 开头表示根目录,后面的表示层级关系 Linux命令入门 Linux命令基础 Linux命令通用格式 comman…...
通过多线程分别获取高分辨率和低分辨率的H264码流
目录 一.RV1126 VI采集摄像头数据并同时获取高分辨率码流和低分辨率码流流程 编辑 1.1初始化VI模块: 1.2初始化RGA模块: 1.3初始化高分辨率VENC编码器、 低分辨率VENC编码器: 1.4 VI绑定高分辨率VENC编码器,VI绑定RGA模块…...
【前端】在WebStorm中安装Node.js与nvm与npm的详细过程
文章目录 一、Node.js安装二、nvm安装三、验证安装成功总结 一、Node.js安装 首先到node.js官网下载安装文件。 https://nodejs.org/zh-cn 直接运行安装文件进行安装: 跳过继续安装: 完成安装: 完成后的安装路径: 环境变量的…...
飞书考勤Excel导入到自己系统
此篇主要用于记录Excel一行中,单条数据的日期拿取,并判断上下班打卡情况。代码可能满足不了大部分需求,目前只够本公司用,如果需要,可以参考。 需要把飞书月度汇总的考勤表导入系统中可以参考下。 下图为需要获取的年…...
Android Flow 示例
在Android开发的世界里,处理异步数据流一直是一个挑战。随着Kotlin的流行,Flow作为Kotlin协程库的一部分,为开发者提供了一种全新的方式来处理这些问题。今天,我将深入探讨Flow的设计理念,并通过具体的例子展示如何在实…...
vue videojs使用canvas截取视频画面
前言 刚开始做的时候太多坑,导致一直报错: Uncaught (in promise) TypeError: Failed to execute ‘drawImage’ on ‘CanvasRenderingContext2D’: The provided value is not of type ‘(CSSImageValue or HTMLCanvasElement or HTMLImageElement or H…...
Android 获取jks的SHA1值:java.io.IOException: Invalid keystore format
命令生成 keytool -list -v -keystore 全路径.jks -alias 别名 -storepass 密码 -keypass 密码 1、遇到 的问题: 通过快捷键 ‘win r’ 启动的小黑框运行上面的命令会出现下面这个错误keytool 错误: java.io.IOException: Invalid keystore format 2、解决问题 …...
CMake学习-生成库文件来链接生成可执行文件
生成库文件的目的就是为了复用代码与功能有一个Complex类,正常会与main.cpp一起经过.o的编译过程后,生成可执行文件demo但如果想要复用Complex类,就需要将其编译为一个库,main.cpp在运行时链接这个库 生成库文件: gcc …...
Vue 3 中 unref 的作用与 Vue Router currentRoute 的知识
目录 前言1. unref2. Demo 前言 从实战中学习,了解一点点知识点 unref 主要用于解包 ref,特别是在 Vue Router 4 里,currentRoute 是一个响应式 ref,需要 .value 或 unref 来访问具体字段 1. unref unref 是 Vue 3 提供的工具函…...
YOLOv12:目标检测新时代的破局者
目录 一、YOLOv12 横空出世二、YOLOv12 的性能飞跃2.1 多规模优势2.2 对比超越 三、技术创新与原理剖析3.1 区域注意力模块(Area Attention,A2)3.2 残差高效层聚合网络(R-ELAN)3.3 架构优化细节 四、实验验证与结果分析…...
网络安全法与等级保护 PPT 精华汇总
资源描述 本资源文件为《网络安全法与等级保护》的PPT精华汇总,内容涵盖了网络安全法与等级保护的总体框架及相关标准规范。该PPT详细介绍了网络安全法与等级保护的各个章节和条款,并提供了基础类和应用类的相关标准文件,帮助读者全面了解和…...
coze生成的工作流,发布后,利用cmd命令行执行。可以定时发日报,周报等。让他总结你飞书里面的表格。都可以
coze生成的工作流,发布后,利用cmd命令行执行。可以定时发日报,周报等。让他总结你飞书里面的表格。都可以。 很简单。 准备工作,先发布你的工作流,和发布应用。 然后,点击扣子API 。 申请一个࿰…...
K8S学习之基础六:k8s中pod亲和性
Pod节点亲和性和反亲和性 podaffinity:pod节点亲和性指的是pod会被调度到更趋近与哪个pod或哪类pod。 podunaffinity:pod节点反亲和性指的是pod会被调度到远离哪个pod或哪类pod 1. Pod节点亲和性 requiredDuringSchedulingIgnoredDuringExecution&am…...
从统计学视角看机器学习的训练与推理
从统计学视角看机器学习的训练与推理 目录 引言:统计学与机器学习的奇妙缘分训练与推理:你得先学会“看数据”再“用数据”最大似然估计(MLE):从直觉到数学证明 3.1 伯努利分布的MLE3.2 单变量高斯分布的MLE3.3 多元…...
《论数据分片技术及其应用》审题技巧 - 系统架构设计师
论数据分片技术及其应用写作框架 一、考点概述 本论题“论数据分片技术及其应用”主要考察的是软件工程中数据分片技术的理解、应用及其实际效果分析。考点涵盖以下几个方面: 首先,考生需对数据分片的基本概念有清晰的认识,理解数据分片是…...
【鸿蒙Next】鸿蒙与flutter使用自定义iconfont的ttf字体库对比总结
ttf的iconfont库如何获取 1、自己创建 第一步、 iconfont-阿里巴巴矢量图标库 打开网址 第二步、搜索自己的需要的图标、并且加购到购物车 第三步、点击购物车,添加至项目 第四步、添加至项目或者新建项目再添加 第五步、下载至本地 就得到了ttf文件 2、设计…...
Redis实战篇《黑马点评》8 附近商铺
8.附近商户 8.1GEO数据结构的基本用法 GEO就是Geolocation的简写形式,代表地理坐标。Redis在3.2版本中加入了对GEO的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据,常见的命令有 GEOADD:添加一个地理空间…...
【大厂AI实践】美团:美团智能客服核心技术与实践
【大厂AI实践】美团:美团智能客服核心技术与实践 🌟 嗨,你好,我是 青松 ! 🌈 自小刺头深草里,而今渐觉出蓬蒿。 NLP Github 项目推荐: 【AI 藏经阁】:https://gitee.com…...
标签的ref属性 vue中为什么不用id标记标签
标签的ref属性 vue中为什么不用id标记标签 假设有一对父子组件,如果父组件和子组件中存在id相同的标签,会产生冲突。通过id获取标签会获取到先加载那个标签。 标签的ref属性的用法 在父组件App中,引入了子组件Person。 并使用ref标记了Pe…...
期权帮|股指期货3月合约交割该如何做?
锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 股指期货3月合约交割该如何做? 股指期货的交割日通常是合约到期月份的第三个星期五。 对于3月合约,若当月无特殊节假日,交割日就是3月的第三…...
Collab-Overcooked:专注于多智能体协作的语言模型基准测试平台
2025-02-27,由北京邮电大学和理想汽车公司联合创建。该平台基于《Overcooked-AI》游戏环境,设计了更具挑战性和实用性的交互任务,目的通过自然语言沟通促进多智能体协作。 一、研究背景 近年来,基于大型语言模型的智能体系统在复…...
[Computer Vision]实验七:图像检索
目录 一、实验内容 二、实验过程 2.1 准备数据集 2.2 SIFT特征提取 2.3 学习“视觉词典”(vision vocabulary) 2.4 建立图像索引并保存到数据库中 2.5 用一幅图像查询 三、实验小结 一、实验内容 实现基于颜色直方图、bag of word等方法的以图搜…...
访问控制列表(ACL)思科、华为
访问控制列表(ACL) 一、ACL的基本概念 随着网络的飞速发展,网络安全和网络服务质量QoS(Quality of Service)问题日益突出。 企业重要服务器资源被随意访问,企业机密信息容易泄露,造成安全隐患。…...
linux磁盘满了怎么安全删除文件
df -h 通过df -h /dir 查看被占满的目录,dir替换为你的文件目录 du -sh * 进入被占满的目录,执行 du -sh * ,查看哪些文件占的磁盘大 查看占用磁盘最大的文件 du -sh * | sort -rh | head -n N N通常可以设置为10 有的docker容器文件太…...
2025国家护网HVV高频面试题总结来了04(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 一、HVV行动面试题分类 根据面试题的内容,我们将其分为以下几类: 漏洞利用与攻击技术 …...
jenkins使用插件在Build History打印基本信息
1、插件安装 分别是description setter plugin插件和user build vars插件,下面介绍一下这两个插件: description setter plugin:作用是在 Build 栏下方增加一个功能块,用于填写自定义信息,也就是 Build history 中需要显示的文字…...
线程池的工作流程
线程池的工作流程主要包括任务提交、线程分配、任务执行和线程回收等环节,以下是对其详细的描述: 任务提交 当有任务需要执行时,用户通过线程池提供的提交方法,如execute()或submit()方法,将任务(通常是实现…...
《深度学习实战》第4集:Transformer 架构与自然语言处理(NLP)
《深度学习实战》第4集:Transformer 架构与自然语言处理(NLP) 在自然语言处理(NLP)领域,Transformer 架构的出现彻底改变了传统的序列建模方法。它不仅成为现代 NLP 的核心,还推动了诸如 BERT、…...
vue下载插件
1.下载路由组件 npm i vue-router2.创建router文件夹 3.创建router.js文件 import {createRouter, createWebHistory} from "vue-router"let router createRouter({history: createWebHistory(),routes: [{path: "/",component: () > import(".…...
两周学习安排
日常安排 白天 看 MySQL实战45讲,每日一讲 看 图解设计模式 每天1-2道力扣算法题(难度中等以上) 每天复习昨天的单词,记20个单词,写一篇阅读 晚上 写服创项目 每日产出 MySQL实战45讲 读书笔记 设计模式 读书笔…...
蓝桥与力扣刷题(蓝桥 k倍区间)
题目:给定一个长度为 N 的数列,A1,A2,⋯AN,如果其中一段连续的子序列 Ai,Ai1,⋯Aj( i≤j ) 之和是 K 的倍数,我们就称这个区间[i,j] 是 K 倍区间。 你能求出数列中总共有多少个 K 倍区间吗? 输入描述 第一行包含两…...
Spring项目-抽奖系统(实操项目-用户管理接口)(END)
^__^ (oo)\______ (__)\ )\/\ ||----w | || || 一:前言: 活动创建及展示博客链接:Spring项目-抽奖系统(实操项目-用户管理接口)(THREE)-CSDN博客 上一次完成了活动的创建和活动的展示,接下来就是重头戏—…...
5个GitHub热点开源项目!!
1.自托管 Moonlight 游戏串流服务:Sunshine 主语言:C,Star:14.4k,周增长:500 这是一个自托管的 Moonlight 游戏串流服务器端项目,支持所有 Moonlight 客户端。用户可以在自己电脑上搭建一个游戏…...
数据结构:二叉搜索树(排序树)
1.二叉搜索树的定义 二叉搜索树要么是空树,要么是满足以下特性的树 (1)左子树不为空,那么左子树左右节点的值都小于根节点的值 (2)右子树不为空,那么右子树左右节点的值都大于根节点的值 &#…...
JavaEE--计算机是如何工作的
一、一台计算机的组成部分 1.CPU(中央处理器) 2.主板(一个大插座) 3.内存(存储数据的主要模板) 4.硬盘(存储数据的主要模板) 内存和硬盘对比: 内存硬盘读写速度快慢存…...
Redis 实战篇 ——《黑马点评》(下)
《引言》 (下)篇将记录 Redis 实战篇 最后的一些学习内容,希望大家能够点赞、收藏支持一下 Thanks♪ (・ω・)ノ,谢谢大家。 传送门(上):Redis 实战篇 ——《黑马…...
OpenCV计算摄影学(10)将一组不同曝光的图像合并成一张高动态范围(HDR)图像的实现类cv::MergeDebevec
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 resulting HDR 图像被计算为考虑了曝光值和相机响应的各次曝光的加权平均值。 cv::MergeDebevec 是 OpenCV 中用于将一组不同曝光的图像合并成一…...
Linux驱动开发之串口驱动移植
原理图 从上图可以看到RS232的串口接的是UART3,接下来我们需要使能UART3的收发功能。一般串口的驱动程序在内核中都有包含,我们配置使能适配即可。 设备树 复用功能配置 查看6ull如何进行uart3的串口复用配置: 设备树下添加uart3的串口复用…...
c语言中return 数字代表的含义
return 数字的含义:表示函数返回一个整数值,通常用于向调用者(如操作系统或其他程序)传递程序的执行状态或结果。 核心规则: return 0: 含义:表示程序或函数正常结束。 示例: int m…...
Android 端侧运行 LLM 框架 MNN 及其应用
MNN Chat Android App - 基于 MNN 引擎的智能聊天应用 一、MNN 框架简介与工作原理1.1 什么是 MNN?1.2 MNN 的工作原理 二、MNN Chat Android App2.1 MNN Chat 的功能2.2 MNN Chat 的优势2.3 MNN Chat Android App 的使用 三、总结 随着移动端人工智能需求的日益增长…...
jupyter汉化、修改默认路径详细讲解
1、配置镜像路径 修改第三方库的下载路径,比如:[清华镜像pypi](https://mirrors.tuna.tsinghua.edu.cn/help/pypi/),配置镜像地址。 首先执行 pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple 2、安…...
java面试笔记(二)
1.流程中如何数据回填 (1)方法1: 在工作流中有一个标识,每一次审批的时候去判断是否审批完成,然后调用反射 (2)方法2: 创建一个流程结束的监听器,监听流程是否结束&a…...
【大语言模型笔记进阶一步】提示语设计学习笔记,跳出框架思维,自己构建提示词
一、大语言模型应用场景 1. 文本生成 文本创作: 诗歌故事,剧本,推文帖子 摘要与改写: 长文本摘要与简化,多语言翻译与本地化 结构化生成: 表格,根据需求生成代码片段,API文档生成…...
sql调优:优化响应时间(优化sql) ; 优化吞吐量
Sql性能调优的目的 1.优化响应时间>>优化sql 经过调优后,执行查询、更新等操作的时候,数据库的反应速度更快,花费的时间更少。 2.优化吞吐量 即“并发”, 就是“同时处理请求”的能力。 优化sql 尽量将多条SQL语句压缩到一句>…...
debian/control中的包关系
软件包依赖就是软件包关系的一种,一般用 Depends 表示。 每个软件包都可以和其他软件包有各种不同的关系。除 Depends 外,还有 Recommends、Suggests、Pre-Depends、Breaks、Conflicts、Provides 和 Replaces,软件包管理工具(如 …...