QT ffmpeg 播放器

1.下载sdl2,ffmpeg dev


2.qt的配置

win32: LIBS += -L$$PWD/libffmpeg/lib/ -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswscale
win32: LIBS += -L$$PWD/libSDL/lib/x86/ -lSDL2 -lSDL2main

INCLUDEPATH += $$PWD/libffmpeg/include
DEPENDPATH += $$PWD/libffmpeg/include

INCLUDEPATH += $$PWD/libSDL/include
DEPENDPATH += $$PWD/libSDL/include

3.类接口源码(参考了雷博士的源码)

#ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H

#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "SDL.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <SDL2/SDL.h>
#ifdef __cplusplus
};
#endif
#endif

class VideoPlayer
{
public:
    VideoPlayer(void* hwnd);
    ~VideoPlayer();
    //init ffmpeg SDL
    static int StaticInit();
    //crate videoplayer
    static VideoPlayer * CreateNew(void *hwnd);

    //
    int OpenVideo(const char * videopath);
    //
    int Play();
    //
    int Stop();
    //
    int Pause();
    //
    int Continue();
    void test();
public:
    static bool IsStaticInit;
    AVFormatContext	*pFormatCtx;
    AVCodecContext	*pCodecCtx;
    int             videoindex;
    //--------------SDL---------
    SDL_Texture* sdlTexture;
    SDL_Renderer* sdlRenderer;
    bool             fPause;
    bool            fEndThread;

private:
    uint8_t *out_buffer;
    //AVPacket *packet;
    //------------SDL----------------
    int screen_w, screen_h;
    SDL_Window *screen;

    SDL_Rect sdlRect;
    SDL_Thread *video_tid;
    SDL_Event event;

    char  fVideoPath[512];
    void * fHwnd;
};

#endif // VIDEOPLAYER_H

#include "videoplayer.h"
#include <QDebug>

bool VideoPlayer::IsStaticInit = false;

int video_refresh_thread(void *opaque)
{
    VideoPlayer *vplayer = (VideoPlayer*)opaque;
    if(vplayer == NULL){
        return 0;
    }

    AVPacket * packet = (AVPacket *)av_malloc(sizeof(AVPacket));
    AVFrame	*pFrame, *pFrameYUV;
    int ret, got_picture;
    struct SwsContext *img_convert_ctx;

    uint8_t *out_buffer;



    pFrame = av_frame_alloc();
    pFrameYUV = av_frame_alloc();
    out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, vplayer->pCodecCtx->width, vplayer->pCodecCtx->height));
    avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, vplayer->pCodecCtx->width, vplayer->pCodecCtx->height);

    img_convert_ctx = sws_getContext(vplayer->pCodecCtx->width, vplayer->pCodecCtx->height, vplayer->pCodecCtx->pix_fmt, vplayer->pCodecCtx->width,vplayer-> pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);


    while(!vplayer->fEndThread){

        if(!vplayer->fPause){
            if (av_read_frame(vplayer->pFormatCtx, packet) >= 0) {
                if (packet->stream_index == vplayer->videoindex) {
                    ret = avcodec_decode_video2(vplayer->pCodecCtx, pFrame, &got_picture, packet);
                    if (ret < 0) {
                        printf("Decode Error.\n");
                        break;
                    }
                    if (got_picture) {
                        sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, vplayer->pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
                        //SDL---------------------------
                        SDL_UpdateTexture(vplayer->sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0]);
                        SDL_RenderClear(vplayer->sdlRenderer);
                        //SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect );
                        SDL_RenderCopy(vplayer->sdlRenderer, vplayer->sdlTexture, NULL, NULL);
                        SDL_RenderPresent(vplayer->sdlRenderer);
                        //SDL End-----------------------
                    }
                }
                av_free_packet(packet);
            }else{
                break;
            }
        }
        SDL_Delay(40);
    }
    if(vplayer->sdlRenderer)
        SDL_RenderClear(vplayer->sdlRenderer);
    sws_freeContext(img_convert_ctx);

    av_frame_free(&pFrameYUV);
    av_frame_free(&pFrame);
    vplayer->fEndThread = false;
    vplayer->fPause = false;
    return 0;
}

VideoPlayer::VideoPlayer(void *hwnd):
    fHwnd(hwnd),pFormatCtx(NULL),pCodecCtx(NULL),sdlRenderer(NULL),
    sdlTexture(NULL),video_tid(NULL),fPause(false),fEndThread(false)
{
    //03.申请context内存
    pFormatCtx = avformat_alloc_context();
}

VideoPlayer::~VideoPlayer()
{
    SDL_Quit();
    Stop();
}

int VideoPlayer::StaticInit()
{

    if(IsStaticInit){
        return 0;
    }
    IsStaticInit = true;
    //00.初始化SDL 视频、音频、定时器
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
        printf("Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }
    //01.ffpeg初始化
    av_register_all();

    //02.网络初始化
    return avformat_network_init();
}

int VideoPlayer::OpenVideo(const char *videopath)
{
    strcpy(fVideoPath, videopath);

    return 0;
}

int VideoPlayer::Play()
{


    //04.打开视频
    if (avformat_open_input(&pFormatCtx, fVideoPath, NULL, NULL) != 0) {
        printf("Couldn't open input stream.\n");
        return -1;
    }
    //05.获取视频信息
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        printf("Couldn't find stream information.\n");
        return -1;
    }
    //06.获取视频流的序号
    videoindex = -1;
    for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoindex = i;
            break;
        }
    //07.是否存在视频流
    if (videoindex == -1) {
        printf("Didn't find a video stream.\n");
        return -1;
    }
    //08.视频编码方式
    pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    AVCodec	*pCodec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL) {
        printf("Codec not found.\n");
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        printf("Could not open codec.\n");
        return -1;
    }
    //09.创建渲染器和纹理
    sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
    sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);


    video_tid = SDL_CreateThread(video_refresh_thread, NULL, (void*)this);
    return 0;
}

int VideoPlayer::Stop()
{

    if(video_tid){
        fEndThread = true;

        SDL_WaitThread(video_tid, NULL);
        video_tid = NULL;
        fEndThread = false;

    }
    if(sdlTexture){
        SDL_DestroyTexture(sdlTexture);
        sdlTexture = NULL;
    }
    if(sdlRenderer){
        SDL_RenderClear(sdlRenderer);
        SDL_DestroyRenderer(sdlRenderer);
        sdlRenderer = NULL;
    }
    if(pCodecCtx){
        avcodec_close(pCodecCtx);
        pCodecCtx = NULL;
    }
    if(pFormatCtx){
        avformat_close_input(&pFormatCtx);
        pFormatCtx = NULL;
    }

    return 0;

}

int VideoPlayer::Pause()
{
    fPause = true;
    return 0;
}

int VideoPlayer::Continue()
{
    fPause = false;
    return 0;
}

void VideoPlayer::test()
{
    SDL_Surface *sur = SDL_GetWindowSurface(screen);
    ;
    SDL_BlitSurface( SDL_LoadBMP("d:/123.bmp") , NULL ,sur ,NULL);
    SDL_UpdateWindowSurface(screen);//更新显示copy the window surface to the screen
}

VideoPlayer *VideoPlayer::CreateNew(void * hwnd)
{

    SDL_Window *screen = SDL_CreateWindowFrom(hwnd);
    if(screen){
        VideoPlayer *vplayer = new VideoPlayer(hwnd);
        vplayer->screen = screen;
        return vplayer;
    }else{
        qDebug()<<SDL_GetError();
        return NULL;
    }
}


猜你喜欢

转载自blog.csdn.net/singleroot/article/details/70230269