yuv的数据是视频一帧一帧的原始数据,里面并没有包含像素格式、大小,因此我们要播放yuv数据,就必须要指定像素格式、大小,否则你就不知道一帧的数据大小是多少,也就无法把yuv数据解析成一帧一帧的图像了。本文我使用的yuv数据像素格式是yuv420p
,大小是540x960
。yuv420p
格式是怎么存储的呢,它是一帧一帧依序存储的,一帧里面又是y
、u
、v
分量依序存储,y
分量的size是540*960
,u
、v
分量的size都是540*960/4
,所以一帧的数据大小就是540*960*3/2
。知道了这些信息,我们就可以取出一帧一帧的数据,再通过OpenGL就可以渲染出来了,一个简单的yuv播放器就实现了,非常简单。
NSInteger videoW = 540;
NSInteger videoH = 960;
NSUInteger frameSizeY = videoW*videoH;
NSUInteger frameSizeU = videoW*videoH/4;
NSUInteger frameSizeV = videoW*videoH/4;
NSString *yuvPath = [[NSBundle mainBundle] pathForResource:@"bb1_test.yuv" ofType:nil];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:yuvPath];
NSUInteger i = 0;
NSTimeInterval sT = NSDate.date.timeIntervalSince1970;
while (1) {
NSData *dataY = [fileHandle readDataOfLength:frameSizeY];
NSData *dataU = [fileHandle readDataOfLength:frameSizeU];
NSData *dataV = [fileHandle readDataOfLength:frameSizeV];
if (dataY.length==0 || dataV.length==0 || dataU.length==0) {
break;
}
STMVideoFrameYUV *frame = STMVideoFrameYUV.new;
frame.format = STMVideoFrameFormatYUV;
frame.width = 540;
frame.height = 960;
frame.luma = dataY.bytes;
frame.chromaB = dataU.bytes;
frame.chromaR = dataV.bytes;
[self.GLView render:frame];
NSTimeInterval cT = NSDate.date.timeIntervalSince1970;
NSTimeInterval dT = cT-sT;
NSTimeInterval tT = i/25.0;
if (dT<tT) {
[NSThread sleepForTimeInterval:tT-dT];
}
i++;
}
网友评论