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

😁博客主页😁:🚀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 logicalOgg 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 compactthis way, but it is simple coupled to thelacing 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 thelogical bitstream */int     b_o_s;          /* set after we've written the initial pageof a logical bitstream */long    serialno;long    pageno;ogg_int64_t  packetno;  /* sequence number for decode; the framingknows where there's a hole in the data,but we need coupling so that the codec(which is in a separate abstractionlayer) also knows about the gap */ogg_int64_t   granulepos;} ogg_stream_state;/* ogg_packet is used to encapsulate the data and metadata belongingto 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 framingknows where there's a hole in the data,but we need coupling so that the codec(which is in a separate abstractionlayer) 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封装格式文件读取的程序。

解码程序步骤:

  • 1、打开文件;
  • 2、调用 ogg_sync_init 初始化一个ogg_sync_state结构体;
  • 3、获取一页数据,并处理;
    • 3.1、根据序列号初始化一个比特流 ogg_stream_init
    • 3.2、把页数据给到比特流 ogg_stream_pagein
    • 3.3、获取数据包 ogg_stream_packetout
    • 3.4、释放比特流;
  • 4、关闭文件

程序使用的 48000Hz-s16le-1ch-ChengDu.opus ,是opus编码的Ogg封装文件。

程序编译需要了解前面编译好的ligogg库和头文件,参考:

gcc liboggDec.c ../../libogg-1.3.5/result_gcc/lib/libogg.a -I ../../libogg-1.3.5/result_gcc/include/

Ogg文件解码程序如下,虽然并没有完整解析出音频,但可以加深对libogg库的理解:

// 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 4096ogg_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)); // 给定一个流序列号,初始化 streamStateogg_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.mzph.cn/news/130159.shtml

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

相关文章

算法随想录算法训练营第四十九天| 503.下一个更大元素II 42. 接雨水

503.下一个更大元素II 题目&#xff1a;给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个…

算法题:16. 最接近的三数之和(Python Java 详解)

解题思路 Step1&#xff1a;先对数组排序&#xff0c;然后设置3个指针&#xff0c;指针1遍历范围为&#xff08;0~数组长度减2&#xff09;。 Step2&#xff1a;指针1位置确定时&#xff0c;指针1后面的数组元素首位各放置一个指针&#xff08;指针2、指针3&#xff09;。 S…

Python笔记——linux/ubuntu下安装mamba,安装bob.learn库

Python笔记——linux/ubuntu下安装mamba&#xff0c;安装bob.learn库 一、安装/卸载anaconda二、安装mamba1. 命令行安装&#xff08;大坑&#xff0c;不推荐&#xff09;2. 命令行下载guihub上的安装包并安装&#xff08;推荐&#xff09;3. 网站下载安装包并安装&#xff08;…

电路正负反馈,电压电流反馈,串并联反馈详细判别方法

正/负反馈&#xff1a;假设输出升高&#xff0c;转一圈回来仍使其升高就是正反馈&#xff0c;反之就是负反馈。作图法&#xff1a;在RL的信号端画一个向上的小箭头&#xff0c;沿着反馈环路&#xff0c;每经过一个元器件就画一个相应的箭头&#xff0c;一直画到放大器的输出端&…

代理模式(静态代理、JDK代理、CGLIB代理)

简介 代理模式有三种不同的形式&#xff1a;静态代理、动态代理&#xff08;JDK代理、接口代理&#xff09;、CGLIB代理 目标&#xff1a;在不修改目标对象的前提下&#xff0c;对目标对象进行扩展。 静态代理 需要定义接口或父类对象&#xff0c;被代理对象和代理对象通过实…

asp.net docker-compose添加dapr配置

docker-compose.yml添加配置 webapplication1-dapr:image: "daprio/daprd:1.9.6"network_mode: "service:webapplication1"depends_on:- webapplication1 docker-compose.override.yml中添加 dapr-placement:command: ["./placement", "-po…

【数据结构】顺序表的学习

前言:在之前我们学习了C语言的各种各样的语法&#xff0c;因此我们今天开始学习数据结构这一个模块&#xff0c;因此我们就从第一个部分来开始学习"顺序表"。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:数据结构 &#x1f…

windows和docker环境下springboot整合gdal3.x

链接: gdal官网地址 gdal gdal的一个用c语言编写的库&#xff0c;用于处理地理信息相关的数据包括转换&#xff0c;识别数据&#xff0c;格式化数据以及解析 同时提供第三方语言的SDK包括python&#xff0c;java上述需要编译后使用 java是需要使用jni接口调用实现方法在wind…

mysql---存储引擎

目录 mysql---存储引擎 功能&#xff1a; mysql的存储引擎分类 MYISAM和INNODB做个对比 MYISAM 在磁盘上有三个文件&#xff1a; MYISAM的特点&#xff1a; 支持的存储格式: INNODB innodb的特点 使用场景&#xff1a; 三个文件&#xff1a; 行锁 表锁 排他锁 …

uniapp原生插件之安卓文件操作原生插件

插件介绍 安卓文件操作原生插件&#xff0c;读写文件&#xff0c;文件下载等&#xff0c;支持读取移动设备路径等外部存储设备路径&#xff0c;如U盘路径 插件地址 安卓文件操作原生插件 - DCloud 插件市场 超级福利 uniapp 插件购买超级福利 详细使用文档 uniapp 安卓文…

互联网医院|湖南互联网医院|智慧医疗改善就医服务

互联网医院系统&#xff0c;是指利用互联网技术和远程医疗技术&#xff0c;提供在线就诊、咨询、诊断和治疗等医疗服务的一种医疗模式。互联网医院系统实际上与医院的HIS系统很相似&#xff0c;是侧重服务于线上问诊的专业HIS&#xff0c;包含传统HIS的基本模块&#xff0c;如挂…

VS Code 开发 Spring Boot 类型的项目

在VS Code中开发Spring Boot的项目&#xff0c; 可以导入如下的扩展&#xff1a; Spring Boot ToolsSpring InitializrSpring Boot Dashboard 比较建议的方式是安装Spring Boot Extension Pack&#xff0c; 这里面就包含了上面的扩展。 安装方式就是在扩展查找 “Spring Boot…

【工具】【IDE】Qt Creator社区版

Qt Creator社区版下载地址&#xff1a;https://download.qt.io/archive/qt/ 参考&#xff1a;https://cloud.tencent.com/developer/article/2084698?areaSource102001.8&traceIduMchNghqp8gWPdFHvSOGg MAC安装并配置Qt&#xff08;超级简单版&#xff09; 1.安装brew&…

精品Python手机选购决策数据的分析与可视化大屏购物商城-爬虫

《[含文档PPT源码等]精品基于Python的手机选购决策数据的分析与可视化-爬虫》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django …

2023-mac rz sz 安装

之前安装过一次&#xff0c;没问题&#xff0c;这次按照之前教程装了就不管上传下载都会卡住&#xff1b; step1: brew install lrzsz step2&#xff1a;在/usr/local/bin 路径下配置两个sh,之前从网上找到的直接用都不对&#xff0c;下面这个是调试过的正式可用的 iterm2…

堆叠注入 [GYCTF2020]Blacklist1

打开题目 判断注入点 输入1&#xff0c;页面回显 输入1 页面报错 输入 1 # 页面正常&#xff0c;说明是单引号的字符型注入 我们输入1; show databases; # 说明有6个数据库 1; show tables; # 说明有三个表 我们直接查看FlagHere的表结构 1;desc FlagHere&#xff1b;# 发…

『PyQt5-基本控件』| 16 什么是屏幕坐标系?

16 什么是屏幕坐标系? 1 什么是屏幕坐标系?2 相关概念3 代码实现4 获取窗口坐标4.1 直接获取4.2 通过坐标系获取4.3 获取Frame坐标1 什么是屏幕坐标系? 2 相关概念 屏幕坐标系,即窗口相对于屏幕的坐标。屏幕左上角坐标称为原点坐标(0,0);窗口的坐标,即窗口的左上角相对…

uniapp在APP端使用swiper进行页面不卡顿滑动

uniapp在APP端使用swiper进行页面会卡顿&#xff0c;主要是渲染的数据有点多&#xff0c;这里只渲染三个数据就不好那么卡顿了&#xff0c;每次滑动后更新数据 <view><swiper change"changePoint" circular :disable-touch"disableTouch"><…

速卖通新卖家有必要测评吗?

大家都知道通过测评可以提升产品的转化率&#xff0c;提升产品的销量&#xff0c;那么做速卖通的卖家有必要测评吗&#xff1f; 测评就是类似于国内电商的补单&#xff0c;而一个类目里面竞争很大很卷的话&#xff0c;不去补销量来提升产品的权重&#xff0c;凭借着平台给的自…

静态链表的定义与实现(数据结构与算法)

1. 静态链表 用数组的方式实现的链表 单链表&#xff1a; 各个结点在内存中星罗棋布、散落天涯 静态链表&#xff1a;分配一整片连续的内存空间&#xff0c; 各个结点集中安置。 1.1 静态链表的优点 不需要像动态链表那样频繁地进行内存分配和释放&#xff0c;可以节省内存…