程序代码:
#include <iostream> #include <string> #include <thread> #include "SDL.h" #include "SDL_thread.h" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswresample/swresample.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" } const int kVideoWidth = 640; const int kVideoHeight = 360; const std::string kVideoPath = "test.mp4"; int main(int argc, char* argv[]) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) { std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl; return -1; } AVFormatContext* format_context = avformat_alloc_context(); if (avformat_open_input(&format_context, kVideoPath.c_str(), nullptr, nullptr) != 0) { std::cerr << "Failed to open video file: " << kVideoPath << std::endl; return -1; } if (avformat_find_stream_info(format_context, nullptr) < 0) { std::cerr << "Failed to find video stream information" << std::endl; return -1; } AVCodec* codec = nullptr; int stream_index = -1; for (int i = 0; i < format_context->nb_streams; i++) { if (format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { codec = avcodec_find_decoder(format_context->streams[i]->codecpar->codec_id); stream_index = i; break; } } if (codec == nullptr) { std::cerr << "Failed to find video codec" << std::endl; return -1; } AVCodecContext* codec_context = avcodec_alloc_context3(codec); if (avcodec_parameters_to_context(codec_context, format_context->streams[stream_index]->codecpar) < 0) { std::cerr << "Failed to copy video codec parameters to context" << std::endl; return -1; } if (avcodec_open2(codec_context, codec, nullptr) < 0) { std::cerr << "Failed to open video codec" << std::endl; return -1; } AVFrame* frame = av_frame_alloc(); AVFrame* frame_rgb = av_frame_alloc(); uint8_t* buffer = nullptr; int buffer_size = 0; buffer_size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1); buffer = reinterpret_cast<uint8_t*>(av_malloc(buffer_size)); av_image_fill_arrays(frame_rgb->data, frame_rgb->linesize, buffer, AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1); struct SwsContext* sws_context = sws_getContext(codec_context->width, codec_context->height, codec_context->pix_fmt, kVideoWidth, kVideoHeight, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr); SDL_Window* window = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, kVideoWidth, kVideoHeight, SDL_WINDOW_OPENGL); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, kVideoWidth, kVideoHeight); AVPacket packet; bool is_running = true; while (av_read_frame(format_context, &packet) >= 0 && is_running) { if (packet.stream_index == stream_index) { if (avcodec_send_packet(codec_context, &packet) == 0) { while (avcodec_receive_frame(codec_context, frame) == 0) { sws_scale(sws_context, frame->data, frame->linesize, 0, codec_context->height, frame_rgb->data, frame_rgb->linesize); SDL_UpdateTexture(texture, nullptr, frame_rgb->data[0], frame_rgb->linesize[0]); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderPresent(renderer); SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { is_running = false; break; } } } } } av_packet_unref(&packet); } av_frame_free(&frame); av_frame_free(&frame_rgb); avcodec_close(codec_context); avformat_close_input(&format_context); avformat_free_context(format_context); av_free(buffer); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }