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

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;
}

猜你喜欢

转载自blog.csdn.net/tech2ipo/article/details/89574637