首页 > 其他分享 >征程 6E/M 快速上手实战 Sample-Codec

征程 6E/M 快速上手实战 Sample-Codec

时间:2024-09-14 17:13:37浏览次数:1  
标签:6E mc mm ret Sample buffer Codec context hb

征程 6E/M 快速上手实战 Sample-Codec

01 Codec 模块简述

Codec(Coder-Decoder)是指编解码器,用于压缩或解压缩视频、图像、音频等媒体数据;J6 Soc 中存在两种硬件编解码单元,分别是 VPU(Video process unit)和 JPU(Jpeg process unit),可提供 4K@90fps 的视频编解码能力和 4K@90fps 的图像编解码能力。

1.1 硬件特性

1.1.1 JPU 硬件特性:

image

1.1.2 VPU 硬件特性:

image

image

1.2 软件功能

MediaCodec 子系统会提供音视频和图像的编解码组件,原始流封装和视频录像等功能。该系统主要会封装底层 codec 硬件资源和软件编解码库,为上层提供编解码能力。开发者可以基于提供的编解码接口实现 H265 和 H264 视频的编解码功能,也可以使用 JPEG 编码功能将摄像头数据存成 JPEG 图片,还可以使用视频录像功能实现摄像头数据的录制。

1.2.1 整体框架:

image

1.2.2 控制接口:

hb_s32 hb_mm_mc_initialize(media_codec_context_t *context):初始化编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_INITIALIZED 状态。

hb_s32 hb_mm_mc_configure(media_codec_context_t *context):配置编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_CONFIGURED 状态。

hb_s32 hb_mm_mc_start(media_codec_context_t *context, const mc_av_codec_startup_params_t *info):启动编码/解码流程,MediaCodec 将创建编解码实例、设置序列或解析数据流、注册 Framebuffer、编码头信息等,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_STARTED 状态。

hb_s32 hb_mm_mc_stop(media_codec_context_t *context):停止编码/解码流程,退出所有子线程并释放相关资源,调用成功后 MediaCodec 回到 MEDIA_CODEC_STATE_INITIALIZED 状态。

hb_s32 hb_mm_mc_release(media_codec_context_t *context):释放 MediaCodec 内部所有资源,用户需要在调用该函数前调用 hb_mm_mc_stop 来停止编解码,操作成功后 MediaCodec 进入 MEDIA_CODEC_STATE_UNINITIALIZED 状态。

hb_s32 hb_mm_mc_queue_input_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, hb_s32 timeout):填充需要处理的 buffer 到 MediaCodec 中。

hb_s32 hb_mm_mc_dequeue_input_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, hb_s32 timeout):获取输入的 buffer。

hb_s32 hb_mm_mc_queue_output_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, hb_s32 timeout):返还处理完的 output buffer 到 MediaCodec 中。

hb_s32 hb_mm_mc_dequeue_output_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, media_codec_output_buffer_info_t *info, hb_s32 timeout):获取输出的 buffer。

1.2.3 码率控制模式:

MediaCodec 支持对 H264/H265 和 MJPEG 协议的码率控制,分别支持 H264/H265 编码通道的 CBR、VBR、AVBR、FixQp 和 QpMap 五种码率控制方式,以及支持 MJPGE 编码通道的 FixQp 码率控制方式。

*1.2.3.1 CBR 说明:*

CBR 表示恒定码率,能够保证整体的编码码率稳定。下面是 CBR 模式下各个参数含义:

image

*1.2.3.2 VBR 说明:*

VBR 表示可变码率,简单场景分配比较大的 qp,压缩率小,质量高。复杂场景分配较小 qp,可以保证编码图像的质量稳定。下面是 VBR 模式下各个参数含义:

image

1.2.3.3 AVBR 说明:

ABR 表示恒定平均目标码率,简单场景分配较低码率,复杂场景分配足够码率,使得有限的码率能够在不同场景下合理分配,这类似 VBR。同时一定时间内,平均码率又接近设置的目标码率,这样可以控制输出文件的大小,这又类似 CBR。可以认为是 CBR 和 VBR 的折中方案,产生码率和图像质量相对稳定的码流。下面是 AVBR 模式下各个参数含义:

