FFMpeg源码分析,关键结构体分析(一)

http://lazybing.github.io/blog/categories/ffmpegyuan-ma-fen-xi/

一、下载FFmpeg的编译源码

 进入网站:http://ffmpeg.org/download.html

二、编译源码

执行下述命令:

./configure --prefix=/usr/local/ffmpeg --enable-debug=3 --enable-ffplay
sudo make -j 4
sudo make install

如果编译成功,那么将会在安装路径/user/local/ffmpeg下出现如下子目录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

FFMpeg 作为音视频领域的开源工具,它几乎可以实现所有针对音视频的处理。本文详细记录使用 FFMpeg 开发过程中,经常使用到的结构体的含义以及使用场景。
首先,我们从 FFMpeg 主要完成的功能视频编解码开始,编解码的大致流程可以使用如下图表
在这里插入图片描述
AVPacket结构体解析
从上面的图中可以看出,解复用器 Demuxer 输出的 packets data 作为解码器 Decoder 的输入;同时也是编码器 Encoder 的输出,复用器 Muxer 的输入。

FFMpeg 中使用 AVpacket 结构定义图中描述的 packet。该结构保存了压缩数据,它由 demuxers 输出,之后作为 decoders 的输入;或作为 encoders 的输出,之后作为 muxers 的输入。

对于视频数据,它只包含一帧压缩数据;对于音频数据,它可能包含多帧压缩数据。

typedef struct AVPacket{AVBufferRef *buf;int64_t      pts;int64_t      dts;uint8_t    *data;int         size;int stream_index;int        flags;AVPacketSideData *side_data;int side_data_elems;int   duration;int64_t pos;int64_t convergence_duration;
}

pts:显示时间戳,它的单位是 AVStream->time_base;如果在文件中没有保存这个值,它被设置为 AV_NOPTS_VALUE。由于图像显示不可能早于图像解压,因此 PTS 必须比 DTS(解码时间戳)大或者相等。某些文件格式中可能会使用 PTS/DTS 表示其他含义,此时时间戳必须转为真正的时间戳才能保存到 AVPacket 结构中。
dts:解码时间戳,它的单位是 AVStream->time_base,表示压缩视频解码的时间,如果文件中没有保存该值,它被设置为 AV_NOPTS_VALUE。
data:指向真正的压缩编码的数据。
size:表示该 AVPacket 结构中 data 字段所指向的压缩数据的大小。
stream_index:标识该 AVPacket 结构所属的视频流或音频流。
duration:该 AVPacket 包以 AVStream->time_base 为单位,所持续的时间,0 表示未知,或者为显示时间戳的差值(next_pts - this pts)。
pos:表示该 AVPacket 数据在媒体中的位置,即字节偏移量。
由上面的图可以看出,该结构主要用于解码器(Decoder)或编码器(Encoder),一般使用方法代码示例如下:

AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.size = ...
avpkt.data = ...

AVFrame结构体解析
上面已经分析了压缩域的表示结构体 AVPacket 结构,与之相对于的,FFMpeg 为之提供的表示像素域的结构体为 AVFrame 结构。从上面的图中也可以看出,Frame 主要作为解码器的输出、编码器的输入。AVFrame 结构主要用来描述未压缩的视频或音频数据,比如视频的 YUV 数据、RGB 数据,音频的 PCM 数据等。

AVFrame 结构体必须使用av_frame_alloc()分配,注意该函数只是分配了 AVFrame 结构本身,它的 data 区域要用其他方式管理;该结构体的释放要用av_frame_free()。

AVFrame 结构体通常只需分配一次,之后即可通过保存不同的数据来重复多次使用,比如一个 AVFrame 结构可以保存从解码器中解码出的多帧数据。此时,就可以使用av_frame_unref()释放任何由 Frame 保存的参考帧并还原回最原始的状态。

