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>
相关推荐
mo477610 分钟前
Webrtc音频模块(四) 音频采集
音视频·webrtc
icy、泡芙14 分钟前
T527-----音频调试
linux·驱动开发·音视频
易我数据恢复大师14 分钟前
怎么提取音频保存到本地?电脑音频提取方法
音视频·软件·音频提取
野蛮的大西瓜17 分钟前
开源呼叫中心中,如何将ASR与IVR菜单结合,实现动态的IVR交互
人工智能·机器人·自动化·音视频·信息与通信
嘟嘟实验室3 小时前
微信小程序xr-frame透明视频实现
微信小程序·ffmpeg·音视频·xr
红米饭配南瓜汤4 小时前
WebRTC服务质量(09)- Pacer机制(01) 流程概述
网络·音视频·webrtc
是十一月末7 小时前
Python进阶之opencv图片和视频基本读取关闭
python·opencv·音视频·cv2
泰勒朗斯7 小时前
如何编译Opencv +ffmpeg linux 明明安装了ffmpeg但是opencv就是找不到
linux·opencv·ffmpeg
gomogomono9 小时前
HDR视频技术之十一:HEVCH.265 的 HDR 编码方案
音视频·h.265·hdr·yuv
Eric.Lee202111 小时前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频