扩展tinyplay使其自适应不同声道数量的媒体
android原来的tinyplay代码,如果遇到播放媒体的升到数量与打开pcm的声道数量不匹配的情况,会没法继续播放。
本例扩展了tinyplay的代码,将不同声道的音频数据展开/压缩到pcm设备支持的数据,再写入pcm设备。
bplay.c
#include <tinyalsa/asoundlib.h>#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <endian.h>
#include <unistd.h>
#include <pthread.h>#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
#define ID_FMT 0x20746d66
#define ID_DATA 0x61746164typedef enum {false = 0, true = 1} bool;struct riff_wave_header {uint32_t riff_id;uint32_t riff_sz;uint32_t wave_id;
};struct chunk_header {uint32_t id;uint32_t sz;
};struct chunk_fmt {uint16_t audio_format;uint16_t num_channels;uint32_t sample_rate;uint32_t byte_rate;uint16_t block_align;uint16_t bits_per_sample;
};#undef TAG
#define TAG "BPLAY"
#if 0 // def 0__ANDROID__
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#else
#define LOGI(str, ...) do{printf("BPLAY ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#define LOGD(str, ...) do{printf("BPLAY ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#define LOGW(str, ...) do{printf("BPLAY ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#define LOGE(str, ...) do{printf("BPLAY ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#endifstatic int isClosing = 0;void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,unsigned int rate, unsigned int bits, unsigned int period_size,unsigned int period_count, uint32_t data_sz);void stream_close(int sig) {/* allow the stream to be closed gracefully */signal(sig, SIG_IGN);isClosing = 1;
}void* play_thread(void* arg) {FILE *file = NULL;struct chunk_header chunk_header;struct riff_wave_header riff_wave_header;struct chunk_fmt chunk_fmt;unsigned int device = 0;unsigned int card = 0;unsigned int period_size = 1024;unsigned int period_count = 4;const char *filename;int more_chunks = 1;char ** argv = (char **) arg;filename = argv[1];file = fopen(filename, "rb");if (!file) {LOGE("Unable to open file '%s'\n", filename);return (void*)(long)1;}fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);if ((riff_wave_header.riff_id != ID_RIFF) ||(riff_wave_header.wave_id != ID_WAVE)) {LOGI("Error: '%s' is not a riff/wave file\n", filename);fclose(file);return (void*)(long)1;}do {fread(&chunk_header, sizeof(chunk_header), 1, file);switch (chunk_header.id) {case ID_FMT:fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);/* If the format header is larger, skip the rest */if (chunk_header.sz > sizeof(chunk_fmt))fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);break;case ID_DATA:/* Stop looking for chunks */more_chunks = 0;chunk_header.sz = le32toh(chunk_header.sz);break;default:/* Unknown chunk, skip bytes */fseek(file, chunk_header.sz, SEEK_CUR);}} while (more_chunks);/* parse command line arguments */argv += 2;while (*argv) {if (strcmp(*argv, "-d") == 0) {argv++;if (*argv)device = atoi(*argv);}if (strcmp(*argv, "-p") == 0) {argv++;if (*argv)period_size = atoi(*argv);}if (strcmp(*argv, "-n") == 0) {argv++;if (*argv)period_count = atoi(*argv);}if (strcmp(*argv, "-D") == 0) {argv++;if (*argv)card = atoi(*argv);}if (*argv)argv++;}play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,chunk_fmt.bits_per_sample, period_size, period_count, chunk_header.sz);fclose(file);return (void*)(long)0;
}int main(int argc, char* argv[]) {pthread_t tid;void* status;if (argc < 2) {LOGI("Usage: %s file.wav [-D card] [-d device] [-p period_size]"" [-n n_periods] \n", argv[0]);return 1;}if (pthread_create(&tid, NULL, play_thread, (void*)argv)) {return 1;}pthread_join(tid, &status);return 0;
}int check_param(struct pcm_params *params, unsigned int param, unsigned int value,char *param_name, char *param_unit) {unsigned int min;unsigned int max;int is_within_bounds = 1;min = pcm_params_get_min(params, param);if (value < min) {//LOGW("%s is %u%s, device supports >= %u%s\n", param_name, value, param_unit, min, param_unit);//is_within_bounds = 0;}max = pcm_params_get_max(params, param);if (value > max) {LOGE("%s is %u%s, device only supports <= %u%s\n", param_name, value,param_unit, max, param_unit);is_within_bounds = 0;}return is_within_bounds;
}int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels,unsigned int rate, unsigned int bits, unsigned int period_size,unsigned int period_count) {struct pcm_params *params;int can_play;params = pcm_params_get(card, device, PCM_OUT);if (params == NULL) {LOGE("Unable to open PCM device %u.\n", device);return 0;}can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz");can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels");can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits");can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", " frames");can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", " periods");pcm_params_free(params);return can_play;
}static int merge_data_to_channel(char* out_buffer, const char* in_buffer, int src_size,int src_channels, int dest_channels, int bit_width) {int i = 0;int copy_channels = src_channels;if (src_channels > dest_channels) copy_channels = dest_channels;int loop_count = src_size / bit_width / src_channels;for(; i < loop_count; i ++) {memcpy(out_buffer + i * dest_channels * bit_width,in_buffer + i * bit_width * src_channels,bit_width * copy_channels);}return src_size * dest_channels / src_channels;
}void play_sample(FILE *file, unsigned int card, unsigned int device, const unsigned int channels,unsigned int rate, unsigned int bits, unsigned int period_size,unsigned int period_count, uint32_t data_sz) {struct pcm_config config;struct pcm *pcm = NULL;char *write_buffer = NULL;char *read_buffer = NULL;unsigned int buffer_size = 0, read_sz;int num_read;uint32_t frame_count = 0; //bose adduint32_t loop_times = 0;uint32_t byte_rate = 1;uint32_t total_seconds = 0;uint32_t current_seconds = 0;uint32_t min_channel = 0;struct pcm_params *params;int bit_width = 1;bit_width = bits / 8;memset(&config, 0, sizeof(config));params = pcm_params_get(card, device, PCM_OUT);min_channel = pcm_params_get_min(params, PCM_PARAM_CHANNELS);if (channels < min_channel) {LOGW("convert config.channels to %d instead of %d", min_channel, channels);config.channels = min_channel;} else {config.channels = channels;}config.rate = rate;config.period_size = period_size;config.period_count = period_count;if (bits == 32)config.format = PCM_FORMAT_S32_LE;else if (bits == 24)config.format = PCM_FORMAT_S24_3LE;else if (bits == 16)config.format = PCM_FORMAT_S16_LE;config.start_threshold = 0;config.stop_threshold = 0;config.silence_threshold = 0;do {if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) {LOGE("sample is not playable");break;}pcm = pcm_open(card, device, PCM_OUT, &config);if (!pcm || !pcm_is_ready(pcm)) {LOGE("Unable to open PCM device %u (%s)\n",device, pcm_get_error(pcm));break;}buffer_size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));write_buffer = (char*)malloc(buffer_size);memset(write_buffer, 0, buffer_size);read_buffer = (char*)malloc(buffer_size);if (!write_buffer || !read_buffer) {LOGE("Unable to allocate %d bytes\n", buffer_size * 2);free(write_buffer);free(read_buffer);pcm_close(pcm);break;}} while(0);byte_rate = (uint32_t) ((channels * rate * bits) / 8);total_seconds = (uint32_t)(data_sz / byte_rate);LOGD(">>> %u ch, %u hz, %u bit byte_rate=%u. Total %u bytes, %u seconds.",channels, rate, bits, byte_rate, data_sz, total_seconds);LOGD(">>> pcm_get_buffer_size(): %d, write_size: %d, read size:%d",pcm_get_buffer_size(pcm), buffer_size, buffer_size * channels / min_channel);/* catch ctrl-c to shutdown cleanly */signal(SIGINT, stream_close);do {float t = total_seconds - data_sz / byte_rate;if ((t - current_seconds) >= 1.000f) {current_seconds = (uint32_t)t;printf("\rPlayed %d seconds, [%d]bytes remain.", current_seconds, data_sz);fflush(stdout);}memset(read_buffer, 0, buffer_size);memset(write_buffer, 0, buffer_size);read_sz = buffer_size * channels / min_channel < data_sz ? buffer_size * channels / min_channel : data_sz;num_read = fread(read_buffer, 1, read_sz, file);if (num_read > 0) {merge_data_to_channel(write_buffer, read_buffer, read_sz, channels, config.channels, bit_width);if (pcm_write(pcm, write_buffer, buffer_size)) {LOGE("Error playing sample, remain bytes=%d, loop=%d", data_sz, loop_times);// receiving signal may interrupt some system call.}frame_count++;data_sz -= num_read;}} while (!isClosing && num_read > 0 && data_sz > 0);printf("\nEnd playing.\n");fflush(stdout);free(write_buffer);free(read_buffer);if(NULL != pcm)pcm_close(pcm);
}
A reference Android.mk
LOCAL_PATH := $(call my-dir)################################### /system/bin/bplay ########################################
include $(CLEAR_VARS)
LOCAL_MODULE := bplay
LOCAL_CFLAGS := -Werror -g -o0
LOCAL_LDFLAGS += -Wl
LOCAL_CPPFLAGS := -Werror -Wfloat-equal -Wformat=2LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES += bplay.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)LOCAL_SHARED_LIBRARIES :=liblog libutils libcutils \libtinyalsaLOCAL_STATIC_LIBRARIES +=include $(BUILD_EXECUTABLE)
相关文章:
扩展tinyplay使其自适应不同声道数量的媒体
android原来的tinyplay代码,如果遇到播放媒体的升到数量与打开pcm的声道数量不匹配的情况,会没法继续播放。 本例扩展了tinyplay的代码,将不同声道的音频数据展开/压缩到pcm设备支持的数据,再写入pcm设备。 bplay.c #include &l…...
[Unity] AppLovin Max接入Native 广告 IOS篇
NativeIOS构建流程 (接入之前备份之前打包得Xcode工程) 下载资源 1.将以下文件放入Unity Assets->Plugins->IOS文件夹下 2.Unity更新max版本至12.4.1 UnityPlugin 6.4.3以上(很重要) 3.NativeSDKManager.CS根据以下附…...
跨平台开发技术的探索:从 JavaScript 到 Flutter
随着多平台支持和用户体验一致性在应用程序开发中变得越来越重要,开发者面临的挑战是如何在不同平台上保持代码的可维护性和高效性。本文将探讨如何利用现代技术栈,包括 Flutter、JavaScript、HTML5、WebAssembly、TypeScript 和 Svelte,在统一的平台上进行高效的跨平台开发…...
计算机网络技术基础:2.计算机网络的组成
计算机网络从逻辑上可以分为两个子网:资源子网和通信子网。 一、资源子网 资源子网主要负责全网的数据处理业务,为全网用户提供各种网络资源与网络服务。资源子网由主机、终端、各种软件资源与信息资源等组成。 1)主机 主机是资源子网的主要…...
PKCS#7、Bit padding(位填充)、Byte padding(字节填充)、Zero padding(零填充)
PKCS#7、Bit padding(位填充)、Byte padding(字节填充)、Zero padding(零填充)是密码学常见的填充方式。 Bit padding(位填充): 位填充可以应用于任意长度的消息。在消息…...
在 Kibana 中为 Vega Sankey 可视化添加过滤功能
作者:来自 Elastic Tim Bosman 及 Miloš Mandić 有兴趣在 Kibana 中为 Vega 可视化添加交互式过滤器吗?了解如何利用 “kibanaAddFilter” 函数轻松创建动态且响应迅速的 Sankey 可视化。 在这篇博客中,我们将了解如何启用 Vega Sankey 可视…...
快速部署一套K8s集群-v1.28
快速部署一套K8s集群-v1.28 1.前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式: kubeadmKubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。 二进制包从github下载发行版的二进…...
python3验证有效正则表达式
Python 中字符串类型本质上没有标记“是否原始”的特性,原始字符串只是为了书写方便。运行时,原始字符串与普通字符串的表现是相同的,唯一的区别是编写代码时是否进行了转义。 因此,如果需要确保某些输入是有效正则表达式&#x…...
Dify+Xinference本地部署Embedding和Rerank模型
文章目录 1、Xinference介绍2、Xinference安装2.1 Xinference Docker安装2.2 pip安装2.3 设置开启自启动(仅针对pip安装用户) 3、部署Embedding和Rerank模型4、Dify调用Xinference模型 1、Xinference介绍 Xinference是一个性能强大且功能全面的分布…...
是时候戒掉小游戏了
玩儿这东西没够!去年本来是要备考CPA,但是赶上写毕业论文,就以此为由,没有去备考,结果论文没完成,考试也没准备,都是游戏惹的祸!今年计划备考,看了两个月书,结…...
ECMAScrip 与 ES2015(ES6):JavaScript 现代化编程的里程碑
在 JavaScript 的发展历程中,ECMASCript 和 ES2015(也称为 ES6)无疑是最具革命性的版本之一。它们不仅引入了大量的新特性和语法糖,还极大地提升了代码的可读性、可维护性和性能。本文将深入探讨 ECMASCrip 和 ES2015 的新特性及其…...
iOS swift开发系列 -- tabbar问题总结
1.单视图如何改为tabbar,以便显示2个标签页 右上角➕,输入tabbar 找到控件,然后选中,把entrypoint移动到tabbar控件 2.改成tabbar,生成两个item,配置各自视图后,启动发现报错 Thread 1: “-[p…...
nginx 部署 ModSecurity3
一、查看本地nginx版本 nginx是yum安装的 # nginx -v nginx version: nginx/1.26.2 二、安装依赖工具 # yum install -y gcc-c flex bison yajl lmdb lua curl-devel curl GeoIP-devel zlib-devel pcre-devel pcre2-devel libxml2-devel ssdeep-devel libtool autoconf aut…...
websocket_asyncio
WebSocket 和 asyncio 指南 简介 本指南涵盖了使用 Python 中的 websockets 库进行 WebSocket 编程的基础知识,以及 asyncio 在异步非阻塞 I/O 中的作用。它提供了构建高效 WebSocket 服务端和客户端的知识,以及 asyncio 的特性和优势。 1. 什么是 WebS…...
一级考试真题(2019)
一级考试真题(2019)...
OpenCV相机标定与3D重建(20)将单应性矩阵分解为旋转矩阵、平移向量和法向量函数decomposeHomographyMat()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将单应性矩阵分解为旋转矩阵、平移向量和法向量。 cv::decomposeHomographyMat 是 OpenCV 库中的一个函数,用于将单应性矩阵…...
题解 - 取数排列
题目描述 取1到N共N个连续的数字(1≤N≤9),组成每位数不重复的所有可能的N位数,按从小到大的顺序进行编号。当输入一个编号M时,就能打印出与该编号对应的那个N位数。例如,当N=3时,可…...
LVGL9.2 鼠标悬停处理
文章目录 前言鼠标悬停处理功能简介使用场景1. **按钮悬停效果**2. **图标高亮**3. **动态工具提示** 实现原理使用方法1. 设置控件样式2. 监听悬停事件 功能亮点注意事项总结 前言 在 v9.2 版本中,新增了许多功能,其中鼠标悬停处理(Mouse H…...
每日计划-1213
1. 完成 SQL2 查询多列 https://www.nowcoder.com/exam/oj?page1tabSQL%E7%AF%87topicId199 2. 八股部分 1) C 中面向对象编程如何实现数据隐藏? 在c中,可以将数据成员声明为私有或受保护,并提供公有的成员函数来访问和修改这些数据成员&am…...
gz中生成模型
生成模型 通过服务调用生成 还记得parameter_bridge 吗? 我们在生成桥接的时候调用了这个cpp文件。 一个 parameter_bridge 实例用于消息传递(传感器数据)。之前的例子 另一个 parameter_bridge 实例用于服务桥接(动态生成模型…...
三相电机不转,如何判断好坏?
在现代工业生产中,三相电机被广泛应用于各类机械设备中,由于其高效能和稳定性,成为驱动设备的首选。然而,在实际使用过程中,三相电机有时会出现不转动的情况,这不仅会影响生产效率,还可能对设备…...
使用观测云排查数据库死锁故障
故障发现 核心应用 pod 发生重启,同时接收到对应使用者反馈业务问题,开始排查。 观测云排查现场 1、根据重启应用信息,查询 APM 执行数据库 update 操作大量报错,执行时间在 5min 以上。 分析 APM 链路异常,发现是触…...
STM32 USB通信知识与应用详解
在嵌入式系统开发中,STM32作为一款性能卓越的微控制器,其USB通信功能的应用十分广泛。本文将深入探讨STM32 USB的相关知识,从基础概念到实际应用,为读者呈现一个全面的STM32 USB通信知识体系。 一、USB基础知识 USB(…...
IoTDB 集群扩容方法
问题 问题1:当时序数据库 IoTDB 集群的存储占用达到多少时,建议增加节点?是等到存储完全满,还是达到一半时就进行扩容?如果集群存储已满,是否需要手动进行数据清理,比如设置 TTL,还…...
控制台报错:Uncaught (in promise):XXXXX问题定位以及前端文件流excel文件下载方法
今天对接上传文件的接口时,明明接口是通的,也正常返回了文件流,然而,控制台就是打印不出返回值,而且一直报错Uncaught (in promise):XXXXX 去查看axios的封装函数,这个internal error是从返回值…...
.NET平台使用C#设置Excel单元格数值格式
设置Excel单元格的数字格式是创建、修改和格式化Excel文档的关键步骤之一,它不仅确保了数据的正确表示,还能够增强数据的可读性和专业性。正确的数字格式可以帮助用户更直观地理解数值的意义,减少误解,并且对于自动化报告生成、财…...
6.2 MapReduce工作原理
MapReduce工作原理涉及将大数据集分割成小块并行处理。Map任务读取数据块并输出中间键值对,而Reduce任务则处理这些排序后的数据以生成最终结果。MapTask工作包括读取数据、应用Map函数、收集输出、内存溢出时写入磁盘以及可选的Combiner局部聚合。ReduceTask工作则…...
C语言指针
1,指针是什么 指针是内存中一个最小内存单元(一个字节)的编号,也就是地址通常口语中说的指针,通常是指指针变量也就是用来存放内存中地址的变量 每个内存单元都有一个地址,这个地址不需要存起来࿰…...
前端(async 和await)
1 async async 将 function 变为成为 async 函数 ●async 内部可以使用 await,也可以不使用,因此执行这个函数时,可以使用 then 和 catch 方法 ●async 函数的返回值是一个 Promise 对象 ●Promise 对象的结果由 async 函数执行的返回值决…...
打造高效的HIS与DAT文件解析工具
在工业数据采集和存储中,HIS 和 DAT 文件是非常常见的二进制数据格式。然而,解析这些固定块大小的二进制文件并将其转换为易读的 CSV 格式并非易事。本文将深入讲解如何使用 Python 和 PyQt5 打造一款图形化工具,轻松解析和转换这些文件&…...
YOLO系列:二、基于yolov8和labelme制作数据集及模型训练
YOLO系列:二、基于yolov8和labelme制作数据集及模型训练 1.新建一个项目1.数据集标注及类型转换1. 1 使用labelme进行数据标注1.1.1打开labelme1.1.2图像标注及存储 1. 2 将数据集转换成yolo类型 2.模型训练的配置文件2. 1打开labelme标注图像2.1.1三级目录 3.模型训…...
PHP搭建环境
一、安装apache 1、获取Apache安装软件 2、双击安装即可:指定对应的路径:E:server/apache 3、选择安装模式:使用自定义模式 4、选择安装位置 二、Apache的目录结构说明 三、Httpd.exe的详细应用 1、服务器进程:运行之后才能够工作...
LeetCode hot100-69-N
https://leetcode.cn/problems/valid-parentheses/description/?envTypestudy-plan-v2&envIdtop-100-liked 20. 有效的括号 已解答 简单 相关标签 相关企业 提示 给定一个只包括 (,),{,},[,] 的字符串 s &#x…...
14:00面试,14:06就出来了,问的问题有点变态。。。
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到5月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…...
ubuntu20.04复现 Leg-KILO
这里写目录标题 opencv版本问题下载3.2.0源代码进入解压后的目录创建构建目录运行 CMake 配置 配置时指定一个独立的安装目录,例如 /opt/opencv-3.2:出错: 使用多线程编译错误1: stdlib.h: 没有那个文件或目录错误2:er…...
Redis应用—1.在用户数据里的应用
大纲 1.社区电商的业务闭环 2.Redis缓存架构的典型生产问题 3.用户数据在读多写少场景下的缓存设计 4.热门用户数据的缓存自动延期机制 5.缓存惊群与穿透问题的解决方案 6.缓存和数据库双写不一致问题分析 7.基于分布式锁保证缓存和数据库双写一致性 8.缓存和数据库双写…...
MySQL InnoDB 中的数据页
文章目录 1. 数据库的存储结构概述1.1 表空间(Tablespace)1.2 段(Segment)1.3 区(Extent)1.4 页(Page) 2. InnoDB 数据页的深入解析2.1 数据页的物理结构2.2 数据页中的行存储2.3 数…...
React Fiber
React Fiber 是 React 16 引入的全新重写的协调(Reconciliation)算法的实现,旨在改善 React 的更新机制和性能,尤其是在复杂应用和大量更新的场景下。它使得 React 更加灵活、可调度,能够实现优先级控制和中断更新等特…...
hive 小文件分析
1、获取fsimage文件: hdfs dfsadmin -fetchImage /data/xy/ 2、从二进制文件解析: hdfs oiv -i /data/xy/fsimage_0000000019891608958 -t /data/xy/tmpdir -o /data/xy/out -p Delimited -delimiter “,” 3、创建hive表 create database if not exists…...
大模型运用-Prompt Engineering(提示工程)
什么是提示工程 提示工程 提示工程也叫指令工程,涉及到如何设计、优化和管理这些Prompt,以确保AI模型能够准确、高效地执行用户的指令,如:讲个笑话、java写个排序算法等 使用目的 1.获得具体问题的具体结果。(如&…...
Linux(网络协议和管理)
后面也会持续更新,学到新东西会在其中补充。 建议按顺序食用,欢迎批评或者交流! 缺什么东西欢迎评论!我都会及时修改的! 在这里真的很感谢这位老师的教学视频让迷茫的我找到了很好的学习视频 王晓春老师的个人空间…...
前端项目打包部署
打包和部署前端项目是将开发环境中的代码转化为生产环境可直接运行的静态文件,并将其部署到服务器上的过程。 # 项目打包 pnpm run build# 上传文件至远程服务器 将本地打包生成的 dist 目录下的所有文件拷贝至服务器的 /usr/share/nginx/html 目录。# nginx.cofig…...
Linux驱动开发(12):中断子系统–按键中断实验
本章我们以按键为例讲解在驱动程序中如何使用中断, 在学习本章之前建议先回顾一下关于中断相关的裸机部分相关章节, 这里主要介绍在驱动中如何使用中断,对于中断的概念及GIC中断控制器相关内容不再进行讲解。 本章配套源码和设备树插件位于“…...
C语言(函数指针与指针函数)
函数指针 定义:函数指针本质上是指针,它是函数的指针(定义了一个指针变量,变量中存储了函数的地 址)。函数都有一个入口地址,所谓指向函数的指针,就是指向函数的入口地址。这里函数名就代 表入…...
中国计算机学会计算机视觉专委会携手合合信息举办企业交流活动,为AI安全治理打开“新思路”
近期,《咬文嚼字》杂志发布了2024年度十大流行语,“智能向善”位列其中,过去一年时间里,深度伪造、AI诈骗等话题屡次登上热搜,AI技术“野蛮生长”引发公众担忧。今年9月,全国网络安全标准化技术委员会发布了…...
MacOs 日常故障排除troubleshooting
1. 关闭开机自启动 app X macOs 15.1 System settings -> General -> Login Items & Extensions->Open at Login -> Select app X and click -...
ArcGIS字符串补零与去零
我们有时候需要 对属性表中字符串的补零与去零操作 我们下面直接视频教学 下面看视频教学 ArcGIS字符串去零与补零 推荐学习 ArcGIS全系列实战视频教程——9个单一课程组合 ArcGIS10.X入门实战视频教程(GIS思维) ArcGIS之模型构建器(Mod…...
【FLASH、SRAM和DRAM、CISC和RISC、冯诺依曼和哈佛】单片机内存结构的了解
【FLASH、SRAM和DRAM、CISC和RISC、冯诺依曼和哈佛】单片机内存结构的了解 一、单片机概念 单片机:Single-Chip Microcomputer,单片微型计算机,是一种集成电路芯片 1.1RAM里的SRAM和DRAM SRAM(Static Random Access Memory&…...
ionic capacitor JSValueEncodingContainer报错
try to clean the build folder. exit Xcode. upgrade your capacitor core libraries update cocoapods to 1.13.0 do “pod install --repo-udpdate” after that: ionic build --prodnpx cap updatenpx cap syncnpx cap open ios capacitor ios最低版本要求13 [Bug]:…...
pdf merge
在 Ubuntu 22.04 上,你可以使用以下命令行工具来合并多个 PDF 文件: 1. pdftk pdftk 是一个强大的 PDF 工具,支持合并、拆分和其他操作。安装和使用方法如下: sudo apt install pdftk pdftk file1.pdf file2.pdf cat output me…...