typedef struct AVFrame{uint8_t *data[AV_NUM_DATA_POINTERS];int linesize[AV_NUM_DATA_POINTERS];uint8_t **extended_data;int width, height;int nb_samples; /* number of audio samples(per channel) described by this frame */int format;int key_frame; /* 1->keyframe, 0->not*/enum AVPictureType pict_type;AVRational sample_aspect_ratio;int64_t pts;int64_t pkt_pts;int64_t pkt_dts;int coded_picture_number;int display_picture_number;int quality;void *opaque; /* for some private data of the user */uint64_t error[AV_NUM_DATA_POINTERS];int repeat_pict;int interlaced_frame;int top_field_first;	/* If the content is interlaced, is top field displayed first */int palette_has_changed;int64_t reordered_opaque;int sample_rate;    /*Sample rate of the audio data*/uint64_t channel_layout; /*channel layout of the audio data*/AVBufferRef *buf[AV_NUM_DATA_POINTERS];AVBufferRef **extended_buf;int nb_exteneded_buf;AVFrameSideData **side_data;int nb_side_data;int flags;enum AVColorRange color_range;enum AVColorPrimaries color_primaries;enum AVColorTransferCharacteristic color_trc;enum AVColorSpace colorspace;enum AVChromaLocation chroma_location;int64_t best_effort_timestamp;int64_t pkt_pos;int64_t pkt_duration;AVDictionary *metadata;int decode _error_flags;int channels;int pkt_size;AVBufferRef *qp_table_buf;
}

data:指向图片或信道的指针,与初始化时分配的大小可能不同,一些解码器取数据范围超出(0,0)-(width, height),具体请查看avcodec_align_dimensions2()方法。一些过滤器或扫描器读数据时可能会超过 16 字节,所以当它们使用时,必须额外分配 16 字节。对于 packed 格式的数据(例如 RGB24),会存放到 data[0] 里面;对于 planar 格式的数据(例如 YUV420P),则会分开 data[0]/data[1]/data[2](YUV420P 中 data[0] 存放 Y,data[1] 存放 U,data[2] 存放 V)。
linesize:对于视频数据,表示每个图像行的字节大小;对于音频数据,表示每个 Plane 的字节大小,只有linesize[0]可以设置,对于plane 音频,每个信道 channel 必须是相同的。对于视频的 linesize 应为 CPU 的对准要求的倍数,一般为 32。注意 linesize 可大于可用的数据的尺寸,有可能存在由于性能原因额外填充。
width/height:视频的宽高
format:帧格式,-1表示未设置的帧格式。对于视频帧,该值为 enum 类型的 AVPixelFormat,例如 AV_PIX_FMT_YUV420P;对于音频帧,该值为 enum 型的 AVSampleFormat,例如 AV_SAMPLE_FMT_S16。
key_frame:关键帧,1 表示关键帧,0 表示非关键帧。
pict_type:帧图片类型,例如 I/P/B。
sample_aspect_ration:帧像素的宽高比,使用 AVRational 表示。
pts:显示时间戳,单位为 time_base。
pkt_pts:该 PTS 是从 AVPacket 结构中拷贝过来的;与之对应的是pkt_dts。
coded_picture_number/display_picture_number:解码序列号和显示序列号(Display Order/Decoded Order)。
interlaced_frame:表示该帧为 interlace 码流或者为 progressive 码流。
top_field_first:对于 interlace 码流,表示该它是 top first or bottom first。

AVCodec结构体解析
上面分析了像素域的表示结构体 AVFrame 和 压缩域的表示结构体 AVPacket,两者之间的转换是通过编解码器来完成的,FFMpeg 中使用 AVCodec 结构体表示编解码。本小节就来看一下 AVCodec 结构体。

typedef struct AVCodec{const char *name;const char *long_name;enum AVMediaType type;enum AVCodecID id;int capabilities;const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}const enum AVPixelFormat *pix_fmts;     ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1const uint64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0uint8_t max_lowres;                     ///< maximum value for lowres supported by the decoder, no direct access, use av_codec_get_max_lowres()const AVClass *priv_class;              ///< AVClass for the private contextconst AVProfile *profiles;              ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}int priv_data_size;struct AVCodec *next;int (*init_thread_copy)(AVCodecContext *);int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src);const AVCodecDefault *defaults;void (*init_static_data)(struct AVCodec *codec);int (*init)(AVCodecContext *);int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size,int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame,int *got_packet_ptr);int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);int (*close)(AVCodecContext *);void (*flush)(AVCodecContext *);int caps_internal;
}

name:具体的 CODEC 的名称的简短描述,比如”HEVC”/”H264”等。
long_name: CODEC 名称的详细描述,比如”HEVC (High Efficiency Video Coding)”。
type:媒体类型的字段,它是 enum 型的,表示视频、音频、字幕等,比如AVMEDIA_TYPE_VIDEO、AVMEIDA_TYPE_AUDIO。
id:唯一标识的 CODEC 类型,比如 AV_CODEC_ID_HEVC。
supported_framerates:支持的视频帧率的数组,以{0,0}作为结束。
pix_fmts:编解码器支持的图像格式的数组,以 -1 作为结束。
profiles:编解码器支持的 Profile,以 HEVC 为例,包含”Main”“Main10”“Main Still Picture”。
每一个编解码器对应一个 AVCodec 结构体,对应一种编解码方式,比如 HEVC、AVC、MPEG2、MPEG4、VP6、VP8、VP9等。以 HEVC 为例,FFMpeg中关于 AVCodec 的定义如下:

AVCodec ff_hevc_decoder = {.name                  = "hevc",.long_name             = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"),.type                  = AVMEDIA_TYPE_VIDEO,.id                    = AV_CODEC_ID_HEVC,.priv_data_size        = sizeof(HEVCContext),.priv_class            = &hevc_decoder_class,.init                  = hevc_decode_init,.close                 = hevc_decode_free,.decode                = hevc_decode_frame,.flush                 = hevc_decode_flush,.update_thread_context = hevc_update_thread_context,.init_thread_copy      = hevc_init_thread_copy,.capabilities          = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,.profiles              = NULL_IF_CONFIG_SMALL(profiles),
};

各种不同的编解码器,FFMpeg 使用注册函数avcodec_register_all()来完成。

关于 AVCodec 的通常使用方法:首先,根据特定的 ID 找到特定的编解码器;其次,根据特定的编解码器分配出特定的描述编解码上下文的 AVCodecContext 结构体;之后,打开编解码器;最后,调用编解码器进行编解码。示例代码如下:

AVCodec *codec = NULL;
AVCodecContext *ctx = NULL;codec = avcodec_find_decoder(origin_ctx->codec_id);
ctx = avcodec_alloc_context3(codec);
avcodec_open2(ctx, codec, NULL);
...

AVCodecContext结构体解析
AVCodecContext 可能是最复杂的结构体了。因为结构体内的变量非常多,不可能一一分析,而且有的变量是编码时候用到、有的是解码时候用到,此处只对几个常用的变量做简要的记录。

typedef struct AVCodecContext{const AVClass *av_class;int log_level_offset;enum AVMediaType codec_type;const struct AVCodec *codec;enum AVCodecID     codec_id;unsigned int codec_tag;void *priv_data;struct AVCodecInternal *internal;void *opaque;int bit_rate;int bit_rate_tolerance;int global_quality;int compression_level;int flags;int flags2;uint8_t *extradata;int extradata_size;AVRational time_base;int ticks_per_frame;int delay;int width, height;int coded_width, coded_height;int gop_size;enum AVPixelFormat pix_fmt;void (*draw_horiz_band)(struct AVCodecContext *s,const AVFrame *src, int offset[AV_NUM_DATA_POINTERS],int y, int type, int height);enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt);int max_b_frames;float b_quant_factor;int b_frame_strategy;float b_quant_offset;int has_b_frames;int mpeg_quant; 		/*decoding: unused*/float i_quant_factor; 	/*decoding: unused*/float i_quant_offset; 	/*decoding: unused*/float lumi_masking;		/*decoding: unused*/float temporal_cplx_masking; /*decoding: unused*/float spatial_cplx_masking;  /*decoding: unused*/float p_masking;		/*decoding: unused*/float dark_masking;		/*decoding: unused*/int slice_count;int prediction_method;	/*decoding: unused*/int *slice_offset;AVRational sample_aspect_ratio;int me_cmp;				/*decoding: unused*/int me_sub_cmp;			/*decoding: unused*/int mb_cmp;				/*decoding: unused*/...
}AVCodecContext;

