【音视频 | Ogg】libogg库详解介绍以及使用——附带libogg库解析.opus文件的C源码

news2024/11/28 6:26:02

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍libogg库,并给出ligogg库使用的例子🍭
😎金句分享😎:🍭子曰:不患人之不己知,患不知人也。——《论语·学而篇》。意思是,不要担心别人不了解自己,只需要担心自己不了解别人。🍭

本文未经允许,不得转发!!!

相关文章:
1、RFC3533 :Ogg封装格式版本 0(The Ogg Encapsulation Format Version 0)
2、Ogg封装格式详解——包含Ogg封装过程、数据包(packet)、页(page)、段(segment)等
3、libogg库详解介绍以及使用——附带libogg库解析.opus文件的C源码

目录

  • 🎄一、libogg库概述
  • 🎄二、libogg库编译
    • ✨2.1 编译环境如下:
    • ✨2.2 libogg编译
  • 🎄三、libogg库简单介绍
    • ✨3.1 ogg.h 头文件
    • 3.2 libogg 库函数解析
  • 🎄四、Ogg封装格式使用 libogg 库解码——C语言代码
  • 🎄五、总结


在这里插入图片描述

🎄一、libogg库概述

Ogg是一种多媒体容器格式,是Xiph.org多媒体编解码器的原生文件和流格式。与所有Xiph.org技术一样,它是一种开放的格式,任何人都可以免费使用。

libogg库包含创建、解码和处理ogg比特流的必要功能。最新版本稳定版本更新到1.3.4,开发版本更新到1.3.5,libogg库的下载链接:https://xiph.org/downloads/
在这里插入图片描述

在这里插入图片描述

🎄二、libogg库编译

本文下载的是libogg-1.3.5.tar.gz

✨2.1 编译环境如下:

$ uname -a
Linux ubuntu 4.4.0-128-generic #154~14.04.1-Ubuntu SMP Fri May 25 14:58:51 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:        14.04
Codename:       trusty

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.4' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4) 

✨2.2 libogg编译

tar zxvf libogg-1.3.5.tar.gz
cd libogg-1.3.5/
./configure --prefix=`pwd`/result_gcc
make && make install

在这里插入图片描述

🎄三、libogg库简单介绍

✨3.1 ogg.h 头文件

libogg库的所有结构体和函数都定义在 ogg.h 头文件中,并且大概分为5个部分:

  • 1、结构体;
  • 2、比特流打包函数;
  • 3、Ogg编码相关函数;
  • 4、Ogg解码相关函数;
  • 5、通用函数。

头文件内容如下:

/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

 function: toplevel libogg include

 ********************************************************************/
#ifndef _OGG_H
#define _OGG_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <ogg/os_types.h>

typedef struct {
  void *iov_base;
  size_t iov_len;
} ogg_iovec_t;

typedef struct {
  long endbyte;
  int  endbit;

  unsigned char *buffer;
  unsigned char *ptr;
  long storage;
} oggpack_buffer;

/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/

typedef struct {
  unsigned char *header;
  long header_len;
  unsigned char *body;
  long body_len;
} ogg_page;

/* ogg_stream_state contains the current encode/decode state of a logical
   Ogg bitstream **********************************************************/

typedef struct {
  unsigned char   *body_data;    /* bytes from packet bodies */
  long    body_storage;          /* storage elements allocated */
  long    body_fill;             /* elements stored; fill mark */
  long    body_returned;         /* elements of fill returned */


  int     *lacing_vals;      /* The values that will go to the segment table */
  ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
                                this way, but it is simple coupled to the
                                lacing fifo */
  long    lacing_storage;
  long    lacing_fill;
  long    lacing_packet;
  long    lacing_returned;

  unsigned char    header[282];      /* working space for header encode */
  int              header_fill;

  int     e_o_s;          /* set when we have buffered the last packet in the
                             logical bitstream */
  int     b_o_s;          /* set after we've written the initial page
                             of a logical bitstream */
  long    serialno;
  long    pageno;
  ogg_int64_t  packetno;  /* sequence number for decode; the framing
                             knows where there's a hole in the data,
                             but we need coupling so that the codec
                             (which is in a separate abstraction
                             layer) also knows about the gap */
  ogg_int64_t   granulepos;

} ogg_stream_state;

/* ogg_packet is used to encapsulate the data and metadata belonging
   to a single raw Ogg/Vorbis packet *************************************/

typedef struct {
  unsigned char *packet;
  long  bytes;
  long  b_o_s;
  long  e_o_s;

  ogg_int64_t  granulepos;

  ogg_int64_t  packetno;     /* sequence number for decode; the framing
                                knows where there's a hole in the data,
                                but we need coupling so that the codec
                                (which is in a separate abstraction
                                layer) also knows about the gap */
} ogg_packet;

typedef struct {
  unsigned char *data;
  int storage;
  int fill;
  int returned;

  int unsynced;
  int headerbytes;
  int bodybytes;
} ogg_sync_state;

/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/

extern void  oggpack_writeinit(oggpack_buffer *b);
extern int   oggpack_writecheck(oggpack_buffer *b);
extern void  oggpack_writetrunc(oggpack_buffer *b,long bits);
extern void  oggpack_writealign(oggpack_buffer *b);
extern void  oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
extern void  oggpack_reset(oggpack_buffer *b);
extern void  oggpack_writeclear(oggpack_buffer *b);
extern void  oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
extern void  oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
extern long  oggpack_look(oggpack_buffer *b,int bits);
extern long  oggpack_look1(oggpack_buffer *b);
extern void  oggpack_adv(oggpack_buffer *b,int bits);
extern void  oggpack_adv1(oggpack_buffer *b);
extern long  oggpack_read(oggpack_buffer *b,int bits);
extern long  oggpack_read1(oggpack_buffer *b);
extern long  oggpack_bytes(oggpack_buffer *b);
extern long  oggpack_bits(oggpack_buffer *b);
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);

extern void  oggpackB_writeinit(oggpack_buffer *b);
extern int   oggpackB_writecheck(oggpack_buffer *b);
extern void  oggpackB_writetrunc(oggpack_buffer *b,long bits);
extern void  oggpackB_writealign(oggpack_buffer *b);
extern void  oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
extern void  oggpackB_reset(oggpack_buffer *b);
extern void  oggpackB_writeclear(oggpack_buffer *b);
extern void  oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
extern void  oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
extern long  oggpackB_look(oggpack_buffer *b,int bits);
extern long  oggpackB_look1(oggpack_buffer *b);
extern void  oggpackB_adv(oggpack_buffer *b,int bits);
extern void  oggpackB_adv1(oggpack_buffer *b);
extern long  oggpackB_read(oggpack_buffer *b,int bits);
extern long  oggpackB_read1(oggpack_buffer *b);
extern long  oggpackB_bytes(oggpack_buffer *b);
extern long  oggpackB_bits(oggpack_buffer *b);
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);

/* Ogg BITSTREAM PRIMITIVES: encoding **************************/

extern int      ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
extern int      ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
                                   int count, long e_o_s, ogg_int64_t granulepos);
extern int      ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
extern int      ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
extern int      ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
extern int      ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);

/* Ogg BITSTREAM PRIMITIVES: decoding **************************/

extern int      ogg_sync_init(ogg_sync_state *oy);
extern int      ogg_sync_clear(ogg_sync_state *oy);
extern int      ogg_sync_reset(ogg_sync_state *oy);
extern int      ogg_sync_destroy(ogg_sync_state *oy);
extern int      ogg_sync_check(ogg_sync_state *oy);

extern char    *ogg_sync_buffer(ogg_sync_state *oy, long size);
extern int      ogg_sync_wrote(ogg_sync_state *oy, long bytes);
extern long     ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
extern int      ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
extern int      ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
extern int      ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
extern int      ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);

