以下是一个使用FFmpeg进行简单视频编解码的实例代码。这个示例将展示如何使用FFmpeg的API来读取一个视频文件,解码其视频流,然后再将其编码回原来的格式,并保存到一个新的文件中。
请注意,这个示例代码是为了教学目的而简化的,并没有处理所有可能的错误和边缘情况。在实际应用中,你需要添加更多的错误检查和资源管理代码。
cCopy Code
#include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> int main(int argc, char *argv[]) { const char *input_filename = "input.mp4"; const char *output_filename = "output.mp4"; AVFormatContext *input_ctx = NULL; AVFormatContext *output_ctx = NULL; AVCodecContext *dec_ctx = NULL; AVCodecContext *enc_ctx = NULL; AVCodec *dec = NULL; AVCodec *enc = NULL; AVPacket *pkt = NULL; AVFrame *frame = NULL; AVFrame *rgb_frame = NULL; int ret; // 注册所有编解码器 av_register_all(); // 打开输入文件 if ((ret = avformat_open_input(&input_ctx, input_filename, NULL, NULL)) < 0) { fprintf(stderr, "Could not open input file '%s'\n", input_filename); goto end; } // 查找流信息 if ((ret = avformat_find_stream_info(input_ctx, NULL)) < 0) { fprintf(stderr, "Could not find stream information\n"); goto end; } // 查找视频流 AVStream *in_stream = NULL; for (int i = 0; i < input_ctx->nb_streams; i++) { if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { in_stream = input_ctx->streams[i]; break; } } if (!in_stream) { fprintf(stderr, "Could not find video stream\n"); goto end; } // 获取解码器 dec = avcodec_find_decoder(in_stream->codecpar->codec_id); if (!dec) { fprintf(stderr, "Could not find video decoder\n"); goto end; } // 分配解码器上下文 dec_ctx = avcodec_alloc_context3(dec); if (!dec_ctx) { fprintf(stderr, "Could not allocate video decoder context\n"); goto end; } // 复制解码器参数 if ((ret = avcodec_parameters_to_context(dec_ctx, in_stream->codecpar)) < 0) { fprintf(stderr, "Could not copy decoder parameters\n"); goto end; } // 打开解码器 if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) { fprintf(stderr, "Could not open codec\n"); goto end; } // 分配视频帧 frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate video frame\n"); goto end; } // 分配AVPacket pkt = av_packet_alloc(); if (!pkt) { fprintf(stderr, "Could not allocate AVPacket\n"); goto end; } // ...(此处省略了编码器的初始化、输出文件的打开、编码和写入过程) // 读取帧、解码、编码和写入循环(也省略了具体实现) end: // 清理资源 av_frame_free(&frame); av_frame_free(&rgb_frame); av_packet_free(&pkt); avcodec_free_context(&dec_ctx); avcodec_free_context(&enc_ctx); avformat_close_input(&input_ctx); if (output_ctx && !(output_ctx->oformat->flags & AVFMT_NOFILE)) avio_close(output_ctx->pb); avformat_free_context(output_ctx); return ret < 0 ? 1 : 0; }
这个示例代码省略了编码器的初始化、输出文件的打开、编码和写入过程,以及读取帧、解码、编码和写入的循环。在实际应用中,你需要完成这些部分,包括:
- 初始化编码器,并设置编码参数。
- 打开输出文件,并写入文件头。
- 在循环中读取输入文件的帧,解码,然后编码成新的格式,并写入输出文件。
- 处理完所有帧后,写入文件尾并关闭文件。
此外,请确保你已经安装了FFmpeg库,并在编译时链接了正确的库文件。编译命令可能类似于:
bashCopy Code
gcc -o my_ffmpeg_example my_ffmpeg_example.c -lavformat -lavcodec -lavutil -lswscale -lswresample
这个命令假设你的系统上已经安装了FFmpeg的开发库,并且库文件的位置在编译器的默认搜索路径中。如果不是这样,你可能需要指定库文件的位置和包含文件的路径。