当前位置: 首页 > web >正文

AVInputFormat 再分析

AVInputFormat 是 FFmpeg 中用于描述输入格式(如文件容器、设备流等)的核心结构体,属于 libavformat 库的一部分。其主要功能是定义解封装(demuxing)过程中如何解析不同格式的输入数据。以下是其关键特性与使用方式的总结:

/*** @addtogroup lavf_decoding* @{*/
typedef struct AVInputFormat {/*** A comma separated list of short names for the format. New names* may be appended with a minor bump.*/const char *name;/*** Descriptive name for the format, meant to be more human-readable* than name. You should use the NULL_IF_CONFIG_SMALL() macro* to define it.*/const char *long_name;/*** Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,* AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.*/int flags;/*** If extensions are defined, then no probe is done. You should* usually not use extension format guessing because it is not* reliable enough*/const char *extensions;const struct AVCodecTag * const *codec_tag;const AVClass *priv_class; ///< AVClass for the private context/*** Comma-separated list of mime types.* It is used check for matching mime types while probing.* @see av_probe_input_format2*/const char *mime_type;/****************************************************************** No fields below this line are part of the public API. They* may not be used outside of libavformat and can be changed and* removed at will.* New public fields should be added right above.******************************************************************/ff_const59 struct AVInputFormat *next;/*** Raw demuxers store their codec ID here.*/int raw_codec_id;/*** Size of private data so that it can be allocated in the wrapper.*/int priv_data_size;/*** Tell if a given file has a chance of being parsed as this format.* The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes* big so you do not have to check for that unless you need more.*/int (*read_probe)(const AVProbeData *);/*** Read the format header and initialize the AVFormatContext* structure. Return 0 if OK. 'avformat_new_stream' should be* called to create new streams.*/int (*read_header)(struct AVFormatContext *);/*** Read one packet and put it in 'pkt'. pts and flags are also* set. 'avformat_new_stream' can be called only if the flag* AVFMTCTX_NOHEADER is used and only in the calling thread (not in a* background thread).* @return 0 on success, < 0 on error.*         Upon returning an error, pkt must be unreferenced by the caller.*/int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);/*** Close the stream. The AVFormatContext and AVStreams are not* freed by this function*/int (*read_close)(struct AVFormatContext *);/*** Seek to a given timestamp relative to the frames in* stream component stream_index.* @param stream_index Must not be -1.* @param flags Selects which direction should be preferred if no exact*              match is available.* @return >= 0 on success (but not necessarily the new offset)*/int (*read_seek)(struct AVFormatContext *,int stream_index, int64_t timestamp, int flags);/*** Get the next timestamp in stream[stream_index].time_base units.* @return the timestamp or AV_NOPTS_VALUE if an error occurred*/int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,int64_t *pos, int64_t pos_limit);/*** Start/resume playing - only meaningful if using a network-based format* (RTSP).*/int (*read_play)(struct AVFormatContext *);/*** Pause playing - only meaningful if using a network-based format* (RTSP).*/int (*read_pause)(struct AVFormatContext *);/*** Seek to timestamp ts.* Seeking will be done so that the point from which all active streams* can be presented successfully will be closest to ts and within min/max_ts.* Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.*/int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);/*** Returns device list with it properties.* @see avdevice_list_devices() for more details.*/int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);/*** Initialize device capabilities submodule.* @see avdevice_capabilities_create() for more details.*/int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);/*** Free device capabilities submodule.* @see avdevice_capabilities_free() for more details.*/int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
} AVInputFormat;
/*** @}*/

1. 结构与字段

AVInputFormat 包含以下核心字段:

  • name‌:格式的短标识符(如 mp4avfoundation)。
  • long_name‌:格式的详细描述(如 MPEG-4 Part 14)。
  • extensions‌:支持的文件扩展名(如 mp4,mov)。
  • mime_type‌:关联的 MIME 类型(如 video/mp4)。
  • 函数指针‌:定义了操作输入格式的方法:
    • read_probe: 探测输入数据是否匹配当前格式。
    • read_header: 读取文件头信息。
    • read_packet: 读取数据包(如音频/视频帧)。
    • read_close: 关闭输入流并释放资源。

2. 功能与用途

  • 格式识别‌:通过 read_probe 自动探测输入数据的格式,或在调用 avformat_open_input 时显式指定。
  • 解封装流程‌:将容器文件(如 MP4)分离为独立的音视频流,供后续解码使用。
  • 设备支持‌:不仅支持文件格式,还可处理摄像头、麦克风等设备输入(如 macOS 的 avfoundation)。

3. 使用场景示例

初始化与注册

通过 av_register_all()(旧版本 FFmpeg)注册所有支持的格式,AVInputFormat 实例会以链表形式存储,供后续查找匹配46。
代码片段示例:

 

cCopy Code

#include <libavformat/avformat.h> int main() { av_register_all(); // 注册格式(旧版本) AVFormatContext *fmt_ctx = avformat_alloc_context(); AVInputFormat *fmt = av_find_input_format("mp4"); // 显式指定格式 avformat_open_input(&fmt_ctx, "input.mp4", fmt, NULL); // ...后续处理 }

自动探测格式

若未指定 AVInputFormat,FFmpeg 会通过 init_input 函数分析文件内容或扩展名,调用匹配的 read_probe 确定格式57。


4. 与其他结构的关联

  • AVFormatContext‌:上下文对象,存储解封装过程中的状态数据(如流信息、私有数据指针 priv_data)36。
  • AVOutputFormat‌:对应输出格式的结构,用于封装(muxing)流程78。

5. 扩展与定制

开发者可通过自定义 AVInputFormat 实现对新容器格式的支持,需实现探测、读包头、读数据包等函数,并注册到 FFmpeg 的全局链表中6。例如,SRT 字幕格式的解封装器实现中,定义了 srt_read_packet 等函数处理字幕数据包6。

6.那么具体的有哪些 AVInputFormat呢?

static const AVInputFormat * const demuxer_list[] = {&ff_aa_demuxer,&ff_aac_demuxer,&ff_aax_demuxer,&ff_ac3_demuxer,&ff_ace_demuxer,&ff_acm_demuxer,&ff_act_demuxer,&ff_adf_demuxer,&ff_adp_demuxer,&ff_ads_demuxer,&ff_adx_demuxer,&ff_aea_demuxer,&ff_afc_demuxer,&ff_aiff_demuxer,&ff_aix_demuxer,&ff_alp_demuxer,&ff_amr_demuxer,&ff_amrnb_demuxer,&ff_amrwb_demuxer,&ff_anm_demuxer,&ff_apac_demuxer,&ff_apc_demuxer,&ff_ape_demuxer,&ff_apm_demuxer,&ff_apng_demuxer,&ff_aptx_demuxer,&ff_aptx_hd_demuxer,&ff_aqtitle_demuxer,&ff_argo_asf_demuxer,&ff_argo_brp_demuxer,&ff_argo_cvg_demuxer,&ff_asf_demuxer,&ff_asf_o_demuxer,&ff_ass_demuxer,&ff_ast_demuxer,&ff_au_demuxer,&ff_av1_demuxer,&ff_avi_demuxer,&ff_avr_demuxer,&ff_avs_demuxer,&ff_avs2_demuxer,&ff_avs3_demuxer,&ff_bethsoftvid_demuxer,&ff_bfi_demuxer,&ff_bintext_demuxer,&ff_bink_demuxer,&ff_binka_demuxer,&ff_bit_demuxer,&ff_bitpacked_demuxer,&ff_bmv_demuxer,&ff_bfstm_demuxer,&ff_brstm_demuxer,&ff_boa_demuxer,&ff_bonk_demuxer,&ff_c93_demuxer,&ff_caf_demuxer,&ff_cavsvideo_demuxer,&ff_cdg_demuxer,&ff_cdxl_demuxer,&ff_cine_demuxer,&ff_codec2_demuxer,&ff_codec2raw_demuxer,&ff_concat_demuxer,&ff_data_demuxer,&ff_daud_demuxer,&ff_dcstr_demuxer,&ff_derf_demuxer,&ff_dfa_demuxer,&ff_dfpwm_demuxer,&ff_dhav_demuxer,&ff_dirac_demuxer,&ff_dnxhd_demuxer,&ff_dsf_demuxer,&ff_dsicin_demuxer,&ff_dss_demuxer,&ff_dts_demuxer,&ff_dtshd_demuxer,&ff_dv_demuxer,&ff_dvbsub_demuxer,&ff_dvbtxt_demuxer,&ff_dxa_demuxer,&ff_ea_demuxer,&ff_ea_cdata_demuxer,&ff_eac3_demuxer,&ff_epaf_demuxer,&ff_ffmetadata_demuxer,&ff_filmstrip_demuxer,&ff_fits_demuxer,&ff_flac_demuxer,&ff_flic_demuxer,&ff_flv_demuxer,&ff_live_flv_demuxer,&ff_fourxm_demuxer,&ff_frm_demuxer,&ff_fsb_demuxer,&ff_fwse_demuxer,&ff_g722_demuxer,&ff_g723_1_demuxer,&ff_g726_demuxer,&ff_g726le_demuxer,&ff_g729_demuxer,&ff_gdv_demuxer,&ff_genh_demuxer,&ff_gif_demuxer,&ff_gsm_demuxer,&ff_gxf_demuxer,&ff_h261_demuxer,&ff_h263_demuxer,&ff_h264_demuxer,&ff_hca_demuxer,&ff_hcom_demuxer,&ff_hevc_demuxer,&ff_hls_demuxer,&ff_hnm_demuxer,&ff_ico_demuxer,&ff_idcin_demuxer,&ff_idf_demuxer,&ff_iff_demuxer,&ff_ifv_demuxer,&ff_ilbc_demuxer,&ff_image2_demuxer,&ff_image2pipe_demuxer,&ff_image2_alias_pix_demuxer,&ff_image2_brender_pix_demuxer,&ff_ingenient_demuxer,&ff_ipmovie_demuxer,&ff_ipu_demuxer,&ff_ircam_demuxer,&ff_iss_demuxer,&ff_iv8_demuxer,&ff_ivf_demuxer,&ff_ivr_demuxer,&ff_jacosub_demuxer,&ff_jv_demuxer,&ff_kux_demuxer,&ff_kvag_demuxer,&ff_laf_demuxer,&ff_lmlm4_demuxer,&ff_loas_demuxer,&ff_luodat_demuxer,&ff_lrc_demuxer,&ff_lvf_demuxer,&ff_lxf_demuxer,&ff_m4v_demuxer,&ff_mca_demuxer,&ff_mcc_demuxer,&ff_matroska_demuxer,&ff_mgsts_demuxer,&ff_microdvd_demuxer,&ff_mjpeg_demuxer,&ff_mjpeg_2000_demuxer,&ff_mlp_demuxer,&ff_mlv_demuxer,&ff_mm_demuxer,&ff_mmf_demuxer,&ff_mods_demuxer,&ff_moflex_demuxer,&ff_mov_demuxer,&ff_mp3_demuxer,&ff_mpc_demuxer,&ff_mpc8_demuxer,&ff_mpegps_demuxer,&ff_mpegts_demuxer,&ff_mpegtsraw_demuxer,&ff_mpegvideo_demuxer,&ff_mpjpeg_demuxer,&ff_mpl2_demuxer,&ff_mpsub_demuxer,&ff_msf_demuxer,&ff_msnwc_tcp_demuxer,&ff_msp_demuxer,&ff_mtaf_demuxer,&ff_mtv_demuxer,&ff_musx_demuxer,&ff_mv_demuxer,&ff_mvi_demuxer,&ff_mxf_demuxer,&ff_mxg_demuxer,&ff_nc_demuxer,&ff_nistsphere_demuxer,&ff_nsp_demuxer,&ff_nsv_demuxer,&ff_nut_demuxer,&ff_nuv_demuxer,&ff_obu_demuxer,&ff_ogg_demuxer,&ff_oma_demuxer,&ff_paf_demuxer,&ff_pcm_alaw_demuxer,&ff_pcm_mulaw_demuxer,&ff_pcm_vidc_demuxer,&ff_pcm_f64be_demuxer,&ff_pcm_f64le_demuxer,&ff_pcm_f32be_demuxer,&ff_pcm_f32le_demuxer,&ff_pcm_s32be_demuxer,&ff_pcm_s32le_demuxer,&ff_pcm_s24be_demuxer,&ff_pcm_s24le_demuxer,&ff_pcm_s16be_demuxer,&ff_pcm_s16le_demuxer,&ff_pcm_s8_demuxer,&ff_pcm_u32be_demuxer,&ff_pcm_u32le_demuxer,&ff_pcm_u24be_demuxer,&ff_pcm_u24le_demuxer,&ff_pcm_u16be_demuxer,&ff_pcm_u16le_demuxer,&ff_pcm_u8_demuxer,&ff_pjs_demuxer,&ff_pmp_demuxer,&ff_pp_bnk_demuxer,&ff_pva_demuxer,&ff_pvf_demuxer,&ff_qcp_demuxer,&ff_r3d_demuxer,&ff_rawvideo_demuxer,&ff_realtext_demuxer,&ff_redspark_demuxer,&ff_rka_demuxer,&ff_rl2_demuxer,&ff_rm_demuxer,&ff_roq_demuxer,&ff_rpl_demuxer,&ff_rsd_demuxer,&ff_rso_demuxer,&ff_rtp_demuxer,&ff_rtsp_demuxer,&ff_s337m_demuxer,&ff_sami_demuxer,&ff_sap_demuxer,&ff_sbc_demuxer,&ff_sbg_demuxer,&ff_scc_demuxer,&ff_scd_demuxer,&ff_sdns_demuxer,&ff_sdp_demuxer,&ff_sdr2_demuxer,&ff_sds_demuxer,&ff_sdx_demuxer,&ff_segafilm_demuxer,&ff_ser_demuxer,&ff_sga_demuxer,&ff_shorten_demuxer,&ff_siff_demuxer,&ff_simbiosis_imx_demuxer,&ff_sln_demuxer,&ff_smacker_demuxer,&ff_smjpeg_demuxer,&ff_smush_demuxer,&ff_sol_demuxer,&ff_sox_demuxer,&ff_spdif_demuxer,&ff_srt_demuxer,&ff_str_demuxer,&ff_stl_demuxer,&ff_subviewer1_demuxer,&ff_subviewer_demuxer,&ff_sup_demuxer,&ff_svag_demuxer,&ff_svs_demuxer,&ff_swf_demuxer,&ff_tak_demuxer,&ff_tedcaptions_demuxer,&ff_thp_demuxer,&ff_threedostr_demuxer,&ff_tiertexseq_demuxer,&ff_tmv_demuxer,&ff_truehd_demuxer,&ff_tta_demuxer,&ff_txd_demuxer,&ff_tty_demuxer,&ff_ty_demuxer,&ff_v210_demuxer,&ff_v210x_demuxer,&ff_vag_demuxer,&ff_vc1_demuxer,&ff_vc1t_demuxer,&ff_vividas_demuxer,&ff_vivo_demuxer,&ff_vmd_demuxer,&ff_vobsub_demuxer,&ff_voc_demuxer,&ff_vpk_demuxer,&ff_vplayer_demuxer,&ff_vqf_demuxer,&ff_w64_demuxer,&ff_wady_demuxer,&ff_wavarc_demuxer,&ff_wav_demuxer,&ff_wc3_demuxer,&ff_webm_dash_manifest_demuxer,&ff_webvtt_demuxer,&ff_wsaud_demuxer,&ff_wsd_demuxer,&ff_wsvqa_demuxer,&ff_wtv_demuxer,&ff_wve_demuxer,&ff_wv_demuxer,&ff_xa_demuxer,&ff_xbin_demuxer,&ff_xmd_demuxer,&ff_xmv_demuxer,&ff_xvag_demuxer,&ff_xwma_demuxer,&ff_yop_demuxer,&ff_yuv4mpegpipe_demuxer,&ff_image_bmp_pipe_demuxer,&ff_image_cri_pipe_demuxer,&ff_image_dds_pipe_demuxer,&ff_image_dpx_pipe_demuxer,&ff_image_exr_pipe_demuxer,&ff_image_gem_pipe_demuxer,&ff_image_gif_pipe_demuxer,&ff_image_hdr_pipe_demuxer,&ff_image_j2k_pipe_demuxer,&ff_image_jpeg_pipe_demuxer,&ff_image_jpegls_pipe_demuxer,&ff_image_jpegxl_pipe_demuxer,&ff_image_pam_pipe_demuxer,&ff_image_pbm_pipe_demuxer,&ff_image_pcx_pipe_demuxer,&ff_image_pfm_pipe_demuxer,&ff_image_pgmyuv_pipe_demuxer,&ff_image_pgm_pipe_demuxer,&ff_image_pgx_pipe_demuxer,&ff_image_phm_pipe_demuxer,&ff_image_photocd_pipe_demuxer,&ff_image_pictor_pipe_demuxer,&ff_image_png_pipe_demuxer,&ff_image_ppm_pipe_demuxer,&ff_image_psd_pipe_demuxer,&ff_image_qdraw_pipe_demuxer,&ff_image_qoi_pipe_demuxer,&ff_image_sgi_pipe_demuxer,&ff_image_svg_pipe_demuxer,&ff_image_sunrast_pipe_demuxer,&ff_image_tiff_pipe_demuxer,&ff_image_vbn_pipe_demuxer,&ff_image_webp_pipe_demuxer,&ff_image_xbm_pipe_demuxer,&ff_image_xpm_pipe_demuxer,&ff_image_xwd_pipe_demuxer,NULL };

也就是说,对于不同容器来说或者设备流来说,都有自己对应的 AVInputFormat。

7.那么某一个具体的mp4文件或者aac文件对应的 AVInputFormat如何知道呢?

av_find_input_format(const char *short_name);方法分析-CSDN博客

我们以mp4 和 aac 文件举例说明:

aac 对应的 AVInputFormat 为:

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,
};

那么对应的三个方法

  • read_probe: 探测输入数据是否匹配当前格式。对于aac则调用adts_aac_probe方法
  • read_header: 读取文件头信息。对于aac则调用adts_aac_read_header方法
  • read_packet: 读取数据包(如音频/视频帧)。对于aac则调用adts_aac_read_packet方法

如果要理解 adts_aac_probe,adts_aac_read_header,adts_aac_read_packet这三个方法为什么这么写,就必要要 知道 aac 协议的情况,才能完整理解。从这里也能看出,ffmpeg是多么的强大,它将音视频所有格式的解封装都给开发者打包好了,再开发者不知道具体协议的情况下,调用一个函数就能搞定。 

mp4 对应的 AVInputFormat 为:

const AVInputFormat ff_mov_demuxer = {.name           = "mov,mp4,m4a,3gp,3g2,mj2",.long_name      = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),.priv_class     = &mov_class,.priv_data_size = sizeof(MOVContext),.extensions     = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif",.flags_internal = FF_FMT_INIT_CLEANUP,.read_probe     = mov_probe,.read_header    = mov_read_header,.read_packet    = mov_read_packet,.read_close     = mov_read_close,.read_seek      = mov_read_seek,.flags          = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
};

