乙荒 发表于 2025-12-19 02:10:02

FFmpeg 关键的结构体

[]
一些重要的结构体

FFMPEG中结构体很多; 最关键的结构体可以分成以下几类:

[*]解协议(http,rtsp,rtmp,mms)
AVIOContext, URLProtocol, URLContext 主要存储视音频使用的协议的类型以及状态; URLProtocol存储输入视音频使用的封装格式; 每种协议都对应一个 URLProtocol 结构; (注意: FFMPEG中文件也被当做一种协议"file")

[*]解封装(flv,avi,rmvb,mp4)
AVFormatContext 主要存储视音频封装格式中包含的信息; AVInputFormat存储输入视音频使用的封装格式; 每种视音频封装格式都对应一个AVInputFormat 结构;

[*]解码(h264,mpeg2,aac,mp3)
每个AVStream存储一个视频/音频流的相关数据;每个AVStream对应一个AVCodecContext, 存储该视频/音频流使用解码方式的相关数据;每个AVCodecContext中对应一个AVCodec, 包含该视频/音频对应的解码器; 每种解码器都对应一个AVCodec结构;

[*]存数据
视频的话, 每个结构一般是存一帧; 音频可能有好几帧
解码前数据: AVPacket
解码后数据: AVFrame
参考雷神博客-FFMPEG中最关键的结构体之间的关系
ffmpeg库函数介绍
FFmpeg 学习整理总结
AVFormatContext

可以理解为整个统领上下文的大结构体, 包含: 多个AVStream(streams), AVCodec, AVCodecContext
对应封装格式例如 (mp3/mp4/avi...)
格式转换过程中实现输入和输出功能, 保存相关数据的主要结构, 描述了一个媒体文件或媒体流的构成和基本信息
nb_streams/streams: AVStream结构指针数组, 包含了所有内嵌媒体流的描述, 其内部有 AVInputFormat + AVOutputFormat 结构体, 来表示输入输出的文件格式
avformat_open_input: 创建并初始化部分值, 但其他一些值(如 mux_rate, key 等)需要手工设置初始值, 否则可能出现异常
avformat_alloc_output_context2: 根据文件的输出格式, 扩展名或文件名等分配合适的 AVFormatContext 结构
获取

AVFormatContext fmt_ctx = nullptr;
avformat_open_input(&fmt_ctx, "filename", nullptr, nullptr);//打开一个输入
//然后使用 读取
if((avformat_find_stream_info(avFormatCtx,nullptr))!=0){
    //reaad error
}

//或者
AVFormatContext *avformat_alloc_context(void);每一个 AVFormatContext 都有AVStream **streams;属性; 而nb_streams属性对应着索引
销毁

avformat_free_context()
API doc
pd 属性 (内存读写数据)

参考下 #ffmpeg内存编解码
AVStream

可理解为 "流通道",例如视频一般会有两个, 音频流和视频流, 保存着解码方式的相关数据
AVStream -- 描述一个媒体流, 其大部分信息可通过 avformat_open_input 根据文件头信息确定, 其他信息可通过 avformat_find_stream_info 获取, 典型的有 视频流, 中英文音频流, 中英文字幕流(Subtitle), 可通过 av_new_stream, avformat_new_stream 等创建;
index: 在AVFormatContext中流的索引, 其值自动生成(AVFormatContext::streams)
nb_frames: 流内的帧数目
time_base: 流的时间基准, 是一个实数, 该流中媒体数据的pts和dts都将以这个时间基准为粒度; 通常, 使用av_rescale/av_rescale_q可以实现不同时间基准的转换
avformat_find_stream_info: 获取必要的编解码器参数(如 AVMediaType, CodecID ), 设置到 AVFormatContext::streams::codec 中
av_read_frame: 从多媒体文件或多媒体流中读取媒体数据, 获取的数据由 AVPacket 来存放
av_seek_frame: 改变媒体文件的读写指针来实现对媒体文件的随机访问, 通常支持基于时间, 文件偏移, 帧号(AVSEEK_FLAG_FRAME)的随机访问方式
每个 AVStream, 下面都至少有一个可用的 AVCodec; 用属性名, video_codec,audio_codec,
获取

依赖于 AVCodecContext 或AVCodecParameters 获取
而AVStream 对应一个 AVCodecContext(新版建议使用 AVCodecParameters), 存储该视频/音频流使用解码方式的相关数据
//必须先读取AVFormatContext
if((avformat_find_stream_info(avFormatCtx,nullptr))!=0){
    //reaad error
}
//流通道 一般两个; 音频/视频
for(unsigned int i=0; inb_streams; i++) {
    if(avFormatCtx->streams->codecpar->codec_type==AVMediaType::AVMEDIA_TYPE_VIDEO){
      this->videoIndex =i;
    }else if(avFormatCtx->streams->codecpar->codec_type==AVMediaType::AVMEDIA_TYPE_AUDIO){
      this->audioIndex =i
    }
}
//或者 avformat_new_stream 函数直接分配
AVStream *out_stream = avformat_new_stream(avFormatCtx, coder);销毁

AVStream的初始化函数是avformat_new_stream(), 销毁函数使用销毁 AVFormatContext 的 avformat_free_context() 就可以了;
建议使用 AVCodecParameters 代替 AVCodecContext

AVCodecContext 结构体在AVStream被声明为已过时, 使用另一个 AVCodecParameters 结构体代替;
注意只是在AVStream被声明为已过时! 但是某些地方该用还是得用..
解码例子

const char *filename = "a.mp4";
AVFormatContext fmt_ctx = nullptr;
avformat_open_input(&fmt_ctx, filename, nullptr, nullptr);//打开一个输入
avformat_find_stream_info(fmt_ctx, nullptr);//读取封装格式
for(size_t i = 0; i < fmt_ctx->nb_streams; ++i)//流通道
{
    AVStream *stream = fmt_ctx->streams;
    AVCodec *codec =avcodec_find_decoder(stream->codecpar->codec_id);//依据ID找的解编码器
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);//需ctx中间过渡;使用avcodec_free_context释放

    //包含了大部分解码器相关的信息, 这里是直接从AVCodecParameters复制到AVCodecContext
    avcodec_parameters_to_context(codec_ctx, stream->codecpar);

    av_codec_set_pkt_timebase(codec_ctx, stream->time_base);
    avcodec_open2(codec_ctx, codec, nullptr);
}编码例子

const char *filename = "b.mp4";
AVFormatContext *fmt_ctx = nullptr;
avformat_alloc_output_context2(&fmt_ctx, nullptr, nullptr, filename); //需要调用avformat_free_context释放

//new一个流并挂到fmt_ctx名下, 调用avformat_free_context时会释放该流
AVStream *stream = avformat_new_stream(fmt_ctx, nullptr);
AVCodec *codec = avcodec_find_encoder(fmt_ctx->oformat->video_codec);//音频为audio_codec
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);

codec_ctx->video_type = AVMEDIA_TYPE_VIDEO;
codec_ctx->codec_id = m_fmt_ctx->oformat->video_codec;

codec_ctx->width = 1280;//你想要的宽度
codec_ctx->height = 720;//你想要的高度
codec_ctx->format = AV_PIX_FMT_YUV420P;//受codec->pix_fmts数组限制

codec_ctx->gop_size = 12;

codec_ctx->time_base = AVRational{1, 25};//应该根据帧率设置
codec_ctx->bit_rate = 1400 * 1000;

avcodec_open2(codec_ctx, codec, nullptr);
//将AVCodecContext的成员复制到AVCodecParameters结构体; 必须先open 再 copy
avcodec_parameters_from_context(stream->codecpar, codec_ctx);

av_stream_set_r_frame_rate(stream, {1, 25});用 AVCodecParameters 代替AVCodecContext
AVCodecContext

可以理解为 编解码器的(上下文或参数) 在AVStream中, 新API建议使用 AVCodecParameters 代替它!
解码器上下文,统领编码器基本结构体
AVFormatContext -- 格式转换过程中实现输入和输出功能, 保存相关数据的主要结构, 描述了一个媒体文件或媒体流的构成和基本信息
nb_streams/streams: AVStream结构指针数组, 包含了所有内嵌媒体流的描述, 其内部有 AVInputFormat + AVOutputFormat 结构体, 来表示输入输出的文件格式
avformat_open_input: 创建并初始化部分值, 但其他一些值(如 mux_rate, key 等)需要手工设置初始值, 否则可能出现异常
avformat_alloc_output_context2: 根据文件的输出格式, 扩展名或文件名等分配合适的 AVFormatContext 结构
avCodecContext.width(1080);
avCodecContext.height(1920);
avCodecContext.bit_rate(90000);//平均码率
//                avCodecContext.profile(FF_PROFILE_H264_HIGH_422);//profile-level-id=000042
avCodecContext.pix_fmt( AV_PIX_FMT_BGR24);//设置颜色格式

//下面挑一些关键的变量来看看(这里只考虑解码);
enum AVMediaType codec_type: 编解码器的类型(视频, 音频...)

struct AVCodec  *codec: 采用的解码器AVCodec(H.264,MPEG2...)

int bit_rate: 平均比特率

uint8_t *extradata; int extradata_size: 针对特定编码器包含的附加信息(例如对于H.264解码器来说, 存储SPS, PPS等)

AVRational time_base: 根据该参数, 可以把PTS转化为实际的时间(单位为秒s)

int width, height: 如果是视频的话, 代表宽和高

int refs: 运动估计参考帧的个数(H.264的话会有多帧, MPEG2这类的一般就没有了)

int sample_rate: 采样率(音频)

int channels: 声道数(音频)

enum AVSampleFormat sample_fmt: 采样格式

int profile: 型(H.264里面就有, 其他编码标准应该也有)

int level: 级(和profile差不太多)参考 - 雷神博客
获取

//依据编码器获得
avCodecContext = avcodec_alloc_context3(avCodec);
//或者
avCodecContext = avcodec_alloc_context3(nullptr); //传nullptr 先分配一个空的
avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams->codecpar);// 在通过AVStream 解析获得
//或者 如果情况允许 最好通过AVStream复制
AVStream *in_stream = ifmt_ctx->streams;
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);//根据输入流创建输出流
avcodec_copy_context(out_stream->codec, in_stream->codec);//复制 ctxAVCodecParamteres

可以理解为 编解码器的(上下文或参数)
AVCodecParamteres 结构体是将AVCodecContext中编解码器参数抽取出而形成的新的结构体, 在新版本中的FFMPEG中, 有些结构体中的AVCodecContext已经被弃用, 取而代之的就是AVCodecParameters这个参数, 该结构体定义在libavcodec/codec_par.h文件中
enum AVMediaType codec_type;// 编解码器的类型
const struct AVCodec *codec;// 编解码器,初始化后不可更改
enum AVCodecID codec_id;// 编解码器的id
int64_t bit_rate;// 平均比特率
uint8_t *extradata;// int extradata_size;// 针对特定编码器包含的附加信息
AVRational time_base;// 根据该参数可以将pts转化为实践
int width, height;// 每一帧的宽和高
int gop_size;// 一组图片的数量, 编码时用户设置, 解码时不使用
enum AVPixelFormat pix_fmt;// 像素格式, 编码时用户设置, 解码时可由用户指定, 但是在分析数据会被覆盖用户的设置
int refs;// 参考帧的数量
enum AVColorSpace colorspace;// YUV色彩空间类型
enum AVColorRange color_range;// MPEG JPEG YUV范围
int sample_rate;// 采样率 仅音频
int channels;// 声道数(音频)
enum AVSampleFormat sample_fmt;// //采样格式
int frame_size;// 每个音频帧中每个声道的采样数量
int profile;//配置类型
int level;//级别分配
avcodec_parameters_alloc()
AVCodec

对应编码方式
每一个编码方式对应一个该结构体, 例如(H264, H265 ..等)
获取

codec_id 有哪些可以参考: AVCodecID 枚举
avCodec = avcodec_find_decoder(codec_id);
AVPacket