AVMediaType codec_type:编解码器的类型,如音频、视频、字幕。
AVCdec *codec:采用的解码器 AVCodec。
bit_rate: 平均比特率。
int width, height: 视频的宽高。
int refs: 运动估计参考帧的个数。
int sample_rate: 采样率。
int channels: 声道数。
AVCodecContext 使用 avcodec_alloc_context3 分配,该函数除了分配 AVCodecContext 外,还会初始化默认的字段。分配的内存必须通过 avcodec_free_context 释放。

上面提到的几个结构体 AVCodec/AVCodecContext,联合使用,通常是如下形式:

avcodec_register_all();
...
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if(!codec)exit(1);context = avcodec_alloc_context3(codec);if(avcodec_open2(context, codec, opts) < 0)exit(1);

AVStream结构体解析
AVStream用于存储一个视频流、音频流的结构体。

typedef struct AVStream{int index;	//stream index in AVFormatContextint id;AVCodecContext *codec;void *priv_data;AVRational time_base;int64_t start_time;int64_t duration;int64_t nb_frames;int disposition;enum AVDiscard discard;AVRational sample_aspect_ratio;AVDictionary *metadata;AVRational avg_frame_rate;AVPacket attached_pic;AVPacketSideData *side_data;int            nb_side_data;int event_flags;int pts_wrap_bits;int64_t first_dts;int64_t cur_dts;int64_t last_IP_pts;int last_IP_duration;int probe_packets;int codec_info_nb_frames;/* av_read_frame() support */enum AVStreamParseType need_parsing;struct AVCodecParserContext *parser;struct AVPacketList *last_in_packet_buffer;AVProbeData probe_data;#define MAX_REORDER_DELAY 16int64_t pts_buffer[MAX_REORDER_DELAY+1];AVIndexEntry *index_entries; /**< Only used if the format does notsupport seeking natively. */int nb_index_entries;unsigned int index_entries_allocated_size;AVRational r_frame_rate;int stream_identifier;int64_t interleaver_chunk_size;int64_t interleaver_chunk_duration;int request_probe;int skip_to_keyframe;int skip_samples;int64_t start_skip_samples;int64_t first_discard_sample;int64_t last_discard_sample;int nb_decoded_frames;int64_t mux_ts_offset;int64_t pts_wrap_reference;int pts_wrap_behavior;int update_initial_durations_done;int64_t pts_reorder_error[MAX_REORDER_DELAY+1];uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];int64_t last_dts_for_order_check;uint8_t dts_ordered;uint8_t dts_misordered;int inject_global_side_data;char *recommended_encoder_configuration;AVRational display_aspect_ratio;struct FFFrac *priv_pts;
}AVStream;

index:标识该视频流、音频流,是 AVFormatContext 中的流索引。
AVCodecContext *codec:指向该视频、音频流的内容。
AVRational time_base:通过该值可以把 PTS/DTS 转化为真正的时间。
int64_t duration:该视频、音频流长度。
AVDictionary *metadata: 元数据信息。
AVRational avg_frame_rate: 帧率。

AVFormatContext 结构体解析
AVFormatContext 是包含码流参数比较多的结构体, 它是 FFmpeg 解封装(flv、mp4、rmvb、avi)功能的结构体。 一般使用 avformat_alloc_context() 来创建该结构体,使用 avformat_free_context 释放该结构体。

typedef struct AVFormatContext {const AVClass *av_class;struct AVInputFormat *iformat;struct AVOutputFormat *oformat;void *priv_data;AVIOContext *pb;int ctx_flags;unsigned int nb_streams;AVStream **streams;char filename[1024];int64_t start_time;int64_t duration;int bit_rate;unsigned int packet_size;int max_delay;int flags;const uint8_t *key;int keylen;unsigned int nb_programs;AVProgram **programs;enum AVCodecID video_codec_id;enum AVCodecID audio_codec_id;enum AVCodecID subtitle_codec_id;unsigned int max_index_size;unsigned int max_picture_buffer;unsigned int nb_chapters;AVChapter **chapters;AVDictionary *metadata;int64_t start_time_realtime;int fps_probe_size;int error_recognition;AVIOInterruptCB interrupt_callback;int64_t max_interleave_delta;int strict_std_compliance;int event_flags;int max_ts_probe;int avoid_negative_ts;int ts_id;int audio_preload;int max_chunk_duration;int max_chunk_size;int use_wallclock_as_timestamps;int avio_flags;enum AVDurationEstimationMethod duration_estimation_method;int64_t skip_initial_bytes;unsigned int correct_ts_overflow;int seek2any;int probe_score;int format_probesize;char *codec_whitelist;char *format_whitelist;AVFormatInternal *internal;int io_repositioned;AVCodec *video_codec;AVCodec *audio_codec;AVCodec *subtitle_codec;AVCodec *data_codec;int metadata_header_padding;void *opaque;av_format_control_message control_message_cb;int64_t output_ts_offset;uint8_t *dump_separator;enum AVCodecID data_codec_id;int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);	
}

