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();
}
网友评论