• SDL2:封装媒体显示播放Csdl2


    Github

    https://github.com/gongluck/SDL2-study/tree/master/Csdl2

    Csdl2.h

    #ifndef __CSDL2_H__
    #define __CSDL2_H__
    
    #include <SDL.h>
    #include <string>
    #include <mutex>
    
    class Csdl2
    {
    public:
        // 状态
        enum STATUS { STOP = 0b00, LOCKEDV = 0b01, LOCKEDA = 0b10, LOCKEDBOTH = 0b11 };
    
        // 全局的初始化
        bool global_init(Uint32 flags, std::string& err);
        // 全局的反初始化
        bool global_uninit(std::string& err);
    
        // 设置(windows)窗口
        bool set_window(const void* hwnd, std::string& err);
        // 设置图像格式(SDL_PIXELFORMAT_???)
        bool set_pix_fmt(Uint32 fmt, int w, int h, std::string& err);
        // 渲染数据,pitch是图像一行的字节大小,rect是渲染目标矩形,angle旋转角度,center旋转中心(在rect,{0,0}为左上),flip翻转
        bool render(const void* data, int pitch, const SDL_Rect* rect, 
            const double angle, const SDL_Point* center, const SDL_RendererFlip flip, std::string& err);
        // 清理图像格式资源
        bool clear_pix_fmt(std::string& err);
        // 销毁关联资源
        bool detach_window(std::string& err);
    
        // 设置音频格式和处理回调
        bool set_audio_fmt(int freq, SDL_AudioFormat fmt, Uint8 channels, Uint16 samples, SDL_AudioCallback callback, void* userdata, std::string& err);
        // 开始音频播放
        bool start_audio(std::string& err);
        // 停止音频播放
        bool stop_audio(std::string& err);
    
    private:
        STATUS status_ = STOP;
        std::recursive_mutex mutex_;
    
        SDL_Window* win_ = nullptr;
        SDL_Renderer* renderer_ = nullptr;
        SDL_Texture* texture_ = nullptr;
    
        SDL_AudioSpec reqspec_ = { 0 };
        SDL_AudioSpec recspec_ = { 0 };
    };
    
    #endif//__CSDL2_H__
    

    Csdl2.cpp

    #include "Csdl2.h"
    
    // 递归锁
    #define LOCKCSDL2() std::lock_guard<std::recursive_mutex> _lock(this->mutex_)
    
    // 检查停止状态
    #define CHECKCSDL2STOP(err) 
    if(this->status_ != STOP)
    {
        err = "status is not stop.";
        return false;
    }
    // 检查视频停止
    #define CHECKCSDL2STOPV(err) 
    if(this->status_ & 1 != 0)
    {
        err = "statusv is not stop.";
        return false;
    }
    // 检查音频停止
    #define CHECKCSDL2STOPA(err) 
    if((this->status_ >> 1) & 1 != 0)
    {
        err = "statusa is not stop.";
        return false;
    }
    // 检查视频未停止
    #define CHECKCSDL2NSTOPV(err) 
    if(this->status_ & 1 == 0)
    {
        err = "statusv is stop.";
        return false;
    }
    // 检查音频未停止
    #define CHECKCSDL2NSTOPA(err) 
    if((this->status_ >> 1) & 1 == 0)
    {
        err = "statusa is stop.";
        return false;
    }
    
    // 返回成功
    #define OPTSUCCEED()
    {
        err = "opt succeed.";
        return true;
    }
    
    // 返回失败
    #define OPTFAILED()
    {
        err = SDL_GetError();
        return false;
     }
    
    // 判断结果,并返回(必定退出函数!!!)
    #define CHECKSDLRET(ret)
    if(ret == 0)
    {
        OPTSUCCEED();
    }
    else
    {
        OPTFAILED();
    }
    
    bool Csdl2::global_init(Uint32 flags, std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2STOP(err);
        if (SDL_Init(flags) < 0)
        {
            OPTFAILED();
        }
        else
        {
            OPTSUCCEED();
        }
    }
    
    bool Csdl2::global_uninit(std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2STOP(err);
        SDL_Quit();
        OPTSUCCEED();
    }
    
    bool Csdl2::set_window(const void* hwnd, std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2STOPV(err);
        detach_window(err);
        win_ = SDL_CreateWindowFrom(hwnd);
        if (win_ != nullptr)
        {
            renderer_ = SDL_CreateRenderer(win_, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            if (renderer_ != nullptr)
            {
                OPTSUCCEED();
            }
            else
            {
                std::string e;
                detach_window(e);
                OPTFAILED();
            }
        }
        else
        {
            OPTFAILED();
        }
    }
    
    bool Csdl2::set_pix_fmt(Uint32 fmt, int w, int h, std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2STOPV(err);
        clear_pix_fmt(err);
        if (renderer_ == nullptr)
        {
            err = "renderer is nullptr.";
            return false;
        }
        texture_ = SDL_CreateTexture(renderer_, fmt, SDL_TEXTUREACCESS_STREAMING, w, h);
        if (texture_ != nullptr)
        {
            status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) | LOCKEDV);
            OPTSUCCEED();
        }
        else
        {
            OPTFAILED();
        }
    }
    
    bool Csdl2::render(const void* data, int pitch, const SDL_Rect* rect, 
        const double angle, const SDL_Point* center, const SDL_RendererFlip flip, 
        std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2NSTOPV(err);
        if (texture_ == nullptr || renderer_ == nullptr)
        {
            err = texture_ == nullptr ? "texture is nullptr." : "renderer is nullptr.";
            return false;
        }
        if (SDL_UpdateTexture(texture_, nullptr, data, pitch) != 0)
        {
            OPTFAILED();
        }
        else
        {
            if (SDL_RenderClear(renderer_) != 0)
            {
                OPTFAILED();
            }
            else
            {
                if (SDL_RenderCopyEx(renderer_, texture_, nullptr, rect, angle, center, flip) != 0)
                {
                    OPTFAILED();
                }
                else
                {
                    SDL_RenderPresent(renderer_);
                    OPTSUCCEED();
                }
            }
        }
    }
    
    bool Csdl2::clear_pix_fmt(std::string& err)
    {
        LOCKCSDL2();
        if (texture_ != nullptr)
        {
            SDL_DestroyTexture(texture_);
            texture_ = nullptr;
        }
        status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) & ~LOCKEDV);
        OPTSUCCEED();
    }
    
    bool Csdl2::detach_window(std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2STOPV(err);
        if (renderer_ != nullptr)
        {
            SDL_DestroyRenderer(renderer_);
            renderer_ = nullptr;
        }
        if (win_ != nullptr)
        {
            SDL_DestroyWindow(win_);
            win_ = nullptr;
        }
        OPTSUCCEED();
    }
    
    bool Csdl2::set_audio_fmt(int freq, SDL_AudioFormat fmt, Uint8 channels, Uint16 samples, SDL_AudioCallback callback, void* userdata, std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2STOPA(err);
        reqspec_ = { 0 };
        recspec_ = { 0 };
        reqspec_.freq = freq;
        reqspec_.format = fmt;
        reqspec_.channels = channels;
        reqspec_.samples = samples;
        reqspec_.callback = callback;
        reqspec_.userdata = userdata;
        if (SDL_OpenAudio(&reqspec_, &recspec_) != 0)
        {
            OPTFAILED();
        }
        else
        {
            status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) | LOCKEDA);
            OPTSUCCEED();
        }
    }
    
    bool Csdl2::start_audio(std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2NSTOPA(err);
        SDL_PauseAudio(0);
        OPTSUCCEED();
    }
    
    bool Csdl2::stop_audio(std::string& err)
    {
        LOCKCSDL2();
        CHECKCSDL2NSTOPA(err);
        SDL_PauseAudio(1);
        status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) & ~LOCKEDA);
        OPTSUCCEED();
    }
    

    测试

    #include "Csdl2.h"
    #include <iostream>
    #include <fstream>
    #include <Windows.h>
    
    #define TESTCHECKRET(ret)
    if(!ret)
    {
        std::cerr << err << std::endl;
        std::cout << "input to end." << std::endl;
        getchar();
        return SDL_Error(SDL_LASTERROR);
    }
    
    Csdl2 g_test;
    void SDLCALL SDL_AudioCB(void* userdata, Uint8* stream, int len)
    {
        static std::ifstream f("in.pcm", std::ios::binary);
        SDL_memset(stream, 0, len);
        void* buf = malloc(len);
        f.read((char*)buf, len);
        SDL_MixAudio(stream, (const Uint8*)buf, len, SDL_MIX_MAXVOLUME);
        free(buf);
        if (f.eof())
        {
            std::cout << "end" << std::endl;
            f.close();
            std::string err;
            g_test.stop_audio(err);
        }    
    }
    
    int main(int argc, char* argv[])
    {
        std::string err;
        RECT rect = { 0 };
        SDL_Point p = { 0, 50 };
        std::ifstream file("in.rgb", std::ios::binary);
        if (!file.is_open())
        {
            std::cerr << "open file failed " << std::endl;
            getchar();
            return 0;
        }
        int size = 320 * 240 * 3;
        void* buf = malloc(size);
    
        file.read(static_cast<char*>(buf), size);
    
        TESTCHECKRET(g_test.global_init(SDL_INIT_VIDEO | SDL_INIT_AUDIO, err));
    
        HWND hwnd = CreateWindow(TEXT("static"), TEXT("test csdl2"), WS_VISIBLE,
            CW_USEDEFAULT, CW_USEDEFAULT, 800, 500, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
        //SDL_Window* hwnd = SDL_CreateWindow("test csdl2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_SHOWN);
        if (hwnd == nullptr)
        {
            std::cerr << "create window failed " << GetLastError() << std::endl;
            goto END;
        }
        TESTCHECKRET(g_test.set_window(hwnd, err));
        TESTCHECKRET(g_test.set_pix_fmt(SDL_PIXELFORMAT_RGB24, 320, 240, err));
        TESTCHECKRET(g_test.render(buf, size / 240, nullptr, 2, &p, SDL_FLIP_NONE, err));
        std::cout << "render succeed." << std::endl;
    
        TESTCHECKRET(g_test.set_audio_fmt(44100, AUDIO_F32, 2, 1024, SDL_AudioCB, nullptr, err));
        TESTCHECKRET(g_test.start_audio(err));
        std::cout << "open audio succeed." << std::endl;
    
    END:
        std::cout << "input to end." << std::endl;
        getchar();
        TESTCHECKRET(g_test.clear_pix_fmt(err));
        TESTCHECKRET(g_test.detach_window(err));
        if (hwnd != nullptr)
        {
            DestroyWindow(hwnd);
            hwnd = nullptr;
        }
        TESTCHECKRET(g_test.stop_audio(err));
        TESTCHECKRET(g_test.global_uninit(err));
        if (buf != nullptr)
        {
            free(buf);
            buf = nullptr;
        }
        return 0;
    }
    
  • 相关阅读:
    Token验证(JWT)JwtUtil工具类 (2)
    iOS UIScrollView基本用法和代理方法
    iOS UIButton左文字右图片,上图片下文字
    iOS-源代码管理工具(SVN)
    iOS-源代码管理工具(Git)
    ios 状态栏statusBar的背景颜色
    iOS 开发中常用的排序(冒泡、选择、快速、插入、希尔、归并、基数)算法
    iOS开发设置View某个角为圆角
    [已解决]Xcode编译项目最后失败:Error: Jar file buglySymboliOS.jar was not found. Please copy the jar file into ~/bin folder
    TableView滚动、自动收起键盘
  • 原文地址:https://www.cnblogs.com/gongluck/p/11066398.html
Copyright © 2020-2023  润新知