Expose and support colorspaces in LibVpx.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=109851975
This commit is contained in:
anjalibh 2015-12-09 17:46:07 -08:00 committed by Oliver Woodman
parent e487fe6fa7
commit 0b0baa28be
3 changed files with 60 additions and 10 deletions

View file

@ -22,14 +22,25 @@ import java.nio.ByteBuffer;
*/
public final class VpxOutputBuffer {
public static final int COLORSPACE_UNKNOWN = 0;
public static final int COLORSPACE_BT601 = 1;
public static final int COLORSPACE_BT709 = 2;
/**
* RGB buffer for RGB mode.
*/
public ByteBuffer data;
public long timestampUs;
public int width;
public int height;
public int flags;
/**
* YUV planes for YUV mode.
*/
public ByteBuffer[] yuvPlanes;
public int[] yuvStrides;
public int mode;
public int colorspace;
/**
* This method is called from C++ through JNI after decoding is done. It will resize the
@ -51,9 +62,10 @@ public final class VpxOutputBuffer {
* This method is called from C++ through JNI after decoding is done. It will resize the
* buffer based on the given stride.
*/
public void initForYuvFrame(int width, int height, int yStride, int uvStride) {
public void initForYuvFrame(int width, int height, int yStride, int uvStride, int colorspace) {
this.width = width;
this.height = height;
this.colorspace = colorspace;
int yLength = yStride * height;
int uvLength = uvStride * ((height + 1) / 2);
int minimumYuvSize = yLength + (uvLength * 2);

View file

@ -31,6 +31,18 @@ import javax.microedition.khronos.opengles.GL10;
*/
/* package */ class VpxRenderer implements GLSurfaceView.Renderer {
private static final float[] kColorConversion601 = {
1.164f, 1.164f, 1.164f,
0.0f, -0.392f, 2.017f,
1.596f, -0.813f, 0.0f,
};
private static final float[] kColorConversion709 = {
1.164f, 1.164f, 1.164f,
0.0f, -0.213f, 2.112f,
1.793f, -0.533f, 0.0f,
};
private static final String VERTEX_SHADER =
"varying vec2 interp_tc;\n"
+ "attribute vec4 in_pos;\n"
@ -46,14 +58,13 @@ import javax.microedition.khronos.opengles.GL10;
+ "uniform sampler2D y_tex;\n"
+ "uniform sampler2D u_tex;\n"
+ "uniform sampler2D v_tex;\n"
+ "uniform mat3 mColorConversion;\n"
+ "void main() {\n"
+ " float y = 1.164 * (texture2D(y_tex, interp_tc).r - 0.0625);\n"
+ " float u = texture2D(u_tex, interp_tc).r - 0.5;\n"
+ " float v = texture2D(v_tex, interp_tc).r - 0.5;\n"
+ " gl_FragColor = vec4(y + 1.596 * v, "
+ " y - 0.391 * u - 0.813 * v, "
+ " y + 2.018 * u, "
+ " 1.0);\n"
+ " vec3 yuv;"
+ " yuv.x = texture2D(y_tex, interp_tc).r - 0.0625;\n"
+ " yuv.y = texture2D(u_tex, interp_tc).r - 0.5;\n"
+ " yuv.z = texture2D(v_tex, interp_tc).r - 0.5;\n"
+ " gl_FragColor = vec4(mColorConversion * yuv, 1.0);"
+ "}\n";
private static final FloatBuffer TEXTURE_VERTICES = nativeFloatBuffer(
-1.0f, 1.0f,
@ -64,6 +75,7 @@ import javax.microedition.khronos.opengles.GL10;
private int program;
private int texLocation;
private int colorMatrixLocation;
private FloatBuffer textureCoords;
private VpxOutputBuffer outputBuffer;
private int previousWidth;
@ -108,6 +120,9 @@ import javax.microedition.khronos.opengles.GL10;
posLocation, 2, GLES20.GL_FLOAT, false, 0, TEXTURE_VERTICES);
texLocation = GLES20.glGetAttribLocation(program, "in_tc");
GLES20.glEnableVertexAttribArray(texLocation);
checkNoGLES2Error();
colorMatrixLocation = GLES20.glGetUniformLocation(program, "mColorConversion");
checkNoGLES2Error();
setupTextures();
checkNoGLES2Error();
}
@ -125,6 +140,12 @@ import javax.microedition.khronos.opengles.GL10;
// Nothing to render yet.
return;
}
// Set color matrix. Assume BT709 if the color space is unknown.
float[] colorConversion = outputBuffer.colorspace == VpxOutputBuffer.COLORSPACE_BT601
? kColorConversion601 : kColorConversion709;
GLES20.glUniformMatrix3fv(colorMatrixLocation, 1, false, colorConversion, 0);
for (int i = 0; i < 3; i++) {
int h = (i == 0) ? outputBuffer.height : (outputBuffer.height + 1) / 2;
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);

View file

@ -71,7 +71,7 @@ FUNC(jlong, vpxInit) {
const jclass outputBufferClass = env->FindClass(
"com/google/android/exoplayer/ext/vp9/VpxOutputBuffer");
initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame",
"(IIII)V");
"(IIIII)V");
initForRgbFrame = env->GetMethodID(outputBufferClass, "initForRgbFrame",
"(II)V");
dataField = env->GetFieldID(outputBufferClass, "data",
@ -128,9 +128,26 @@ FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) {
img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
dst, img->d_w * 2, img->d_w, img->d_h);
} else if (outputMode == kOutputModeYuv) {
const int kColorspaceUnknown = 0;
const int kColorspaceBT601 = 1;
const int kColorspaceBT709 = 2;
int colorspace = kColorspaceUnknown;
switch (img->cs) {
case VPX_CS_BT_601:
colorspace = kColorspaceBT601;
break;
case VPX_CS_BT_709:
colorspace = kColorspaceBT709;
break;
default:
break;
}
// resize buffer if required.
env->CallVoidMethod(jOutputBuffer, initForYuvFrame, img->d_w, img->d_h,
img->stride[VPX_PLANE_Y], img->stride[VPX_PLANE_U]);
img->stride[VPX_PLANE_Y], img->stride[VPX_PLANE_U],
colorspace);
// get pointer to the data buffer.
const jobject dataObject = env->GetObjectField(jOutputBuffer, dataField);