对应未解码的原始数据, 对视频(Video)来说, AVPacket通常包含一个压缩的Frame; 而音频(Audio)则有可能包含多个压缩的Frame;
AVPacket -- 暂存解码之前的媒体数据(一个音/视频帧, 一个字幕包等)及附加信息(解码时间戳, 显示时间戳, 时长等), 主要用于建立缓冲区并装载数据;
在 AVPacket 结构体中, 重要的变量:
data/size/pos: 数据缓冲区指针, 长度和媒体流中的字节偏移量
flags: 标志域的组合, 1(AV_PKT_FLAG_KEY)表示该数据是一个关键帧, 2(AV_PKT_FLAG_CORRUPT)表示该数据已经损坏
destruct: 释放数据缓冲区的函数指针, 其值可为 /av_destruct_packet_nofree, 会被 av_free_packet 调用
uint8_t *data;//压缩编码的数据;
//例如对于H.264来说; 1个AVPacket的data通常对应一个NAL;
//注意: 在这里只是对应, 而不是一模一样; 他们之间有微小的差别;//使用FFMPEG类库分离出多媒体文件中的H.264码流
//因此在使用FFMPEG进行视音频处理的时候, 常常可以将得到的AVPacket的data数据直接写成文件, 从而得到视音频的码流文件;
int size;//data的大小
int64_t pts;//显示时间戳
int64_t dts;//解码时间戳
int stream_index;//标识该AVPacket所属的视频/音频流;
flats// 标志, 其中最低为1表示该数据是一个关键帧// 判断是否I帧 if (pkt->flags & AV_PKT_FLAG_KEY) // is keyframe
duration//时长, 以所属媒体流的时间基准为单位https://blog.csdn.net/leixiaohua1020/article/details/14215755
从 FFmpeg 5.0+ 开始,av_init_packet() 已经被 弃用(deprecated),在 FFmpeg 6.0 及以上版本 甚至直接 移除 了。
官方推荐改用新的 av_packet_alloc() / av_packet_unref() / av_packet_free() 接口。
AVPacket *pkt = av_packet_alloc();
if (!pkt) {
    LOGE("Could not allocate AVPacket");
    return;
}

while (ctx->running && av_read_frame(fmt_ctx, pkt) >= 0) {
    if (pkt->stream_index == videoIndex) {

    }
    av_packet_unref(pkt);
}

av_packet_free(&pkt);获取

//分配
av_packet_alloc();

//擦除数据
void av_packet_unref (AVPacket *pkt)

//释放结构体
void av_packet_free (AVPacket**pkt)API 文档

参考官方文档:
AVFrame


[*]This structure describes decoded (raw) audio or video data.
[*]
[*]AVFrame must be allocated using av_frame_alloc(). Note that this only
[*]allocates the AVFrame itself, the buffers for the data must be managed
[*]through other means (see below).
[*]AVFrame must be freed with av_frame_free().
struct AVFrame

[*]存放从AVPacket中解码后的原始数据, 其必须通过av_frame_alloc()来创建, 通过av_frame_free()来释放;
[*]
[*]和AVPacket类似, AVFrame中也有一块数据缓存空间, 在调用av_frame_alloc的时候并不会为这块缓存区域分配空间,
[*]需要使用其他的方法;
[*]在解码的过程使用了两个AVFrame, 这两个AVFrame分配缓存空间的方法也不相同
[*]
[*]AVFrame 通常分配一次,然后重复使用多次, 不同的数据(如一个AVFrame持有来自解码器的frames; )
[*]在再次使用时,av_frame_unref()将自由持有的任何之前的帧引用并重置它变成初始态;
[*]
[*]使用 av_frame_unref(packet);重置数据 和 av_frame_free(packet);来释放
data/linesize: FFMpeg内部以平面的方式存储原始图像数据, 即将图像像素分为多个平面(R/G/B或Y/U/V)数组
data 数组: 其中的指针指向各个像素平面的起始位置, 编码时需要用户设置数据
linesize数组: 存放各个存贮各个平面的缓冲区的行宽, 编码时需要用户设置数据
key_frame: 该图像是否是关键帧, 由 libavcodec 设置
pict_type: 该图像的编码类型: Intra(1)/Predicted(2)/Bi-dir(3) 等 (就是I帧/P帧/B帧), 默认值是 NONE(0), 其值由libavcodec设置
pts: 呈现时间, 编码时由用户设置
quality: 从1(最好)到FF_LAMBDA_MAX(256*128-1,最差), 编码时用户设置, 默认值是0
nterlaced_frame: 表明是否是隔行扫描的,编码时用户指定, 默认0
//分配
av_frame_alloc();
//擦除数据
av_frame_unref(pFrame);
//释放结构体
av_frame_free()
图像处理 行宽(linesize/步长(stride)/间距(pitch)

自定义编码时,AVFrame::data需要手动初始化分配内存, 这些参数很关键
cpu都是32位或者64位的cpu, 他们一次最少读取4, 8个字节, 如果少于这些, 反而要做一些额外的工作, 会花更长的时间; 所有会有一个概念叫做内存对齐, 将结构体的长度设为4, 8的倍数;
间距就是指图像中的一行图像数据所占的存储空间的长度, 它是一个大于等于图像宽度的内存对齐的长度; 这样每次以行为基准读取数据的时候就能内存对齐, 虽然可能会有一点内存浪费, 但是在内存充裕的今天已经无所谓了;
所以如果图像的宽度如果是内存对齐长度的整数倍, 那么间距就会等于宽度, 而现在的cpu通常一次读取都是4个字节, 而我们通常见到的分辨率都是4的整数倍, 所以我们通常发现间距和图像的宽度一样(通常rgb32格式或者以通道表示的yuv420p格式的y通道);
在用ffmpeg进行图像格式转换的时候, 需要传入一个参数 stride, 其实也是间距; 只不过这次不需要复杂的处理, 只需要知道传入ffmpeg进行转换的图像数据使用的间距, 然后传入就行, ffmpeg会自动根据这个值进行相应的处理;
图像处理, 显示中的行宽
给 AVFrame data分配内存

新APIavpicture_get_size->av_image_get_buffer_size, avpicture_fill>av_image_fill_arrays 就是增加间距以内存对齐?
//旧api
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height,4);

