分析AAC raw data

news2024/11/28 22:38:22

分析AAC raw data

本文的主要目标是分析说明AAC解码器如何处理RAW AAC数据。通过拆解理解AAC解码器处理raw aac的关键点,通过数据分析和代码阅读,来说明这个细节,某些细微之处尚需深入探索,留待后续更为详尽的阐述。

几种格式介绍

AAC(Advanced Audio Coding)是一种高效的音频压缩技术,广泛用于音频流媒体和存储。AAC数据可以以几种不同的封装格式存在,每种格式都有其特定的头部信息(Header),用于描述音频流的属性,如采样率、比特率和通道配置等。下面将详细解释AAC中常见的四种头部格式:LOAS, ADIF, ADTS, 和 LATM。

RAWS (Raw AAC Data Stream)

RAWS数据流不包含任何额外的头部信息,它只是连续的AAC帧数据。在这种情况下,解码器必须从外部源获取解码所需的元数据,或者使用特定的同步字(如0xFFF0)来识别和分割音频帧。

LOAS (Lossless Audio Stream)

LOAS是一种无损音频流格式,用于MPEG-4 ALS(Audio Lossless Streaming)标准中。

LOAS头包含了音频流的元数据,允许解码器重建原始音频信号。

LOAS头中包含的信息有助于解码器理解如何正确解码音频数据。然而,由于LOAS关注的是无损音频,它与通常的有损压缩AAC格式的其他变体有所不同。

ADIF (AAC Data Interchange Format)

ADIF格式主要用于文件交换,它不包含头部信息来描述音频流的属性。

ADIF文件的音频参数(如采样率和比特率)需要通过外部手段获取。ADIF文件中,音频数据是连续的,没有分割成帧。

ADIF没有固定的头部信息,音频参数通过外部元数据提供。

ADTS (AAC ADaptive Transport Stream)

ADTS(Audio Data Transport Stream)头部包含了一组固定的参数,这些参数描述了音频流的属性,如采样率、比特率、通道数等。

ADTS将音频数据分割成帧,并在每一帧的开始处插入头部信息,这使得解码器能够在接收到每一帧时立即开始解码,而无需等待整个音频流。

LATM (Low-latency Audio Transport Mechanism)

LATM(Low-overhead MPEG-4 Audio TransportMultiplex 低开销音频传输复用)格式是MPEG-4 AAC制定的一种高效率的码流传输方式,MPEG-2 TS 流也采用LATM。

LATM格式以帧为单位,主要由AudioSpecificConfig(音频特定配置单元)与音频负载组成。

AudioSpecificConfig相当于ADTS header,它包含了音频信息,如采样率,声道数等信息。

这里对LOAS,ADIF,ADTS,LATM不进行展开,这里重点要说的是除了这几种格式之外的aac raw data,就是没有任何header的raw数据,用gstreamer aacparse的SRC pad来看就好理解了,aacparse支持的stream-format有四种raw,adts,adif,loas:

  SRC template: 'src'
    Availability: Always
    Capabilities:
      audio/mpeg
                 framed: true
            mpegversion: { (int)2(int)4 }
          stream-format: { (string)raw, (string)adts, (string)adif, (string)loas }

FFmpeg对AAC的支持

FFmpeg aac demxer

ff_aac_demuxer只支持adts格式:

const AVInputFormat ff_aac_demuxer = {
    .name         = "aac".long_name    = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)").read_probe   = adts_aac_probe,
    .read_header  = adts_aac_read_header,
    .read_packet  = adts_aac_read_packet,
    .flags        = AVFMT_GENERIC_INDEX,
    .extensions   = "aac".mime_type    = "audio/aac,audio/aacp,audio/x-aac".raw_codec_id = AV_CODEC_ID_AAC,
};

FFmpeg aac decoder

从aac_decode_frame的代码看,aac decoder是能支持raw aac解码:

const FFCodec ff_aac_decoder = {
    .p.name          = "aac".p.long_name     = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)").p.type          = AVMEDIA_TYPE_AUDIO,
    .p.id            = AV_CODEC_ID_AAC,
    .priv_data_size  = sizeof(AACContext).init            = aac_decode_init,
    .close           = aac_decode_close,
    FF_CODEC_DECODE_CB(aac_decode_frame).p.sample_fmts   = (const enum AVSampleFormat[]) {
        AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
    }.p.capabilities  = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
    .caps_internal   = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
#if FF_API_OLD_CHANNEL_LAYOUT
    .p.channel_layouts = aac_channel_layout,
#endif
    .p.ch_layouts    = aac_ch_layout,
    .flush = flush,
    .p.priv_class    = &aac_decoder_class,
    .p.profiles      = NULL_IF_CONFIG_SMALL(ff_aac_profiles)};

但是实际上通过命令行测试的时候有报错,报错如下,原因是我用的raw aac中包含FF F0的字节,这个会被当做adts而去做adts parse:

[aac @ 0x556af5d4e370] Format aac detected only with low score of 1, misdetection possible!
[aac @ 0x556af5d4eee0] Assuming an incorrectly encoded 7.1 channel layout instead of a spec-compliant 7.1(wide) layout
, use -strict 1 to decode according to the specification instead.
[aac @ 0x556af5d4eee0] channel element 1.13 is not allocated
[aac @ 0x556af5d4eee0] Error decoding AAC frame header.
[aac @ 0x556af5d4eee0] More than one AAC RDB per ADTS frame is not implemented. Update your FFmpeg version to the newe
st one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented.
[aac @ 0x556af5d4eee0] invalid band type
[aac @ 0x556af5d4eee0] channel element 1.8 is not allocated
[aac @ 0x556af5d4eee0] channel element 2.11 is not allocated
[aac @ 0x556af5d4eee0] Multiple frames in a packet.
[aac @ 0x556af5d4eee0] channel element 3.0 is not allocated
[aac @ 0x556af5d4eee0] channel element 1.6 is not allocated
[aac @ 0x556af5d4eee0] channel element 3.9 is not allocated
[aac @ 0x556af5d4eee0] channel element 2.13 is not allocated
[aac @ 0x556af5d4eee0] channel element 1.4 is not allocated
[aac @ 0x556af5d4eee0] Sample rate index in program config element does not match the sample rate index configured by 
the container.
[aac @ 0x556af5d4eee0] channel element 1.10 is not allocated
[aac @ 0x556af5d4eee0] channel element 3.3 is not allocated

关于aac raw data bloack

从ISO_IEC-14996-3文档中找到raw_data_block的说明:
在这里插入图片描述

在这里插入图片描述

raw_data_block

这部分是google翻译而来

包含 1024 或 960 个样本时间段内的音频数据、相关信息和其他数据的原始数据块。

七个语法元素,由数据元素 id_syn_ele 标识。

一个 raw_data_block() 中的 audio_channel_element() 必须只有一个采样率。在 raw_data_block() 中,可以出现相同语法元素的多个实例,但必须具有不同的 4 位 element_instance_tag,data_stream_element() 和 fill_element() 除外。

因此,在一个 raw_data_block() 中,任何语法元素的实例可以有 0 到最多 16 个,data_stream_element() 和 fill_element() 除外,这些实例不受此限制。如果出现多个具有相同 element_instance_tag 的 data_stream_element(),则它们是同一数据流的一部分。 fill_element() 没有 element_instance_tag(因为内容不需要后续引用)并且可以出现任意次数。raw_data_block() 的结尾用特殊的 id_syn_ele (TERM) 表示,该 id_syn_ele (TERM) 在 raw_data_block() 中只能出现一次。

single_channel_element()

缩写 SCE。包含单个音频通道编码数据的比特流的语法元素。single_channel_element() 基本上由 individual_channel_stream() 组成。每个原始数据块最多可能有 16 个这样的元素,每个元素都必须具有唯一的 element_instance_tag。

channel_pair_element()

缩写 CPE。包含一对通道数据的比特流有效负载的语法元素。channel_pair_element() 由两个 individual_channel_streams 和附加联合通道编码信息组成。两个通道可以共享公共边信息。 channel_pair_element() 的限制与单通道元素的 element_instance_tag 和出现次数相同。

coupling_channel_element()

缩写 CCE。包含耦合通道音频数据的语法元素。耦合通道表示一个块的多通道强度信息,或用于多语言编程的对话信息。coupling_channel_element() 的数量和实例标签的规则与 single_channel_element() 相同。

lfe_channel_element()

缩写 LFE。包含低采样频率增强通道的语法元素。lfe_channel_element() 的数量和实例标签的规则与single_channel_element() 相同。

program_config_element()