image

1.2.3.4 FixQp 说明:

FixQp 表示固定每一个 I 帧、P 帧的 QP 值,对于 I/P 帧可以分别设值。下面是 FixQp 模式下各个参数含义:

image

1.2.3.5 QPMAP 说明:

image

1.2.4 编码效果:

根据当前客户使用 codec 进行视频编码的场景,多将码率模式设置为 CBR,当编码的场景较为复杂时,为了保证视频质量,硬件会自动提高码率值,导致输出的视频较预期更大。因此为了兼顾视频质量和实际码率,需要统筹 bit_rate 和 max_qp_I/P 值的设置。下面给出了全 I 帧模式下,不同复杂场景下,码率设置为 15000kbps 时,不同 max_qp_I 下实际码率和 qp 的情况(不同场景复杂程度不同,下列数据仅供参考):

image

H264/H265 编码支持 GOP 结构的设置,用户可从预置的 3 种 GOP 结构种选择,也可自定义 GOP 结构。

GOP 结构表可定义一组周期性的 GOP 结构,该 GOP 结构将用于整个编码过程。单个结构表中的元素如下表所示,其中可以指定该图像的参考帧,如果 IDR 帧后的其他帧指定的参考帧为 IDR 帧前的数据帧,编码器内部会自动处理这种情况使其不参考其他帧,用户无需关心这种情况。用户在自定义 GOP 结构时需要指明结构表的数量,最多可定义 3 个结构表,结构表的顺序需要按照解码顺序排列。下面表示了结构表中各个元素的含义:

image

征程6 中一共支持设置九种 GOP 预置结构:

image

02 Codec-Sample 使用

编码 yuv 图像, 生成 h264/h265 视频或 jpg 图片。

2.1 encoder

** **

2.1.1 调用流程

采用 MediaCodec 的 poll 模式来解耦输入和输出,可使编码帧率性能达到最优。在主线程中灌 YUV 数据:取出一个空的 input buffer,配置 YUV 数据的地址信息(如 phys addr),再 queue input buffer 并通知编码器处理该帧数据;另一个线程取输出码流:通过 select 接收硬件编码完成通知,取出一个硬件填满输出码流的 output buffer,将编码结果写到文件中后归还 output buffer。

image

check_and_init_test:打开输入文件(yuv),并打开内存管理模块申请内存缓冲;

hb_mm_mc_initialize:初始化编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_INITIALIZED 状态;

hb_mm_mc_configure:配置编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_CONFIGURED 状态;

hb_mm_mc_start:启动编码/解码流程,MediaCodec 将创建编解码实例、设置序列或解析数据流、注册 Framebuffer、编码头信息等,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_STARTED 状态;

hb_mm_mc_dequeue_input_buffer:获取输入的 buffer;

read_input_frames:从输入文件(yuv)中读取视频帧数据,并将其刷新到 buffer 中;

hb_mm_mc_queue_input_buffer:填充需要处理的 buffer 到 MediaCodec 中;

hb_mm_mc_dequeue_output_buffer:获取输出的 buffer;

write_output_streams:outputbuffer 写入 outFile 中;

hb_mm_mc_queue_output_buffer:返还处理完的 output buffer 到 MediaCodec 中;

hb_mm_mc_stop:停止编码/解码流程,退出所有子线程并释放相关资源,调用成功后 MediaCodec 回到 MEDIA_CODEC_STATE_INITIALIZED 状态;

hb_mm_mc_release:释放 MediaCodec 内部所有资源,操作成功后 MediaCodec 进入 MEDIA_CODEC_STATE_UNINITIALIZED 状态。

2.1.2 源码主干:

#Sample源码路径
/test/samples/platform_samples/source/S83_Sample/S83E04_Module/codec_sample

Encoder:

