当前位置: 首页 > 编程日记 > 正文

Android NDK开发之旅29 云服务器Ubuntu下搭建NDK环境,并编译FFmpeg

###前言

因为在Linux环境下编译FFmpeg生成库和头文件下比较方便,所以接下来主要操作在Linux环境下进行。但是对于Android NDK 开发新手来说,自己电脑配置Ubuntu Linux环境过程比较繁琐。而采用云服务器极大的方便了此过程,服务器对客户端远程的支持,让个人开发更加有拓展性和创意性,而且也便利于接下来课程学习。 现在云服务器发展迅速,有阿里云、腾讯云、百度云、京东云、美团云、网易云等等。开发者可以根据自己的需求选择合适的云服务器。学习与使用云服务器的过程,有利于提升自己个人能力。 这里我购买了京东云服务器Ubuntu 14.04 64位进行开发。

###1、了解Linux基本操作指令与常用快捷键 熟悉Linux 基本操作指令与常用快捷键能加快我们的编程速度,在这里我只列举本篇文章中遇到的指令与快捷键,其他的大家可以自己查找资料去学习。

基本指令与快捷键解释
ls输出当前文件夹下包含的子文件
mkdir xx创建文件夹xx
cd ../进入到上一级目录
cd /xx/进入到xx目录
reset让终端回到预设状态
clear清屏
Tab键内容联想;比如,该目录下有一个android-ndk-r14b文件夹,先输入一个a,
再按Tab键就会自动把android-ndk-r14b 文件名输入到命令行中,便于操作。
touch xxx.xx新建xxx.xx的文件
apt-get install xx在linux系统下安装某个程序
rm -rf xx删除文件夹xx和及其目录下所有文件

###2、云服务器Ubuntu基本配置 了解完Linux基本操作指令与常用快捷键,现在我们进行云服务器Ubuntu基本配置。 ####2.1、下载Xshell和Xftp,用来远程控制云服务器。

Xshell是一个强大的安全终端模拟软件,方便操作命令行。 Xftp是一个基于 MS windows 平台的功能强大的SFTP、FTP 文件传输软件,方便传输文件。

####2.2、Xshell连接云服务器 #####2.2.1、新建会话 ######(1)文件->新建
输入云服务器对应的公网IP地址

######(2)属性->用户身份验证
输入云服务器设置的用户名和密码

#####2.2.2、连接

####3.1、xftp连接云服务器 #####3.1.1、新建会话

######注意:这里一定要选择SFTP

#####3.1.2、连接

#####注意:有文件新增和删除和修改时,记得点击刷新按钮刷新目录。


###4、在云主机Ubuntu 中安装所需的程序 ####4.1、安装vim并对其配置 #####4.1.1、安装 输入命令 ``` apt-get install vim /etc/vim/vimrc-gtk ``` ![安装vim](http://upload-images.jianshu.io/upload_images/1824809-fadfeb39da76ede7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) #####4.1.2、查看vim安装成功 输入命令 ``` vim /etc/vim/vimrc ``` ![vim安装成功页面](http://upload-images.jianshu.io/upload_images/1824809-472c5f168553d779.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) #####4.1.3、配置vimrc ######(1)点击 i 键,进入到进入编辑模式 ######(2)设定光标和行数参数 ``` set nu "显示行号 set tabstop set ruler "显示光标位置 set cursorline "光标高亮显示 ``` ![](http://upload-images.jianshu.io/upload_images/1824809-f973da4e643a991a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ######注意:`-- INSERT --`表示现在是编辑模式 ######(3)保存退出 ``` 按Esc键 再次进入命令模式 shift + : 再输入 x 保存退出 或shift + z z 保存退出 ``` ######其他快捷键的使用 ``` shift + : 再输入 q! 强制退出

命令模式下,x 表示删除,dd 表示删除行

####4.2、安装 dos2unix 将DOS格式的文本文件转换成UNIX格式
复制代码

apt-get install dos2unix

####4.3、安装make用来完成编译工作
复制代码

apt-get install make

####4.4、安装unzip用来解压zip文件包
复制代码

apt-get install unzip

