当前位置: 首页 > news >正文

X264简介-Android使用(二)

X264简介-Android使用(二)

4、Ubuntu上安装ffmpeg:

检查更新本地软件包(如果未更新,reboot Vmware):
sudo apt update 
sudo apt upgrade
官网下载的source文件安装: http://ffmpeg.org/

下载完成后,到根目录执行:

make  
make install
查看FFMpeg版本:
ffmpeg –version

在这里插入图片描述

Tips 如果查看ffmpeg出现如下错误:

在这里插入图片描述

解办法->配置ffmpeg的环境变量:

环境变量:

vi /etc/profile

在这里插入图片描述
在开启的配置文件末尾添加如下配置:

#set ffmpeg path environment
PATH=$PATH:/snap/ffmpeg/current/bin
export PATH
编译ffmpeg

sh脚本"build_ffmpeg.sh":

#!/bin/bashexport NDK=/home/bruceli/Work/android-ndk-r25d
export PREBUILD=$NDK/toolchains/llvm/prebuilt
export CROSS_PREFIX=${PREBUILD}/linux-x86_64/bin/arm-linux-androideabi-
export CC=$PREBUILD/linux-x86_64/bin/armv7a-linux-androideabi21-clang
export NM=$CROSS_PREFIXnm
export AR=$CROSS_PREFIXarexport PREFIX=./android/armeabi-v7afunction build_so{./configure \--prefix=$PREFIX \--cc=$CC \--nm=$NM \--ar=$AR \--enable-small \--disable-programs \--disable-avdevice \--disable-encoders \--disable-muxers \--disable-filters \--cross-prefix=$CROSS_PREFIX \--target-os=android \--arch=arm \--disable-shared \--enable-static \--enable-cross-compile}make clean
build_so
make -j4
make install
}
将以上脚本放置与ffmpeg的根目录,并执行:
./build_ffmpeg.sh
Tips 出现以下错误
错误: make: *** [libavfilter/libavfilter.a] 错误 127
解决方案一->授权r25c文件夹权限(NG):
chmod +777 -R android-ndk-r25c/
解决方案二->install libavfilter(NG):
sudo apt-get install -y libavfilter-dev
解决方案三->配置 android-ndk-r21e 版本的NDK(SUCCESS):
...
export NDK=/home/bruceli/Work/android-ndk-r21e
...
文件生成路径:/home/bruceli/Work/ffmpeg-5.1.2/android/armeabi-v7a

运行结果:
在这里插入图片描述

下载NDK:

LINK1:

wget -c http://dl.google.com/android/ndk/android-ndk-r25c-linux-x86_64.bin

LINK2: https://developer.android.google.cn/ndk/downloads?hl=zh-cn
DOC: https://developer.android.google.cn/ndk/guides/other_build_systems?hl=zh-cn

配置NDK环境变量: 编辑
sudo gedit ~/.bashrc
文件末尾添加路径
export   NDK=/文件夹路径 
export   PATH=${PATH}:$NDK
保存文件
source  ~/.bashrc

build ndk:

ndk-build

在这里插入图片描述

5、编译X264:

官网连接: https://www.videolan.org/developers/x264.html
编译配置:
./configure --disable-asm --enable-shared --enable-pic
编译和安装:
make
make install

x264编译脚本

脚本(build_x264.sh):
新建以下文件:
vim build_x264.sh
文件内容:
#!/bin/bashexport NDK=/home/bruceli/Work/android-ndk-r21e
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
export API=21function build_one
{
./configure \--prefix=$PREFIX \--disable-cli \--enable-static \--enable-pic \--host=$my_host \--cross-prefix=$CROSS_PREFIX \--sysroot=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot \make clean
make -j8
make install
}#arm64-v8a
PREFIX=./android/arm64-v8a
my_host=aarch64-linux-android
export TARGET=aarch64-linux-android
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
build_one#armeabi-v7a
PREFIX=./android/armeabi-v7a
my_host=armv7a-linux-android
export TARGET=armv7a-linux-androideabi
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
build_one
开启文件权限:
chmod +777 build_x264.sh
放置x264文件夹下并执行
./build_x264.sh

