mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +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 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 ByteBuffer data;
|
||||||
public long timestampUs;
|
public long timestampUs;
|
||||||
public int width;
|
public int width;
|
||||||
public int height;
|
public int height;
|
||||||
public int flags;
|
public int flags;
|
||||||
|
/**
|
||||||
|
* YUV planes for YUV mode.
|
||||||
|
*/
|
||||||
public ByteBuffer[] yuvPlanes;
|
public ByteBuffer[] yuvPlanes;
|
||||||
public int[] yuvStrides;
|
public int[] yuvStrides;
|
||||||
public int mode;
|
public int mode;
|
||||||
|
public int colorspace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from C++ through JNI after decoding is done. It will resize the
|
* 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
|
* This method is called from C++ through JNI after decoding is done. It will resize the
|
||||||
* buffer based on the given stride.
|
* 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.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
this.colorspace = colorspace;
|
||||||
int yLength = yStride * height;
|
int yLength = yStride * height;
|
||||||
int uvLength = uvStride * ((height + 1) / 2);
|
int uvLength = uvStride * ((height + 1) / 2);
|
||||||
int minimumYuvSize = yLength + (uvLength * 2);
|
int minimumYuvSize = yLength + (uvLength * 2);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,18 @@ import javax.microedition.khronos.opengles.GL10;
|
||||||
*/
|
*/
|
||||||
/* package */ class VpxRenderer implements GLSurfaceView.Renderer {
|
/* 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 =
|
private static final String VERTEX_SHADER =
|
||||||
"varying vec2 interp_tc;\n"
|
"varying vec2 interp_tc;\n"
|
||||||
+ "attribute vec4 in_pos;\n"
|
+ "attribute vec4 in_pos;\n"
|
||||||
|
|
@ -46,14 +58,13 @@ import javax.microedition.khronos.opengles.GL10;
|
||||||
+ "uniform sampler2D y_tex;\n"
|
+ "uniform sampler2D y_tex;\n"
|
||||||
+ "uniform sampler2D u_tex;\n"
|
+ "uniform sampler2D u_tex;\n"
|
||||||
+ "uniform sampler2D v_tex;\n"
|
+ "uniform sampler2D v_tex;\n"
|
||||||
|
+ "uniform mat3 mColorConversion;\n"
|
||||||
+ "void main() {\n"
|
+ "void main() {\n"
|
||||||
+ " float y = 1.164 * (texture2D(y_tex, interp_tc).r - 0.0625);\n"
|
+ " vec3 yuv;"
|
||||||
+ " float u = texture2D(u_tex, interp_tc).r - 0.5;\n"
|
+ " yuv.x = texture2D(y_tex, interp_tc).r - 0.0625;\n"
|
||||||
+ " float v = texture2D(v_tex, interp_tc).r - 0.5;\n"
|
+ " yuv.y = texture2D(u_tex, interp_tc).r - 0.5;\n"
|
||||||
+ " gl_FragColor = vec4(y + 1.596 * v, "
|
+ " yuv.z = texture2D(v_tex, interp_tc).r - 0.5;\n"
|
||||||
+ " y - 0.391 * u - 0.813 * v, "
|
+ " gl_FragColor = vec4(mColorConversion * yuv, 1.0);"
|
||||||
+ " y + 2.018 * u, "
|
|
||||||
+ " 1.0);\n"
|
|
||||||
+ "}\n";
|
+ "}\n";
|
||||||
private static final FloatBuffer TEXTURE_VERTICES = nativeFloatBuffer(
|
private static final FloatBuffer TEXTURE_VERTICES = nativeFloatBuffer(
|
||||||
-1.0f, 1.0f,
|
-1.0f, 1.0f,
|
||||||
|
|
@ -64,6 +75,7 @@ import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
private int program;
|
private int program;
|
||||||
private int texLocation;
|
private int texLocation;
|
||||||
|
private int colorMatrixLocation;
|
||||||
private FloatBuffer textureCoords;
|
private FloatBuffer textureCoords;
|
||||||
private VpxOutputBuffer outputBuffer;
|
private VpxOutputBuffer outputBuffer;
|
||||||
private int previousWidth;
|
private int previousWidth;
|
||||||
|
|
@ -108,6 +120,9 @@ import javax.microedition.khronos.opengles.GL10;
|
||||||
posLocation, 2, GLES20.GL_FLOAT, false, 0, TEXTURE_VERTICES);
|
posLocation, 2, GLES20.GL_FLOAT, false, 0, TEXTURE_VERTICES);
|
||||||
texLocation = GLES20.glGetAttribLocation(program, "in_tc");
|
texLocation = GLES20.glGetAttribLocation(program, "in_tc");
|
||||||
GLES20.glEnableVertexAttribArray(texLocation);
|
GLES20.glEnableVertexAttribArray(texLocation);
|
||||||
|
checkNoGLES2Error();
|
||||||
|
colorMatrixLocation = GLES20.glGetUniformLocation(program, "mColorConversion");
|
||||||
|
checkNoGLES2Error();
|
||||||
setupTextures();
|
setupTextures();
|
||||||
checkNoGLES2Error();
|
checkNoGLES2Error();
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +140,12 @@ import javax.microedition.khronos.opengles.GL10;
|
||||||
// Nothing to render yet.
|
// Nothing to render yet.
|
||||||
return;
|
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++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
int h = (i == 0) ? outputBuffer.height : (outputBuffer.height + 1) / 2;
|
int h = (i == 0) ? outputBuffer.height : (outputBuffer.height + 1) / 2;
|
||||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ FUNC(jlong, vpxInit) {
|
||||||
const jclass outputBufferClass = env->FindClass(
|
const jclass outputBufferClass = env->FindClass(
|
||||||
"com/google/android/exoplayer/ext/vp9/VpxOutputBuffer");
|
"com/google/android/exoplayer/ext/vp9/VpxOutputBuffer");
|
||||||
initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame",
|
initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame",
|
||||||
"(IIII)V");
|
"(IIIII)V");
|
||||||
initForRgbFrame = env->GetMethodID(outputBufferClass, "initForRgbFrame",
|
initForRgbFrame = env->GetMethodID(outputBufferClass, "initForRgbFrame",
|
||||||
"(II)V");
|
"(II)V");
|
||||||
dataField = env->GetFieldID(outputBufferClass, "data",
|
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],
|
img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
|
||||||
dst, img->d_w * 2, img->d_w, img->d_h);
|
dst, img->d_w * 2, img->d_w, img->d_h);
|
||||||
} else if (outputMode == kOutputModeYuv) {
|
} 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.
|
// resize buffer if required.
|
||||||
env->CallVoidMethod(jOutputBuffer, initForYuvFrame, img->d_w, img->d_h,
|
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.
|
// get pointer to the data buffer.
|
||||||
const jobject dataObject = env->GetObjectField(jOutputBuffer, dataField);
|
const jobject dataObject = env->GetObjectField(jOutputBuffer, dataField);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue