原YUV格式的解析 Android NV21 视频采集
来源:互联网 发布:淘宝网钱包男士 编辑:程序博客网 时间:2024/05/04 08:17
最近在搞视频分析类的项目,android默认视频采集格式是NV21,Y Cr Cb格式,4.2.0.方式采样还有其他采样方式,默认使用NV21Sets the image format for preview pictures.
If this is never called, the default format will be NV21
, which uses the NV21 encoding format.
intJPEGEncoded formats.intNV16YCbCr format, used for video.intNV21YCrCb format used for images, which uses the NV21 encoding format.intRGB_565RGB format used for pictures encoded as RGB_565 see setPictureFormat(int)
.intUNKNOWN intYUY2YCbCr format used for images, which uses YUYV (YUY2) encoding format.intYV12Android YUV format: This format is exposed to software decoders and applications.具体参见http://developer.android.com/reference/android/graphics/ImageFormat.html -----------------------------------------------------------------------------------------------------------首先是其数据是怎样存储的// 我们通过下列方式获取数据class Buf implements Camera.PreviewCallback {public byte[] yuv420sp =null;public void onPreviewFrame(byte[] data, Camera camera) {// 这里出来的data和tackPic出来的有区别,这边是NV21格式yuv420sp=data;}}420这种格式采样方式如下X X X XO O X X X X
X X X XO O X X X X即每4个Y对应一个U和一个VY0U0V0 Y1 Y2U2V2 Y3Y4 Y5 Y6 Y7Y8U8V8 Y9 Y10U10V10 Y11Y12 Y13 Y14 Y15通过对采样数组的研究其存放规律是YYYYY...(采样宽度width)...YYYYY......(采样高度height)...YYYYY...(采样宽度width)...YYYYY(vu)(vu)(vu)...(采样宽度)...(vu)(vu)(vu)...(采样高度除以2,height/2,遇单加1)(vu)(vu)(vu)...(采样宽度)...(vu)(vu)(vu)即width=320,height=480,采样Y值长度320×480,采样VU长度320×480/2.yuv420sp=data;总长度为宽高乘积的一点五倍
// YUV转RGB rgb长度即width×heghtstatic public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); } }}
以上是android自带的YUV420SP转RGB的函数,但是坑爹的问题在于函数处理数据的能力有限,我们有的时候并不需要全部转完毕再解析。以下是更改后的方法,用于取值某点的RGB,在一些实时性要求的应用中可以用到// 自定义RGBstatic public int myDecodeYUV420SP(byte[] yuv420sp, int width, int height,int mWidth, int mHeight) {// Y矩阵长度frameSize , V和U矩阵第一位即frameSizefinal int frameSize = width * height;// yp为Y在矩阵中的位置,yph为所需要点的高mHeight-1,ypw为所需要点的宽mWidthint yp, yph = mHeight - 1, ypw = mWidth;yp = width * yph + ypw;// uvp为// uv在数组中的位置,V和U矩阵第一位即frameSize,yph>>1取值范围(0,0,1,1,2,2...)yph从0开始,即UV数组为Y数组的1/2.int uvp = frameSize + (yph >> 1) * width, u = 0, v = 0;// 获取Y的数值int y = (0xff & ((int) yuv420sp[yp])) - 16;if (y < 0)y = 0;if ((ypw & 1) == 0) {v = (0xff & yuv420sp[uvp++]) - 128;u = (0xff & yuv420sp[uvp]) - 128;} else {u = (0xff & yuv420sp[uvp--]) - 128;v = (0xff & yuv420sp[uvp]) - 128;}
int y1192 = 1192 * y;int r = (y1192 + 1634 * v);int g = (y1192 - 833 * v - 400 * u);int b = (y1192 + 2066 * u);
if (r < 0)r = 0;else if (r > 262143)r = 262143;if (g < 0)g = 0;else if (g > 262143)g = 262143;if (b < 0)b = 0;else if (b > 262143)b = 262143;
return (0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff));
}
两套函数出来的数据int型需要转换成r/g/b。亮点就是转换方式public static int red (int color)
Since: API Level 1Return the red component of a color int. This is the same as saying (color >> 16) & 0xFF
public static int green (int color)
Since: API Level 1Return the green component of a color int. This is the same as saying (color >> 8) & 0xFF
public static int blue (int color)
Since: API Level 1Return the blue component of a color int. This is the same as saying color & 0xFF
至此yuv取点rgb完成1 需要代码的童鞋可以留下你的email2 如果描述有误请指正3 感谢 幸福的起点 博主,更多视频格式说明请参照http://hi.baidu.com/joygogo0130/blog/item/04b707529efbec090df3e345.html4 更多视频问题 请参照http://developer.android.com/reference/android/graphics/Camera.htmlhttp://ai4work.blog.163.com/blog/static/189873306201171883316264/
Sets the image format for preview pictures.
If this is never called, the default format will be NV21
, which uses the NV21 encoding format.
setPictureFormat(int)
.intUNKNOWN intYUY2YCbCr format used for images, which uses YUYV (YUY2) encoding format.intYV12Android YUV format: This format is exposed to software decoders and applications.具体参见// 我们通过下列方式获取数据
class Buf implements Camera.PreviewCallback {
public byte[] yuv420sp =null;
public void onPreviewFrame(byte[] data, Camera camera) {
// 这里出来的data和tackPic出来的有区别,这边是NV21格式
yuv420sp=data;
}
}
X X X X
O O
X X X X
Y0U0V0 Y1 Y2U2V2 Y3
Y4 Y5 Y6 Y7
Y8U8V8 Y9 Y10U10V10 Y11
Y12 Y13 Y14 Y15
(vu)(vu)(vu)...(采样宽度)...(vu)(vu)(vu)
// YUV转RGB rgb长度即width×heght
static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;
rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
}
}
}
// 自定义RGB
static public int myDecodeYUV420SP(byte[] yuv420sp, int width, int height,
int mWidth, int mHeight) {
// Y矩阵长度frameSize , V和U矩阵第一位即frameSize
final int frameSize = width * height;
// yp为Y在矩阵中的位置,yph为所需要点的高mHeight-1,ypw为所需要点的宽mWidth
int yp, yph = mHeight - 1, ypw = mWidth;
yp = width * yph + ypw;
// uvp为
// uv在数组中的位置,V和U矩阵第一位即frameSize,yph>>1取值范围(0,0,1,1,2,2...)yph从0开始,即UV数组为Y数组的1/2.
int uvp = frameSize + (yph >> 1) * width, u = 0, v = 0;
// 获取Y的数值
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0)
y = 0;
if ((ypw & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp]) - 128;
} else {
u = (0xff & yuv420sp[uvp--]) - 128;
v = (0xff & yuv420sp[uvp]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0)
r = 0;
else if (r > 262143)
r = 262143;
if (g < 0)
g = 0;
else if (g > 262143)
g = 262143;
if (b < 0)
b = 0;
else if (b > 262143)
b = 262143;
return (0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff));
}
public static int red (int color)
Since: API Level 1
Return the red component of a color int. This is the same as saying (color >> 16) & 0xFF
public static int green (int color)
Since: API Level 1
Return the green component of a color int. This is the same as saying (color >> 8) & 0xFF
public static int blue (int color)
Since: API Level 1
Return the blue component of a color int. This is the same as saying color & 0xFF
- 原YUV格式的解析 Android NV21 视频采集
- 原YUV格式的解析 Android NV21 视频采集
- android 基于ffmpeg将视频采集的nv21转h264格式数据
- YUV格式视频的解析
- YUV格式 及 davinci视频采集格式
- YUV格式 及 davinci视频采集格式
- Android YUV使用总结之Android常用的几种格式:NV21/NV12/YV12/YUV420P的区别
- 【Android】YUV使用总结 —— Android常用的几种格式:NV21/NV12/YV12/YUV420P的区别
- 【Android】直播必备之YUV使用总结 —— 常用的几种格式:NV21/NV12/YV12/YUV420P的区别
- YUV使用总结 —— Android常用的几种格式:NV21/NV12/YV12/YUV420P的区别
- YUV格式的解析
- YUV格式的解析
- YUV格式的解析
- YUV格式的解析
- YUV格式的解析
- YUV格式的解析
- YUV格式的解析
- YUV 格式的视频呈现
- YUV420 NV12 NV21
- Oracle中start with...connect by prior子句用法
- 记,17个日夜
- Windows 下 Python easy_install 的安装---转载
- 使用Entity Data Model 之创建模型(一)
- 原YUV格式的解析 Android NV21 视频采集
- IOS 加载网络图片注意点
- linux之编写命令解释器
- 从eclipse部署liferay工程到tomcat-theme篇
- SilkTest循序渐进1-调用DLL函数
- SilkTest循序渐进2-建立SilkTest分布式测试环境
- SilkTest循序渐进3-编程规范
- Android桌面悬浮窗效果实现
- apple http live streaming 测试: 使用segmenter.exe + apache + vlc