void do_sync_encoding(void *arg)
{
 hb_s32 ret = 0;
 MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
 media_codec_context_t *context = NULL;
 media_codec_buffer_t inputBuffer;
 media_codec_buffer_t outputBuffer;
 media_codec_output_buffer_info_t info;

 ret = check_and_init_test(ctx);
 if (ret != 0) {
     printf("check_and_init_test failed(%d).\n", ret);
     return;
 }

 context = ctx->context;
 ret = hb_mm_mc_initialize(context);
 if (ret != 0) {
     printf("hb_mm_mc_initialize failed(%d).\n", ret);
     return;
 }

 // set_message(ctx);

 ret = hb_mm_mc_configure(context);
 if (ret != 0) {
     printf("hb_mm_mc_configure failed(%d).\n", ret);
     hb_mm_mc_release(context);
     return;
 }

 mc_av_codec_startup_params_t startup_params;
 startup_params.video_enc_startup_params.receive_frame_number = 0;
 ret = hb_mm_mc_start(context, &startup_params);
 if (ret != 0) {
     printf("hb_mm_mc_start failed(%d).\n", ret);
     hb_mm_mc_release(context);
     return;
 }

 do {
     // process input buffers
     memset(&inputBuffer, 0x00, sizeof(media_codec_buffer_t));
     ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 3000);
     if (ret == 0) {
         ret = read_input_frames(ctx, &inputBuffer);
         if (ret <= 0) {
             printf("There is no more input data(ret=%d)!\n", ret);
             inputBuffer.vframe_buf.size = 0;
             inputBuffer.vframe_buf.frame_end = TRUE;
         }

         ctx->input_num++;
         // ASSERT_EQ(do_encode_params_setting(ctx, &inputBuffer), 0);

         ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
         if (ret != 0) {
             break;
         }
     } else {
         printf("dequeue input buffer fail(%d).\n", ret);
         if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
             break;
         }
     }

     // process output buffers
     memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
     memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
     ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info, 3000);
     if (ret == 0) {
         write_output_streams(ctx, &outputBuffer);
         ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
         if (outputBuffer.vstream_buf.stream_end) {
             printf("There is no more output data!\n");
             break;
         }
         if (ret) {
             break;
         }
     } else {
         printf("dequeue output buffer fail(ret=0x%x).\n", ret);
         if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
             break;
         }
     }

 } while(TRUE);

 ret = hb_mm_mc_stop(context);
 if (ret != 0) {
     printf("hb_mm_mc_stop failed(%d).\n", ret);
 }

 ret = hb_mm_mc_release(context);
 if (ret != 0) {
     printf("hb_mm_mc_release failed(%d).\n", ret);
 }

 check_and_release_test(ctx);

}

2.2 decoder

VPU/JPU 从 DDR 中获得 H265/H264/JPG 输入源,经过硬件解码后生成 yuv 图像

2.2.1 调用流程

image

check_and_init_test:打开输入文件(h265),并打开内存管理模块申请内存缓冲;

hb_mm_mc_initialize:初始化编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_INITIALIZED 状态;

hb_mm_mc_configure:配置编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_CONFIGURED 状态;

hb_mm_mc_start:启动编码/解码流程,MediaCodec 将创建编解码实例、设置序列或解析数据流、注册 Framebuffer、编码头信息等,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_STARTED 状态;

hb_mm_mc_dequeue_input_buffer:获取输入的 buffer;

hb_mm_mc_dequeue_output_buffer:获取输出的 buffer;

write_output_streams:outputbuffer 写入 outFile 中;

hb_mm_mc_queue_output_buffer:返还处理完的 output buffer 到 MediaCodec 中;

hb_mm_mc_stop:停止编码/解码流程,退出所有子线程并释放相关资源,调用成功后 MediaCodec 回到 MEDIA_CODEC_STATE_INITIALIZED 状态;

hb_mm_mc_release:释放 MediaCodec 内部所有资源,操作成功后 MediaCodec 进入 MEDIA_CODEC_STATE_UNINITIALIZED 状态。

** **

2.2.2 源码主干:

void do_sync_decoding(void *arg)
{
 int ret = 0;
 MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
 media_codec_context_t *context = NULL;
 media_codec_buffer_t inputBuffer;
 media_codec_buffer_t outputBuffer;
 media_codec_output_buffer_info_t info;

 ret = check_and_init_test(ctx);
 if (ret != 0) {
     printf("check_and_init_test failed(%d).\n", ret);
     return;
 }   context = ctx->context;

 context = ctx->context;
 ret = hb_mm_mc_initialize(context);
 if (ret != 0) {
     printf("hb_mm_mc_initialize failed(%d).\n", ret);
     return;
 }

 ret = hb_mm_mc_configure(context);
 if (ret != 0) {
     printf("hb_mm_mc_configure failed(%d).\n", ret);
     hb_mm_mc_release(context);
     return;
 }

 mc_av_codec_startup_params_t startup_params;
 startup_params.video_enc_startup_params.receive_frame_number = 0;
 ret = hb_mm_mc_start(context, &startup_params);
 if (ret != 0) {
     printf("hb_mm_mc_start failed(%d).\n", ret);
     hb_mm_mc_release(context);
     return;
 }

 do {
     // process input buffers
     ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 3000);
     if (ret == 0) {
         ret = read_input_streams(ctx, &inputBuffer);
         if (ret <= 0) {
             printf("There is no more input data(ret=%d)!\n", ret);
             inputBuffer.vstream_buf.stream_end = TRUE;
             inputBuffer.vstream_buf.size = 0;
             ctx->lastStream = 1;
         }

         ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
         if (ret != 0) {
             break;
         }
     } else {
         if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
             char info[256];
             hb_mm_strerror(ret, info, 256);
             printf("dequeue input buffer fail.(%s)\n", info);
             break;
         }
     }

     // process output buffers
     memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
     memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
     ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info, 100);
     if (ret == 0) {
         printf("info.video_frame_info.nalu_type %d\n", info.video_frame_info.nalu_type);
         write_output_frames(ctx, &outputBuffer);

         if (ctx->enable_get_userdata) {
             mc_user_data_buffer_t userdata = {0};
             ret = hb_mm_mc_get_user_data(context, &userdata, 0);
             if (!ret) {
                 printf("Get userdata %d:\n", userdata.size);
                 for (uint32_t i = 0; i < userdata.size; i++) {
                     if (i < 16) {
                         printf("userdata[i]:%x\n", userdata.virt_addr[i]);
                     } else {
                         printf("userdata[i]:%c\n", userdata.virt_addr[i]);
                     }
                 }
                 ret = hb_mm_mc_release_user_data(context, &userdata);
             } else {
                 ret = 0;
             }
         }

         ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
         if (outputBuffer.vframe_buf.frame_end) {
             printf("There is no more output data!\n");
             break;
         }
         if (ret) {
             break;
         }
     } else {
         char info[256];
         hb_mm_strerror(ret, info, 256);
         printf("dequeue output buffer fail.(%s)\n", info);
         if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
             break;
         }
     }
 } while (TRUE);

 ret = hb_mm_mc_stop(context);
 if (ret != 0) {
     printf("hb_mm_mc_stop failed(%d).\n", ret);
 }

 ret = hb_mm_mc_release(context);
 if (ret != 0) {
     printf("hb_mm_mc_release failed(%d).\n", ret);
 }

 check_and_release_test(ctx);
}

2.3 编译&运行

获取 AppSDK 包后,进入 appuser 执行:

*其中 hbrootfs-sdk_0.0.1.XXX_all.deb 是地平线自己的库和头文件,rootfs-sdk-focal_0.0.1.XXX_all.deb 是系统库,aarch64-linux-hb-gcc_12.2.0_amd64.deb 是 gcc 12.2.0 工具链,目前在 ubuntu22.04 非 docker 环境下运行正常。其它环境不能保证。

dpkg-deb -x rootfs-sdk*.deb ./sdk
dpkg-deb -x hbrootfs-sdk*.deb ./sdk
##移动sdk库路径,本文档放入/usr/lib中
sudo mv sdk/ /usr/lib

进入 toolchain 执行:

dpkg -x aarch64-linux-hb-gcc_12.2.0_amd64.deb ./arm-gnu-toolchain
##移动toolchain库路径,本文档放入/usr/lib中
sudo mv arm-gnu-toolchain/ /usr/lib
nano ~/.bashrc
##添加系统路径
export PATH="/usr/lib/arm-gnu-toolchain/bin:$PATH"
export LD_LIBRARY_PATH="/usr/lib/arm-gnu-toolchain/lib:$LD_LIBRARY_PATH"
##
source ~/.bashrc

