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…...
泵吸式激光可燃气体监测仪:快速精准守护燃气管网安全
在城市化进程加速的今天,燃气泄漏、地下管网老化等问题时刻威胁着城市安全。如何实现精准、高效的可燃气体监测,守护“城市生命线”,成为新型基础设施建设的核心课题。泵吸式激光可燃气体监测仪,以创新科技赋能安全监测࿰…...
Stiring-PDF:开源免费的PDF文件处理软件
Stiring-PDF是一款开源免费且比较好用的PDF文件处理工具。 Stiring-PDF官网网址为:https://www.stiringpdf.com/。Stiring-PDF是一款专业的PDF文件处理工具,支持Windows和macOS操作系统;提供丰富的PDF编辑和转换功能,适用于日常工…...
Cherno C++ P60 为什么不用using namespace std
这篇文章我们讲一下之前写代码的时候的一个习惯,也就是不使用using namespace std。如果我们接触过最早的C教程,那么第一节课都会让我们写如下的代码: #include<iostream>using namespace std;int main() {cout << "Hello …...
大模型微调实验记录(一)数据探索
文章目录 概要整体架构流程前期的技术探索技术构造技术细节小结 概要 根据之前博客使用的docker技术,如果换公司了,我可能就要重新搭建环境了,哎,公司没资源给我,给我一台带不走的电脑,哎,这可…...
JavaWeb-社区版Idea安装配置
idea配置 一,下载idea社区版 百度搜索IntelliJ IDEA,点击下载链接。 二,全局配置 前提安装好jdk,这一步不再赘述。进入引导页,把可以配置的东西都先配置上,这个配置是全局的,省的之后&#…...
iOS 实现UIButton自动化点击埋点
思路:我们HOOK UIControl的 addtarget:action:forControlEvents方法,交换UIControl的 addtarget:action:forControlEvents 方法的实现, 在交换的方法中添加原来响应的同时,再添加一个埋点响应,该响应方法实现了点击埋点…...
商城系统单商户开源版源码
环境配置 1.软件安装 宝塔安装系统软件:Nginx、MySQL5.6、PHP( PHP用7.1-7.4版本)、phpMyAdmin(Web端MySQL管理工具)。 2.配置mysql 设置mysql,在已安装的软件里面找到 mysql点击进行设置 3.修改sql-mode 选择左侧配置修改,找到里面的sql-mode&…...
用不同语言写力扣题的思考:如何选择最适合的编程语言
目录 1. 为什么选择不同的编程语言? 2. 如何根据题目特点选择编程语言? 2.1 题目类型 2.2 个人熟练度 2.3 性能要求 3. 实例分析 3.1 两数之和(Two Sum) Python 实现 C 实现 3.2 反转链表(Reverse Linked Li…...
Python PDF文件拆分-详解
目录 使用工具 将PDF按页数拆分 将PDF的每一页拆分为单独的文件 将PDF按指定页数拆分 根据页码范围拆分PDF 根据指定内容拆分PDF 将PDF的一页拆分为多页 在日常生活中,我们常常会遇到大型的PDF文件,这些文件可能难以发送、管理和查阅。将PDF拆分成…...
ubuntu部署gitlab-ce及数据迁移
ubuntu部署gitlab-ce及数据迁移 进行前梳理: 在esxi7.0 Update 3 基础上使用 ubuntu22.04.5-server系统对 gitlab-ce 16.10进行部署,以及将gitlab-ee 16.9 数据进行迁移到gitlab-ce 16.10 进行后总结: 起初安装了极狐17.8.3-jh 版本(不支持全局中文,就没用了) …...
Y3学习打卡
网络结构图 YOLOv5配置了4种不同大小的网络模型,分别是YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x,其中 YOLOv5s 是网络深度和宽度最小但检测速度最快的模型,其他3种模型都是在YOLOv5s的基础上不断加深、加宽网络使得网络规模扩大,在增强…...
英码科技携昇腾DeepSeek大模型一体机亮相第三届北京人工智能产业创新发展大会
2025年2月28日,第三届北京人工智能产业创新发展大会在国家会议中心隆重开幕。本届大会以"好用、易用、愿用——以突破性创新加速AI赋能千行百业”为主题,重点展示人工智能技术创新成果与产业化应用实践。作为昇腾生态的APN伙伴,英码科技…...
系统讨论Qt的并发编程2——介绍一下Qt并发的一些常用的东西
目录 QThreadPool与QRunnable 互斥机制:QMutex, QMutexLocker, QSemaphore, QWaitCondition 跨线程的通信 入门QtConcurrent,Qt集成的一个并发框架 一些参考 QThreadPool与QRunnable QThreadPool自身预备了一些QThread。这样,我们就不需…...
JS禁止web页面调试
前言 由于前端在页面渲染的过程中 会调用很多后端的接口,而有些接口是不希望别人看到的,所以前端调用后端接口的行为动作就需要做一个隐藏。 禁用右键菜单 document.oncontextmenu function() {console.log("禁用右键菜单");return false;…...
modbus 协议的学习,谢谢老师
(1)谢谢这位老师 ,谢谢老师的教导 (2) 谢谢...
Go 接口使用
个人学习笔记 接口作用 1. 实现多态 多态允许不同的类型通过实现相同的接口,以统一的方式进行处理。这使得代码更加灵活和可扩展,提高了代码的复用性。 示例代码: package mainimport ("fmt" )// 定义一个接口 type Speaker int…...
题解 | 牛客周赛82 Java ABCDEF
目录 题目地址 做题情况 A 题 B 题 C 题 D 题 E 题 F 题 牛客竞赛主页 题目地址 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 做题情况 A 题 判断字符串第一个字符和第三个字符是否相等 import java.io.*; import java.math.*; import java.u…...
命名管道——进程间通信
个人主页:敲上瘾-CSDN博客 匿名管道:进程池的制作(linux进程间通信,匿名管道... ...)-CSDN博客 一、命名管道的使用 1.创建命名管道 1.1.在命令行中: 创建: mkfifo 管道名 删除:…...
高频 SQL 50 题(基础版)_1141. 查询近30天活跃用户数
1141. 查询近30天活跃用户数 select activity_date day,count(distinct user_id) active_users from Activity where (activity_date<2019-07-27 and activity_date>DATE_sub(2019-07-27,INTERVAL 30 DAY)) group by(activity_date)...
Yocto + 树莓派摄像头驱动完整指南
—— 从驱动配置、Yocto 构建,到 OpenCV 实战 在树莓派上运行摄像头,在官方的 Raspberry Pi OS 可能很简单,但在 Yocto 项目中,需要手动配置驱动、设备树、软件依赖 才能确保摄像头正常工作。本篇文章从 BSP 驱动配置、Yocto 关键…...
seaborn中文乱码
在进行matplotlib画图的时候,经常会出现中文乱码的问题,这主要是默认的文件不支持中文,可以在代码中显示指定。解决方法: import seaborn as sns import matplotlib.pyplot as pltplt.rcParams["font.sans-serif"] ["SimHei"] # …...
函数的特殊形式——递归函数
C递归函数入门指南:从概念到实践 1. 什么是递归? 递归是指函数直接或间接调用自身的过程,就像照镜子时影像无限反射,通过不断分解问题解决问题 适用场景: 问题可分解为相同子问题(如阶乘、斐波那契数列…...
计算最大海岛面积
最大海岛面积问题的不同解法 问题举例 给定一个包含了一些 0 和 1 的非空二维数组 matrix 。 一个岛屿是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设matrix的四个边缘都被 0(代表水&am…...
list的两个实现类
ArrayList:适用于需要频繁随机访问元素 LinkedList:适用于需要频繁进行插入和删除操作,尤其是在列表的头部或尾部进行操作 二者的用法基本一致,只是时间和空间复杂度不同 List<Integer> arrayList new ArrayList<>…...
Spark核心之02:RDD、算子分类、常用算子
spark内存计算框架 一、目标 深入理解RDD弹性分布式数据集底层原理掌握RDD弹性分布式数据集的常用算子操作 二、要点 ⭐️1. RDD是什么 RDD(Resilient Distributed Dataset)叫做**弹性分布式数据集,是Spark中最基本的数据抽象,…...
配置Nginx日志url encode问题
文章目录 配置Nginx日志url encode问题方法1-lua方法2-set-misc-nginx-module 配置Nginx日志url encode问题 问题描述: 当自定义日志输出格式,需要输出http请求中url参数时,如果参数中包含中文,是会进行url encode的,…...
[Windows] 批量为视频或者音频生成字幕 video subtitle master 1.5.2
Video Subtitle Master 1.5.2 介绍 Video Subtitle Master 1.5.2 是一款功能强大的客户端工具,能够批量为视频或音频生成字幕,还支持批量将字幕翻译成其他语言。该工具具有跨平台性,无论是 mac 系统还是 windows 系统都能使用。 参考原文&a…...
AIP-158 分页
编号158原文链接AIP-158: Pagination状态批准创建日期2019-02-18更新日期2019-02-18 API通常需要提供数据集,最常见的是 List 标准方法。但集合大小往往是不受控制的,会随着时间增长,提高了查找时间和通过网络传输的应答大小。因此对集合进行…...
进来了解一下python的深浅拷贝
深浅拷贝是什么:在Python中,理解深拷贝(deep copy)和浅拷贝(shallow copy)对于处理复杂的数据结构,如列表、字典或自定义对象,是非常重要的。这两种拷贝方式决定了数据在内存中的复制…...
