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

news2024/10/9 18:29:47

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 -1
    const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
    const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
    const uint64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
    uint8_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 context
    const 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 AVFormatContext
	int 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 16
    int64_t pts_buffer[MAX_REORDER_DELAY+1];

    AVIndexEntry *index_entries; /**< Only used if the format does not
                                    support 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.coloradmin.cn/o/2199692.html

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

相关文章

22年408数据结构

第一题&#xff1a; 解析&#xff1a; 观察一下这个程序&#xff1a;我们注意到最外层的循环是从i1开始的&#xff0c;每次ii*2&#xff0c;直到i<n为止&#xff0c;假设程序总共执行k次执行&#xff0c;则有2^(k1)>n。则k1>log(2)n这里是以2为底n的对数, k>log(2)…

Oracle11g服务器linux 安装

一&#xff0e;安装前准备 1.检查硬件&#xff08;内存&#xff0c;交换分区&#xff0c;tmp分区&#xff0c;cpu信息&#xff0c;内核版本&#xff09; # grep MemTotal /proc/meminfo # grep SwapTotal /proc/meminfo # df -k /tmp&#xff08;>400M&#xff09; # grep …

汽车氛围灯行业分析:未来几年年复合增长率CAGR为7.15%

汽车氛围灯是一种起到装饰和指示作用的照明灯&#xff0c;它属于装饰类的照明灯。通常是红色、蓝色、绿色等&#xff0c;主要是为了使车厢更加绚丽&#xff0c;烘托气氛&#xff0c;营造室内情调。氛围灯能够具有以下特性&#xff1a;功能性、舒适性、设计感、豪华感、个性化、…

【C++】——继承

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

深入解析MySQL事务管理:ACID特性与基本操作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

自动猫砂盆是养猫新型智商税吗?测评2024年热门款智能猫砂盆分享

铲屎官们只要一察觉到猫主子拉屎&#xff0c;就要马上去铲掉&#xff0c;这不仅是为了猫砂盆中其他干净的猫砂&#xff0c;更是为了防止猫屎残留发臭&#xff0c;特别是便便这种东西&#xff0c;一旦放久了就很招虫子&#xff0c;家里出现这些虫子又要大扫除消杀&#xff0c;特…

2024 年顶级智能文档处理解决方案

在当今的数字时代&#xff0c;智能文档处理(IDP) 对于提高业务效率和降低成本至关重要。IDP 可实现文档处理的自动化&#xff0c;最大限度地减少人工劳动和错误。由于有众多 IDP 解决方案可供选择&#xff0c;因此选择合适的解决方案可能具有挑战性。 本指南回顾了 10 款最…

Android Handler消息机制完全解析-同步屏障(三)

Android 消息机制Handler完全解析(一) Android 消息机制Handler完全解析(二) 前面两篇我们主要讲了Handler消息机制的一些基础&#xff0c;今天来看下消息屏障&#xff0c;通过本篇文章你将学到如下知识点 (1)什么是同步屏障 (2)为什么要有同步屏障 (3)同步屏障的原理 (4…

获取时隔半个钟的三天

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

24下软考中级系统集成项目管理工程师怎么备考?

备考资料&#xff1a; 1.教材 教材可以准备由清华大学出版社出版的系统集成项目管理工程师教材&#xff0c;这也是官方所推荐的教材&#xff0c;准备这本书是绝对没错的。 2.真题 真题也是在备考过程中少不了的资料之一&#xff0c;而且系统集成项目管理工程师考试就是需要多…

初始项目托管到gitee教程,开箱即用

0.本地仓库与远程仓库关联&#xff08;需先在gitee创建仓库&#xff09; ①打开powershell生成ssh key ssh-keygen -t ed25519 -C "Gitee SSH Key"-t key 类型-C 注释 生成成功如下&#xff0c;并按下三次回车 ②查看公私钥文件 ls ~/.ssh/输出&#xff1a; id_…

华为---Super VLAN简介及示例配置

目录 1. Super VLAN技术产生背景 2. Super VLAN概念 3. Super VLAN应用场景 4. Super VLAN工作原理 5. Super-VLAN主要配置命令 6. Super-VLAN主要配置步骤 7. 示例配置 7.1 示例场景 7.2 网络拓扑 7.3 配置代码 7.4 代码解析 7.5 测试验证 1. Super VLAN技术产生背…

虹软人脸 报错 Can‘t find dependent libraries

系列文章目录 文章目录 系列文章目录一、虹软人脸 报错 Can‘t find dependent libraries 一、虹软人脸 报错 Can‘t find dependent libraries 在项目中使用了 虹软 人脸识别SDK&#xff0c;环境一直出错。 错误&#xff1a; Can’t find dependent libraries 从错误信息来…

项目启动 | 盘古信息赋能奥尼视讯数字化转型升级,实现全面数智化发展

随着信息技术的飞速发展与全球市场竞争的日益激烈&#xff0c;传统制造业正面临生存和发展的危机&#xff0c;制造企业为谋求发展&#xff0c;纷纷开启数字化转型之路&#xff0c;深度融入数字技术&#xff0c;实现生产流程的智能化、管理模式的精细化以及产品服务的个性化&…

[面试] java开发面经-1

前言 目录 1.看到你的简历里说使用Redis缓存高频数据&#xff0c;说一下Redis的操作 2.说一下Redis的缓存击穿、缓存穿透、缓存雪崩 3.你的项目中使用了ThreadLocal&#xff0c;那么当有两个请求同时发出时&#xff0c;会怎么处理&#xff0c;可以同时处理两个请求吗 4.使用…

CUDA、Pytorch、Pycharm的安装与配置

文章目录 一、CUDA安装1.检查英伟达驱动支持的最高CUDA版本 二、Pytorch的安装与环境配置1.选择是下载CPU版本还是GPU版本2.上Pytorch官网找到安装命令3.运行指令(1)CPU版本(2)GPU版本 4.验证5.安装其他所需模块(0)安装torch(1)安装Matplotlib(2)安装 pillow&#xff08;可能an…

高效稳压,YB2411 DCDC降压芯片助力高电压功率转换系统

在现代的科技发展中&#xff0c;高电压功率转换系统的需求越来越多。为满足市场需求&#xff0c;我们推出了一款高输入电压DCDC降压芯片——YB2411。 YB2411系列 1>昱灿 YB2411R SOT23-6 DC-DC高压降压 36V 0.6A 2>昱灿 YB2411SR SOT23-6 DC-DC高压降压 60V 0.8A YB241…

【simulink仿真模型】Buck变换器闭环控制,电力电子仿真模型

摘要 本文介绍了基于Simulink的Buck变换器闭环控制系统的设计与仿真。通过对Buck变换器的数学模型进行建模&#xff0c;并引入PI控制器对输出电压进行实时调节&#xff0c;实现了系统的稳态控制。仿真结果显示&#xff0c;该闭环控制系统能够快速响应负载变化&#xff0c;保持…

头戴式耳机性价比推荐有哪些?头戴式耳机性价比之王推荐

这不是马上就要双十一了&#xff1f;对于环境比较吵的人来说&#xff0c;趁着最近双11开始&#xff0c;是购买耳机的好时机。即将入冬&#xff0c;佩戴头戴式耳机频率越来越多&#xff0c;包裹着耳朵很舒适保暖。有的人入耳式已经非常多了&#xff0c;而且同样的价格&#xff0…

地图箭头方向检测系统源码分享

地图箭头方向检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…