缩写 PCE。包含程序配置数据的语法元素。program_config_element() 的数量和元素实例标签的规则与 single_channel_element() 相同。 PCE 必须位于 raw_data_block() 中的所有其他语法元素之前。

fill_element()

缩写 FIL。包含填充数据的语法元素。填充元素的数量可能任意,它们可以以任何顺序出现在原始数据块中。

data_stream_element()

缩写 DSE。包含数据的语法元素。同样,有 16 个 element_instance_tags。但是,对于任何一个实例标签的 data_stream_element() 的数量没有限制,因为单个数据流可以跨越具有相同实例标签的多个 data_stream_element()。

紧接着后面还有一个解码的举例:

在这里插入图片描述

faad2的解码

faad中的header type:

/* header types */
#define RAW        0
#define ADIF       1
#define ADTS       2
#define LATM       3

faad2中,RAW/ADIF/ADTS存在于aac文件中,LATM存在于mp4文件中,可以在文件头中先找到‘ftyp’。

faad2解码的代码:

/** frontend/main.c */

static int faad_main(int argc, char *argv[])
    
/* frontend/main.c: parse aac header */

static int decodeAACfile(char *aacfile, char *sndfile, char *adts_fn, int to_stdout,
                  int def_srate, int object_type, int outputFormat, int fileType,
                  int downMatrix, int infoOnly, int adts_out, int old_format,
                  float *song_length)

/* libfaad/decoder.c: decode frame */
void* NeAACDecDecode(NeAACDecHandle hpDecoder,
                                 NeAACDecFrameInfo *hInfo,
                                 unsigned char *buffer,
                                 unsigned long buffer_size)

/* libfaad/syntax.c: raw_data_block */

void raw_data_block(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo,
                    bitfile *ld, program_config *pce, drc_info *drc)

通过试验,faad2支持raw,adif,adts的解码。

gstreamer aacparse代码

adif header解析

/* Check if an ADIF header is present */
if ((buffer[0] == 'A') && (buffer[1] == 'D') &&
    (buffer[2] == 'I') && (buffer[3] == 'F'))
{
    hDecoder->adif_header_present = 1;

adts header解析

/* Check if an ADTS header is present */
} else if (faad_showbits(&ld, 12) == 0xfff) {
    hDecoder->adts_header_present = 1;

    adts.old_format = hDecoder->config.useOldADTSFormat;
    adts_frame(&adts, &ld);

    hDecoder->sf_index = adts.sf_index;
    hDecoder->object_type = adts.profile + 1;

    *samplerate = get_sample_rate(hDecoder->sf_index);
    *channels = (adts.channel_configuration > 6) ?
        2 : adts.channel_configuration;
}

生成aac格式

gstreamer生成aac raw格式

gst-launch-1.0 filesrc location=~/audio/cunzai.aac ! aacparse \
! audio/mpeg,mpegversion=4,stream-format=raw ! filesink location=./cunzai-aacraw.aac

这个命令生成的aac虽然开头缺少adts的0xFFF1,但是文件中间是有0xFFF1的,两个0xFFF1之间的size看着也很大,下面的faad解析log来看是raw格式,所以raw格式为什么也有0xFFF1,需要后续再研究一下。

在这里插入图片描述

faad直接解码aac raw
$ ./frontend/faad cunzai-adif.raw

 *********** Ahead Software MPEG-4 AAC Decoder V2.10.0 ******************

 Build: Aug 13 2024
 Copyright 2002-2004: Ahead Software AG
 http://www.audiocoding.com
 bug tracking: https://sourceforge.net/p/faac/bugs/
 Floating point version

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License.

 **************************************************************************

cunzai-adif.raw file info:
RAW

  ---------------------
 | Config:  2 Ch       |
  ---------------------
 | Ch |    Position    |
  ---------------------
 | 00 | Left front     |
 | 01 | Right front    |
  ---------------------

Decoding cunzai-adif.raw took:  0.58 sec.  0.00x real-time.

faad解析raw aac生成带adts头的aac文件,然后用ffplay播放:

./frontend/faad ~/audio/cunzai-aacraw.aac -a cunzai-adts.aac
ffplay cunzai-adts.aac
aacparse支持三种格式
Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      audio/mpeg
            mpegversion: { (int)2(int)4 }
  
  SRC template: 'src'
    Availability: Always
    Capabilities:
      audio/mpeg
                 framed: true
            mpegversion: { (int)2(int)4 }
          stream-format: { (string)raw, (string)adts, (string)adif, (string)loas }