struct AVInputFormat *iformat; 输入数据的封装格式,由avformat_open_input设置,仅仅在Demuxing使用。
struct AVOutputFormat *oformat; 输出数据的封装格式,必须由使用者在avformat_write_header前设置,由Muxing使用。
priv_data,在muxing中,由avformat_write_header设置;在demuxing中,由avformat_open_input设置。
AVIOContext *pb;输入数据的缓存。如果iformat/oformat.flags设置为AVFMT_NOFILE的话,该字段不需要设置。对于Demuxing ,需要在avformat_open_input前设置,或由avformat_open_input设置;对于Muxing,在avformat_write_header前设置。
ctx_flags,码流的信息,表明码流属性的的信号。由libavformat设置,例如AVFMTCTX_NOHEADER。
nb_streams 指AVFormatContext.streams的数量,必须由avformat_new_stream设置,不能由其他代码改动。
AVStream **streams;文件中所有码流的列表,新的码流创建使用avformat_new_stream函数。Demuxing中,码流由avformat_open_input创建。 如果AVFMTCTX_NOHEADER被设置,新的码流可以出现在av_read_frame中。Muxing中,码流在avformat_write_header之前由用户创建。它的释放是由avformat_free_context完成的。
filename,输入或输出的文件名,Demuxing中由avformat_open_input设置,Muxing中在使用avformat_write_header前由调用者设置。
int64_t duration;码流的时长。
bit_rate,比特率。
enum AVCodecID video_codec_id;
AVDictionary *metadata; 元数据,适用于整个文件。 ·

AVIOContext 结构体解析
AVIOContext 是 FFMpeg 管理输入输出数据的结构体。

typedef struct AVIOContext{const AVClass *av_class;unsigned char *buffer;  /**< Start of the buffer. */int buffer_size;        /**< Maximum buffer size */unsigned char *buf_ptr; /**< Current position in the buffer */unsigned char *buf_end; /**< End of the data */int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);int64_t (*seek)(void *opaque, int64_t offset, int whence);int64_t pos;            /**< position in the file of the current buffer */int must_flush;         /**< true if the next seek should flush */int eof_reached;        /**< true if eof reached */int write_flag;         /**< true if open for writing */int max_packet_size;unsigned long checksum;unsigned char *checksum_ptr;unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);int error;              /**< contains the error code or 0 if no error happened */int (*read_pause)(void *opaque, int pause);int64_t (*read_seek)(void *opaque, int stream_index,int64_t timestamp, int flags);int seekable;int64_t maxsize;int direct;int64_t bytes_read;int seek_count;int writeout_count;int orig_buffer_size;int short_seek_threshold;
}

unsigned char *buffer:缓存开始位置。
int buffer_size:缓存大小。
unsigned char *buf_ptr:当前指针读取到的位置。
unsigned char *buf_end:缓存结束的位置。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Ffmpeg 中 Demux 这一步是通过 avformat_open_input()这个 api 来做的,这个 api 读出文件的头部信息,并做 demux, 在此之后我们就可以读取媒体文件中的音频和视频流,然后通过 av_read_frame()从音频和视频流中读取出基本数据 流 packet,然后将 packet 送到 avcodec_decode_video2()和相对应的 api 进行解码。

在这里插入图片描述
在这里插入图片描述
FFMpeg 的 output_example.c 例子分析

该例子讲了如何输出一个 libavformat 库所支持格式的媒体文件。
在这里插入图片描述
在这里插入图片描述

