基于ffmpeg的简单音视频播放器的demo
时间: 2023-07-06 10:41:16 浏览: 207
以下是基于ffmpeg的简单音视频播放器的demo的代码,使用C++语言编写:
```c++
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
using namespace std;
int main(int argc, char* argv[]) {
if (argc != 2) {
cout << "Usage: " << argv[0] << " filename" << endl;
return 1;
}
// Initialize FFmpeg
av_register_all();
avcodec_register_all();
// Open video file
AVFormatContext* format_ctx = nullptr;
if (avformat_open_input(&format_ctx, argv[1], nullptr, nullptr) != 0) {
cerr << "Error: Failed to open file " << argv[1] << endl;
return 1;
}
// Retrieve stream information
if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
cerr << "Error: Failed to retrieve stream information" << endl;
return 1;
}
// Find the first video stream
int video_stream_index = -1;
AVCodecParameters* codec_params = nullptr;
AVCodec* codec = nullptr;
AVCodecContext* codec_ctx = nullptr;
for (int i = 0; i < format_ctx->nb_streams; i++) {
codec_params = format_ctx->streams[i]->codecpar;
if (codec_params->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
codec = avcodec_find_decoder(codec_params->codec_id);
if (codec == nullptr) {
cerr << "Error: Unsupported codec" << endl;
return 1;
}
codec_ctx = avcodec_alloc_context3(codec);
if (codec_ctx == nullptr) {
cerr << "Error: Failed to allocate codec context" << endl;
return 1;
}
if (avcodec_parameters_to_context(codec_ctx, codec_params) < 0) {
cerr << "Error: Failed to copy codec parameters to codec context" << endl;
return 1;
}
if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
cerr << "Error: Failed to open codec" << endl;
return 1;
}
break;
}
}
if (video_stream_index == -1) {
cerr << "Error: Failed to find video stream" << endl;
return 1;
}
// Allocate video frame and buffer
AVFrame* frame = av_frame_alloc();
if (frame == nullptr) {
cerr << "Error: Failed to allocate video frame" << endl;
return 1;
}
AVFrame* rgb_frame = av_frame_alloc();
if (rgb_frame == nullptr) {
cerr << "Error: Failed to allocate RGB video frame" << endl;
return 1;
}
uint8_t* buffer = nullptr;
int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
buffer = (uint8_t*)av_malloc(num_bytes * sizeof(uint8_t));
if (buffer == nullptr) {
cerr << "Error: Failed to allocate buffer" << endl;
return 1;
}
av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, buffer, AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
// Allocate SwsContext
SwsContext* sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
if (sws_ctx == nullptr) {
cerr << "Error: Failed to allocate SwsContext" << endl;
return 1;
}
// Initialize window and renderer
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
cerr << "Error: Failed to initialize SDL" << endl;
return 1;
}
window = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, codec_ctx->width, codec_ctx->height, SDL_WINDOW_SHOWN);
if (window == nullptr) {
cerr << "Error: Failed to create window" << endl;
return 1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) {
cerr << "Error: Failed to create renderer" << endl;
return 1;
}
// Read packets from stream and decode
AVPacket packet;
while (av_read_frame(format_ctx, &packet) >= 0) {
if (packet.stream_index == video_stream_index) {
avcodec_send_packet(codec_ctx, &packet);
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
sws_scale(sws_ctx, frame->data, frame->linesize, 0, frame->height, rgb_frame->data, rgb_frame->linesize);
SDL_UpdateTexture(SDL_CreateTextureFromSurface(renderer, av_frame_get_surface(rgb_frame)), nullptr, nullptr, 0);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, SDL_CreateTextureFromSurface(renderer, av_frame_get_surface(rgb_frame)), nullptr, nullptr);
SDL_RenderPresent(renderer);
this_thread::sleep_for(chrono::milliseconds(10));
}
}
av_packet_unref(&packet);
}
// Clean up
av_frame_free(&frame);
av_frame_free(&rgb_frame);
av_free(buffer);
avcodec_free_context(&codec_ctx);
avformat_close_input(&format_ctx);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
```
这个demo使用SDL库来显示视频,使用FFmpeg库来解码视频。在运行时需要提供一个视频文件的路径作为参数。可以根据需要进行修改和扩展。
阅读全文