在这里插入图片描述
生成文件路径:

1> /home/bruceli/Work/x264/android/arm64-v8a 
2> /home/bruceli/Work/x264/android/armeabi-v7a

使用

Android Studio

CmakeList配置文件

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.add_library( # Sets the name of the library.native-lib# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).queue.cnative-lib.c)set(distribution_DIR ../../../../libs)add_library(libx264SHAREDIMPORTED)
set_target_properties(libx264PROPERTIES IMPORTED_LOCATION${distribution_DIR}/${ANDROID_ABI}/libx264.a)add_library(librtmpSHAREDIMPORTED)
set_target_properties(librtmpPROPERTIES IMPORTED_LOCATION${distribution_DIR}/${ANDROID_ABI}/librtmp.a)add_library(libfaacSHAREDIMPORTED)
set_target_properties(libfaacPROPERTIES IMPORTED_LOCATION${distribution_DIR}/${ANDROID_ABI}/libfaac.a)# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.find_library( # Sets the name of the path variable.log-lib# Specifies the name of the NDK library that# you want CMake to locate.log)# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.target_link_libraries( # Specifies the target library.native-liblibx264librtmplibfaac# Links the target library to the log library# included in the NDK.${log-lib})

交叉编译后生成文件放置的位置:

在这里插入图片描述

配置参数及说明

///setVideoOptions
JNIEXPORT void JNICALL
Java_com_example_smallwalnut_jni_PushNative_setVideoOptions(JNIEnv *env, jobject instance,jint width, jint height, jint bitrate,jint fps) {//x264流程://x264_encoder_encode 编码//x264_encoder_close( h ) 关闭编码器,释放资源//x264_param_default_preset 设置x264_param_t param;//"ultrafast" - "medium" ... 与速度和画质有关 ,zerolatency ->可降低在线转码的编码延迟x264_param_default_preset(&param, "ultrafast", "zerolatency");//编码输入的像素格式//YUV 4:4:4采样,每一个Y对应一组UV分量。//YUV 4:2:2采样,每两个Y共用一组UV分量。//YUV 4:2:0采样,每四个Y共用一组UV分量。param.i_csp = X264_CSP_I420;param.i_width = width;param.i_height = height;y_len = width * height;u_len = y_len / 4;v_len = u_len;//参数i_rc_method表示码率控制,CQP(恒定质量),CRF(恒定码率),ABR(平均码率)//恒定码率,会尽量控制在固定码率param.rc.i_rc_method = X264_RC_CRF;param.rc.i_bitrate = bitrate / 1000; //* 码率(比特率,单位Kbps)param.rc.i_vbv_max_bitrate = bitrate / 1000 * 1.2; //瞬时最大码率//码率控制不通过timebase和timestamp,而是fpsparam.b_vfr_input = 0;param.i_fps_num = fps; //* 帧率分子param.i_fps_den = 1; //* 帧率分母param.i_timebase_den = param.i_fps_num;param.i_timebase_num = param.i_fps_den;param.i_threads = 1;//并行编码线程数量,0默认为多线程//码率控制不通过timebase和timestamp,而是fps//是否把sps和pts放入一个关键帧//SPS Sequence Parameter Set 参数序列集,PPs Picture Params Set图像参数集//为了提高图像的纠错能力param.b_repeat_headers = 1;//设置级别levelparam.i_level_idc = 51;//x264_param_apply_profile 设置档次x264_param_apply_profile(&param, "baseline");//x264_picture_alloc(x264_picture_t输入图像)初始化x264_picture_alloc(&pic_in, param.i_csp, param.i_width, param.i_height);pic_in.i_pts = 0;//x264_encoder_open 打开编码器video_encode_handle = x264_encoder_open(&param);if (video_encode_handle) {LOGI("%s", "打开编码器成功");} else {LOGI("%s", "打开编码器失败");throwNativeError(env,INIT_FAILED);}
}
YUV

YUV格式有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交叉存储的。

YUV分为三个分量,Y表示明亮度(Luminance或Luma),也就是灰度值;而U和V表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。

采样方式
YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0,用三个图来直观地表示采集的方式,以黑点表示采样该像素点的Y分量,以空心圆圈表示采样该像素点的UV分量。

在这里插入图片描述

start

///startPush
JNIEXPORT void JNICALL
Java_com_example_smallwalnut_jni_PushNative_startPush(JNIEnv *env, jobject instance, jstring url_) {//jobj_push_native = (*env)->NewGlobalRef(env, instance);jclass j_cls_push_native_temp = (*env)->GetObjectClass(env, jobj_push_native);jcls_push_native = (*env)->NewGlobalRef(env,j_cls_push_native_temp);//PushNative.throwNativeErrorjmid_throw_native_error = (*env)->GetMethodID(env, jcls_push_native,"throwNativeError","(I)V");
//    jmid_throw_native_error =  (*env)->NewGlobalRef(env,throw_native_error_mid_temp);//jmethodId 不能全局引用const char *url_cstr = (*env)->GetStringUTFChars(env, url_, 0);LOGI("播放地址:%s", url_cstr);//utl赋值rtmp_path = malloc(strlen(url_cstr) + 1);//数组初始化,临时变量清0memset(rtmp_path, 0, strlen(url_cstr) + 1);memcpy(rtmp_path, url_cstr, strlen(url_cstr));//初始化互斥锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);//创建create_queue();//init//启动消费者线程(从队列中能够不断拉取RTMPPacket发送给流媒体服务器)pthread_t push_thread_id;pthread_create(&push_thread_id, NULL, push_thread, NULL);(*env)->ReleaseStringUTFChars(env, url_, url_cstr);
}

视频编码

JNIEXPORT void JNICALL
Java_com_example_smallwalnut_jni_PushNative_fireVideo(JNIEnv *env, jobject instance,jbyteArray data_) {jbyte *nv21_buffer = (*env)->GetByteArrayElements(env, data_, NULL);//视频数据转为yuv420p//nv21->yuv420pjbyte *u = (jbyte *) pic_in.img.plane[1];jbyte *v = (jbyte *) pic_in.img.plane[2];memcpy(pic_in.img.plane[0], nv21_buffer, y_len);int i = 0;for (; i < u_len; i++) {//notice*(u + i) = *(nv21_buffer + y_len + i * 2 + 1);*(v + i) = *(nv21_buffer + y_len + i * 2);}//x264编码得到NALU指针数组x264_nal_t *nal = NULL;int n_nal = -1;//nalu的个数//进行h264编码if (x264_encoder_encode(video_encode_handle, &nal, &n_nal, &pic_in, &pic_out) < 0) {LOGI("%s", "编码失败");throwNativeError(env,INIT_FAILED);return;}//使用rtmp协议将数据发送到流媒体服务器//帧分为关键帧和普通帧,为了提高画面的纠错率,关键帧必须包含sps和pps数据unsigned char sps[100];unsigned char pps[100];int sps_len, pps_len;memset(sps, 0, 100);memset(pps, 0, 100);pic_in.i_pts += 1;//顺序叠加i = 0;//遍历NALU数组,根据NALU的类型判断(SPS PPS )for (; i < n_nal; i++) {if (nal[i].i_type == NAL_SPS) {//复制sps数据sps_len = nal[i].i_payload - 4;memcpy(sps, nal[i].p_payload + 4, sps_len);//不复制4字节起始码} else if (nal[i].i_type == NAL_PPS) {//复制pps数据pps_len = nal[i].i_payload - 4;memcpy(pps, nal[i].p_payload + 4, pps_len);//不复制4字节起始码//发送序列信息//将sps和pps数据添加到h264关键帧发送add_264_key_header(pps, sps, pps_len, sps_len);} else {//发送普通帧信息add_264_body(nal[i].p_payload, nal[i].i_payload);}}// TODO(*env)->ReleaseByteArrayElements(env, data_, nv21_buffer, 0);
}

在H.264标准协议中规定了多种不同的NAL
Unit类型,其中类型7表示该NAL Unit内保存的数据为Sequence Paramater
Set。在H.264的各种语法元素中,SPS中的信息至关重要。如果其中的数据丢失或出现错误,那么解码过程很可能会失败。SPS及后续将要讲述的图像参数集PPS在某些平台的视频处理框架(比如iOS的VideoToolBox等)还通常作为解码器实例的初始化信息使用。

SPS即Sequence Paramater Set,又称作序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:
解码器需要在码流中间开始解码;
编码器在编码的过程中改变了码流的参数(如图像分辨率等);
在做视频播放器时,为了让后续的解码过程可以使用SPS中包含的参数,必须对其中的数据进行解析。

除了序列参数集SPS之外,H.264中另一重要的参数集合为图像参数集Picture Paramater
Set(PPS)。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL
Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。

SPS
在这里插入图片描述
PPS
在这里插入图片描述

发送frame信息

///发送帧信息
void add_264_body(unsigned char *buf, int len) {
//去掉起始码(界定符)if (buf[2] == 0x00) {  //00 00 00 01buf += 4;len -= 4;} else if (buf[2] == 0x01) { // 00 00 01buf += 3;len -= 3;}int body_size = len + 9;RTMPPacket *packet = malloc(sizeof(RTMPPacket));RTMPPacket_Alloc(packet, body_size);unsigned char *body = packet->m_body;//当NAL头信息中,type(5位)等于5,说明这是关键帧NAL单元//buf[0] NAL Header与运算,获取type,根据type判断关键帧和普通帧//00000101 & 00011111(0x1f) = 00000101int type = buf[0] & 0x1f;//Inter Frame 帧间压缩body[0] = 0x27;//VideoHeaderTag:FrameType(2=Inter Frame)+CodecID(7=AVC)//IDR I帧图像if (type == NAL_SLICE_IDR) {body[0] = 0x17;//VideoHeaderTag:FrameType(1=key frame)+CodecID(7=AVC)}//AVCPacketType = 1body[1] = 0x01; /*nal unit,NALUs(AVCPacketType == 1)*/body[2] = 0x00; //composition time 0x000000 24bitbody[3] = 0x00;body[4] = 0x00;//写入NALU信息,右移8位,一个字节的读取?body[5] = (len >> 24) & 0xff;body[6] = (len >> 16) & 0xff;body[7] = (len >> 8) & 0xff;body[8] = (len) & 0xff;/*copy data*/memcpy(&body[9], buf, len);packet->m_hasAbsTimestamp = 0;packet->m_nBodySize = body_size;packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;//当前packet的类型:Videopacket->m_nChannel = 0x04;packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
//	packet->m_nTimeStamp = -1;packet->m_nTimeStamp = RTMP_GetTime() - start_time;//记录了每一个tag相对于第一个tag(File Header)的相对时间add_rtmp_packet(packet);
}

Native class

public class PushNative {public static final int CONNECTION_FAILED=101;public static final int INIT_FAILED=102;static {System.loadLibrary("native-lib");}LiveStateChangeListener liveStateChangeListener;public void setLiveStateChangeListener(LiveStateChangeListener liveStateChangeListener) {this.liveStateChangeListener = liveStateChangeListener;}public void removeLiveStateChangeLitener(){if (liveStateChangeListener != null){liveStateChangeListener =null;}}/*** 接收native抛出的错误*/public void throwNativeError(int code) {if (liveStateChangeListener != null) {liveStateChangeListener.onError(code);}}public native void startPush(String url);public native void releasePush();public native void stopPush();//设置音频参数public native void setAudioOptions(int sampleRateInHz, int channel);//设置视频参数public native void setVideoOptions(int width, int height, int bitrate, int fps);//发送视频public native void fireVideo(byte[] data);//发送音频public native void fireAudio(byte[] bytes, int len);
}

小结

本次主要介绍X264,其中提到的rtmp,faac,ffmpeg不展开介绍

相关资料整理如下:

《x264_SPS&PPS_简介.docx》

《x264_command.docx》

《nginx.conf》

《ffmpeg的中文文档.pdf》

《build_ffmpeg.sh》

《build_x264.sh》


上一篇:X264简介-Android使用(一)

相关文章:

X264简介-Android使用(二)

X264简介-Android使用&#xff08;二&#xff09; 4、Ubuntu上安装ffmpeg&#xff1a; 检查更新本地软件包&#xff08;如果未更新&#xff0c;reboot Vmware&#xff09;&#xff1a; sudo apt update sudo apt upgrade官网下载的source文件安装&#xff1a; http://ffmpe…...

【独家】华为OD机试 - 统计差异值大于相似值二元组个数(C 语言解题)

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...

掌握好Framework 才是王道~

现在面试对Android开发者的要求越来越高了&#xff01;从最开始的阿里、头条、腾讯等大厂&#xff0c;到现在的互联网车企&#xff0c;面试总喜欢问道 Framework底层原理的相关问题 Android Framework的三大核心功能&#xff1a; 1、View.java:View工作原理&#xff0c;实现包…...

Codeforces Round 856 (Div. 2) A — C

Codeforces Round 856 (Div. 2) 文章目录A. Prefix and Suffix Array题目大意题目分析codeB. Not Dividing题目大意题目分析codeC. Scoring Subsequences题目大意题目分析codeA. Prefix and Suffix Array 题目大意 给出一个字符串所有的非空前后缀&#xff0c;判断原字符串是…...

2022年MathorCup数学建模B题无人仓的搬运机器人调度问题解题全过程文档加程序

2022年第十二届MathorCup高校数学建模 B题 无人仓的搬运机器人调度问题 原题再现 本题考虑在无人仓内的仓库管理问题之一&#xff0c;搬运机器人 AGV 的调度问题。更多的背景介绍请参看附件-背景介绍。对于无人仓来说&#xff0c;仓库的地图模型可以简化为图的数据结构。 仓库…...

开源项目的演进会遇到哪些“坑”?KubeVela 从发起到晋级 CNCF 孵化的全程回顾

作者&#xff1a;孙健波、曾庆国 点击查看&#xff1a;「开源人说」第五期《KubeVela&#xff1a;一场向应用交付标准的冲锋》 2023 年 2 月&#xff0c;**KubeVela [ 1] ** 经过全体 ToC 投票成功进入 CNCF Incubation&#xff0c;是云原生领域首个晋级孵化的面向应用的交付…...

MSDP实验配置

目录 配置MSDP 配置PIM SM协议 配置各PIM SM域内的静态RP 配置MSDP对等体 配置域内的MSDP对等体 AR8和AR9建立EBGP邻居 配置域间的MSDP对等体 进行实验验证 什么是MSDP MSDP&#xff08;Multicast Source Discovery Protocol&#xff09;组播源发现协议的简称 用来传递…...

惊!初中生也来卷了……

大家好&#xff0c;我是良许。 前两天在抖音直播的时候&#xff0c;突然来了一位不速之客…… 他自称是初中生&#xff0c;一开始我还有点不太相信&#xff0c;直到跟他连麦&#xff0c;听到他还略带一些稚嫩的声音&#xff0c;我才知道&#xff0c;他没有骗我…… 他说他想学…...

kafka相关配置介绍

kafka默认配置 每个kafka broker中配置文件server.properties默认必须配置的属性如下&#xff1a; broker.id0 num.network.threads2 num.io.threads8 socket.send.buffer.bytes1048576 socket.receive.buffer.bytes1048576 socket.request.max.bytes104857600 log.dirs/tmp/…...

【PyTorch】教程:torch.nn.Hardtanh

torch.nn.Hardtanh 原型 CLASS torch.nn.Hardtanh(min_val- 1.0, max_val1.0, inplaceFalse, min_valueNone, max_valueNone) 参数 min_val ([float]) – 线性区域的最小值&#xff0c;默认为 -1max_val ([float]) – 线性区域的最大值&#xff0c;默认为 1inplace ([bool]) …...

神垕古镇景区5A级十年都没有实现的三大主因

钧 瓷 内 参 第40期&#xff08;总第371期&#xff09; 2023年3月5日 神垕古镇景区5A级十年都没有实现的三大主因 这是2013年&#xff0c;禹州市市政府第一次提出创建5A级景区到今年三月份整整十年啊&#xff01; 目前神垕古镇景区是4A级景区&#xff0c;5A级一直进行中&a…...

react函数组件常用的几个钩子函数useState、useEffect、useRef、useCallback

react框架react框架包括包括两大类&#xff1a;类组件函数组件。类组件构成&#xff1a;constructor自定义方法。调用方法通过this.方法名()。constructor(superstate)构造器里面必有super字段。render()方法里面写页面布局。函数组件构成&#xff1a;各种钩子函数return()方法…...

4N60-ASEMI高压MOS管4N60

编辑-Z 4N60在TO-220封装里的静态漏极源导通电阻&#xff08;RDS(ON)&#xff09;为2.5Ω&#xff0c;是一款N沟道高压MOS管。4N60的最大脉冲正向电流ISM为16A&#xff0c;零栅极电压漏极电流(IDSS)为1uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。4N60功耗&#xff08;…...

现代神经网络(VGG),并用VGG16进行实战CIFAR10分类

专栏&#xff1a;神经网络复现目录 本章介绍的是现代神经网络的结构和复现&#xff0c;包括深度卷积神经网络&#xff08;AlexNet&#xff09;&#xff0c;VGG&#xff0c;NiN&#xff0c;GoogleNet&#xff0c;残差网络&#xff08;ResNet&#xff09;&#xff0c;稠密连接网络…...

Java代码弱点与修复之——Dereference null return value(间接引用空返回值)

弱点描述 Dereference null return value,间接引用空返回值。是Coverity Scan静态代码分析工具中的一个警告,表示代码中有对可能为空(null)的方法或函数返回值进行间接引用(Dereference)操作。 该类型的漏洞可能会导致 NullPointerException 异常,并且会导致程序崩溃或…...

【冲刺蓝桥杯的最后30天】day3

大家好&#x1f603;&#xff0c;我是想要慢慢变得优秀的向阳&#x1f31e;同学&#x1f468;‍&#x1f4bb;&#xff0c;断更了整整一年&#xff0c;又开始恢复CSDN更新&#xff0c;从今天开始更新备战蓝桥30天系列&#xff0c;一共30天&#xff0c;如果对你有帮助或者正在备…...

光伏发电嵌入式ARM工控机

随着智慧电力技术的不断发展和普及&#xff0c;越来越多的电力设备和系统需要采用先进的控制和监测技术来实现自动化管理和优化运行。其中&#xff0c;嵌入式 ARM 控制器技术在智慧电力领域中得到了广泛应用。同时&#xff0c;导轨安装也是该技术的重要应用场景之一。 导轨安装…...

推荐 7 个 Vue.js 插件,也许你的项目用的上(五)

当我们可以通过使用库轻松实现相同的结果时&#xff0c;为什么还要编写自定义功能&#xff1f;开发人员最好的朋友和救星就是这些第三方库。我相信一个好的项目会利用一些可用的最佳库。Vue.js 是创建用户界面的最佳 JavaScript 框架之一。这篇文章是关于 Vue.js 的优秀库系列的…...

1.1基于知识图谱的项目实战:优酷搜索泛查询意图优化

NLU的技术实现主要分为在线识别和离线数据挖掘两块。 1.在线识别 NLU的在线识别技术栈如下图所示,共由下述2个部分组成: 第一个部分是Slot Filling(成分分析),负责对query进行实体识别和槽位抽取;第二部分Inention Detection(意图识别),根据提取的槽位进行意图的判定(目…...

[java Spring JdbcTemplate配合mysql实现数据批量删除

之前的文章 java Spring JdbcTemplate配合mysql实现数据批量添加和文章java Spring JdbcTemplate配合mysql实现数据批量修改 先后讲解了 mysql数据库的批量添加和批量删除操作 会了这两个操作之后 批量删除就不要太简单 我们看到数据库 这里 我们用的是mysql工具 这里 我们有…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...