Android视频编码——RGBARGBBGRABGR转YUV420PYUV420SP
Posted 湖广午王
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android视频编码——RGBARGBBGRABGR转YUV420PYUV420SP相关的知识,希望对你有一定的参考价值。
做视频处理一般都会涉及到RGBA与YUV颜色格式的相互转换,理论知识就不多说了,直接贴出转换公式来:
Y’= 0.299*R’ + 0.587*G’ + 0.114*B’
U’= -0.147*R’ - 0.289*G’ + 0.436*B’ = 0.492*(B’- Y’)
V’= 0.615*R’ - 0.515*G’ - 0.100*B’ = 0.877*(R’- Y’)
R’ = Y’ + 1.140*V’
G’ = Y’ - 0.394*U’ - 0.581*V’
B’ = Y’ + 2.032*U’
根据公式,写出相应的代码就OK了。当然编码需要考虑效率问题,在转换运算中应该尽量避免浮点运算。以下代码实现相对简介,效率也还可以,如果需要更高的转换效率,可以用空间换时间,采用查表法来做。如果有更好的方法,希望可以指点我一下,感激不尽。
JNI实现代码如下:
#include "jni.h"
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define y(r,g,b) (((66 * r + 129 * g + 25 * b + 128) >> 8) + 16)
#define u(r,g,b) (((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128)
#define v(r,g,b) (((112 * r - 94 * g - 18 * b + 128) >> 8) + 128)
#define color(x) ((unsigned char)((x < 0) ? 0 : ((x > 255) ? 255 : x)))
#define RGBA_YUV420SP 0x00004012
#define BGRA_YUV420SP 0x00004210
#define RGBA_YUV420P 0x00014012
#define BGRA_YUV420P 0x00014210
#define RGB_YUV420SP 0x00003012
#define RGB_YUV420P 0x00013012
#define BGR_YUV420SP 0x00003210
#define BGR_YUV420P 0x00013210
/**
* type 0-3位表示b的偏移量
* 4-7位表示g的偏移量
* 8-11位表示r的偏移量
* 12-15位表示rgba一个像素所占的byte
* 16-19位表示yuv的类型,0为420sp,1为420p
*/
void rgbaToYuv(int width,int height,unsigned char * rgb,unsigned char * yuv,int type)
const int frameSize = width * height;
const int yuvType=(type&0x10000)>>16;
const int byteRgba=(type&0x0F000)>>12;
const int rShift=(type&0x00F00)>>8;
const int gShift=(type&0x000F0)>>4;
const int bShift= (type&0x0000F);
const int uIndex=0;
const int vIndex=yuvType; //yuvType为1表示YUV420p,为0表示420sp
int yIndex = 0;
int uvIndex[2]=frameSize,frameSize+frameSize/4;
unsigned char R, G, B, Y, U, V;
unsigned int index = 0;
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
index = j * width + i;
R = rgb[index*byteRgba+rShift]&0xFF;
G = rgb[index*byteRgba+gShift]&0xFF;
B = rgb[index*byteRgba+bShift]&0xFF;
Y = y(R,G,B);
U = u(R,G,B);
V = v(R,G,B);
yuv[yIndex++] = color(Y);
if (j % 2 == 0 && index % 2 == 0)
yuv[uvIndex[uIndex]++] =color(U);
yuv[uvIndex[vIndex]++] =color(V);
extern "C"
void Java_com_aiya_jni_DataConvert_rgbaToYuv
(JNIEnv * env, jobject obj, jbyteArray rgba, jint width, jint height,
jbyteArray yuv,jint type)
jbyte * rgbaBuffer = env->GetByteArrayElements(rgba,0);
unsigned char * cRgba=(unsigned char *)rgbaBuffer;
jbyte* yuvBuffer = env->GetByteArrayElements(yuv,0);
unsigned char * cYuv=(unsigned char *)yuvBuffer;
rgbaToYuv(width,height,cRgba,cYuv,type);
env->ReleaseByteArrayElements(rgba, rgbaBuffer, 0);
env->ReleaseByteArrayElements(yuv, yuvBuffer, 0);
以上是关于Android视频编码——RGBARGBBGRABGR转YUV420PYUV420SP的主要内容,如果未能解决你的问题,请参考以下文章
研究Android音视频-3-在Android设备上采集音视频并使用MediaCodec编码为H.264