这个mp4对应的AVInputFormat 是如何找到的呢?一般的想法是从 demuxer_list.c中用眼睛看,有没有mp4之类的关键字,实际上这样是不合适的。

合适的方法是通过 av_find_input_format()

int avinputformat() {AVInputFormat* input_format = av_find_input_format("mp4");if (input_format) {printf("Found input format: %s\n", input_format->name);cout << "input_format->long_name = " << input_format->long_name<< endl;//input_format.}else {printf("Input format not found!\n");}return 0;
}

可以通过打印出来的 short name,long name 等再search ffmpeg 源码,进而找到对应的 解复用器的 具体方法

例如我们 对于mp4打印的信息如下,

Found input format: mov,mp4,m4a,3gp,3g2,mj2
input_format->long_name = QuickTime / MOV

那么就可以在源码中search "mov,mp4,m4a,3gp,3g2,mj2" 关键字,进而找到解复用mp4文件的具体的 AVInputFormat。

const AVInputFormat ff_mov_demuxer = {.name           = "mov,mp4,m4a,3gp,3g2,mj2",.long_name      = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),.priv_class     = &mov_class,.priv_data_size = sizeof(MOVContext),.extensions     = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif",.flags_internal = FF_FMT_INIT_CLEANUP,.read_probe     = mov_probe,.read_header    = mov_read_header,.read_packet    = mov_read_packet,.read_close     = mov_read_close,.read_seek      = mov_read_seek,.flags          = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
};

