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>
相关推荐
jike_20269 小时前
iPhone采访录音同时拍现场照片的APP:图片音频同步记录实测
笔记·智能手机·音视频·语音识别
小猴子爱上树9 小时前
跨境电商翻译工具推荐:批量图片翻译、视频字幕翻译、智能抠图一站式搞定
人工智能·python·音视频
林澈在路上10 小时前
AI翻唱软件哪个好 2026国产AI写歌工具对比推荐
大数据·人工智能·深度学习·github·aigc·音视频·音频
阿童木写作11 小时前
跨马翻译:AI批量图片翻译与视频字幕翻译工具推荐
人工智能·python·音视频
Dovis(誓平步青云)12 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
敢敢のwings17 小时前
Wan2.2 模型系统解读:从视频扩散到 WAM 世界模型模块
音视频
小猴子爱上树18 小时前
跨境电商AI批量图片翻译工具,视频字幕翻译免费试用
人工智能·python·音视频
AI服务老曹18 小时前
车牌识别算法接入AI视频分析平台的流程和误报优化
人工智能·算法·音视频
betazhou18 小时前
mysql shell8.4.10+mysql 8.4.10搭建MySQL replicaset主从
数据库·mysql·ffmpeg·replicaset·mysql shell
深念Y20 小时前
视频平台架构重构:从微服务到可插拔基础设施
后端·微服务·云原生·架构·rabbitmq·音视频·rocketmq