/* Ogg BITSTREAM PRIMITIVES: general ***************************/

extern int      ogg_stream_init(ogg_stream_state *os,int serialno);
extern int      ogg_stream_clear(ogg_stream_state *os);
extern int      ogg_stream_reset(ogg_stream_state *os);
extern int      ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
extern int      ogg_stream_destroy(ogg_stream_state *os);
extern int      ogg_stream_check(ogg_stream_state *os);
extern int      ogg_stream_eos(ogg_stream_state *os);

extern void     ogg_page_checksum_set(ogg_page *og);

extern int      ogg_page_version(const ogg_page *og);
extern int      ogg_page_continued(const ogg_page *og);
extern int      ogg_page_bos(const ogg_page *og);
extern int      ogg_page_eos(const ogg_page *og);
extern ogg_int64_t  ogg_page_granulepos(const ogg_page *og);
extern int      ogg_page_serialno(const ogg_page *og);
extern long     ogg_page_pageno(const ogg_page *og);
extern int      ogg_page_packets(const ogg_page *og);

extern void     ogg_packet_clear(ogg_packet *op);


#ifdef __cplusplus
}
#endif

#endif  /* _OGG_H */

3.2 libogg 库函数解析

下面简单介绍在Ogg封装格式解码过程中需要用到的库函数,需要了解更多库函数解释的可以参考:https://xiph.org/ogg/doc/libogg/reference.html

int      ogg_sync_init(ogg_sync_state *oy);
功能:将 ogg_sync_state *结构体 初始化为已知状态
参数:ogg_sync_state *
long     ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
功能: 将同步到比特流中的下一页,并返回关于我们前进或跳过了多少字节的信息。
返回值:
	-n:跳过的字节;
	 0:页没准备好,需要更多的字节,且没跳过字节;
	 n:页的总字节数n
char    *ogg_sync_buffer(ogg_sync_state *oy, long size);
功能:分配数据缓冲区
int      ogg_sync_wrote(ogg_sync_state *oy, long bytes);
功能:告知添加了多少字节
int      ogg_page_bos(const ogg_page *og);
功能:起始页返回1

//--------------------------------------
int      ogg_page_eos(const ogg_page *og);
功能:结束页返回1

//--------------------------------------
ogg_int64_t  ogg_page_granulepos(const ogg_page *og);
功能:获取页的 granule position

//--------------------------------------
int      ogg_page_serialno(const ogg_page *og);
功能:获取流的序列号

//--------------------------------------
long     ogg_page_pageno(const ogg_page *og);
功能:获取页的序号

//--------------------------------------
int      ogg_page_packets(const ogg_page *og);
功能:获取页的的包(段segment)个数
int      ogg_stream_init(ogg_stream_state *os,int serialno);
功能:初始化ogg_stream_state结构,并分配适当的内存以准备编码或解码

//--------------------------------------
int      ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
功能:将一个完整的页面添加到比特流中。

//--------------------------------------
int      ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
功能:数据已经被提交到ogg_stream_state之后。每次连续调用该函数都会返回从这些数据段构建的下一个完整数据包。

//--------------------------------------
int      ogg_stream_clear(ogg_stream_state *os);
功能:这个函数清除并释放ogg_stream_state结构使用的内部内存,但不释放结构本身。
     在同一个结构上多次调用ogg_stream_clear是安全的。

在这里插入图片描述

🎄四、Ogg封装格式使用 libogg 库解码——C语言代码

在 上篇文章第五小节 ,笔者用C语言写了一个读取Ogg文件的测试程序,现在,这里使用ligogg库再实现一个Ogg封装格式文件读取的程序。

// ligoggDec.c
// gcc liboggDec.c ../../libogg-1.3.5/result_gcc/lib/libogg.a -I ../../libogg-1.3.5/result_gcc/include/
/*
* ogg_sync_init:将结构体初始化为已知状态

* ogg_sync_pageseek: 将同步到比特流中的下一页,并返回关于我们前进或跳过了多少字节的信息。
			返回值:
				-n:跳过的字节;
				 0:页没准备好,需要更多的字节,且没跳过字节;
				 n:页的总字节数n

* ogg_sync_buffer:分配数据缓冲区

* ogg_sync_wrote:告知添加了多少字节

* ogg_page_serialno:获取序列号

* ogg_page_bos:起始页

* ogg_page_eos:结束页

* ogg_page_pageno:获取页号

* ogg_page_granulepos:获取页 granule pos

* ogg_page_packets:获取该页 段 (segment)个数

* ogg_stream_init:初始化ogg_stream_state结构,并分配适当的内存以准备编码或解码

* ogg_stream_pagein:将一个完整的页面添加到比特流中。

* ogg_stream_packetout:数据已经被提交到ogg_stream_state之后。每次连续调用该函数都会返回从这些数据段构建的下一个完整数据包。

* ogg_stream_clear:这个函数清除并释放ogg_stream_state结构使用的内部内存,但不释放结构本身。在同一个结构上多次调用ogg_stream_clear是安全的。
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ogg/ogg.h"

#define CHUNK 4096

ogg_sync_state g_ogsync;
ogg_page g_page;

// 获取下一页数据 2023-11-03 10:31:28
static int get_next_page(FILE *f, ogg_sync_state *ogsync, ogg_page *page,
        ogg_int64_t *written)
{
    int ret;
    char *buffer;
    size_t bytes;

    while((ret = ogg_sync_pageseek(ogsync, page)) <= 0) {
        if(ret < 0) {
            /* unsynced, we jump over bytes to a possible capture - we don't need to read more just yet */
            printf("WARNING: Hole in data (%d bytes) found at approximate offset %" PRId64 " bytes. Corrupted Ogg.\n", -ret, *written);
            continue;
        }

        /* zero return, we didn't have enough data to find a whole page, read */
        buffer = ogg_sync_buffer(ogsync, CHUNK);
        bytes = fread(buffer, 1, CHUNK, f);
        if(bytes == 0) {
            ogg_sync_wrote(ogsync, 0);
            return 0;
        }
        ogg_sync_wrote(ogsync, (long)bytes);
        *written += bytes;
    }

    return 1;
}

int main()
{
	FILE *file = fopen("48000Hz-s16le-1ch-ChengDu.opus", "rb");
	if(!file) {
        printf("fopen error\n");
        return -1;
    }
	
	ogg_sync_init(&g_ogsync);
	ogg_int64_t written;
	while (get_next_page(file, &g_ogsync, &g_page, &written))
	{
		int packets = ogg_page_packets(&g_page);
		printf("page_num:%03lu; ",ogg_page_pageno(&g_page));
		printf("Oggs:%c %c %c %c; ",g_page.header[0],g_page.header[1],g_page.header[2],g_page.header[3]);
		printf("type=%d, granule_position:%08lld, seg_num=%d; ", g_page.header[5],(long long)ogg_page_granulepos(&g_page), packets);
		
		// 准备bit流
		ogg_stream_state streamState;
		ogg_packet packet;
		ogg_stream_init(&streamState, ogg_page_serialno(&g_page)); // 给定一个流序列号,初始化 streamState
        ogg_stream_pagein(&streamState, &g_page); // 将页数据给到 比特流
		
		int i = 0;
		for(i=0; i<packets; i++)
		{
			ogg_stream_packetout(&streamState, &packet);
			if(packet.bytes >= 19 && memcmp(packet.packet, "OpusHead", 8)==0)
			{
				printf("OpusHead; ");
			}
		}
		printf("\n");
		ogg_stream_clear(&streamState);
	}
	
	return 0;
}

Ogg编码程序,这里就不给了,需要的话,可以去看看opus-tool工具的源码。

在这里插入图片描述

🎄五、总结

本文介绍了ligogg-1.3.5库的下载、编译,以及个别库函数的用法,最后给出一个Ogg封装格式的解码程序代码。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1166587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Charles小白新手入门教程

最近系统地重温了下Charles的各种功能&#xff0c;根据小破站上百里老师的讲解&#xff0c;做了一些笔记&#xff0c;对于Charles入门小白&#xff0c;多少会有点帮助&#xff0c; 下面就把分享给大家~ 一、Charles介绍 1、Charles简介 是基于http和https的代理服务器。 2、…

【windows Docker镜像占用许多空间:将数据迁移到D盘】

查看其占据的空间 导出数据到D盘 首先退出docker C:\Users\lxh>wsl --shutdownC:\Users\lxh> C:\Users\lxh>wsl --export docker-desktop-data docker-desktop-data.tar 正在导出&#xff0c;这可能需要几分钟时间。 操作成功完成。C:\Users\lxh> C:\Users\lxh&g…

探讨安科瑞智慧型动态无功补偿的工业应用-安科瑞 蒋静

摘要&#xff1a;低压配电系统的无功补偿是电能质量治理的重要环节。在传统无功补偿中&#xff0c;响应速度较慢&#xff0c;补偿电流呈阶梯式&#xff0c;存在过补或欠补的现象&#xff0c;有时未必能到达理想的效果。为了解决这一问题&#xff0c;人们提出了一种无功补偿综合…

三篇文章了解计算机网络(小白篇)

目标 三篇文章&#xff08;小白&#xff0c;入门&#xff0c;进阶&#xff09;&#xff0c;由浅入深理解计算机网络 适宜人群 小小白、无计算机网络基础&#xff0c;非技术人员&#xff0c;网络兴趣爱好者 内容简介 本文不谈技术&#xff0c;不谈理论&#xff0c;通过我们…

Sulfo-CY5 NHS荧光染料的生物应用2230212-27-6星戈瑞

Sulfo-CY5 NHS ester是一种用于生物学和生物医学研究中的荧光染料&#xff0c;它在生物应用方面具有许多重要用途&#xff0c;包括但不限于以下几个方面&#xff1a; **生物标记&#xff1a;**Sulfo-CY5 NHS ester可以与生物分子&#xff08;如抗体、蛋白质、核酸等&#xff09…

【Python Numpy】修改数组形状

文章目录 前言一、什么是NumPy数组形状&#xff1f;二、NumPy改变数组形状的方法2.1 reshape方法2.2 resize方法2.3 flatten方法2.4 ravel方法2.5 transpose方法 三、关于修改数组形状更多的示例代码总结 前言 NumPy&#xff08;Numerical Python&#xff09;是Python中用于处…

活跃气氛神器小程序源码系统 带完整搭建教程

在现代社会&#xff0c;人们越来越注重社交和娱乐&#xff0c;而各种聚会和活动更是人们日常生活中的重要组成部分。然而&#xff0c;如何在聚会中创造出轻松愉悦的气氛&#xff0c;让参与者更好地相互了解和交流&#xff0c;一直是活动组织者面临的难题。正是在这样的背景下&a…

Galaxybase全面支持国密算法

万物互联时代&#xff0c;图技术作为底层技术基座&#xff0c;赋能企业关联全域数据&#xff0c;充分激活数据资产价值&#xff0c;受到社会和国家的关注。而随着图技术在各行业的落地和应用&#xff0c;图技术如何保障关联数据的安全&#xff0c;成为重点议题。 在此背景下&a…

SQL语法实践(一)

文章 原文链接 实践 CREATE TABLE friend(fid INT NOT NULL,NAME VARCHAR(10) NOT NULL,age INT NOT NULL,adress VARCHAR(10) )SHOW TABLES; SELECT * FROM friend; SELECT fid,NAME FROM friend;INSERT INTO friend VALUES(1,Jack,18,Tianjing); INSERT INTO friend VALUE…

[Machine Learning][Part 8]神经网络的学习训练过程

目录 训练过程 一、建立模型&#xff1a; 二、建立损失函数 J(w,b): 三、寻找最小损失函数的(w,b)组合 为什么需要激活函数 激活函数种类 二分法逻辑回归模型 线性回归模型 回归模型 训练过程 一、建立模型&#xff1a; 根据需求建立模型&#xff0c;从前面神经网络的…

VMware 虚拟机安装 CentOS 7

CentOS 7 1. 下载CentOS 7 iso镜像 Index of /centos/7.9.2009/isos/x86_64/ 2. Vmware安装CentOS 7 安装教程&#xff1a; 超详细VMware CentOS7(最小安装)安装教程_虚拟机最小化安装-CSDN博客 【精选】VMware 安装 Centos7 详细过程_vm虚拟机安装centos7_expectation Fu…

AI:49-基于深度学习的杂草识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…

JumpServer开源堡垒机与万里安全数据库完成兼容性认证

近日&#xff0c;中国领先的开源软件提供商FIT2CLOUD飞致云宣布&#xff0c;JumpServer开源堡垒机已经与万里安全数据库软件GreatDB完成兼容性认证。针对产品的功能、性能、兼容性方面&#xff0c;经过双方共同测试&#xff0c;万里安全数据库软件&#xff08;简称&#xff1a;…

如何搭建稳定独享的美国IP?优质美国静态住宅代理IP哪里有?

相信很多做跨境电商或外贸如TikTok shop、Facebook商店、Amazon、领英的玩家都需要搭建独享的美国IP环境来运营店铺&#xff0c;那么如何搭建稳定独享的IP环境呢&#xff1f;加下来为你详细介绍&#xff0c;并为你优质的美国静态住宅代理IP&#xff0c;助力您的跨境业务。 一、…

ROS分布式演练,多台设备进行通信的配置

1、概述 前面我们做的操作都是在单个设备上进行&#xff0c;也就是分别开启多个终端&#xff0c;在不同终端上启动节点等相关操作&#xff0c;这里我们使用两台设备来控制&#xff0c;一台虚拟机和一台无人车(使用VNC Viewer连上去&#xff0c;也可以看做一台Linux虚拟机) VNC…

算法:Java构建二叉树并迭代实现二叉树的前序、中序、后序遍历

先自定义一下二叉树的类&#xff1a; // Definition for a binary tree node. public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left…

【优选算法系列】【专题六模拟】第一节.1576. 替换所有的问号和495. 提莫攻击

文章目录 前言一、替换所有的问号 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写二、提莫攻击 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写总结 前言 一、替换所有的问号 1.1…

干洗店洗鞋店小程序开发,洗衣洗鞋管理系统

干洗店洗鞋店小程序开发&#xff0c;洗衣洗鞋管理系统&#xff1b; 一、会员洗衣管理录单取衣&#xff1b; 会员送衣上门&#xff0c;系统完成录单&#xff0c;记录当前衣服的情况&#xff0c;衣物拍照描述&#xff0c;洗涤注意事项&#xff0c;设置好取衣时间等&#xff0c;衣…

山西电力市场日前价格预测【2023-11-04】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-04&#xff09;山西电力市场全天平均日前电价为360.22元/MWh。其中&#xff0c;最高日前电价为452.71元/MWh&#xff0c;预计出现在18: 15。最低日前电价为304.04元/MWh&#xff0c;预计…

设备接入服务组件->微服务and容器化改造说明文档

SVN路径 https://192.0.0.241/USTA-dac/branches/dev/V1.10.500/dac 目录结构 das为设备接入服务&#xff0c;负责驱动管理&#xff0c;资源同步&#xff0c;订阅下发。下面有两个文件夹分别对应了openssl1.0的版本和后面更换接口后openssl1.1的版本。das_proxy为设备信令下发…