但是不能用stream-format=adif指定adif格式,下面这个命令会报协商失败的错误:

gst-launch-1.0 filesrc location=~/audio/cunzai.aac ! aacparse \
  ! audio/mpeg,mpegversion=4,stream-format=adif ! filesink location=./cunzai-adif.adif

解析aac文件(带adts头),生成adif格式aac,实际上这个命令运行不了,aacparse不支持adif。

从aacparse的srcpad代码来看,其output_header_type只支持DSPAAC_HEADER_NONEDSPAAC_HEADER_ADTS,而DSPAAC_HEADER_NONE就是raw格式:

allowed = gst_pad_get_allowed_caps (GST_BASE_PARSE (aacparse)->srcpad);
if (allowed && !gst_caps_can_intersect (src_caps, allowed)) {
 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
     "Caps can not intersect");
 if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
   GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
       "Input is ADTS, trying raw");
   gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "raw"NULL);
   if (gst_caps_can_intersect (src_caps, allowed)) {
     GstBuffer *codec_data_buffer;

     GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
         "Caps can intersect, we will drop the ADTS layer");
     aacparse->output_header_type = DSPAAC_HEADER_NONE;

     /* The codec_data data is according to AudioSpecificConfig,
        ISO/IEC 14496-3, 1.6.2.1 */
     codec_data_buffer = gst_buffer_new_and_alloc (2);
     gst_buffer_fill (codec_data_buffer, 0, codec_data, 2);
     gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER,
         codec_data_buffer, NULL);
   }
 } else if (aacparse->header_type == DSPAAC_HEADER_NONE) {
   GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
       "Input is raw, trying ADTS");
   gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts"NULL);
   if (gst_caps_can_intersect (src_caps, allowed)) {
     GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
         "Caps can intersect, we will prepend ADTS headers");
     aacparse->output_header_type = DSPAAC_HEADER_ADTS;
   }
 }

所以把adif换成raw是可以的:

gst-launch-1.0 filesrc location=~/audio/cunzai.aac ! aacparse \
! audio/mpeg,mpegversion=4,stream-format=raw ! filesink location=./cunzai-aacraw.aac

faad2解码raw aac

./frontend/faad ~/audio/cunzai-aacraw.aac

修改faad2代码:

$ git diff .
diff --git a/libfaad/syntax.c b/libfaad/syntax.c
index a0ea100..eb953bb 100644
--- a/libfaad/syntax.c
+++ b/libfaad/syntax.c
@@ -624,6 +624,11 @@ void raw_data_block(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo,
         faad_byte_align(ld);
     }
 
+    if (id_syn_ele == ID_END)
+    {
+        printf("id_syn_ele == ID_END bytesconsumed %d\n", ld->buffer_size - ld->bytes_left);
+    }
+
     return;
 }

通过增加这个打印,可以看到raw_data_block,会在id_syn_ele == ID_END的时候结束,ID_END意味着当前一帧的结束。从输出的log中grep ID_END也能判断处理的帧数。

gstreamer生成adif aac

因为前面通过gstreamer生成adif格式失败,所以换个思路,通过fdkaacenc生成:

gst-launch-1.0 audiotestsrc ! fdkaacenc \
  ! audio/mpeg,stream-format=adif ! filesink location=test-aac.adif

这个命令生成ADIF文件成功,文件开头是ADIF,faad可以直接解码:

在这里插入图片描述

$ faad test-aac.adif 

 *********** Ahead Software MPEG-4 AAC Decoder V2.9.1 ******************

 Build: 2023-08-22
 Copyright 2002-2004: Ahead Software AG
 http://www.audiocoding.com
 bug tracking: https://sourceforge.net/p/faac/bugs/
 Floating point version

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License.

 **************************************************************************

test-aac.adif file info:
ADIF, 393.291 sec, 56 kbps, 44100 Hz

  ---------------------
 | Config:  2 Ch       |
  ---------------------
 | Ch |    Position    |
  ---------------------
 | 00 | Left front     |
 | 01 | Right front    |
  ---------------------

Decoding test-aac.adif took:  0.35 sec. 1124.36x real-time.

gstreamer avdec_aac解码adif会报错,虽然avdec_aac的sink pad来看也支持adif:

gst-play-1.0 test-aac.adif \
  --audiosink="audio/mpeg,stream-format=adif ! aacparse ! avdec_aac ! autoaudiosink"

fdkaacdec可以:

gst-play-1.0 test-aac.adif \
  --audiosink="audio/mpeg,stream-format=adif ! aacparse ! fdkaacdec ! autoaudiosink"

因为fdkaacdec的pad如下,支持adif:

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      audio/mpeg
            mpegversion: { (int)2(int)4 }
          stream-format: { (string)adts, (string)adif, (string)raw }
               channels: [ 18 ]
  

faad不行,faad不支持adif输入,但是支持raw:

$ gst-launch-1.0 filesrc location=./test-aac.adif \
  ! audio/mpeg,stream-format=adif ! aacparse ! faad ! autoaudiosink

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstAacParse:aacparse0: Internal data stream error.

faad的pad:

  SINK template: 'sink'
    Availability: Always
    Capabilities:
      audio/mpeg
            mpegversion: 2
      audio/mpeg
            mpegversion: 4
          stream-format: { (string)raw, (string)adts }

附:faad的编译调试

下载代码

git clone https://github.com/knik0/faad2.git

编译

cd faad2
mkdir build
cd build
../configure --disable-shared
make -j8

调试

编译完后在frontend目录下生成了faad,如果没有--disable-shared选项,frontend/.libs下会生成faad,但是还要依赖libfaad.so

$ file frontend/faad 
frontend/faad: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, \
interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b3a7cbde55448d6ba74f4922ec23061d20b29eff, \
for GNU/Linux 3.2.0, with debug_info, not stripped

gdb或者vscode就可以直接启动faad进行调试。

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

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

相关文章

C语言 ——— 常见的动态内存错误(上篇)

对NULL指针的解引用操作 代码演示: int* ptr (int*)malloc(sizeof(int) * INT_MAX); *ptr 10; free(ptr); 代码解析: 使用 malloc 函数动态开辟 sizeof(int)*INT_MAX 这么多个字节的空间,而 INT_MAX 是整型类型的最大值,那么…

优化WAN流量:如何通过调整系统设置降低企业网络成本

一、症状与问题背景 当电脑显示空闲状态时,如果满足以下条件,第二拨号链接可能会意外激活: 您正在使用基于 Microsoft Windows 的计算机,该计算机连接到远程网络并且是 Active Directory 域服务 (AD DS) 域的成员。 您通过二级…

jpg怎么转换成pdf?6个简单方法,实现jpg转换成pdf

你是否也曾想将jpg图片转换为pdf格式文档呢?亦或者在处理文档或制作报告时,不知道怎么才能更快地将多张图片整合成一个pdf文件呢?如果你正在寻找简单快速的方法,又有哪些工具可以帮助您完成图片转pdf呢?别着急&#xf…

Windows服务器部署基于【若依管理系统】开发的项目

🎯导读:本文档详述了基于前后端分离的若依系统(版本3.8.8)在Windows环境下从零开始的部署流程,包括JDK、Redis、MySQL等环境的搭建与配置。前端部署涉及Vue项目构建、图片优化及利用Nginx托管;而后端则涵盖…

猫咪掉毛严重如何清理?希喂,霍尼韦尔宠物空气净化器实测分享

随着养宠人群的增多,市场关注到铲屎官们的需要,带来了新的科技产品——宠物空气净化器。宠物空气净化器是在普通空气净化器基础上,调整服务对象,为吸附宠物毛发而设计的。不少消费者被它的功能所吸引,打算购入使用。然…

带你速通C语言——函数(11)

在 C 语言中,函数是组织代码的重要方式,它们允许我们将代码划分为可重用的模块,每个模块执行特定的任务。函数的使用有助于代码的清晰性和维护性,也是编写结构化程序的基本构建块之一。 1.函数的基本组成 在 C 中定义函数时&…

Agentic Security:一款针对LLM模型的模糊测试与安全检测工具

关于Agentic Security Agentic Security是一款针对LLM模型的模糊测试与安全检测工具,该工具可以帮助广大研究人员针对任意LLM执行全面的安全分析与测试。 请注意 Agentic Security 是作为安全扫描工具设计的,而不是万无一失的解决方案。它无法保证完全防…

八爪鱼现金流-034,实际使用,资产折线图

每个月发工资后,记账月报。 回顾资产折线图。 比较大的波动,一次是22年2月左右贷款买房。一次是24年8月宝宝出生。 孩子开销太大。呜呜呜。 话说,这个折线图,能不能加一个标签或者备注呢? 这个需求功能稍后我研究一…

【STM32 HAL库】寻迹小车 开环控制 状态机 TB6612+TCRT5000+HC-05

【STM32 HAL库】寻迹小车 开环控制 状态机 TB6612TCRT5000HC-05 前言硬件硬件准备模块说明主控 APM32F103VBT6核心板DC/DC降压模块TB6612电机驱动TCRT5000红外循迹模块HC-05蓝牙透传模块 代码逻辑宏观框架状态机 框架测试微观模块电机模块循迹模块蓝牙控制模块 前言 碎碎念一下…

keepalived安装-centos7

一、yum安装 1、安装Keepalived: yum install -y keepalived 2、启动Keepalived服务: systemctl start keepalived 3、设置Keepalived服务开机自启 systemctl enable keepalived 4、检查Keepalived服务状态: systemctl status keepal…

VAuditDemo常规漏洞

VAuditDemo常规漏洞 一、留言类功能漏洞 messageDetail.php - 存在数字型SQL注入,反射型XSS SQL注入 sqlwaf修改措施 反射型XSS messageSub.php search.php - 存在反射型xss 二、用户操作类漏洞 1、登录功能 logCheck.php - 空验证码绕过漏洞 2、编辑用户信息类 upd…

秘密指南!浮毛会危害人体健康吗?宠物空气净化器帮助解决危害

每当立秋一到,对于我这样的重度鼻炎患者而言,无疑是又一轮掉毛季的预警。家中猫咪的毛发仿佛永远扫不尽,皮屑也无处不在,让人头疼不已。好在,两年前我采纳了宠物医生的建议,用上了宠物空气净化器&#xff0…

Element-plus el-input 添加图标

案例图 根据官方文档来,我们需要先注册图标并应用到全局。 import { createApp } from "vue" import App from "./App.vue"const app createApp(App) //创建VUE对象import * as ElementPlusIconsVue from "element-plus/icons-vue"f…

竞争和冒险

竞争和冒险 文章目录 竞争和冒险总结 产生原因 数字电路中,信号传输与状态变换时都会有一定的延时。 在组合逻辑电路中,不同路径的输入信号变化传输到同一点门级电路时,在时间上有先有后,这种先后所形成的时间差称为竞争&#xf…

【方法】如何给ZIP压缩文件添加密码?

如果想要保护ZIP压缩文件不被他人随意打开,可以设置密码保护,那要如何设置呢?下面推荐两种方法,一起来看看吧! 方法1: 如果想在压缩文件的时候,同时设置密码,可以使用WinRAR或者7-…

Qt 系统相关 - 文件

目录 1. 文件概述 2. 输入输出设备类 3. 文件读写类 4. 文件和目录信息类 1. 文件概述 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。 Qt 提供了很多关于文件的类,通过这些类能够对文件系统进行操作&#x…

04.震动控制灯

vibrate 的意思就是震动 #include "reg52.h" #include <intrins.h>sbit led1 P3^7; sbit vibrate P3^3;void Delay2000ms() //11.0592MHz {unsigned char i, j, k;_nop_();i 15;j 2;k 235;do{do{while (--k);} while (--j);} while (--i); }void main()…

1块钱的家用桶装水抽水泵方案开发

目录 背景介绍需求分析 背景介绍 2024年8月&#xff0c;接到惠州大亚湾客户一个开发桶装水的一个PCB方案开发&#xff0c;要求成本控制在1万套&#xff0c;Bom成本在一块钱。 说干就干&#xff0c;先在网上搜索一下目前市面上的方案。 需求分析 想这种传统的桶装水是手动的…

DVWA综合靶场漏洞讲解

目录 综合靶场漏洞讲解 Brute Force Low Medium High Command Injection Low Medium High File Inclusion Low,Medium,High File Upload Low Medium High SQL Injection Low Medium High SQL Injection (Blind) Low Medium High XSS&#xff08;DOM&am…

未来购物新境界:商品样机3D展示可视化引领潮流

在这个日新月异的数字时代&#xff0c;科技的每一次飞跃都在深刻改变着我们的生活方式&#xff0c;尤其是购物体验。从传统的实体店选购到线上商城的便捷浏览&#xff0c;再到如今商品样机3D展示可视化的兴起&#xff0c;消费者正逐步踏入一个前所未有的沉浸式购物新时代。 想象…