欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

100行代码的简单视频播放器(ffmpeg4.1.3+SDL2.0.9)

程序员文章站 2022-07-01 13:32:13
...

100行代码的简单视频播放器

#include <stdio.h>
#include <signal.h>

#include "SDL2/SDL.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"

const char *stream_source = "/home/user1/test.mp4";
const unsigned int frame_width = 1920;
const unsigned int frame_height = 1080;
const unsigned int display_width = 960;
const unsigned int display_height = 540;

void force_exit() {
    fprintf(stderr, "video_player stop!!!\n");
    exit(0);
}

int main() {
    signal(SIGINT, force_exit);

    if (SDL_Init(SDL_INIT_VIDEO)) {
        fprintf(stderr, "[video_player] Error: Could not initialize. %s\n", SDL_GetError());
        return -1;
    }
    SDL_Window *screen = SDL_CreateWindow("video_player", 0, 0, display_width, display_height, SDL_WINDOW_OPENGL);
    if (!screen) {
        fprintf(stderr, "[video_player] Error: could not create window. %s\n", SDL_GetError());
        return -1;
    }

    SDL_Renderer *sdl_renderer = SDL_CreateRenderer(screen, -1, 0);
    SDL_Texture *sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,
                                                 frame_width, frame_height);

    AVFormatContext *format_ctx = NULL;

    int err_code = avformat_open_input(&format_ctx, stream_source, NULL, NULL);
    if (err_code < 0) {
        fprintf(stderr, "[video_player] Error: avformat_open_input failed! err_code = %d\n", err_code);
        return -1;
    }

    err_code = avformat_find_stream_info(format_ctx, NULL);
    if (err_code < 0) {
        fprintf(stderr, "[video_player] Error: avformat_find_stream_info failed! err_code = %d\n", err_code);
        return -1;
    }

    int stream_type = -1;
    for (int i = 0; i < format_ctx->nb_streams; i++) {
        if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            stream_type = i;
            break;
        }
    }

    if (stream_type == -1) {
        fprintf(stderr, "[video_player] Error: NOT find a video stream. ERROR! \n");
        return -1;
    }

    AVCodec *codec = avcodec_find_decoder(format_ctx->streams[stream_type]->codecpar->codec_id);
    if (codec == NULL) {
        fprintf(stderr, "[video_player] Error: Unsupported codec. ERROR! \n");
        return -1;
    }

    AVCodecContext *avctx = avcodec_alloc_context3(codec);
    if (avctx == NULL) {
        fprintf(stderr, "[video_player] Error: Unsupported codec. ERROR! \n");
        return -1;
    }

    err_code = avcodec_parameters_to_context(avctx, format_ctx->streams[stream_type]->codecpar);
    if (err_code != 0) {
        fprintf(stderr, "[video_player] Error: avcodec_parameters_to_context\n");
        return -1;
    }

    err_code = avcodec_open2(avctx, codec, NULL);
    if (err_code != 0) {
        fprintf(stderr, "[video_player] Error: can not open the codec! ERROR! \n");
        return -1;
    }

    AVFrame *frame = av_frame_alloc();
    if (frame == NULL) {
        fprintf(stderr, "[video_player] Error: pFrame alloc fail! ERROR!\n");
        return -1;
    }

    AVPacket *raw_packet = av_packet_alloc();
    if (raw_packet == NULL) {
        fprintf(stderr, "[video_player] Error: raw_packet alloc fail!\n");
        return -1;
    }

    while (av_read_frame(format_ctx, raw_packet) >= 0) {
        if (raw_packet->stream_index != stream_type) {
            continue;
        }

        int ret = avcodec_send_packet(avctx, raw_packet);
        if (0 != ret) {
            fprintf(stderr, "[video_player] Error: avcodec_send_packet failed! ret = %d\n", ret);
            continue;
        }

        ret = avcodec_receive_frame(avctx, frame);
        if (0 != ret) {
            fprintf(stderr, "[video_player] Error: avcodec_receive_frame failed! ret = %d\n", ret);
            continue;
        }

        SDL_UpdateYUVTexture(sdl_texture, NULL,
                             frame->data[0], frame->linesize[0],
                             frame->data[1], frame->linesize[1],
                             frame->data[2], frame->linesize[2]);

        SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
        SDL_RenderPresent(sdl_renderer);
        SDL_Delay(40);
    }

	av_frame_free(&frame);
    av_packet_free(&raw_packet);
    avformat_close_input(&format_ctx);
    avcodec_close(avctx);

    SDL_Quit();

    return 0;
}
相关标签: 流媒体