美文网首页
SDL2常用代码

SDL2常用代码

作者: 何亮hook_8285 | 来源:发表于2022-12-04 22:49 被阅读0次

    SDL2渲染YUV420P数据

    提取YUV420P:ffmpeg -i a.mp4 -pix_fmt yuv420p a.yuv

    方式一

    #include <iostream>
    #include <fstream>
    #include <memory.h>
    #include <SDL2/SDL.h>
    #undef main
    //heliang
    int main()
    {
        int w=1364;
        int h=768;
        //打开yuv文件
        std::ifstream yuv_file;
        yuv_file.open("D:\\ds.yuv",std::ios::binary);
    
        //初始化SDL
        SDL_Init(SDL_INIT_VIDEO);
        //创建窗口
        SDL_Window *sdl_win=SDL_CreateWindow("test",
                                             SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,w,h,
                                             SDL_WindowFlags::SDL_WINDOW_OPENGL| SDL_WINDOW_RESIZABLE);
        //如果想绑定到QT的Widget元素中,可使用SDL_CreateWindowFrom函数
        //sdl_win=SDL_CreateWindowFrom((void*)this->ui->centralwidget->winId());
    
        //创建渲染器
        SDL_Renderer *sdl_rend=SDL_CreateRenderer(sdl_win,-1,SDL_RENDERER_ACCELERATED);
        //创建材质
        SDL_Texture *sdl_text=SDL_CreateTexture(sdl_rend,          SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMING,w,h);
    
    
    
        while(yuv_file.good())
        {
            //读取yuv文件,按照y分量,u分量,v分量读取
            int lenY=w*h;
            int lenU=w*h/4;
            int lenV=w*h/4;
            unsigned char *pYBuf = (unsigned char *)malloc(lenY);
            unsigned char *pUBuf = (unsigned char *)malloc(lenU);
            unsigned char *pVBuf = (unsigned char *)malloc(lenV);
    
            yuv_file.read((char*)pYBuf,lenY);
            yuv_file.read((char*)pUBuf,lenU);
            yuv_file.read((char*)pVBuf,lenV);
    
            SDL_Rect  rect;
            rect.x=0;
            rect.y=0;
            rect.w=w;
            rect.h=h;
            //更新材质
            SDL_UpdateYUVTexture(sdl_text, &rect, pYBuf, w, pUBuf, w / 2, pVBuf, w / 2);
            //清除渲染器
            SDL_RenderClear(sdl_rend);
            //材质和渲染器绑定
            SDL_RenderCopy(sdl_rend,sdl_text,NULL,NULL);
            //渲染器图像显示到显示器
            SDL_RenderPresent(sdl_rend);
            //销毁数据
            free(pYBuf);
            free(pUBuf);
            free(pVBuf);
        }
    
    
    
        //销毁材质(纹理)
        SDL_DestroyTexture(sdl_text);
        //销毁创建
        SDL_DestroyWindow(sdl_win);
        SDL_Quit();
    }
    

    方式二

    
    #include <iostream>
    #include <fstream>
    #include <memory.h>
    #include <SDL2/SDL.h>
    #undef main
    //heliang
    int main()
    {
        int w=1364;
        int h=768;
        //打开yuv文件
        std::ifstream yuv_file;
        yuv_file.open("D:\\ds.yuv",std::ios::binary);
    
        //初始化SDL
        SDL_Init(SDL_INIT_VIDEO);
        //创建窗口
        SDL_Window *sdl_win=SDL_CreateWindow("test",
                                             SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,w,h,
                                             SDL_WindowFlags::SDL_WINDOW_OPENGL| SDL_WINDOW_RESIZABLE);
        //如果想绑定到QT的Widget元素中,可使用SDL_CreateWindowFrom函数
        //sdl_win=SDL_CreateWindowFrom((void*)this->ui->centralwidget->winId());
    
        //创建渲染器
        SDL_Renderer *sdl_rend=SDL_CreateRenderer(sdl_win,-1,SDL_RENDERER_ACCELERATED);
        //创建材质(纹理)
        SDL_Texture *sdl_text=SDL_CreateTexture(sdl_rend,          SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMING,w,h);
    
    
    
    
        while(yuv_file.good())
        {
            //读取1帧数据
            unsigned char * yuvData=(unsigned char *)malloc(w*h*2);
            yuv_file.read((char*)yuvData,w*h*1.5);
    
            SDL_Rect rect;
            rect.x = 0;
            rect.y = 0;
            rect.w = w;
            rect.h = h;
            //更新材质(纹理)
            SDL_UpdateTexture(sdl_text, NULL, yuvData, w);
            //清除渲染器
            SDL_RenderClear(sdl_rend);
            //材质和渲染器绑定
            SDL_RenderCopy(sdl_rend,sdl_text,NULL,NULL);
            //渲染器图像显示到显示器
            SDL_RenderPresent(sdl_rend);
            //销毁数据
            free(yuvData);
        }
    
    
    
        //销毁材质(纹理)
        SDL_DestroyTexture(sdl_text);
        //销毁创建
        SDL_DestroyWindow(sdl_win);
        SDL_Quit();
    
        return 0;
    }
    

    SDL2渲染RGBA数据

    
    #include <iostream>
    #include <fstream>
    #include <memory.h>
    #include <SDL2/SDL.h>
    #undef main
    //heliang
    int main()
    {
        int w=1364;
        int h=768;
        int pix_size=4;
    
        //初始化SDL
        SDL_Init(SDL_INIT_VIDEO);
        //创建窗口
        SDL_Window *sdl_win=SDL_CreateWindow("test",
                                             SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,w,h,
                                             SDL_WindowFlags::SDL_WINDOW_OPENGL| SDL_WINDOW_RESIZABLE);
        //如果想绑定到QT的Widget元素中,可使用SDL_CreateWindowFrom函数
        //sdl_win=SDL_CreateWindowFrom((void*)this->ui->centralwidget->winId());
    
        //创建渲染器
        SDL_Renderer *sdl_rend=SDL_CreateRenderer(sdl_win,-1,SDL_RENDERER_ACCELERATED);
        //创建材质(纹理)
        SDL_Texture *sdl_text=SDL_CreateTexture(sdl_rend,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMING,w,h);
    
        unsigned char tempcount=255;
        bool  flag=true;
        while(flag)
        {
            //事件结构体 
            SDL_Event  ev;
            //获取事件
            SDL_WaitEventTimeout(&ev,10);
            //按下鼠标则退出
            if(ev.type==SDL_MOUSEBUTTONDOWN)
            {
                flag=false;
                break;
            }
            //生成一帧RGBA数据
            unsigned char * rgbaData=(unsigned char *)malloc(w*h*pix_size);
            for(int i=0;i<h;i++)
            {
                //高*宽*字节数=当前行宽度
                int b=i*w*pix_size;
                for(int j=0;j<w*pix_size;j+=pix_size)
                {
                    rgbaData[b+j]=0;//B
                    rgbaData[b+j+1]=211;  //G
                    rgbaData[b+j+2]=tempcount; //R
                    rgbaData[b+j+3]=0; //A
    
                }
            }
    
    
            //更新材质
            SDL_UpdateTexture(sdl_text, NULL, rgbaData, w*pix_size);
            //清除渲染器
            SDL_RenderClear(sdl_rend);
            //材质和渲染器绑定
            SDL_RenderCopy(sdl_rend,sdl_text,NULL,NULL);
            //渲染器图像显示到显示器
            SDL_RenderPresent(sdl_rend);
            //销毁数据
            free(rgbaData);
    
            tempcount--;
        }
    
        //销毁材质(纹理)
        SDL_DestroyTexture(sdl_text);
        //销毁创建
        SDL_DestroyWindow(sdl_win);
        SDL_Quit();
    
        return 0;
    }
    

    SDL2播放PCM音频

    // 提取PCM文件
    // ffmpeg -i input.mp4 -t 20 -codec:a pcm_s16le -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm
    // 测试PCM文件
    // ffplay -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm

    
    
    #include <iostream>
    #include <memory.h>
    #include <SDL2/SDL.h>
    #undef main
    
    
    //每次读取2帧数据,以1024采样点一帧2通道 16bit采样点为例
    #define PCM_BUFFER_SIZE (1024*2*2*2)
    
    //读取PCM数据缓存
    static  unsigned char * audioBuf=NULL;
    //目前读取的位置
    static  unsigned char * audioPos=NULL;
    //缓存结束的位置
    static  unsigned char * audioEnd=NULL;
    
    //音频回调方法
    void sdl_AudioCallback (void *userdata, Uint8 * stream,int len)
    {
        SDL_memset(stream,0,len);
        if(audioPos>=audioEnd) //数据读取完成
        {
            return;
        }
    
        // 数据够了就读预设长度,数据不够就只读部分(不够的时候剩多少就读取多少)
        int remain_buffer_len = audioEnd - audioPos;
        len = (len < remain_buffer_len) ? len : remain_buffer_len;
        // 拷贝数据到stream并调整音量
        SDL_MixAudio(stream, audioPos, len, SDL_MIX_MAXVOLUME);
    
        std::cout << "len=" << len << std::endl;
        audioPos += len;  // 移动缓存指针
    }
    
    //heliang
    int main()
    {
    
        //初始化SDL 音频
        SDL_Init(SDL_INIT_AUDIO);
    
        //设置音频参数
        SDL_AudioSpec spec;
        spec.freq=44100; //采样频率
        spec.format=AUDIO_S16SYS; //采样点格式
        spec.channels=2; //通道
        spec.silence=0; //音频缓冲静音值
        spec.samples=1024; //每次读取的采样率数量,多久产生一次回调
        spec.callback=sdl_AudioCallback; //回调方法
        spec.userdata=NULL;
    
        //打开音频设备
        if(SDL_OpenAudio(&spec,NULL))
        {
            std::cout << "open audio device error" <<std::endl;
            return 0;
        }
    
        //播放音频
        SDL_PauseAudio(0);
    
        FILE *pcmFP=fopen("d:\\BaiduNetdiskDownload\\44100_16bit_2ch.pcm","rb");
        //初始化buff
        audioBuf=(unsigned char *)malloc(PCM_BUFFER_SIZE);
    
        while(true)
        {
    
            //读取文件内容
            int readBufferLen=fread(audioBuf,1,PCM_BUFFER_SIZE,pcmFP);
            //读取长度等于0,表示未读取到内容
            if(readBufferLen==0)
            {
                break;
            }
    
            audioEnd=audioBuf+readBufferLen; // 更新buffer的结束位置
            audioPos=audioBuf;// 更新buffer的起始位置
            while(audioPos<audioEnd)
            {
                SDL_Delay(10);  // 等待PCM数据消耗
            }
        }
        //关闭pcm文件句柄
        fclose(pcmFP);
        //销毁内存数据
        free(audioBuf);
        // 关闭音频设备
        SDL_CloseAudio();
        //退出SDL
        SDL_Quit();
    }
    

    相关文章

      网友评论

          本文标题:SDL2常用代码

          本文链接:https://www.haomeiwen.com/subject/wzpmfdtx.html