FFmpeg命令及其用途

FFmpeg是一个功能强大的开源项目,用于处理音视频数据。它支持记录、转换和流化数字音频和视频。
FFmpeg命令行工具提供了丰富的功能,包括但不限于视频格式转换、视频剪辑、音频处理等。以下是一些常用的FFmpeg命令及其用途:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

还有很多命令参数,不说了

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

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

相关文章

(12)MATLAB莱斯(Rician)衰落信道仿真2补充:莱斯衰落信道与莱斯随机变量

文章目录 前言1.关于莱斯衰落信道仿真的两个公式2.由式&#xff08;1&#xff09;推出式&#xff08;2&#xff09; 前言 本文给出关于莱斯衰落信道仿真的两个公式之间的推导。 1.关于莱斯衰落信道仿真的两个公式 在上一篇《&#xff08;11&#xff09;MATLAB莱斯&#xff08…

Linux入门3——vim的简单使用

1.vim 1.1 vim的模式 vim有三种主要模式&#xff1a; ①命令模式&#xff1a;使用vim刚打开进入的模式就是命令模式&#xff1b; ②插入模式&#xff1a;只有在插入模式下才可以做文字输入&#xff0c;按[Esc]键可退回命令模式&#xff1b; ③末行模式&#xff1a;文件保存或退…

智能医疗:Spring Boot医院管理系统开发

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…

行为设计模式 -观察者模式- JAVA

观察者模式 一.简介二. 案例2.1 抽象主题&#xff08;Subject&#xff09;2.2 具体主题&#xff08;Concrete Subject&#xff09;2.3 抽象观察者&#xff08;Observer&#xff09;2.4 具体观察者&#xff08;Concrete Observer&#xff09;2.5 测试 三. 结论3.1 优缺点3.2 使用…

Vortex GPGPU的github流程跑通与功能模块波形探索(二)

文章目录 前言一、环境配置和debugging.md文档1.1 调试 Vortex GPU1.1.1测试 RTL 或模拟器 GPU 驱动的更改1.1.2 SimX 调试1.1.3 RTL 调试1.1.4 FPGA 调试1.1.5 分析 Vortex 跟踪日志 二、跑出波形文件和日志文件总结 前言 昨天另辟蹊径地去探索了子模块的波形仿真&#xff0c…

【简介Sentinel-1】

Sentinel-1是欧洲航天局哥白尼计划&#xff08;GMES&#xff09;中的地球观测卫星&#xff0c;由Sentinel-1A和Sentinel-1B两颗卫星组成。以下是对Sentinel-1的详细介绍&#xff1a; 一、基本信息 卫星名称&#xff1a;Sentinel-1 所属计划&#xff1a;欧洲航天局哥白尼计划…

【含开题报告+文档+PPT+源码】基于SSM框架的民宿酒店预定系统的设计与实现

开题报告 随着人们旅游需求的增加&#xff0c;民宿行业呈现出快速发展的趋势。传统的住宿方式逐渐无法满足人们对个性化、舒适、便捷的需求&#xff0c;而民宿作为一种新型的住宿选择&#xff0c;逐渐受到人们的青睐。民宿的特点是具有独特的风格、便捷的地理位置、相对亲近的…

简单使用DrissionPage网页自动化工具

DrissionPage 是一个基于 python 的网页自动化工具&#xff0c;类似Selenium&#xff0c;可以操控浏览器进行一些自动测试&#xff0c;也可以直接发请求&#xff1b; 官网&#xff1a;DrissionPage官网 &#xff08;那个浏览器黑白图标一眼看去还以为是只哭泣的小猪&#xff0…

云计算Openstack Neutron

OpenStack Neutron是OpenStack云计算平台中的网络服务组件&#xff0c;它为OpenStack提供了强大的网络连接功能。 一、基本概念 Neutron是一个网络服务项目&#xff0c;旨在为OpenStack提供网络连接。它允许用户创建和管理虚拟网络&#xff0c;包括子网、路由、安全组等&…

VMWare安装和基本使用NixOS Linux 24.05版本