<br>
###5、搭建NDK环境
####5.1、下载Linux版本的[NDK](https://developer.android.google.cn/ndk/downloads/index.html)
我下载的是android-ndk-r14b-linux-x86_64.zip这个文件,大家则根据自己项目需要下载。
####5.2、在\目录下创建一个usr文件夹
![](http://upload-images.jianshu.io/upload_images/1824809-b5b9ac474a9dcc5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
复制代码

cd / mkdir usr


![创建了usr文件夹](http://upload-images.jianshu.io/upload_images/1824809-474008f5c97daaa9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
######说明:有些开发者问我,usr之外的文件是怎么来的?这些文件是你买云服务的时候,已经配置好的。大家可以先不用管。
####5.3、在usr目录中创建NDK目录,通过Xftp上传已下载好压缩文件
复制代码

mkdir NDK

####5.4、 赋予ndk文件夹下所有文件的drwx权限,使其可执行解压操作。
复制代码

chmod 777 -R ndk

![权限操作](http://upload-images.jianshu.io/upload_images/1824809-b908d1a40dc246dd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
####5.5、解压上传的的`zip`文件解压zip文件到ndk文件下
复制代码

unzip android-ndk-r14b-linux-x86_64.zip

######注意:解压过程比较长属于正常情况
![解压结果](http://upload-images.jianshu.io/upload_images/1824809-3437dd84a503c72c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
####5.6、配置NDK环境变量使用命令`vim ~/.bashrc`  进入到环境变量配置文件进行编辑  (~代表用户),添加
复制代码

export NDKROOT=/usr/ndk/android-ndk-r14b export PATH=$NDKROOT:$PATH

![配置环境变量](http://upload-images.jianshu.io/upload_images/1824809-9a2a15b2118d659e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)####5.7、更新环境变量
使用命令`source ~/.bashrc`更新环境变量,`ndk-build -v` 查看是否配置成功
![环境变量配置成功](http://upload-images.jianshu.io/upload_images/1824809-d17328c94a133eeb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
至此,NDK环境已经搭建好了。<br>
###6、编译FFmpeg
####6.1、到[FFmpeg官网](http://ffmpeg.org/download.html)下载`FFmpge. zip`
我这里使用`FFmpeg 2.6.9`版本,建议大家用2.8以下版本,出现问题便于解决。
####6.2、上传FFmpeg文件并解压
使用`xftp`上传`ffmpeg`压缩包,使用命令`unzip ffmpeg-2.6.9.zip`解压文件
![](http://upload-images.jianshu.io/upload_images/1824809-caa99e0c279ca41a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
####6.3、修改 ffmpeg-2.6.9 目录下的configure文件
修改输出的动态库的命名规则:
复制代码

注释或删除以下语句 SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

同时修改成以下语句 SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS='$(SLIBNAME)'

######注意:如果不进行这一步操作,将生成以.56、.5、.3等结尾的库,这种库Android很难加载到,我们需要的是后缀.so结尾的库。
####6.4、编写shell脚本文件并将其放在ffmpeg-2.6.9目录下
```build_android.sh```文件:
复制代码

#!/bin/bash make clean export NDK=/usr/ndk/android-ndk-r14b
export SYSROOT=$NDK/platforms/android-9/arch-arm/ export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 export CPU=arm export PREFIX=$(pwd)/android/$CPU export ADDI_CFLAGS="-marm"

function build_one { ./configure --target-os=linux
--prefix=$PREFIX --arch=arm
--disable-doc
--enable-shared
--disable-static
--disable-yasm
--disable-symver
--enable-gpl
--disable-ffmpeg
--disable-ffplay
--disable-ffprobe
--disable-ffserver
--disable-doc
--disable-symver
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi-
--enable-cross-compile
--sysroot=$SYSROOT
--extra-cflags="-Os -fpic $ADDI_CFLAGS"
--extra-ldflags="$ADDI_LDFLAGS"
$ADDITIONAL_CONFIGURE_FLAG make clean make -j4 make install }

>指定NDK路径:export NDK=/usr/ndk/android-ndk-r14b ;
配置CPU架构类型:export CPU=arm,PREFIX是指定动态库输出的路径,然后disable一些不需要的库(可减小输出的动态库的大小);
enable-shared:生成共享库。#####注意:* 换行的时候需要有\,注意不要有额外的空格,否则编译出错
* 脚本文件统一转为UTF-8无BOM格式。可通过note pad++进行转码,或者先由Linux创建文件再由Windows编辑。
* NDK尽量不要使用太新的版本,一般使用Android-9即可,否则会出现在Android编译不兼容老版本而无法使用的问题。
* 将编写好的shell脚本放在解压后的ffmpeg-2.6.9文件夹中。
####6.5、build_android.sh给予执行权限。
复制代码

chmod 777 -R build_android.sh

####6.6、执行文件build_android
复制代码

./build_android.sh

![执行结束页面](http://upload-images.jianshu.io/upload_images/1824809-e8c0b38c94fb21db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)######说明:
如果出现问题`:bad interpreter : No such file or directory`,原因:没有将文件转成Linux编码格式。
转换Linux编码格式有两种方式:
复制代码

1、在Linux下创建这个文件touch build_android.sh,从Linux传出到桌面,然后把脚本命令拷入这个文件中,再重新上传到Linux; 2、使用 dos2unix build_android.sh 转成Linux编码格式

####6.7、用xftp查看生成文件
我们发现在ffmpeg-2.6.9文件夹生成android文件夹,在android文件夹下生成arm文件夹
![生成的include和lib](http://upload-images.jianshu.io/upload_images/1824809-a8e0c18e1f083305.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![include目录](http://upload-images.jianshu.io/upload_images/1824809-47b0310748554500.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![lib目录](http://upload-images.jianshu.io/upload_images/1824809-e9b3131668d4738e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
至此,FFmpeg库已编译完成。<br>
###7、利用编译好的FFmpeg库写一个视频解码Demo
####7.1、jni Java声明
复制代码

public class VideoUtils {

public native static void decode(String input,String output);static{System.loadLibrary("avutil-54");System.loadLibrary("swresample-1");System.loadLibrary("avcodec-56");System.loadLibrary("avformat-56");System.loadLibrary("swscale-3");System.loadLibrary("postproc-53");System.loadLibrary("avfilter-5");System.loadLibrary("avdevice-56");System.loadLibrary("myffmpeg");
}
复制代码

}

####7.2、编写C主程序
![jni目录](http://upload-images.jianshu.io/upload_images/1824809-a2ba5b80afca7b65.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)#####ffmpeg_player.c
复制代码

#include <com_haocai_ffmpegtest_VideoUtils.h>

#include <android/log.h>

//解码 #include "include/libavcodec/avcodec.h" //封装格式处理 #include "include/libavformat/avformat.h" //像素处理 #include "include/libswscale/swscale.h"

#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"FFmpeg",FORMAT,##VA_ARGS); #define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"FFmpeg",FORMAT,##VA_ARGS);

JNIEXPORT void JNICALL Java_com_haocai_ffmpegtest_VideoUtils_decode (JNIEnv env, jclass jcls, jstring input_jstr, jstring output_jstr){ //需要转码的视频文件(输入的视频文件) const char input_cstr = (env)->GetStringUTFChars(env,input_jstr,NULL); const char output_cstr = (*env)->GetStringUTFChars(env,output_jstr,NULL);

//1.注册所有组件
av_register_all();//封装格式上下文,统领全局的结构体,保存了视频文件封装格式的相关信息
AVFormatContext *pFormatCtx = avformat_alloc_context();//2.打开输入视频文件
if (avformat_open_input(&pFormatCtx, input_cstr, NULL, NULL) != 0)
{LOGE("%s","无法打开输入视频文件");return;
}//3.获取视频文件信息
if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
{LOGE("%s","无法获取视频文件信息");return;
}//获取视频流的索引位置
//遍历所有类型的流(音频流、视频流、字幕流),找到视频流
int v_stream_idx = -1;
int i = 0;
//number of streams
for (; i < pFormatCtx->nb_streams; i++)
{//流的类型if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){v_stream_idx = i;break;}
}if (v_stream_idx == -1)
{LOGE("%s","找不到视频流\n");return;
}//只有知道视频的编码方式,才能够根据编码方式去找到解码器
//获取视频流中的编解码上下文
AVCodecContext *pCodecCtx = pFormatCtx->streams[v_stream_idx]->codec;
//4.根据编解码上下文中的编码id查找对应的解码
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
//(迅雷看看,找不到解码器,临时下载一个解码器)
if (pCodec == NULL)
{LOGE("%s","找不到解码器\n");return;
}//5.打开解码器
if (avcodec_open2(pCodecCtx,pCodec,NULL)<0)
{LOGE("%s","解码器无法打开\n");return;
}//输出视频信息
LOGI("视频的文件格式:%s",pFormatCtx->iformat->name);
LOGI("视频时长:%lld", (pFormatCtx->duration)/1000000);
LOGI("视频的宽高:%d,%d",pCodecCtx->width,pCodecCtx->height);
LOGI("解码器的名称:%s",pCodec->name);//准备读取
//AVPacket用于存储一帧一帧的压缩数据(H264)
//缓冲区,开辟空间
AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));//AVFrame用于存储解码后的像素数据(YUV)
//内存分配
AVFrame *pFrame = av_frame_alloc();
//YUV420
AVFrame *pFrameYUV = av_frame_alloc();
//只有指定了AVFrame的像素格式、画面大小才能真正分配内存
//缓冲区分配内存
uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
//初始化缓冲区
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//用于转码(缩放)的参数,转之前的宽高,转之后的宽高,格式等
struct SwsContext *sws_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,SWS_BICUBIC, NULL, NULL, NULL);int got_picture, ret;FILE *fp_yuv = fopen(output_cstr, "wb+");int frame_count = 0;//6.一帧一帧的读取压缩数据
while (av_read_frame(pFormatCtx, packet) >= 0)
{//只要视频压缩数据(根据流的索引位置判断)if (packet->stream_index == v_stream_idx){//7.解码一帧视频压缩数据,得到视频像素数据ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);if (ret < 0){LOGE("%s","解码错误");return;}//为0说明解码完成,非0正在解码if (got_picture){//AVFrame转为像素格式YUV420,宽高//2 6输入、输出数据//3 7输入、输出画面一行的数据的大小 AVFrame 转换是一行一行转换的//4 输入数据第一列要转码的位置 从0开始//5 输入画面的高度sws_scale(sws_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);//输出到YUV文件//AVFrame像素帧写入文件//data解码后的图像像素数据(音频采样数据)//Y 亮度 UV 色度(压缩了) 人对亮度更加敏感//U V 个数是Y的1/4int y_size = pCodecCtx->width * pCodecCtx->height;fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);frame_count++;LOGI("解码第%d帧",frame_count);}}//释放资源av_free_packet(packet);
}fclose(fp_yuv);(*env)->ReleaseStringUTFChars(env,input_jstr,input_cstr);
(*env)->ReleaseStringUTFChars(env,output_jstr,output_cstr);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_free_context(pFormatCtx);
复制代码

}

####7.3、写mk文件
#####Android.mk
复制代码

LOCAL_PATH := $(call my-dir)

#ffmpeg lib include $(CLEAR_VARS) LOCAL_MODULE := avcodec LOCAL_SRC_FILES := libavcodec-56.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := avdevice LOCAL_SRC_FILES := libavdevice-56.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := avfilter LOCAL_SRC_FILES := libavfilter-5.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := avformat LOCAL_SRC_FILES := libavformat-56.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := avutil LOCAL_SRC_FILES := libavutil-54.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := postproc LOCAL_SRC_FILES := libpostproc-53.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := swresample LOCAL_SRC_FILES := libswresample-1.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := swscale LOCAL_SRC_FILES := libswscale-3.so include $(PREBUILT_SHARED_LIBRARY)

#myapp include $(CLEAR_VARS) LOCAL_MODULE := myffmpeg LOCAL_SRC_FILES := ffmpeg_player.c LOCAL_C_INCLUDES += $(LOCAL_PATH)/include LOCAL_LDLIBS := -llog LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale include $(BUILD_SHARED_LIBRARY)

#####Applicatoin.mk
复制代码

APP_MODULES := myffmpeg APP_ABI := armeabi APP_PLATFORM := android-9


####7.4、Android调用主函数
复制代码

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
}public void mDecode(View btn){String input = new File(Environment.getExternalStorageDirectory(),"小苹果.mp4").getAbsolutePath();String output = new File(Environment.getExternalStorageDirectory(),"小苹果_out.yuv").getAbsolutePath();VideoUtils.decode(input, output);
}
复制代码

}

####7.5、其它文件配置
#####build.gradle中
复制代码
    ndk{moduleName "myffmpeg"}sourceSets.main{jni.srcDirs = []jniLibs.srcDir "src/main/libs"}
复制代码

#####AndroidManifest.xml中
复制代码
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
复制代码

####7.6 结果运行
#####7.6.1、Log输出
复制代码

I/FFmpeg: 视频的文件格式:mov,mp4,m4a,3gp,3g2,mj2 I/FFmpeg: 视频时长:211 I/FFmpeg: 视频的宽高:720,480 I/FFmpeg: 解码器的名称:mpeg4 I/FFmpeg: 解码第1帧 I/FFmpeg: 解码第2帧 I/FFmpeg: 解码第3帧 I/FFmpeg: 解码第4帧 I/FFmpeg: 解码第5帧 I/FFmpeg: 解码第6帧 I/FFmpeg: 解码第7帧 I/FFmpeg: 解码第8帧 I/FFmpeg: 解码第9帧 太多省略......

#####7.6.2、mp4转换格式生成的文件![](http://upload-images.jianshu.io/upload_images/1824809-1fcf1a62c2b94c7b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
至此,Android调用FFmpeg库完成。
<br>
###结语
#####虽然过程漫长,但我相信大家会涨不少知识。
<br>
###源码下载
#####Github:[https://github.com/kpioneer123/FFmpegTest](https://github.com/kpioneer123/FFmpegTest)复制代码

相关文章:

一个App卖了4亿美元,这家听声识曲公司为何得到Apple的青睐?

作者 | 琥珀 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 是否可以将 Shazam 称为有听歌识曲功能应用的鼻祖&#xff1f; 2018 年 9 月&#xff0c;苹果最终以 4 亿美金完成对 Shazam 公司的收购&#xff0c;让不少人为之振奋&#xff0c;在当时对外公布的一份声…

Product Orders(生产订单)状态相关函数BAPI

[相关表] JEST-对象的系统状态&#xff08;I****&#xff09;和用户状态(E****) JSTO-状态对象信息 TJ02T-系统状态文本 -用户状态文本 【锁对象】&#xff1a;生产订单锁对象 ESORDER 函数&#xff1a; ENQUEUE_ESORDER&#xff0c; DEQUEUE_ESORDER [函数1]&#xff1a;检…

5行代码就能入门爬虫?

作者 | 苏克1900来源 | 第2大脑&#xff08;ID&#xff1a;Mocun6&#xff09;责编 | swallow不少读者是刚刚入门Python或者想学习Python的&#xff0c;今天就来谈谈如何用快速入门爬虫。先说结论&#xff1a;入门爬虫很容易&#xff0c;几行代码就可以&#xff0c;可以说是学习…

【云周刊】第146期:史上最大规模人机协同的双11,12位技术大V揭秘背后黑科技...

摘要&#xff1a;史上最大规模人机协同的双11&#xff0c;12位技术大V揭秘背后黑科技&#xff0c;INTERSPEECH 2017系列 | 语音识别之语言模型技术&#xff0c;机器学习初学者必须知道的十大算法&#xff0c;云数据库SQL Server 2016和新技术应用...更多精彩内容&#xff0c;尽…

【驱动】GNSS驱动基础

GNSS:Global Navigation Satellite System(全球卫星导航系统) GPS:Global Positioning System(全球定位系统) GPS是美国的卫星导航系统。 还有&#xff0c;俄罗斯的GLONASS&#xff1b;欧盟的Galileo&#xff1b;中国的北斗。 这几大导航系统统称为GNSS GLONASS、Galileo、…

ibaits插入即获取主键(mssql,mysql,oracle)

oracle主键需预先生成&#xff0c;通过sequence&#xff1b;mysql和mssql是插入后生成。 mysql: <insert id"insertStu_mysql" parameterClass"stu"> insert into stu(name) values (#name#) <selectKey resultClass"int" keyProper…

【驱动】GNSS驱动:gpsOneXTRA 援助技术

什么是 “gpsOneXTRA 援助技术”&#xff1f; 高通 gpsOneXTRA 的援助技术在公司的改进中扩展了 gps 芯片组, 允许通过互联网连接下载辅助 gps。芯片组为更精确的位置发现提供了更高的灵敏度, 尤其是在通常难以找到 GPS 信号的位置。 gpsOneXTRA:帮助提高了独立的性能&#x…

2017年书单整理

android书籍: Android进阶之光 刘望舒 点评一下&#xff0c;这本书呢&#xff0c;涉猎很广&#xff0c;涉及的技术&#xff0c;开源库挺多的&#xff0c;适合广度面上的知识增长&#xff0c;对于深度上的提高价值不大&#xff0c;我觉得对我没啥太大价值额 Android安全技术揭秘…

华南理工大学院长涉嫌篡改8名研究生成绩,4人已停职

整理 | 一一出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;2 月 11 日&#xff0c;网友平凡的世界overlooker 在新浪微博上报料&#xff0c;称华南理工大学计算机科学与工程学院的院领导于 2018 年研究生复试结束后&#xff0c;篡改 8 位考生的考试成绩&#xff0c;…

我心中的最佳阵容

世界杯的激情还在心中涤荡&#xff0c;但新赛季的各大联赛却已悄然开打&#xff0c;这里给出我心中的几项最佳&#xff0c;期待他们本赛季的完美表现。 最佳球队&#xff1a;切尔西&#xff08;上赛季切尔西在安帅执掌球队的首个赛季便夺得英超冠军&#xff0c;欧冠虽惜败于曾经…

如何让AI教机器自己玩俄罗斯方块?

作者 | Ahab转载自公众号Ahab杂货铺&#xff08;ID:PythonLearningCamp&#xff09;人工智能大火的今天&#xff0c;如果还是自己玩俄罗斯方块未免显得太 LOW&#xff0c;为什么不对游戏升级&#xff0c;让机器自己去玩俄罗斯方块呢&#xff1f;有了这个想法之后&#xff0c;我…

【驱动】内核打印级别设置

在uboot中设置 setenv loglevel loglevel8 setenv loglevel debug setenv loglevel quiet setenv loglevel setenv mmcargs run set_disp; setenv bootargs console${console},${baudrate} ${loglevel} ${smp} root${mmcroot} ${disp_args}内核对应代码 main.c (init) 467 s…

vue基本标签

2019独角兽企业重金招聘Python工程师标准>>> vue基本是数据驱动&#xff0c;数据双向绑定&#xff0c;组件化&#xff0c;常用标签v-modal,v-html,v-if,v-else,v-show,v-for,v-on(简写)&#xff0c;v-bind(简写 :) vue.js 兼具 angular.js 和 react.js 的优点&#…

C#操作域用户

using System;using System.DirectoryServices;namespace SystemFrameworks.Helper{ /// ///活动目录辅助类。封装一系列活动目录操作相关的方法。 /// public sealed class ADHelper { /// ///域名 /// private static s…

Redis进阶实践之三如何在Windows系统上安装安装Redis

一、Redis的简介 Redis是一个key-value存储系统。和Memcached类似&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash&#xff08;哈希类型&#xff09;。这些数据类型都支持push/po…

31页PPT概述:图神经网络表达能力有多强?

整理 | 一一出品 | AI科技大本营近年来&#xff0c;图神经网络的研究成为深度学习领域的热点。图是一种数据结构&#xff0c;它对一组对象&#xff08;节点&#xff09;及其关系&#xff08;边&#xff09;进行建模&#xff0c;由于图结构的强大表现力&#xff0c;用机器学习方…

【linux】Linux kernel uapi header file(用户态头文件)

uapi目录的创建原因 Linux在3.7以后把很多header file移到 include/uapi或是arch/xxxx/include/uapi下&#xff0c;为了解决include recursive&#xff08;循环包含头文件&#xff09;的问题。 英文参考文档&#xff1a;https://lwn.net/Articles/507794/ 解决include recur…

诊断IIS中的ASP0115错误

诊断IIS中的ASP0115错误 作者:未知 重要说明&#xff1a;本文包含有关修改注册表的信息。修改注册表之前&#xff0c;一定要备份注册表&#xff0c;并且一定要知道在发生问题时如何还原注册表。有关如何备份、还原和编辑注册表的信息&#xff0c;请单击下面的文章…

【imx6】libipu.so.0说明

###代码位置 在目录fsl-release-bsp/build-fb/tmp/work/imx6qsabresd-poky-linux-gnueabi/imx-lib/1_3.14.28-1.0.0-r0/imx-lib-3.14.28-1.0.0/ipu中 编译完成后有如下文件列表 ipu$ ls Android.mk libipu.so Makefile mxc_ipu_hl_lib_dummy.c mxc_ipu_hl_lib.…

“安利”一款debug神器:在AI面前,bug都不是事儿

作者 | 琥珀出品 | AI科技大本营&#xff08;公众号ID&#xff1a;rgznai100&#xff09;为了帮程序员解决 bug 问题&#xff0c;Facebook 可算是操碎了心&#xff01;你可以这么想&#xff0c;如果在开发和测试阶段没有发现 bug 问题&#xff0c;那么 bug 将会随着产品发布&am…

Spring中@Value用法收集

一、配置方式 Value需要参数&#xff0c;这里参数可以是两种形式&#xff1a; Value("#{configProperties[t1.msgname]}") 或者 Value("${t1.msgname}")&#xff1b; 这两形式&#xff0c;在配置上有什么区别&#xff1a; 1、Value("#{configPropert…

vue从入门到进阶:指令与事件(二)

一.插值 v-once 通过使用 v-once 指令&#xff0c;你也能执行一次性地插值&#xff0c;当数据改变时&#xff0c;插值处的内容不会更新。但请留心这会影响到该节点上所有的数据绑定&#xff1a; span v-once>这个将不会改变: {{ msg }}</span> v-html 双大括号会将数据…

【ubuntu工具】bless:二进制查看工具,类似win下的UltraEdit

###安装 sudo apt-get install bless 使用 bless filename 或者执行bless&#xff0c;在图形界面中打开准备操作的文件 工具主界面

马斯克连发三推,发布退出OpenAI内情

整理 | 一一出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;美国时间 2 月 17 日&#xff0c;特斯拉 CEO 马斯克在 Twitter 连发三帖&#xff0c;道出自己退出人工智能研究组织 OpenAI的缘由。他在推文中表示&#xff0c;他已经有一年多时间没有深度参与 OpenAI 事务…

开发代码命名规范!

今天查看以前的资料看见代码命名规范。呵呵 就拿出来给大家分享以下&#xff0c;还是比较老的。估计现在也是这种开发的命名规范。仅供参考&#xff01;谢谢。 1.用Pascal规则来命名方法和类型。 public class DataGrid { public void DataBind() {…

【linux命令】readelf工具中英文说明

简介 readelf命令用来显示一个或者多个elf格式的目标文件的信息&#xff0c;可以通过它的选项来控制显示哪些信息。 ELF文件由4部分组成&#xff0c;分别是ELF头&#xff08;ELF header&#xff09;、程序头表&#xff08;Program header table&#xff09;、节&#xff08;Se…

再见Python!Yann LeCun警告:深度学习需要新编程语言

整理 | 一一出品 | AI科技大本营尽管工程师们普遍定位 Python 是简单、优雅的编程语言&#xff0c;但它并非毫无缺点&#xff0c;比如人们一直吐槽它的执行速度不够快&#xff0c;线程不能利用多 CPU 等缺点&#xff0c;如今 AI 界泰斗也放话说要用新编程语言替代 Python。Face…

Linux系统与我之间的故事

2019独角兽企业重金招聘Python工程师标准>>> 说起Linux想必大家都不是很陌生的&#xff0c;关注这方面的不是大神就是对Linux特别热爱的人&#xff0c;那么接下来我给大家介绍下我和Linux之间的一些事&#xff0c;还有如何去快速的学习Linux。 我接触Linux大概就是大…

Google Instant 瞬时搜索上手指南

Google Instant是Google刚刚发布的一种新的搜索方式&#xff0c;随着你在搜索框里输入文字&#xff0c;Google将同时给出搜索结果&#xff0c;同时在搜索框里还会根据你输入的关键字给出搜索建议&#xff0c;通过上下键即可切换。按TAB键可自动补全第一位的搜索建议。随着你不断…

【视频】显示器固定参数struct fb_fix_screeninfo中char id[16]说明

imx6q关于fb和video的设备信息 设备节点 root@myzr:/unit_tests# ls /dev/fb* -l lrwxrwxrwx 1 root root 3 Jan 1 1970 /dev/fb -> fb0 crw-rw---- 1 root video 29, 0 Jan 1 1970 /dev/fb0 crw-rw---- 1 root video 29, 1 Jan 1 1970 /dev/fb1 crw-rw---- 1 …