创建测试文件
// 将mp4转yuv
ffmpeg -i hello.mp4 hello.yuv
// 输出内容如下:
[mov,mp4,m4a,3gp,3g2,mj2 @ 000001a216228800] overread end of atom 'colr' by 1 bytes
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'hello.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf55.33.100
copyright :
copyright-eng :
Duration: 00:00:32.60, start: 0.000000, bitrate: 2160 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 720x1280, 2102 kb/s, 30 fps, 30 tbr, 12800 tbn, 25600 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 48 kb/s (default)
Metadata:
handler_name : SoundHandler
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> rawvideo (native))
Press [q] to stop, [?] for help
Output #0, rawvideo, to 'hello.yuv':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
copyright-eng :
copyright :
encoder : Lavf58.45.100
Stream #0:0(und): Video: rawvideo (I420 / 0x30323449), yuv420p, 720x1280, q=2-31, 331776 kb/s, 30 fps, 30 tbn, 30 tbc (default)
Metadata:
handler_name : VideoHandler
encoder : Lavc58.91.100 rawvideo
frame= 978 fps=185 q=-0.0 Lsize= 1320300kB time=00:00:32.60 bitrate=331776.0kbits/s speed=6.17x
video:1320300kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
// 测试播放
ffplay -s 720x1280 -pix_fmt yuv420p hello.yuv
代码实现
#define IMAGE_WIDTH 720
#define IMAGE_HEIGHT 1280
int ret = SDL_Init(SDL_INIT_VIDEO);
if(ret){
qDebug() << "SDL_Init error" << SDL_GetError();
return;
}
SDL_Window * _window = SDL_CreateWindow("SDL显示YUV文件",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
IMAGE_WIDTH,
IMAGE_HEIGHT,
SDL_WINDOW_SHOWN);
if(!_window){
qDebug() << "SDL_CreateWindow error" << SDL_GetError();
SDL_Quit();
return;
}
SDL_Renderer * _renderer = SDL_CreateRenderer(_window,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(!_renderer){
qDebug() << "SDL_CreateRenderer error" << SDL_GetError();
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
SDL_Texture * _texture = SDL_CreateTexture(_renderer,SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMING,IMAGE_WIDTH,IMAGE_HEIGHT);
if(!_texture){
qDebug() << "SDL_CreateTexture error" << SDL_GetError();
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
char * file_name = "../../resources/output.yuv";
QFile file(file_name);
if(!file.open(QFile::ReadOnly)){
qDebug() << "file open error" << file_name;
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
const int data_size = 1280*720 *1.5;
char buffers [data_size] = {0};
while (file.read(buffers,data_size) > 0) {
ret = SDL_UpdateTexture(_texture,nullptr,buffers,IMAGE_WIDTH);
if(ret){
qDebug() << "SDL_UpdateTexture error" << SDL_GetError();
file.close();
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
ret = SDL_SetRenderDrawColor(_renderer,0,0,0,SDL_ALPHA_OPAQUE);
if(ret){
qDebug() << "SDL_SetRenderDrawColor error" << SDL_GetError();
file.close();
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
ret = SDL_RenderClear(_renderer);
if(ret){
qDebug() << "SDL_RenderClear error" << SDL_GetError();
file.close();
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
ret = SDL_RenderCopy(_renderer,_texture,nullptr,nullptr);
if(ret){
qDebug() << "SDL_RenderCopy error" << SDL_GetError();
file.close();
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();
return;
}
SDL_RenderPresent(_renderer);
SDL_Delay(1000/30);
}
file.close();
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
SDL_Quit();