Sample 代码路径:

#Sample源码路径
/test/samples/platform_samples/source/S83_Sample/S83E04_Module/codec_sample

运行参数说明:

image

复制/src 源码到新建文件夹 codec 并构建新 Makefile:

codec
├── Makefile
└── src
 ├── sample.c
 ├── sample_common.c
 ├── sample.h
 ├── sample_vdec.c
 └── sample_venc.c

Makefile:

CROSS_COMPILE = aarch64-none-linux-gnu-
OUTPUT_HBROOTFS_DIR = /usr/lib/sdk

CXX := ${CROSS_COMPILE}gcc

INC_DIR := ${OUTPUT_HBROOTFS_DIR}/usr/hobot/include
INC_DIR += ${OUTPUT_HBROOTFS_DIR}/include
LIB_DIR := ${OUTPUT_HBROOTFS_DIR}/usr/hobot/lib 
LIB_DIR += ${OUTPUT_HBROOTFS_DIR}/usr/lib/aarch64-linux-gnu
LIBS += -lpthread -ldl -lhbmem -lalog  -lmultimedia
LIBS += -lavformat -lavcodec -lavutil -lswresample
CXXFLAGS := -Wall -O2 $(foreach dir,$(INC_DIR),-I$(dir))
LDFLAGS := $(addprefix -L, $(LIB_DIR)) $(LIBS)