同理,如果要知道mp4文件的对应的这些方法 为什么 这么写,就必要要明白 mp4协议,才能理解。

8.从解复用流程上再说明

在解复用文件的时候,会调用如下的如下三个函数

AVFormatContext *avformat_alloc_context(void);

int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

在实际开发中,在avformat_open_input函数中,需要传递一个 AVInputFormat ,当我们传递的AVInputFormat 为nullptr时,ffmpeg 在 avformat_open_input源码中是如何知道你要解析的文件,用的是那个具体的 AVInputFormat 呢?

参考 avformat_open_input的过程分析,这个哥们很多博客都写的不错。

ffmpeg的avformat_open_input()分析过程--以mp4为例(十)_ffmpeg mp4 avformat-CSDN博客

‌9. 设备支持‌:从摄像头、麦克风等设备输入(如 macOS 的 avfoundation)。

​从前面的学习我们知道,
用于根据输入格式的名称(如 "mp4"、"wav"、"avfoundation" 等)查找对应的输入格式结构体 AVInputFormat。

av_find_input_format(const char *short_name);方法分析-CSDN博客

http://www.xdnf.cn/news/3698.html

相关文章:

  • 青少年ctf练习平台--做题wp(1)
  • 第九章:反击的序曲(续)
  • C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 19)
  • IP伪装、代理池与分布式爬虫
  • 探索内容智能化的关键解决方案
  • java学习之数据结构:二、链表
  • 模拟SIP终端向Freeswitch注册用户
  • ES6入门---第二单元 模块二:关于数组新增
  • 工业传动核心部件深度剖析:丝杆升降机与气缸的技术特性及选型指南
  • MCP多智能体消息传递机制(Message Passing Between Agents)
  • c#数据结构 线性表篇 非常用线性集合总结
  • springboot基于推荐算法的景点推荐系统(源码+lw+部署文档+讲解),源码可白嫖!
  • 20:深度学习-多层感知器原理
  • Android 端如何监控 ANR、Crash、OOM 等严重问题
  • 深度学习系统学习系列【2】之人工神经网络(ANN)
  • Javase 基础入门 —— 07 接口
  • ChatGPT:重塑人工智能交互范式的破晓之作
  • 【AI论文】交互式生成视频综述
  • 【libuv】基于libuv的exe链接错误
  • JVM——JVM 是如何处理异常的?
  • 传奇各版本迭代时间及内容变化,屠龙/嗜魂法杖/逍遥扇第一次出现的时间和版本
  • Linux53 百度网盘运行(下载devtoolset11后仍提示stdc++3.0.29缺失 计划用docker容器隔离运行,计划后续再看)
  • 鼠标悬浮特效:常见6种背景类悬浮特效
  • Docker与WSL2如何清理
  • 一篇文章看懂web服务
  • NV203NV207SSD固态闪存NV208NV213
  • NoxLucky:个性化动态桌面,打造独一无二的手机体验
  • 用docker ffmpeg测试视频vmaf分数,很快不用编译
  • C#VisionMaster算子二次开发(非方案版)
  • NocoDB:开源的 Airtable 替代方案