ffmpeg c++ ffplay例子
时间: 2023-08-01 17:12:27 浏览: 197
以下是一个简单的使用FFmpeg和SDL库编写的C++代码示例,用于播放视频文件:
```cpp
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
#include <SDL2/SDL.h>
int main(int argc, char* argv[])
{
// 初始化FFmpeg
av_register_all();
// 打开视频文件
AVFormatContext* formatContext = nullptr;
if (avformat_open_input(&formatContext, argv[1], nullptr, nullptr) != 0)
{
fprintf(stderr, "无法打开视频文件\n");
return -1;
}
// 检索流信息
if (avformat_find_stream_info(formatContext, nullptr) < 0)
{
fprintf(stderr, "无法找到流信息\n");
return -1;
}
// 查找视频流
int videoStreamId = -1;
for (unsigned int i = 0; i < formatContext->nb_streams; i++)
{
if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStreamId = i;
break;
}
}
if (videoStreamId == -1)
{
fprintf(stderr, "无法找到视频流\n");
return -1;
}
// 获取视频流解码器参数
AVCodecParameters* codecParameters = formatContext->streams[videoStreamId]->codecpar;
// 查找视频解码器
AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id);
if (!codec)
{
fprintf(stderr, "无法找到视频解码器\n");
return -1;
}
// 创建解码器上下文
AVCodecContext* codecContext = avcodec_alloc_context3(codec);
if (!codecContext)
{
fprintf(stderr, "无法分配解码器上下文\n");
return -1;
}
// 设置解码器参数
if (avcodec_parameters_to_context(codecContext, codecParameters) < 0)
{
fprintf(stderr, "无法设置解码器参数\n");
return -1;
}
// 打开解码器
if (avcodec_open2(codecContext, codec, nullptr) < 0)
{
fprintf(stderr, "无法打开解码器\n");
return -1;
}
// 分配帧内存
AVFrame* frame = av_frame_alloc();
if (!frame)
{
fprintf(stderr, "无法分配帧内存\n");
return -1;
}
// 创建SDL窗口
SDL_Window* window = SDL_CreateWindow("FFmpeg SDL播放器", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, codecContext->width, codecContext->height, 0);
if (!window)
{
fprintf(stderr, "无法创建SDL窗口\n");
return -1;
}
// 创建SDL渲染器
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer)
{
fprintf(stderr, "无法创建SDL渲染器\n");
return -1;
}
// 创建SDL纹理
SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, codecContext->width, codecContext->height);
if (!texture)
{
fprintf(stderr, "无法创建SDL纹理\n");
return -1;
}
// 创建AVPacket
AVPacket packet;
av_init_packet(&packet);
// 读取帧数据并渲染
while (av_read_frame(formatContext, &packet) >= 0)
{
if (packet.stream_index == videoStreamId)
{
// 解码视频帧
int response = avcodec_send_packet(codecContext, &packet);
if (response < 0)
{
fprintf(stderr, "解码错误\n");
break;
}
while (response >= 0)
{
response = avcodec_receive_frame(codecContext, frame);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
break;
else if (response < 0)
{
fprintf(stderr, "解码错误\n");
break;
}
// 将YUV数据复制到SDL纹理
SDL_UpdateYUVTexture(texture, nullptr, frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]);
// 清除原有渲染
SDL_RenderClear(renderer);
// 将纹理复制到渲染器
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
// 显示渲染结果
SDL_RenderPresent(renderer);
}
}
// 释放AVPacket
av_packet_unref(&packet);
}
// 清理资源
av_frame_free(&frame);
avcodec_close(codecContext);
avformat_close_input(&formatContext);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
```
这个例子使用FFmpeg库解码视频文件,并使用SDL库进行视频渲染。你需要将FFmpeg和SDL库包含到你的项目中,并确保链接正确的库文件。请注意,这只是一个简单的例子,没有处理音频、错误处理和其他高级功能。
阅读全文