c 调用ffmpeg 进行视频抽帧
时间: 2023-09-19 14:08:28 浏览: 254
要在 C 语言中调用 FFmpeg 进行视频抽帧,可以使用 FFmpeg 的 C API。以下是一个简单的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#define INBUF_SIZE 4096
int main(int argc, char **argv)
{
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *dec_ctx = NULL;
AVCodec *dec = NULL;
AVPacket pkt;
int ret, i;
if (argc != 2) {
fprintf(stderr, "Usage: %s <input_file>\n", argv[0]);
exit(1);
}
av_register_all();
if (avformat_open_input(&fmt_ctx, argv[1], NULL, NULL) < 0) {
fprintf(stderr, "Could not open source file %s\n", argv[1]);
exit(1);
}
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not find stream information\n");
exit(1);
}
for (i = 0; i < fmt_ctx->nb_streams; i++) {
AVStream *stream = fmt_ctx->streams[i];
dec_ctx = stream->codec;
dec = avcodec_find_decoder(dec_ctx->codec_id);
if (!dec) {
fprintf(stderr, "Failed to find decoder for stream #%d\n", i);
exit(1);
}
if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
fprintf(stderr, "Failed to open decoder for stream #%d\n", i);
exit(1);
}
}
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
if (pkt.stream_index == i) {
AVFrame *frame = av_frame_alloc();
int got_frame;
if (!frame) {
fprintf(stderr, "Could not allocate frame\n");
exit(1);
}
ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &pkt);
if (ret < 0) {
fprintf(stderr, "Error decoding video frame\n");
exit(1);
}
if (got_frame) {
char buf[1024];
snprintf(buf, sizeof(buf), "frame-%d.pgm", dec_ctx->frame_number);
FILE *f = fopen(buf, "wb");
if (!f) {
fprintf(stderr, "Could not open output file\n");
exit(1);
}
AVFrame *rgb = av_frame_alloc();
if (!rgb) {
fprintf(stderr, "Could not allocate RGB frame\n");
exit(1);
}
int w = dec_ctx->width;
int h = dec_ctx->height;
av_image_alloc(rgb->data, rgb->linesize, w, h, AV_PIX_FMT_RGB24, 1);
struct SwsContext *sws_ctx = sws_getContext(w, h, dec_ctx->pix_fmt, w, h, AV_PIX_FMT_RGB24, 0, NULL, NULL, NULL);
if (!sws_ctx) {
fprintf(stderr, "Could not initialize conversion context\n");
exit(1);
}
sws_scale(sws_ctx, (const uint8_t * const *)frame->data, frame->linesize, 0, h, rgb->data, rgb->linesize);
fprintf(f, "P6\n%d %d\n255\n", w, h);
fwrite(rgb->data[0], 1, w * h * 3, f);
fclose(f);
av_freep(&rgb->data[0]);
av_frame_free(&rgb);
}
av_frame_free(&frame);
}
av_packet_unref(&pkt);
}
avcodec_free_context(&dec_ctx);
avformat_close_input(&fmt_ctx);
return 0;
}
```
上面的代码会将输入文件的视频流抽帧,并将每一帧转换为 PGM 图像格式并保存到磁盘上。你可以根据自己的需求修改代码来实现更复杂的功能。
阅读全文