写一个ffmpeg采集视频数据后通过SDL渲染的代码例程
时间: 2023-03-13 14:19:52 浏览: 220
ffmpeg与SDL编程
5星 · 资源好评率100%
#include <SDL2/SDL.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>int main() {
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int videoStream;
SDL_Window *screen;
SDL_Renderer *renderer;
SDL_Texture *texture;
int i, numBytes;
uint8_t *buffer = NULL;
// 首先打开视频文件
if(avformat_open_input(&pFormatCtx, "test.mp4", NULL, NULL) != 0) {
printf("Couldn't open the file");
return -1;
}
// 找到视频流
if(avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Couldn't find stream info");
return -1;
}
// 查找视频流索引
videoStream = -1;
for(i=0; i<pFormatCtx->nb_streams; i++) {
if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
}
if(videoStream == -1) {
printf("Couldn't find a video stream");
return -1;
}
// 初始化SDL
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
printf("Couldn't initialize SDL: %s", SDL_GetError());
return -1;
}
// 创建窗口
screen = SDL_CreateWindow("FFmpeg Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
pFormatCtx->streams[videoStream]->codec->width,
pFormatCtx->streams[videoStream]->codec->height,
SDL_WINDOW_OPENGL);
if(!screen) {
printf("SDL: could not create window - exiting: %s", SDL_GetError());
return -1;
}
// 创建渲染器
renderer = SDL_CreateRenderer(screen, -1, 0);
if(!renderer) {
printf("SDL: could not create renderer - exiting: %s", SDL_GetError());
return -1;
}
// 创建纹理
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING,
pFormatCtx->streams[videoStream]->codec->width,
pFormatCtx->streams[videoStream]->codec->height);
if(!texture) {
printf("SDL: could not create texture - exiting: %s", SDL_GetError());
return -1;
}
// 获取解码器
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec == NULL) {
printf("Unsupported codec");
return -1;
}
// 打开解码器
if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec");
return -1;
}
// 分配视频帧
pFrame = av_frame_alloc();
// 申请缓冲区
numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// 将缓冲区放入视频帧中
avpicture_fill((AVPicture *)pFrame, buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
// 开始解码
while(av_read_frame(pFormatCtx, &packet) >= 0) {
if(packet.stream_index == videoStream) {
int frameFinished;
// 解码视频帧
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
// 如果解码完成
if(frameFinished) {
SDL_UpdateYUVTexture(texture, NULL, pFrame->data[0], pFrame->linesize[0],
pFrame->data[1], pFrame->linesize[1],
pFrame->data[2], pFrame->linesize[2]);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
}
// 释放packet
av_free_packet(&packet);
}
// 释放资源
av_free(buffer);
av_free(pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}答案:使用FFmpeg采集视频数据,然后通过SDL渲染,可以使用如下代码例程:
阅读全文