SRC_DIR := src
TARGET := program
SRCS := $(wildcard $(SRC_DIR)/*.c)

OBJS := $(SRCS:.c=.o)

$(TARGET): $(OBJS)
 $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@
%.o: %.c
 $(CXX) $(CXXFLAGS) -c $< -o $@
clean:
 rm -f $(OBJS) $(TARGET)

执行 make 完成编译,生成的文件为。/program

image

使用 WinScp 将 program 传输到单板上。*需要 encode 的 yuv 文件请用户自行准备,本文档使用 PYM 生成的 yuv 文件。

*WinScp 使用方法请参考征程 6E/M 底软开发 Sample-IPC 2.1.2

通过 ssh 或串口进入/home/hobot/执行:*w 和 h 需要进行 16 字节对齐,如原始 yuv 不支持则会出现数据丢失

chmod +x program
#encode
#代码可参考源码目录中的codec_sample.sh
./program -m 0 -c 3 -w 3840 -h 2160 -p 1 -i 3840x2160_pipe0_pym_ds0_f0_roi_1.yuv -o ./3840x2160.jpg
./program -m 0 -c 1 -w 3840 -h 2160 -p 1 -i 3840x2160_pipe0_pym_ds0_f0_roi_1.yuv -o ./3840x2160.h265

Sample 运行时日志:

g_samplemode = 0
g_codecid = 3
g_width = 3840
g_height = 2160
g_pixfmt = 1
g_pixfmt = 1
g_inputfilename = 3840x2160_pipe0_pym_ds0_f0_roi_1.yuv
g_outputfilename = ./3840x2160.jpg
InputFileName = 3840x2160_pipe0_pym_ds0_f0_roi_1.yuv
OutputFileName = ./3840x2160.jpg
Thread use internal buffer mode, 0 rc mode
Failed to read input file (size=12441600)
There is no more input data(ret=0)!
There is no more output data!

生成的缩放 jpg 文件存放在指定-o 目录下。

生成的 Jpeg 效果如下:

image

*有关 jpg 工具查看 1080p 图片时出现绿边问题:

image

问题说明:这是因为当前 ip 进行编码时按照 16 位对齐进行,假如到最后如果是 8 位对齐而不是 16 位对齐,那么编码器就会在后面补齐,这部分补齐的数据是随机产生的,不属于有效数据;

#decode
#使用上述生成的3840x2160.h265为例
./program -m 1 -c 1 -w 3840 -h 2160 -p 1 -i 3840x2160.h265 -o ./3840x2160.yuv

image

使用 YUView 打开生成的 3840x2160.yuv:

image

*注意配置 offset:

image

image

附件:

1、[codec.7z]

标签:6E,mc,mm,ret,Sample,buffer,Codec,context,hb
From: https://www.cnblogs.com/horizondeveloper/p/18414382

相关文章

  • ABC246Ex 01? Queries(动态 DP)
    题意给定长度为\(n\)的字符串\(s\),只包含0,1,?,其中?可以任意替换为0和1。再给定\(q\)次单点修改,修改后查询字符串本质不同的子序列个数,对\(998244353\)取模。\(n,q\le10^5\)分析考虑没有修改怎么做。首先跟SA没有任何关系。设\(f_{i,0/1}\)表示考虑前\(......
  • YOLOv9改进策略【Neck】| 有效且轻量的动态上采样算子:DySample
    一、本文介绍本文记录的是利用DySample上采样对YOLOv9的颈部网络进行改进的方法研究。YOLOv9采用传统的最近邻插值的方法进行上采样可能无法有效地捕捉特征的细节和语义信息,从而影响模型在密集预测任务中的性能。DySample通过动态采样的方式进行上采样,能够更好地处理特征的......
  • SciTech-Mathmatics-Probability+Statistics-Population-Sampling-Population vs. Sam
    Difference:Populationvs.SampleBYZACHBOBBITTPOSTEDONNOVEMBER27,2020Ofteninstatisticswe'reinterestedincollectingdatasothatwecananswersomeresearchquestion.Forexample,wemightwanttoanswerthefollowingquestions:Whatis......
  • 1 件全新6ES7314-6EH04-0AB0 6ES73146EH040AB0 中央处理单元
    6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元引脚线6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元说明书......
  • 征程 6E/M 快速上手实战 Sample-PYM
    01IPC模块简述1.1硬件数据流PYM(Pyramid)作为一个硬件加速模块(图像缩小及ROI提取),对输入的图像按照金字塔图层的方式处理,并输出到DDR:PYM模块在Camsys子系统的数量和位置如下,总共3个PYM硬件,PYM0、PYM1、PYM4(只支持offline)。1.2PYM-Sample软件架构本文的demosa......
  • JSP酒店宾馆客房管理系统ei6e8--程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统功能:公告信息,用户,员工,客房信息,客房预订,入住信息,退房信息开题报告内容一、项目背景随着旅游业的蓬勃发展,酒店宾馆业面临着日益增长的客户需求与日益......
  • 芯片闪存(FLASH)空间不够报错——.\Objects\SL_DEMO.axf: Error: L6406E: No space in
    目录问题描述:问题解决:问题分析:解决方法:1,2,问题描述:当出现这种报错的时候:.\Objects\SL_DEMO.axf:Error:L6406E:Nospaceinexecutionregionswith.ANYselectormatchingdrv_iap.o(i.EraseFlashSector).。是由于芯片闪存(FLASH)空间不够导致的问题解决:问题分析......
  • 【Python】ValueError:Sample larger than population or is negative的原因
    ValueError:Samplelargerthanpopulationorisnegative的原因以及解决办法1.出现这几天重构kook-valorant-bot的代码的时候,遇到了这个问题Job"vip_roll_task(trigger:interval[0:01:20],nextrunat:2023-01-2519:59:21CST)"raisedanexceptionTraceback(mostrec......
  • JNI -cmake sample
    CMakeLists.txtcmake_minimum_required(VERSION3.16)set(CMAKE_CXX_STANDARD11)project(test)set(SRCsrc/HelloWorld.cpp)#配置cpp源文件到SRC变量中set(EXECUTABLE_OUTPUT_PATH./build)#配置输出目录set(JAVA_HOME$ENV{JAVA_HOME})#获取系统环境变量中的......
  • 征程6E_M快速上手实战Sample-IPC
    系列文章目录手把手教你利用算法工具链训练、量化、编译、可视化征程6参考算法BEVFormer征程6E/M快速上手实战Sample-IPC@目录系列文章目录关于本文一、IPC模块简述1.1硬件数据流说明1.2IPCSample软件架构1.3Acore-IPC-Sample:1.3.1API调用流程:1.3.2Sample源码解析:1.4......