//新api
av_image_fill_arrays

//更简单的
AVFrame * convert_frame= av_frame_alloc();
av_image_alloc(convert_frame->data, convert_frame->linesize, t_ctx->codecCtx->width, t_ctx->codecCtx->height,AV_PIX_FMT_YUV420P, 4);

/**

The following fields must be set on frame before calling this function:
(也行, 需设置)
format (pixel format for video, sample format for audio)
width and height for video
nb_samples and channel_layout for audio
*/
int av_frame_get_buffer        (        AVFrame *         frame, int         align)        注意: av_free() 并没有释放AVFrame中data指向的 数据, 仅仅是把data本身指向的数据释放了, 但其作为二级指针指向的数据跳过了, 需要手动释放, 添加 av_free(AVFrame->data)后问题解决;
AVDictionary

封装的一个类似Map的结构体, 主要在配置选项是使用.
注意一下, 这个使用完也要释放?
av_dict_free(&dict);
关于有哪些配置项可以参考:官方文档 Options, 以及各编解码的 Options
关于怎么用可以参考: ffmpeg.exe源码
主要结构体的分配与销毁 表

结构体初始化销毁AVFormatContextavformat_alloc_context()avformat_free_context()AVIOContextavio_alloc_context()AVStreamavformat_new_stream()AVCodecContextavcodec_alloc_context3()avcodec_close(vCodecCtx);AVFrameav_frame_alloc(); 填充数据: av_image_fill_arrays();av_frame_free()AVPacketav_init_packet(); av_new_packet()av_free_packet已过时, av_packet_unref取代之小坑指南

AVDictionary

AVDictionary 不管成功失败都要释放av_dict_free(&options);
AVDictionary* options = nullptr;//一些 option
av_dict_set(&options, "rtsp_transport", "tcp", 0);//over tcp
// av_dict_set(&options, "buffer_size", "102400", 0); //设置缓存大小, 1080p可将值调大
av_dict_set(&options, "stimeout", "3000000", 0); //设置socket 超时断开连接时间, 单位微秒
av_dict_free(&options);//坑!
if((ret=avformat_open_input(&inAvFormatCtx,rtspUrl,nullptr,&options)) != 0){
}av_write_trailer

//注意即使无限直播, 结束时也要写尾, 不然还有私有数据没有被释放, 有文件则会占用文件锁!
ret = av_write_trailer(outAvFormatCtx);
内存的释放

总之有调用 alloc 相关函数名的, 就一定要调用free 释放之, 参考 FFmpeg.exe 工具的源码:
static void ffmpeg_cleanup(int ret)
{
    int i, j;

    if (do_benchmark) {
      int maxrss = getmaxrss() / 1024;
      av_log(NULL, AV_LOG_INFO, "bench: maxrss=%ikB\n", maxrss);
    }

    for (i = 0; i < nb_filtergraphs; i++) {
      FilterGraph *fg = filtergraphs;
      avfilter_graph_free(&fg->graph);
      for (j = 0; j < fg->nb_inputs; j++) {
            InputFilter *ifilter = fg->inputs;
            struct InputStream *ist = ifilter->ist;

            while (av_fifo_size(ifilter->frame_queue)) {
                AVFrame *frame;
                av_fifo_generic_read(ifilter->frame_queue, &frame,
                                     sizeof(frame), NULL);
                av_frame_free(&frame);
            }
            av_fifo_freep(&ifilter->frame_queue);
            if (ist->sub2video.sub_queue) {
                while (av_fifo_size(ist->sub2video.sub_queue)) {
                  AVSubtitle sub;
                  av_fifo_generic_read(ist->sub2video.sub_queue,
                                       &sub, sizeof(sub), NULL);
                  avsubtitle_free(&sub);
                }
                av_fifo_freep(&ist->sub2video.sub_queue);
            }
            av_buffer_unref(&ifilter->hw_frames_ctx);
            av_freep(&ifilter->name);
            av_freep(&fg->inputs);
      }
      av_freep(&fg->inputs);
      for (j = 0; j < fg->nb_outputs; j++) {
            OutputFilter *ofilter = fg->outputs;

            avfilter_inout_free(&ofilter->out_tmp);
            av_freep(&ofilter->name);
            av_freep(&ofilter->formats);
            av_freep(&ofilter->channel_layouts);
            av_freep(&ofilter->sample_rates);
            av_freep(&fg->outputs);
      }
      av_freep(&fg->outputs);
      av_freep(&fg->graph_desc);

      av_freep(&filtergraphs);
    }
    av_freep(&filtergraphs);

    av_freep(&subtitle_out);

    /* close files */
    for (i = 0; i < nb_output_files; i++) {
      OutputFile *of = output_files;
      AVFormatContext *s;
      if (!of)
            continue;
      s = of->ctx;
      if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE))
            avio_closep(&s->pb);
      avformat_free_context(s);
      av_dict_free(&of->opts);

      av_freep(&output_files);
    }
    for (i = 0; i < nb_output_streams; i++) {
      OutputStream *ost = output_streams;

      if (!ost)
            continue;

      av_bsf_free(&ost->bsf_ctx);

      av_frame_free(&ost->filtered_frame);
      av_frame_free(&ost->last_frame);
      av_dict_free(&ost->encoder_opts);

      av_freep(&ost->forced_keyframes);
      av_expr_free(ost->forced_keyframes_pexpr);
      av_freep(&ost->avfilter);
      av_freep(&ost->logfile_prefix);

      av_freep(&ost->audio_channels_map);
      ost->audio_channels_mapped = 0;

      av_dict_free(&ost->sws_dict);
      av_dict_free(&ost->swr_opts);

      avcodec_free_context(&ost->enc_ctx);
      avcodec_parameters_free(&ost->ref_par);

      if (ost->muxing_queue) {
            while (av_fifo_size(ost->muxing_queue)) {
                AVPacket pkt;
                av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL);
                av_packet_unref(&pkt);
            }
            av_fifo_freep(&ost->muxing_queue);
      }

      av_freep(&output_streams);
    }
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

聚怪闩 发表于 2025-12-20 16:03:13

yyds。多谢分享

苗嘉惠 发表于 2026-1-14 07:44:18

鼓励转贴优秀软件安全工具和文档!

博咱 发表于 2026-1-15 05:31:30

感谢分享,下载保存了,貌似很强大

客臂渐 发表于 2026-1-18 19:47:12

鼓励转贴优秀软件安全工具和文档!

羊舌正清 发表于 2026-1-19 14:53:07

新版吗?好像是停更了吧。

王妍芳 发表于 2026-1-20 13:16:08

收藏一下   不知道什么时候能用到

仁夹篇 发表于 2026-1-20 22:26:38

新版吗?好像是停更了吧。

凉砧掌 发表于 2026-1-21 10:03:44

鼓励转贴优秀软件安全工具和文档!

尚腱埂 发表于 2026-1-21 16:37:04

谢谢楼主提供!

嶝扁 发表于 2026-1-24 10:56:52

鼓励转贴优秀软件安全工具和文档!

褐洌 发表于 2026-1-26 05:26:21

前排留名,哈哈哈

司寇涵涵 发表于 2026-1-26 09:36:23

鼓励转贴优秀软件安全工具和文档!

抑卞枯 发表于 2026-1-27 03:47:45

感谢分享,下载保存了,貌似很强大

泡市 发表于 2026-1-30 06:34:34

新版吗?好像是停更了吧。

全叶农 发表于 2026-2-2 02:42:38

谢谢分享,试用一下

阎逼 发表于 2026-2-3 09:09:52

这个有用。

箝德孜 发表于 2026-2-7 04:24:11

过来提前占个楼

悯拄等 发表于 2026-2-8 02:42:01

谢谢分享,试用一下

米嘉怡 发表于 2026-2-9 01:47:37

懂技术并乐意极积无私分享的人越来越少。珍惜
页: [1] 2
查看完整版本: FFmpeg 关键的结构体