FFmpeg 视频播放demo

sourcecode

main.c

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <SDL2/SDL.h>
#include <signal.h>
#include <stdbool.h>

// 全局标志变量,用于指示程序是否应该退出
volatile sig_atomic_t exit_program = false;

// 信号处理函数
void handle_sigint(int sig) {
    if (sig == SIGINT) {
        printf("Caught SIGINT, exiting...\n");
        exit_program = true;
    }
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Usage: %s <video_file>\n", argv[0]);
        return -1;
    }

    const char *filename = argv[1];

     // 注册信号处理函数
    signal(SIGINT, handle_sigint);

    avformat_network_init();

    // Open video file
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
        printf("Couldn't open file.\n");
        return -1;
    }

    // Retrieve stream information
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        printf("Couldn't find stream information.\n");
        return -1;
    }

    // Find the first video stream
    int videoStream = -1;
    for (int i = 0; i < pFormatCtx->nb_streams; i++) {
        if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream = i;
            break;
        }
    }
    if (videoStream == -1) {
        printf("Didn't find a video stream.\n");
        return -1;
    }

    // Get a pointer to the codec context for the video stream
    AVCodecParameters *pCodecPar = pFormatCtx->streams[videoStream]->codecpar;
    AVCodec *pCodec = (AVCodec*)avcodec_find_decoder(pCodecPar->codec_id);
    if (pCodec == NULL) {
        printf("Unsupported codec!\n");
        return -1;
    }

    AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
    if (avcodec_parameters_to_context(pCodecCtx, pCodecPar) < 0) {
        printf("Couldn't copy codec context.\n");
        return -1;
    }

    // Open codec
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        printf("Couldn't open codec.\n");
        return -1;
    }

    // Allocate video frame
    AVFrame *pFrame = av_frame_alloc();
    AVFrame *pFrameRGB = av_frame_alloc();
    if (pFrameRGB == NULL || pFrame == NULL) {
        printf("Couldn't allocate frames.\n");
        return -1;
    }

    int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 32);
    uint8_t *buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
    av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 32);

    struct SwsContext *sws_ctx = sws_getContext(
        pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
        pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24,
        SWS_BILINEAR, NULL, NULL, NULL);

    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
    SDL_Window *screen = SDL_CreateWindow(
        "FFmpeg Video Playback",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        pCodecCtx->width,
        pCodecCtx->height,
        SDL_WINDOW_OPENGL);

    if (!screen) {
        printf("SDL: could not create window - exiting:%s\n", SDL_GetError());
        return -1;
    }

    SDL_Renderer *renderer = SDL_CreateRenderer(screen, -1, 0);
    SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);

    while (!exit_program) {
      AVPacket packet;
      int response;

      // Read frames and save first five frames to disk
      while (av_read_frame(pFormatCtx, &packet) >= 0) {
        if (packet.stream_index == videoStream) {
          response = avcodec_send_packet(pCodecCtx, &packet);
          if (response < 0) {
            printf("Error while sending a packet to the decoder.\n");
            break;
          }

          while (response >= 0) {
            response = avcodec_receive_frame(pCodecCtx, pFrame);
            if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
              break;
            } else if (response < 0) {
              printf("Error while receiving a frame from the decoder.\n");
              return -1;
            }

            sws_scale(sws_ctx, (uint8_t const *const *)pFrame->data,
                      pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
                      pFrameRGB->linesize);

            SDL_UpdateTexture(texture, NULL, pFrameRGB->data[0],
                              pFrameRGB->linesize[0]);
            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, NULL);
            SDL_RenderPresent(renderer);
            SDL_Delay(40); // 25 fps
          }
        }
        av_packet_unref(&packet);
        // 检查SDL事件
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
          if (event.type == SDL_QUIT) {
            exit_program = true;
          }
        }

        if (exit_program) {
          break;
        }
      }
      if (exit_program) {
        break;
      }
    }

    // Free resources
    av_free(buffer);
    av_frame_free(&pFrameRGB);
    av_frame_free(&pFrame);
    avcodec_free_context(&pCodecCtx);
    avformat_close_input(&pFormatCtx);
    sws_freeContext(sws_ctx);

    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(screen);
    SDL_Quit();

    return 0;
}

dependence

安装 FFmpeg 开发库:

sh

sudo apt-get install libavformat-dev libavcodec-dev libswscale-dev libavutil-dev

安装 SDL2 开发库:

sh

sudo apt-get install libsdl2-dev

compile

复制代码
gcc -o  video_player main.c  -lavformat -lavcodec -lswscale -lavutil -lSDL2

run

复制代码
./video_player <video_file>
相关推荐
乐橙开放平台26 分钟前
智慧连锁客流检测和离岗检测怎么对接
大数据·人工智能·笔记·物联网·自动化·音视频·智能家居
Anhty2 小时前
2026最新免费手机音频处理工具 !!
android·功能测试·ios·智能手机·音视频
企业数字化笔记3 小时前
AI工具参数很多怎么办?预设、表单校验、危险参数与配置审计
java·spring boot·python·音视频
VidDown4 小时前
上传 2GB 文件别让 Django 接:分片上传、对象存储直传与秒传
python·django·音视频·状态模式·实时音视频·视频编解码·视频
阿明副业观察5 小时前
AI视频生成工具功能与作用全面解析:赋能高效内容创作
大数据·人工智能·aigc·音视频·ai写作
EasyDSS6 小时前
告别视频资源浪费!云点播/本地点播/网络点播EasyDSS平台点播实现企业视频高效复用
音视频·媒体·easydss
智能直播6 小时前
RK3528 Tinyalsa/ALSA框架:输入源声音获取与HDMI out声音输出,一文讲透直播音频链路
音视频·实时音视频·视频编解码
镭封6 小时前
做电视剧解说视频用什么软件?配音、文案处理一次解决
人工智能·小程序·音视频·语音识别·媒体
VidDown8 小时前
自动给视频挑一张能看的封面:帧评分、构图与批量生成
python·ffmpeg·音视频·视频
AliCloudROS9 小时前
MiniMax-H3 视频生成模型 — 一键部署与使用指南
人工智能·音视频