mirror of
https://github.com/samsonjs/media.git
synced 2026-04-13 12:35:48 +00:00
Expose and support colorspaces in LibVpx.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=109851975
This commit is contained in:
parent
e487fe6fa7
commit
0b0baa28be
3 changed files with 60 additions and 10 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue