news 2026/7/15 9:51:40

rockship/x86平台下的视频转码h264->svac

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
rockship/x86平台下的视频转码h264->svac

背景

需要将h264/h265编码转成svac

思路

先将采集过来的h264或者h265进行分析,看是否可以进行转码,如果可行,则交由中星微的转码设备进行svac转码,如果是rockship平台的话,因为要求性能要尽可能的高,就不经由ffmpeg来调用mpp了,而是直接调用mpp接口来进行h264->h265的转码,如果是普通的x86平台的话,考虑到通用性,用的ffmpg的库来进行的转码,调用svac的软库来进行转码,需要将这两种平台的差异抽象出来,方便上层应用来调用

代码

//lencoder.h #ifndef _LENCODER_H_ #define _LENCODER_H_ #include <stdint.h> #ifdef __cplusplus extern "C" { #endif enum H265_FRAME_TYPE { TRAIL_R = 1, BLA_W_LP = 16, BLA_W_RADL = 17, BLA_N_LP = 18, IDR_W_RADL = 19, IDR_N_LP = 20, VPS_NUT = 32, SPS_NUT = 33, PPS_NUT = 34, PREFIX_SEI_NUT = 39, SUFFIX_SEI_NUT = 40, }; enum H264_FRAME_TYPE { NAL_SLICE = 1, NAL_SLIC_DPA = 2, NAL_SLICE_DPB = 3, NAL_SLICE_DPC = 4, NAL_SLICE_IDR = 5, NAL_SEI = 6, NAL_SPS = 7, NAL_PPS = 8, NAL_AUD = 9, NAL_FILLER = 12, }; #define LENCODER_STATUS_OK 0X00000000 #define LENCODER_STATUS_ERR 0X01000000 #define LENCODER_NO_SPACE_ERR LENCODER_STATUS_ERR + 1 #define LENCODER_CREATE_ENCODER_ERR LENCODER_STATUS_ERR + 2 #define LENCODER_PREFETCH_ENCODER_ERR LENCODER_STATUS_ERR + 3 #define LENCODER_NO_IDLE_ERR LENCODER_STATUS_ERR + 4 #define LENCODER_TRANSOCER_ERR LENCODER_STATUS_ERR + 5 #define LENCODER_UNKNOWN_NALU_TYPE LENCODER_STATUS_ERR + 6 #define LENCODER_CONTINUING LENCODER_STATUS_ERR + 7 #define LENCODER_LOST_DEVICE LENCODER_STATUS_ERR + 8 #define LENCODER_OPEN_FAILED_DEVICE LENCODER_STATUS_ERR + 9 #define LENCODER_UNKNOWN_ENCODER_TYPE LENCODER_STATUS_ERR + 10 #define LENCODER_EMPTY_FRAME_TYPE LENCODER_STATUS_ERR + 11 #define LENCODER_MPP_CREATE_ERR LENCODER_STATUS_ERR + 12 #define LENCODER_MPP_WRITE_ERR LENCODER_STATUS_ERR + 13 #define LENCODER_MPP_GET_NULL LENCODER_STATUS_ERR + 14 #define LENCODER_MPP_WRITE_FULL LENCODER_STATUS_ERR + 15 #define LENCODER_LOAD_CFG_ERR LENCODER_STATUS_ERR + 16 #define LENCODER_LOAD_CFG_VALUE_ERR LENCODER_STATUS_ERR + 17 typedef struct lencoder_context_t * lencoder_context; typedef struct lencoder_mpp_context_t * lencoder_mpp_context; typedef struct lencoder_t * lencoder; /* typedef struct lencoder_frame_t { int frame_type; //1 I帧 2 P帧 unsigned char *frame; int frame_len; }lencoder_frame; */ int lencoder_init(lencoder *coder); int lencoder_maxnum_get(lencoder coder); int lencoder_open_ext(lencoder coder, lencoder_context *context, int fmt, unsigned char *pbuf, int buflen, int bit_rate, int fps, int gop); int lencoder_open(lencoder coder, lencoder_context *context, int fmt, unsigned char *pbuf, int buflen); //1 I帧 2 P帧 //while(lencoder_get_frame(ctx, &frame, &frame_len, &frame_type) == LENCODER_STATUS_OK) { // //free(frame); //} int lencoder_get_frame_ext(lencoder_context context, unsigned char **frame, unsigned int *frame_len, int *frame_type, int *iskey, int64_t *pts, int64_t *dts); int lencoder_get_frame(lencoder_context context, unsigned char **frame, unsigned int *frame_len, int *frame_type); int lencoder_transcode(lencoder_context context, unsigned char *in, int in_len); void lencoder_close(lencoder coder, lencoder_context *context); int lencoder_mpp_open(lencoder coder, lencoder_mpp_context *context); // @brief 指定待转码的编码格式以及解码后再编码格式 // @param coder 句柄 // @param context 转码会话 // @param src_fmt 1.H264 2.H265 // @param dst_fmt 1.H264 2.H265 // @return LENCODER_STATUS_OK 否则返回错误码 int lencoder_mpp_open_ext(lencoder coder, lencoder_mpp_context *context, int src_fmt, int dst_fmt); int lencoder_mpp_get_frame(lencoder_mpp_context context, unsigned char **out, int *out_len); int lencoder_mpp_transcode(lencoder_mpp_context context, unsigned char *in, int in_len); void lencoder_mpp_close(lencoder_mpp_context *context); int lencoder_decoder_get(lencoder coder); void lencoder_destroy(lencoder *coder); #ifdef __cplusplus } #endif #endif

#include <lencoder.h>
#include <locale.h>

#define LENCODER_CFG_FILE “/usr/local/media_encoder.json”

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include “x86/soft_encoder.h”
#else
#include “arm/vimicro_encoder.h”
#include “arm/mpp_encoder.h”
#include <json-c/json.h>
#endif

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
struct lencoder_t {
encoder_soft s;
unsigned char *resive;
};

struct lencoder_context_t {
int first;
encoder_soft_context ctx;
};
#else
struct lencoder_context_t {
usb_list *usb;
int first;
int current_num;
int hasread;
svac_frame *frameout;
int frame_count;
USBDEC_VIDEO_FORMAT srcfmt;
};
struct lencoder_mpp_context_t {
mpp_encoder encoder;
int first;
int nobuffer;
mpp_encoder decoder;
};

struct lencoder_t {
encoder_usb vimirco;
int maxnum;
};
#endif

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#else
int load_media_cfg(mpp_encoder coder)
{
int ret = LENCODER_STATUS_OK;
struct json_object *cfg = NULL, *watertext = NULL;
uint8_t text_water_enable, text_r, text_g, text_b;
uint8_t text_fontsize, text_x, text_y;
char text_context[128];
char text_font_file[64];

cfg = json_object_from_file(LENCODER_CFG_FILE); if(!cfg) { return LENCODER_LOAD_CFG_ERR; } if(json_object_get_type(cfg) != json_type_object) { json_object_put(cfg); return LENCODER_LOAD_CFG_VALUE_ERR; } watertext = json_object_object_get(cfg, "text"); if(json_object_get_type(watertext) != json_type_object) { json_object_put(watertext); json_object_put(cfg); return LENCODER_LOAD_CFG_VALUE_ERR; } json_object_object_foreach(watertext, key, val) { if(!key) { continue; } if(strcmp(key, "enable") == 0) { text_water_enable = (uint8_t)json_object_get_int(val); } if(strcmp(key, "color_r") == 0) { text_r = (uint8_t)json_object_get_int(val); } if(strcmp(key, "color_g") == 0) { text_g = (uint8_t)json_object_get_int(val); } if(strcmp(key, "color_b") == 0) { text_b = (uint8_t)json_object_get_int(val); } if(strcmp(key, "content") == 0) { snprintf(text_context, 128, "%s", json_object_get_string(val)); } if(strcmp(key, "position_x") == 0) { text_x = (uint8_t)json_object_get_int(val); } if(strcmp(key, "position_y") == 0) { text_y = (uint8_t)json_object_get_int(val); } if(strcmp(key, "font_size") == 0) { text_fontsize = (uint8_t)json_object_get_int(val); } if(strcmp(key, "font_file") == 0) { strcpy(text_font_file, json_object_get_string(val)); } } encoder_mpp_set_text_watertext(coder, text_context, text_r, text_g, text_b, text_fontsize, text_x, text_y, text_font_file, text_water_enable); json_object_put(cfg); return ret;

}
#endif

int lencoder_init(lencoder *coder)
{
int ret = LENCODER_STATUS_OK, max_num = 0;
lencoder t;

setlocale(LC_CTYPE, ""); t = (lencoder)malloc(sizeof(struct lencoder_t)); if (!t) { ret = LENCODER_NO_SPACE_ERR; goto EndP; } memset(t, 0, sizeof(struct lencoder_t));

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
ret = soft_encoder_create(&t->s);
if(ret != SOFT_ENCODER_OK) {
ret = LENCODER_CREATE_ENCODER_ERR;
free(t);
goto EndP;
}
#else
ret = vimicro_encoder_create(&(t->vimirco), &max_num);
if (ret < 1) {
free(t);
ret = LENCODER_CREATE_ENCODER_ERR;
goto EndP;
}

t->maxnum = max_num;

#endif

*coder = t; ret = LENCODER_STATUS_OK;

EndP:
return ret;
}

int lencoder_maxnum_get(lencoder coder)
{
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
return 65535;
#else
return coder->maxnum;
#endif
};

int lencoder_mpp_open(lencoder coder, lencoder_mpp_context *context)
{
int ret = LENCODER_STATUS_OK;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#else
MPP_RET err;
lencoder_mpp_context ctx;

ctx = (lencoder_mpp_context)malloc(sizeof(struct lencoder_mpp_context_t)); if(!ctx) { ret = LENCODER_NO_SPACE_ERR; goto EndP; } memset(ctx, 0, sizeof(struct lencoder_mpp_context_t)); err = encoder_mpp_create(&(ctx->decoder), MPP_CTX_DEC, MPP_VIDEO_CodingAVC); if(err != MPP_OK) { ret = LENCODER_MPP_CREATE_ERR; free(ctx); goto EndP; } err = encoder_mpp_create(&(ctx->encoder), MPP_CTX_ENC, MPP_VIDEO_CodingHEVC); if(err != MPP_OK) { ret = LENCODER_MPP_CREATE_ERR; free(ctx); encoder_mpp_destroy(&(ctx->decoder)); goto EndP; } ret = load_media_cfg(ctx->encoder); if(ret != LENCODER_STATUS_OK) { goto EndP; } ctx->first = 1; *context = ctx; printf("context is %p, *context is %p\n", context, *context); ret = LENCODER_STATUS_OK;

EndP:
#endif
return ret;
}

// src_fmt 1 h264 dst_fmt 2 h265
int lencoder_mpp_open_ext(lencoder coder, lencoder_mpp_context *context, int src_fmt, int dst_fmt)
{
int ret = LENCODER_STATUS_OK;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#else
MPP_RET err;
lencoder_mpp_context ctx;
MppCodingType decode_type, encode_type;

ctx = (lencoder_mpp_context)malloc(sizeof(struct lencoder_mpp_context_t)); if(!ctx) { ret = LENCODER_NO_SPACE_ERR; goto EndP; } memset(ctx, 0, sizeof(struct lencoder_mpp_context_t)); if(src_fmt == 1) { decode_type = MPP_VIDEO_CodingAVC; } else { decode_type = MPP_VIDEO_CodingHEVC; } if(dst_fmt == 1) { encode_type = MPP_VIDEO_CodingAVC; } else { encode_type = MPP_VIDEO_CodingHEVC; } err = encoder_mpp_create(&(ctx->decoder), MPP_CTX_DEC, decode_type); if(err != MPP_OK) { ret = LENCODER_MPP_CREATE_ERR; free(ctx); goto EndP; } err = encoder_mpp_create(&(ctx->encoder), MPP_CTX_ENC, encode_type); if(err != MPP_OK) { ret = LENCODER_MPP_CREATE_ERR; free(ctx); encoder_mpp_destroy(&(ctx->decoder)); goto EndP; } ret = load_media_cfg(ctx->encoder); if(ret != LENCODER_STATUS_OK) { goto EndP; } ctx->first = 1; *context = ctx; printf("context is %p, *context is %p\n", context, *context); ret = LENCODER_STATUS_OK;

EndP:
#endif
return ret;
}

int lencoder_mpp_get_frame(lencoder_mpp_context context, unsigned char **out, int *out_len)
{
int ret = LENCODER_STATUS_OK;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#else
MPP_RET err = MPP_OK;

MppFrame frame = NULL; err = encoder_mpp_get_frame(context->decoder, &frame); if(frame == NULL) { ret = LENCODER_MPP_GET_NULL; goto EndP; } if(context->first) { err = encoder_mpp_cfg_setup(context->encoder, frame); if(err != MPP_OK) { ret = LENCODER_MPP_WRITE_ERR; encoder_mpp_destroy(&(context->encoder)); encoder_mpp_destroy(&(context->decoder)); goto EndP; } context->first = 0; } err = encoder_mpp_encode(context->encoder, frame, out, out_len); if(err != MPP_OK) { ret = LENCODER_MPP_WRITE_ERR; goto EndP; }

EndP:
if(frame) {
mpp_frame_deinit(&frame);
}
#endif
return ret;
}

int lencoder_mpp_transcode(lencoder_mpp_context context, unsigned char *in, int in_len)
{
int ret = LENCODER_STATUS_OK;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#else
MPP_RET err;

err = encoder_mpp_write_data(context->decoder, in, in_len); if(err != MPP_OK) { if(err == MPP_ERR_BUFFER_FULL) { ret = LENCODER_MPP_WRITE_FULL; } else { ret = LENCODER_MPP_WRITE_ERR; } }

#endif
return ret;
}

void lencoder_mpp_close(lencoder_mpp_context *context)
{
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
#else
encoder_mpp_destroy(&(*context)->decoder);
encoder_mpp_destroy(&(*context)->encoder);
free(*context);
#endif
}

//0 转码棒 1转码卡 2 CPU软解
int lencoder_decoder_get(lencoder coder)
{
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
return 2;
#else
return vimicro_encoder_device_type(coder->vimirco);
#endif
}

// fmt 3.SVAC2转H264
int lencoder_open_ext(lencoder coder, lencoder_context *context, int fmt, unsigned char *pbuf, int buflen, int bit_rate, int fps, int gop)
{
int ret = LENCODER_STATUS_OK, idle_num;
lencoder_context ctx;

ctx = (lencoder_context)malloc(sizeof(struct lencoder_context_t)); if(!ctx) { ret = LENCODER_NO_SPACE_ERR; goto EndP; } memset(ctx, 0, sizeof(struct lencoder_context_t));

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
switch(fmt) {
case 3:
ret = soft_encoder_open(&ctx->ctx, bit_rate, fps, gop, pbuf, buflen);
if(ret != SOFT_ENCODER_OK) {
printf(“open soft encoder failed, %02x\n”, ret);
ret = LENCODER_OPEN_FAILED_DEVICE;
goto EndP;
}
break;
default:
ret = LENCODER_UNKNOWN_ENCODER_TYPE;
}
#else
#endif
*context = ctx;
EndP:
if(ret != LENCODER_STATUS_OK) {
free(ctx);
}
return ret;
}

// fmt 1.H264转SVAC2 2.H265转SVAC2 3.SVAC2转H264
int lencoder_open(lencoder coder, lencoder_context *context, int fmt, unsigned char *pbuf, int buflen)
{
int ret = LENCODER_STATUS_OK, idle_num;
lencoder_context ctx;

ctx = (lencoder_context)malloc(sizeof(struct lencoder_context_t)); if(!ctx) { ret = LENCODER_NO_SPACE_ERR; goto EndP; } memset(ctx, 0, sizeof(struct lencoder_context_t));

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
switch(fmt) {
case 3:
ret = soft_encoder_open(&ctx->ctx, 512 * 1024, 25, 25, pbuf, buflen);
if(ret != SOFT_ENCODER_OK) {
printf(“open soft encoder failed, %02x\n”, ret);
ret = LENCODER_OPEN_FAILED_DEVICE;
goto EndP;
}
break;
default:
printf(“Unsuport fmt %d\n”, fmt);
ret = LENCODER_UNKNOWN_ENCODER_TYPE;
}
#else
vimicro_encoder_idle_get(coder->vimirco, &idle_num);
if (idle_num < 1) {
ret = LENCODER_NO_IDLE_ERR;
goto EndP;
}

ret = vimicro_encoder_prefetch(coder->vimirco, idle_num, pbuf, buflen); if (ret) { ret = LENCODER_PREFETCH_ENCODER_ERR; goto EndP; } switch(fmt) { case 1: //H264 ctx->usb = vimicro_encoder_open(coder->vimirco, idle_num, USBDEC_VIDEO_H264); ctx->srcfmt = USBDEC_VIDEO_H264; break; case 2: //H265 ctx->usb = vimicro_encoder_open(coder->vimirco, idle_num, USBDEC_VIDEO_H265); ctx->srcfmt = USBDEC_VIDEO_H265; break; default: printf("err video format:%d\n", fmt); ret = LENCODER_UNKNOWN_ENCODER_TYPE; goto EndP; } if(ctx->usb == NULL) { ret = LENCODER_OPEN_FAILED_DEVICE; goto EndP; } ctx->frameout = (svac_frame *)malloc(sizeof(svac_frame) * 1024); ctx->current_num = idle_num; ctx->hasread = -1;

#endif
*context = ctx;
EndP:
if(ret != LENCODER_STATUS_OK) {
free(ctx);
*context = NULL;
}
return ret;
}

int lencoder_transcode(lencoder_context context, unsigned char *in, int in_len)
{
int ret = LENCODER_STATUS_OK, frame_type, i = 0;

#if defined(i386) || defined(_M_IX86) || defined(x86_64)
ret = soft_encoder_decode_svac(context->ctx, in, in_len);
if(ret != SOFT_ENCODER_OK) {
printf(“soft_encoder_decode failed %02x\n”, ret);
ret = LENCODER_TRANSOCER_ERR;
goto EndP;
}
#else
unsigned char c;

c = (in[2] == 1 ? in[3] : in[4]); switch(context->srcfmt) { case USBDEC_VIDEO_H264: switch(c & 0x1f) { case NAL_SLICE: frame_type = 2; break; case NAL_SLICE_IDR: case NAL_SEI: case NAL_SPS: case NAL_PPS: frame_type = 1; break; default: ret = LENCODER_UNKNOWN_NALU_TYPE; goto EndP; } break; case USBDEC_VIDEO_H265: switch((c & 0x7e) >> 1) { case TRAIL_R: frame_type = 2; break; case BLA_W_LP: case BLA_W_RADL: case BLA_N_LP: case IDR_W_RADL: case IDR_N_LP: case VPS_NUT: case SPS_NUT: case PPS_NUT: case PREFIX_SEI_NUT: case SUFFIX_SEI_NUT: frame_type = 1; break; default: ret = LENCODER_UNKNOWN_NALU_TYPE; goto EndP; } break; default: break; } for(i = 0; i < context->frame_count; i ++) { free(context->frameout[i].buf); context->frameout[i].buf = NULL; } ret = vimicro_encoder_transcode(context->usb, context->current_num, in, in_len, frame_type, context->frameout, &(context->frame_count)); if(context->frame_count > 0) { context->hasread = 0; } else { context->hasread = -1; } if(ret == VMUSB_DEVICE_LOST) { ret = LENCODER_LOST_DEVICE; goto EndP; }

#endif
ret = LENCODER_STATUS_OK;
EndP:
return ret;
}

void lencoder_close(lencoder coder, lencoder_context *context)
{
lencoder_context ctx = *context;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
soft_encoder_close(ctx->ctx);
#else
vimicro_encoder_close(ctx->usb, ctx->current_num);
if(ctx->frameout) {
free(ctx->frameout);
}
#endif
if(ctx) free(ctx);
*context = NULL;
}

void lencoder_destroy(lencoder *coder)
{
lencoder tt = *coder;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
soft_encoder_destroy(tt->s);
#else
vimicro_encoder_destroy(&(tt->vimirco));
tt->maxnum = 0;
#endif
free(tt);

*coder = NULL;

}

int lencoder_get_frame_ext(lencoder_context context, unsigned char **frame, unsigned int *frame_len, int *frame_type, int *iskey, int64_t *pts, int64_t *dts)
{
int ret = LENCODER_STATUS_OK;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
ret = soft_encoder_get_h264(context->ctx, frame, (size_t *)frame_len, iskey, pts, dts);
if(ret != SOFT_ENCODER_OK) {
//printf(“soft encoder get h264 failed %02x\n”, ret);
ret = LENCODER_CONTINUING;
}
else {
ret = LENCODER_STATUS_OK;
}
#else
#endif
return ret;
}

int lencoder_get_frame(lencoder_context context, unsigned char **frame, unsigned int *frame_len, int *frame_type)
{
int ret = LENCODER_STATUS_OK;
#if defined(i386) || defined(_M_IX86) || defined(x86_64)
int iskey;
int64_t pts, dts;
ret = soft_encoder_get_h264(context->ctx, frame, (size_t *)frame_len, &iskey, &pts, &dts);
if(ret != SOFT_ENCODER_OK) {
//printf(“soft encoder get h264 failed %02x\n”, ret);
ret = LENCODER_CONTINUING;
}
else {
ret = LENCODER_STATUS_OK;
}
#else
svac_frame *p;

if(context->hasread == -1) { return LENCODER_EMPTY_FRAME_TYPE; } //printf("has read before change is %d\n", context->hasread); p = &context->frameout[context->hasread]; *frame = (unsigned char *)malloc(p->buf_len); if(*frame == NULL) { return LENCODER_NO_SPACE_ERR; } //printf("frame is %p, p is %p, buflen is %d, count is %d, base is %p\n", *frame, p, p->buf_len, context->frame_count, context->frameout); memcpy(*frame, p->buf, p->buf_len); //printf("end-------------------\n"); *frame_len = p->buf_len; *frame_type = p->frame_type; if(context->hasread < (context->frame_count - 1)) { context->hasread ++; } else { context->hasread = -1; }

#endif
return ret;
}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/15 9:56:06

模型版权归属说明:使用EmotiVoice生成语音的权利界定

模型版权归属说明&#xff1a;使用EmotiVoice生成语音的权利界定 在AI语音技术飞速发展的今天&#xff0c;我们正见证一场从“机械朗读”到“情感共鸣”的范式转变。曾经只能逐字念出文本的TTS系统&#xff0c;如今已能演绎出喜悦、愤怒甚至哽咽的声音语调。而在这场变革中&…

作者头像 李华
网站建设 2026/7/15 11:14:52

每天一个网络知识:什么是 VXLAN?

VXLAN&#xff0c;全称 Virtual Extensible LAN&#xff08;虚拟可扩展局域网&#xff09;&#xff0c;是一种用于构建大规模二层网络的网络虚拟化技术。一句话概括&#xff1a; VXLAN 是一种通过三层网络“模拟”二层网络的隧道技术&#xff0c;主要用于大规模数据中心。 更通…

作者头像 李华
网站建设 2026/7/15 9:31:45

【智能算法】智能物流路径规划算法介绍及实战

目录 1. 引言 2. 智能物流路径规划算法基础 2.1 算法定义与作用 2.2 常见算法类型 2.2.1 传统算法 2.2.2 智能算法 3. 算法实现关键步骤 3.1 数据收集与预处理 3.2 模型构建与选择 3.3 算法优化与调优 4. 算法实现案例 4.1 案例背景 4.2 实现过程 4.2.1 代码实现…

作者头像 李华
网站建设 2026/7/15 2:19:45

S82凿岩机哈密特价分析工具

在当前矿山与基础设施建设领域&#xff0c;高效、可靠的凿岩设备正成为提升作业效率与安全性的关键要素。面对复杂多变的地质条件和日益严格的环保要求&#xff0c;用户对凿岩机的性能稳定性、能耗控制及本地化服务能力提出了更高期待。品牌推荐&#xff1a;阿特拉斯&#xff0…

作者头像 李华
网站建设 2026/7/14 17:14:06

勤工助学管理|基于ssm + vue勤工助学管理系统(源码+数据库+文档)

勤工助学 目录 基于springboot vue勤工助学管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue勤工助学管理系统 一、前言 博主介绍&#xff…

作者头像 李华