文章目录 简介Nix 语言基础知识NixOS 虚拟机创建 VMWare 的 NixOS 虚拟机安装说明Nix 包管理器安装Windows(WSL)上安装Linux 上安装Docker 上安装MacOS 上安装NixOS 的安装下载 ISO 镜像安装 NixOS修改语言网络配置设置位置设置键盘设置账号和密码桌面环境分区完成安装登录系…

MFC多媒体定时器实例(源码下载)

用MFC多媒体定时器做一个每1秒钟加一次的计时器&#xff0c;点开始计时按钮开始计时&#xff0c;点关闭计时按钮关闭计时。 1、在库文件Med_timeDlg.h文件中添加代码 class CMed_timeDlg : public CDialog { // Construction public:CMed_timeDlg(CWnd* pParent NULL); // st…

Microsoft 更新 Copilot AI,未來將能使用語音並看到你瀏覽的網頁

不過受到 Recall 事件的影響&#xff0c;更新的推出將更緩慢謹慎。 Microsoft 也同步對其網頁版及行動版的 Copilot AI 進行大改版。這主要是為網頁版換上了一個較為簡單乾淨的介面&#xff0c;並增加了一些新的功能&#xff0c;像是 Copilot Voice 能讓你與 AI 助手進行對話式…

HTML5实现古典音乐网站源码模板1

文章目录 1.设计来源1.1 网站首页1.2 古典音乐界面1.3 著名人物界面1.4 古典乐器界面1.5 历史起源界面2.效果和源码2.1 动态效果2.2 源代码源码下载万套模板,程序开发,在线开发,在线沟通作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/142…

【韩顺平Java笔记】第8章:面向对象编程(中级部分)【285-296】

文章目录 285. 为什么需要继承286. 继承原理图287. 继承快速入门288. 289. 290. 291. 292. 继承使用细节1,2,3,4,5288.1 继承给编程带来的便利288.2 继承的深入讨论/细节问题 293. 继承本质详解294. 继承课堂练习1295. 继承课堂练习2296. 继承课堂练习3 285. 为什么需要继承 28…

【微服务】服务注册与发现、分布式配置管理 - Consul(day5)

概述 作用 Consul的两大作用就是服务发现和注册与分布式配置管理。 服务发现在介绍Eureka组件的时候已经进行过详细概述&#xff0c;大概就是将硬编码到服务中的IP地址和端口号进行解耦&#xff0c;从而实现动态扩缩容、容错处理、服务管理等功能&#xff0c;通过服务注册和…

台球助教预约小程序源码开发:技术解析与示例代码

随着数字化时代的到来&#xff0c;信息技术与体育运动的融合日益紧密。台球作为一项深受大众喜爱的运动&#xff0c;其教学训练领域也迎来了技术创新的浪潮。本文将探讨台球助教预约小程序的开发过程&#xff0c;从技术选型、功能设计到示例代码展示renxb001&#xff0c;全面解…

yub‘s Algorithmic Adventures_Day7

环形链表 link&#xff1a;https://leetcode.cn/problems/linked-list-cycle-ii/description/ 思路分析 我只能说双指针yyds【刻板hh】 我们分两种情况来分析 起码在第二圈才会相遇 fast比slow多走环的整数倍 fast 走的步数是 slow 步数的 2 倍&#xff0c;即 f2s&#xff…

计算机网络:计算机网络体系结构 —— 专用术语总结

文章目录 专用术语实体协议服务服务访问点 SAP 服务原语 SP 协议数据单元 PDU服务数据单元 SDU 专用术语 实体 实体是指任何可以发送或接收信息的硬件或软件进程 对等实体是指通信双方处于相同层次中的实体&#xff0c;如通信双方应用层的浏览器进程和 Web 服务器进程。 协…

Kubernetes中部署ELK Stack日志收集平台

1 、ELK概念 ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被成为Elastic Stack。其中: Elasticsearch是一个基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用Elas…

单目3d重建DUSt3R 笔记

目录 DUSt3R 三维重建 报错RecursionError: maximum recursion depth exceeded in comparison 报错 numpy.core.multiarray failed to import 报错Numpy is not available 解决 升级版mast3r 速度变慢 修改了参数设置脚本&#xff1a; 测试效果 操作技巧 DUSt3R 三维重…