提交 7b9a9379 编写于 作者: Z Zhang Rui

ios/GLES2: share common GLES2 renderer

上级 6cb2c056
......@@ -48,13 +48,15 @@
<string-array name="pref_entries_pixel_format">
<item>Auto Select</item>
<item>RGB 565</item>
<item>RGB 888X</item>
<item>RGB 888</item>
<item>RGBX 8888</item>
<item>YV12</item>
<item>OpenGL ES2</item>
</string-array>
<string-array name="pref_entry_values_pixel_format">
<item></item>
<item>fcc-rv16</item>
<item>fcc-rv24</item>
<item>fcc-rv32</item>
<item>fcc-yv12</item>
<item>fcc-_es2</item>
......@@ -62,7 +64,8 @@
<string-array name="pref_entry_summaries_pixel_format">
<item>Auto Select</item>
<item>RGB 565</item>
<item>RGB 888X</item>
<item>RGB 888</item>
<item>RGBX 8888</item>
<item>YV12</item>
<item>OpenGL ES2</item>
</string-array>
......
......@@ -40,9 +40,11 @@ LOCAL_SRC_FILES += ijksdl_vout.c
LOCAL_SRC_FILES += gles2/color.c
LOCAL_SRC_FILES += gles2/common.c
LOCAL_SRC_FILES += gles2/renderer.c
LOCAL_SRC_FILES += gles2/renderer_rgb.c
LOCAL_SRC_FILES += gles2/renderer_yuv420p.c
LOCAL_SRC_FILES += gles2/renderer_yuv444p10le.c
LOCAL_SRC_FILES += gles2/shader.c
LOCAL_SRC_FILES += gles2/fsh/rgb.fsh.c
LOCAL_SRC_FILES += gles2/fsh/yuv420p.fsh.c
LOCAL_SRC_FILES += gles2/fsh/yuv444p10le.fsh.c
LOCAL_SRC_FILES += gles2/vsh/mvp.vsh.c
......
......@@ -165,17 +165,29 @@ static int func_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay)
switch(overlay->format) {
case SDL_FCC__AMC: {
// only ANativeWindow support
IJK_EGL_terminate(opaque->egl);
return SDL_VoutOverlayAMediaCodec_releaseFrame_l(overlay, NULL, true);
}
case SDL_FCC_YV12:
case SDL_FCC_RV24:
case SDL_FCC_I420:
case SDL_FCC_I444P10LE:
case SDL_FCC_I444P10LE: {
// only GLES support
if (opaque->egl)
return IJK_EGL_display(opaque->egl, native_window, overlay);
break;
}
case SDL_FCC_YV12:
case SDL_FCC_RV16:
case SDL_FCC_RV32: {
// both GLES & ANativeWindow support
if (vout->overlay_format == SDL_FCC__GLES2 && opaque->egl)
return IJK_EGL_display(opaque->egl, native_window, overlay);
break;
}
}
// fallback to ANativeWindow
IJK_EGL_terminate(opaque->egl);
return SDL_Android_NativeWindow_display_l(native_window, overlay);
}
......
......@@ -38,7 +38,5 @@ static const GLfloat g_bt601[] = {
};
const GLfloat *IJK_GLES2_getColorMatrix_bt601()
{
return g_bt709;
return g_bt601;
}
/*
* IJKSDLGLShader.m
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
* copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
......@@ -22,19 +18,20 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "IJKSDLGLShader.h"
//////////////////////////////////////////////////////////
#include "ijksdl/gles2/internal.h"
#pragma mark - shaders
NSString *const rgbFragmentShaderString = IJK_SHADER_STRING
(
varying highp vec2 v_texcoord;
uniform sampler2D s_texture;
static const char g_shader[] = IJK_GLES_STRING(
precision highp float;
varying highp vec2 vv2_Texcoord;
uniform lowp sampler2D us2_SamplerX;
void main()
{
gl_FragColor = texture2D(s_texture, v_texcoord);
gl_FragColor = vec4(texture2D(us2_SamplerX, vv2_Texcoord).rgb, 1);
}
);
const char *IJK_GLES2_getFragmentShader_rgb()
{
return g_shader;
}
/*
* IJKSDLGLRenderNV12.h
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
* copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
......@@ -20,11 +18,28 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import <CoreVideo/CoreVideo.h>
#import "IJKSDLGLRender.h"
#include "ijksdl/gles2/internal.h"
static const char g_shader[] = IJK_GLES_STRING(
precision highp float;
varying highp vec2 vv2_Texcoord;
uniform mat3 um3_ColorConversion;
uniform lowp sampler2D us2_SamplerX;
uniform lowp sampler2D us2_SamplerY;
@interface IJKSDLGLRenderNV12 : NSObject<IJKSDLGLRender>
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
-(id)initWithTextureCache:(CVOpenGLESTextureCacheRef) textureCache;
yuv.x = (texture2D(us2_SamplerX, vv2_Texcoord).r - (16.0 / 255.0));
yuv.yz = (texture2D(us2_SamplerY, vv2_Texcoord).rg - vec2(0.5, 0.5));
rgb = um3_ColorConversion * yuv;
gl_FragColor = vec4(rgb, 1);
}
);
@end
const char *IJK_GLES2_getFragmentShader_yuv420sp()
{
return g_shader;
}
......@@ -32,6 +32,48 @@
#define IJK_GLES_STRINGIZE2(x) IJK_GLES_STRINGIZE(x)
#define IJK_GLES_STRING(x) IJK_GLES_STRINGIZE2(x)
typedef struct IJK_GLES2_Renderer_Opaque IJK_GLES2_Renderer_Opaque;
typedef struct IJK_GLES2_Renderer
{
IJK_GLES2_Renderer_Opaque *opaque;
GLuint program;
GLuint vertex_shader;
GLuint fragment_shader;
GLuint plane_textures[IJK_GLES2_MAX_PLANE];
GLuint av4_position;
GLuint av2_texcoord;
GLuint um4_mvp;
GLuint us2_sampler[IJK_GLES2_MAX_PLANE];
GLuint um3_color_conversion;
GLboolean (*func_use)(IJK_GLES2_Renderer *renderer);
GLsizei (*func_getBufferWidth)(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay);
GLboolean (*func_uploadTexture)(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay);
GLvoid (*func_destroy)(IJK_GLES2_Renderer *renderer);
GLsizei buffer_width;
GLsizei visible_width;
GLfloat texcoords[8];
GLfloat vertices[8];
int vertices_changed;
int format;
int gravity;
GLsizei layer_width;
GLsizei layer_height;
int frame_width;
int frame_height;
int frame_sar_num;
int frame_sar_den;
} IJK_GLES2_Renderer;
typedef struct IJK_GLES_Matrix
{
GLfloat m[16];
......@@ -41,6 +83,8 @@ void IJK_GLES2_loadOrtho(IJK_GLES_Matrix *matrix, GLfloat left, GLfloat right, G
const char *IJK_GLES2_getVertexShader_default();
const char *IJK_GLES2_getFragmentShader_yuv420p();
const char *IJK_GLES2_getFragmentShader_yuv444p10le();
const char *IJK_GLES2_getFragmentShader_yuv420sp();
const char *IJK_GLES2_getFragmentShader_rgb();
const GLfloat *IJK_GLES2_getColorMatrix_bt709();
const GLfloat *IJK_GLES2_getColorMatrix_bt601();
......@@ -48,5 +92,10 @@ const GLfloat *IJK_GLES2_getColorMatrix_bt601();
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_base(const char *fragment_shader_source);
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv420p();
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv444p10le();
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv420sp();
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv420sp_vtb(SDL_VoutOverlay *overlay);
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_rgb565();
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_rgb888();
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_rgbx8888();
#endif
......@@ -35,7 +35,7 @@ static void IJK_GLES2_printProgramInfo(GLuint program)
char buf_stack[32];
char *buf_heap = NULL;
char *buf = buf_stack;
size_t buf_len = sizeof(buf_stack) - 1;
GLsizei buf_len = sizeof(buf_stack) - 1;
if (info_len > sizeof(buf_stack)) {
buf_heap = (char*) malloc(info_len + 1);
if (buf_heap) {
......@@ -51,7 +51,7 @@ static void IJK_GLES2_printProgramInfo(GLuint program)
free(buf_heap);
}
void IJK_GLES2_Render_reset(IJK_GLES2_Renderer *renderer)
void IJK_GLES2_Renderer_reset(IJK_GLES2_Renderer *renderer)
{
if (!renderer)
return;
......@@ -77,6 +77,9 @@ void IJK_GLES2_Renderer_free(IJK_GLES2_Renderer *renderer)
if (!renderer)
return;
if (renderer->func_destroy)
renderer->func_destroy(renderer);
#if 0
if (renderer->vertex_shader) ALOGW("[GLES2] renderer: vertex_shader not deleted.\n");
if (renderer->fragment_shader) ALOGW("[GLES2] renderer: fragment_shader not deleted.\n");
......@@ -155,25 +158,39 @@ IJK_GLES2_Renderer *IJK_GLES2_Renderer_create(SDL_VoutOverlay *overlay)
IJK_GLES2_printString("Renderer", GL_RENDERER);
IJK_GLES2_printString("Extensions", GL_EXTENSIONS);
IJK_GLES2_Renderer *renderer = NULL;
switch (overlay->format) {
case SDL_FCC_YV12: return IJK_GLES2_Renderer_create_yuv420p();
case SDL_FCC_I420: return IJK_GLES2_Renderer_create_yuv420p();
case SDL_FCC_I444P10LE: return IJK_GLES2_Renderer_create_yuv444p10le();
default: return NULL;
case SDL_FCC_RV16: renderer = IJK_GLES2_Renderer_create_rgb565(); break;
case SDL_FCC_RV24: renderer = IJK_GLES2_Renderer_create_rgb888(); break;
case SDL_FCC_RV32: renderer = IJK_GLES2_Renderer_create_rgbx8888(); break;
#ifdef __APPLE__
case SDL_FCC_NV12: renderer = IJK_GLES2_Renderer_create_yuv420sp(); break;
case SDL_FCC__VTB: renderer = IJK_GLES2_Renderer_create_yuv420sp_vtb(overlay); break;
#endif
case SDL_FCC_YV12: renderer = IJK_GLES2_Renderer_create_yuv420p(); break;
case SDL_FCC_I420: renderer = IJK_GLES2_Renderer_create_yuv420p(); break;
case SDL_FCC_I444P10LE: renderer = IJK_GLES2_Renderer_create_yuv444p10le(); break;
default:
ALOGE("[GLES2] unknown format %4s(%d)", (char *)&overlay->format, overlay->format);
return NULL;
}
renderer->format = overlay->format;
return renderer;
}
GLboolean IJK_GLES2_Renderer_isValid(IJK_GLES2_Renderer *renderer)
{
return renderer && renderer->program;
return renderer && renderer->program ? GL_TRUE : GL_FALSE;
}
static const GLfloat g_vertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
GLboolean IJK_GLES2_Renderer_isFormat(IJK_GLES2_Renderer *renderer, int format)
{
if (!IJK_GLES2_Renderer_isValid(renderer))
return GL_FALSE;
return renderer->format == format ? GL_TRUE : GL_FALSE;
}
/*
* Per-Context routine
......@@ -188,6 +205,103 @@ GLboolean IJK_GLES2_Renderer_setupGLES()
return GL_TRUE;
}
static void IJK_GLES2_Renderer_Vertices_reset(IJK_GLES2_Renderer *renderer)
{
renderer->vertices[0] = -1.0f;
renderer->vertices[1] = -1.0f;
renderer->vertices[2] = 1.0f;
renderer->vertices[3] = -1.0f;
renderer->vertices[4] = -1.0f;
renderer->vertices[5] = 1.0f;
renderer->vertices[6] = 1.0f;
renderer->vertices[7] = 1.0f;
}
static void IJK_GLES2_Renderer_Vertices_apply(IJK_GLES2_Renderer *renderer)
{
switch (renderer->gravity) {
case IJK_GLES2_GRAVITY_RESIZE_ASPECT:
break;
case IJK_GLES2_GRAVITY_RESIZE_ASPECT_FILL:
break;
case IJK_GLES2_GRAVITY_RESIZE:
IJK_GLES2_Renderer_Vertices_reset(renderer);
return;
default:
ALOGE("[GLES2] unknown gravity %d\n", renderer->gravity);
IJK_GLES2_Renderer_Vertices_reset(renderer);
return;
}
if (renderer->layer_width <= 0 ||
renderer->layer_height <= 0 ||
renderer->frame_width <= 0 ||
renderer->frame_height <= 0)
{
ALOGE("[GLES2] invalid width/height for gravity aspect\n");
IJK_GLES2_Renderer_Vertices_reset(renderer);
return;
}
float width = renderer->frame_width;
float height = renderer->frame_height;
const float dW = (float)renderer->layer_width / width;
const float dH = (float)renderer->layer_height / height;
float dd = 1.0f;
float nW = 1.0f;
float nH = 1.0f;
if (renderer->frame_sar_num > 0 && renderer->frame_sar_den > 0) {
width = width * renderer->frame_sar_num / renderer->frame_sar_den;
}
switch (renderer->gravity) {
case IJK_GLES2_GRAVITY_RESIZE_ASPECT_FILL: dd = FFMAX(dW, dH); break;
case IJK_GLES2_GRAVITY_RESIZE_ASPECT: dd = FFMIN(dW, dH); break;
}
nW = (width * dd / (float)renderer->layer_width);
nH = (height * dd / (float)renderer->layer_height);
renderer->vertices[0] = - nW;
renderer->vertices[1] = - nH;
renderer->vertices[2] = nW;
renderer->vertices[3] = - nH;
renderer->vertices[4] = - nW;
renderer->vertices[5] = nH;
renderer->vertices[6] = nW;
renderer->vertices[7] = nH;
}
static void IJK_GLES2_Renderer_Vertices_reloadVertex(IJK_GLES2_Renderer *renderer)
{
glVertexAttribPointer(renderer->av4_position, 2, GL_FLOAT, GL_FALSE, 0, renderer->vertices); IJK_GLES2_checkError_TRACE("glVertexAttribPointer(av2_texcoord)");
glEnableVertexAttribArray(renderer->av4_position); IJK_GLES2_checkError_TRACE("glEnableVertexAttribArray(av2_texcoord)");
}
#define IJK_GLES2_GRAVITY_MIN (0)
#define IJK_GLES2_GRAVITY_RESIZE (0) // Stretch to fill layer bounds.
#define IJK_GLES2_GRAVITY_RESIZE_ASPECT (1) // Preserve aspect ratio; fit within layer bounds.
#define IJK_GLES2_GRAVITY_RESIZE_ASPECT_FILL (2) // Preserve aspect ratio; fill layer bounds.
#define IJK_GLES2_GRAVITY_MAX (2)
GLboolean IJK_GLES2_Renderer_setGravity(IJK_GLES2_Renderer *renderer, int gravity, GLsizei layer_width, GLsizei layer_height)
{
if (renderer->gravity != gravity && gravity >= IJK_GLES2_GRAVITY_MIN && gravity <= IJK_GLES2_GRAVITY_MAX)
renderer->vertices_changed = 1;
else if (renderer->layer_width != layer_width)
renderer->vertices_changed = 1;
else if (renderer->layer_height != layer_height)
renderer->vertices_changed = 1;
else
return GL_TRUE;
renderer->gravity = gravity;
renderer->layer_width = layer_width;
renderer->layer_height = layer_height;
return GL_TRUE;
}
static void IJK_GLES2_Renderer_TexCoords_reset(IJK_GLES2_Renderer *renderer)
{
renderer->texcoords[0] = 0.0f;
......@@ -238,36 +352,8 @@ GLboolean IJK_GLES2_Renderer_use(IJK_GLES2_Renderer *renderer)
IJK_GLES2_Renderer_TexCoords_reset(renderer);
IJK_GLES2_Renderer_TexCoords_reloadVertex(renderer);
glVertexAttribPointer(renderer->av4_position, 2, GL_FLOAT, GL_FALSE, 0, g_vertices); IJK_GLES2_checkError_TRACE("glVertexAttribPointer(av2_texcoord)");
glEnableVertexAttribArray(renderer->av4_position); IJK_GLES2_checkError_TRACE("glEnableVertexAttribArray(av2_texcoord)");
return GL_TRUE;
}
static GLboolean IJK_GLES2_Renderer_prepareForOverlay(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
assert(renderer);
assert(overlay);
assert(renderer->func_getBufferWidth);
GLsizei buffer_width = renderer->func_getBufferWidth(renderer, overlay);
GLsizei visible_width = overlay->w;
if (buffer_width > 0 &&
buffer_width > visible_width &&
buffer_width != renderer->buffer_width &&
visible_width != renderer->visible_width) {
renderer->buffer_width = buffer_width;
renderer->visible_width = visible_width;
GLsizei padding_pixels = buffer_width - visible_width;
GLfloat padding_normalized = ((GLfloat)padding_pixels) / buffer_width;
ALOGI("[yuv420p] padding changed: %d - %d = %d (%f)\n",
buffer_width, visible_width,
padding_pixels, padding_normalized);
IJK_GLES2_Renderer_TexCoords_reset(renderer);
IJK_GLES2_Renderer_TexCoords_cropRight(renderer, padding_normalized);
IJK_GLES2_Renderer_TexCoords_reloadVertex(renderer);
}
IJK_GLES2_Renderer_Vertices_reset(renderer);
IJK_GLES2_Renderer_Vertices_reloadVertex(renderer);
return GL_TRUE;
}
......@@ -277,15 +363,54 @@ static GLboolean IJK_GLES2_Renderer_prepareForOverlay(IJK_GLES2_Renderer *render
*/
GLboolean IJK_GLES2_Renderer_renderOverlay(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!renderer || !overlay || !renderer->func_uploadTexture)
if (!renderer || !renderer->func_uploadTexture)
return GL_FALSE;
glClear(GL_COLOR_BUFFER_BIT); IJK_GLES2_checkError_TRACE("glClear");
IJK_GLES2_Renderer_prepareForOverlay(renderer, overlay);
if (overlay) {
GLsizei visible_width = overlay->w;
GLsizei visible_height = overlay->h;
if (renderer->frame_width != visible_width ||
renderer->frame_height != visible_height ||
renderer->frame_sar_num != overlay->sar_num ||
renderer->frame_sar_den != overlay->sar_den) {
renderer->frame_width = visible_width;
renderer->frame_height = visible_height;
renderer->frame_sar_num = overlay->sar_num;
renderer->frame_sar_den = overlay->sar_den;
renderer->vertices_changed = 1;
}
if (!renderer->func_uploadTexture(renderer, overlay))
return GL_FALSE;
if (renderer->vertices_changed) {
renderer->vertices_changed = 0;
IJK_GLES2_Renderer_Vertices_apply(renderer);
IJK_GLES2_Renderer_Vertices_reloadVertex(renderer);
}
GLsizei buffer_width = renderer->func_getBufferWidth(renderer, overlay);
if (buffer_width > 0 &&
buffer_width > visible_width &&
buffer_width != renderer->buffer_width &&
visible_width != renderer->visible_width) {
renderer->buffer_width = buffer_width;
renderer->visible_width = visible_width;
GLsizei padding_pixels = buffer_width - visible_width;
GLfloat padding_normalized = ((GLfloat)padding_pixels) / buffer_width;
ALOGI("[yuv420p] padding changed: %d - %d = %d (%f)\n",
buffer_width, visible_width,
padding_pixels, padding_normalized);
IJK_GLES2_Renderer_TexCoords_reset(renderer);
IJK_GLES2_Renderer_TexCoords_cropRight(renderer, padding_normalized);
IJK_GLES2_Renderer_TexCoords_reloadVertex(renderer);
}
if (!renderer->func_uploadTexture(renderer, overlay))
return GL_FALSE;
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); IJK_GLES2_checkError_TRACE("glDrawArrays");
......
/*
* copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "internal.h"
static GLboolean rgb_use(IJK_GLES2_Renderer *renderer)
{
ALOGI("use render rgb\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glUseProgram(renderer->program); IJK_GLES2_checkError_TRACE("glUseProgram");
if (0 == renderer->plane_textures[0])
glGenTextures(1, renderer->plane_textures);
for (int i = 0; i < 1; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniform1i(renderer->us2_sampler[i], i);
}
return GL_TRUE;
}
static GLsizei rgb565_getBufferWidth(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!overlay)
return 0;
return overlay->pitches[0] / 2;
}
static GLboolean rgb565_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!renderer || !overlay)
return GL_FALSE;
int planes[1] = { 0 };
const GLsizei widths[1] = { overlay->pitches[0] / 2 };
const GLsizei heights[3] = { overlay->h };
const GLubyte *pixels[3] = { overlay->pixels[0] };
switch (overlay->format) {
case SDL_FCC_RV16:
break;
default:
ALOGE("[rgb565] unexpected format %x\n", overlay->format);
return GL_FALSE;
}
for (int i = 0; i < 1; ++i) {
int plane = planes[i];
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[i]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
widths[plane],
heights[plane],
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
pixels[plane]);
}
return GL_TRUE;
}
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_rgb565()
{
ALOGI("create render rgb565\n");
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_rgb());
if (!renderer)
goto fail;
renderer->us2_sampler[0] = glGetUniformLocation(renderer->program, "us2_SamplerX"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerX)");
renderer->func_use = rgb_use;
renderer->func_getBufferWidth = rgb565_getBufferWidth;
renderer->func_uploadTexture = rgb565_uploadTexture;
return renderer;
fail:
IJK_GLES2_Renderer_free(renderer);
return NULL;
}
static GLsizei rgb888_getBufferWidth(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!overlay)
return 0;
return overlay->pitches[0] / 3;
}
static GLboolean rgb888_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!renderer || !overlay)
return GL_FALSE;
int planes[1] = { 0 };
const GLsizei widths[1] = { overlay->pitches[0] / 3 };
const GLsizei heights[3] = { overlay->h };
const GLubyte *pixels[3] = { overlay->pixels[0] };
switch (overlay->format) {
case SDL_FCC_RV24:
break;
default:
ALOGE("[rgb888] unexpected format %x\n", overlay->format);
return GL_FALSE;
}
for (int i = 0; i < 1; ++i) {
int plane = planes[i];
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[i]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
widths[plane],
heights[plane],
0,
GL_RGB,
GL_UNSIGNED_BYTE,
pixels[plane]);
}
return GL_TRUE;
}
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_rgb888()
{
ALOGI("create render rgb888\n");
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_rgb());
if (!renderer)
goto fail;
renderer->us2_sampler[0] = glGetUniformLocation(renderer->program, "us2_SamplerX"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerX)");
renderer->func_use = rgb_use;
renderer->func_getBufferWidth = rgb888_getBufferWidth;
renderer->func_uploadTexture = rgb888_uploadTexture;
return renderer;
fail:
IJK_GLES2_Renderer_free(renderer);
return NULL;
}
static GLsizei rgbx8888_getBufferWidth(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!overlay)
return 0;
return overlay->pitches[0] / 4;
}
static GLboolean rgbx8888_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!renderer || !overlay)
return GL_FALSE;
int planes[1] = { 0 };
const GLsizei widths[1] = { overlay->pitches[0] / 4 };
const GLsizei heights[3] = { overlay->h };
const GLubyte *pixels[3] = { overlay->pixels[0] };
switch (overlay->format) {
case SDL_FCC_RV32:
break;
default:
ALOGE("[rgbx8888] unexpected format %x\n", overlay->format);
return GL_FALSE;
}
for (int i = 0; i < 1; ++i) {
int plane = planes[i];
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[i]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
widths[plane],
heights[plane],
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixels[plane]);
}
return GL_TRUE;
}
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_rgbx8888()
{
ALOGI("create render rgbx8888\n");
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_rgb());
if (!renderer)
goto fail;
renderer->us2_sampler[0] = glGetUniformLocation(renderer->program, "us2_SamplerX"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerX)");
renderer->func_use = rgb_use;
renderer->func_getBufferWidth = rgbx8888_getBufferWidth;
renderer->func_uploadTexture = rgbx8888_uploadTexture;
return renderer;
fail:
IJK_GLES2_Renderer_free(renderer);
return NULL;
}
......@@ -22,6 +22,7 @@
static GLboolean yuv420p_use(IJK_GLES2_Renderer *renderer)
{
ALOGI("use render yuv420p\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glUseProgram(renderer->program); IJK_GLES2_checkError_TRACE("glUseProgram");
......@@ -97,6 +98,7 @@ static GLboolean yuv420p_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOve
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv420p()
{
ALOGI("create render yuv420p\n");
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_yuv420p());
if (!renderer)
goto fail;
......
/*
* copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "internal.h"
#ifdef __APPLE__
#import <CoreVideo/CoreVideo.h>
#include "ijksdl_vout_overlay_videotoolbox.h"
#endif
static GLboolean yuv420sp_use(IJK_GLES2_Renderer *renderer)
{
ALOGI("use render yuv420sp\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glUseProgram(renderer->program); IJK_GLES2_checkError_TRACE("glUseProgram");
if (0 == renderer->plane_textures[0])
glGenTextures(2, renderer->plane_textures);
for (int i = 0; i < 2; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniform1i(renderer->us2_sampler[i], i);
}
glUniformMatrix3fv(renderer->um3_color_conversion, 1, GL_FALSE, IJK_GLES2_getColorMatrix_bt709());
return GL_TRUE;
}
static GLsizei yuv420sp_getBufferWidth(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!overlay)
return 0;
return overlay->pitches[0] / 1;
}
static GLboolean yuv420sp_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!renderer || !overlay)
return GL_FALSE;
const GLsizei widths[2] = { overlay->pitches[0], overlay->pitches[1] / 2 };
const GLsizei heights[2] = { overlay->h, overlay->h / 2 };
const GLubyte *pixels[2] = { overlay->pixels[0], overlay->pixels[1] };
switch (overlay->format) {
case SDL_FCC__VTB:
break;
default:
ALOGE("[yuv420sp] unexpected format %x\n", overlay->format);
return GL_FALSE;
}
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[0]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED_EXT,
widths[0],
heights[0],
0,
GL_RED_EXT,
GL_UNSIGNED_BYTE,
pixels[0]);
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[1]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RG_EXT,
widths[1],
heights[1],
0,
GL_RG_EXT,
GL_UNSIGNED_BYTE,
pixels[1]);
return GL_TRUE;
}
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv420sp()
{
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_yuv420sp());
if (!renderer)
goto fail;
renderer->us2_sampler[0] = glGetUniformLocation(renderer->program, "us2_SamplerX"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerX)");
renderer->us2_sampler[1] = glGetUniformLocation(renderer->program, "us2_SamplerY"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerY)");
renderer->um3_color_conversion = glGetUniformLocation(renderer->program, "um3_ColorConversion"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(um3_ColorConversionMatrix)");
renderer->func_use = yuv420sp_use;
renderer->func_getBufferWidth = yuv420sp_getBufferWidth;
renderer->func_uploadTexture = yuv420sp_uploadTexture;
return renderer;
fail:
IJK_GLES2_Renderer_free(renderer);
return NULL;
}
/*
* copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "internal.h"
#import <OpenGLES/EAGL.h>
#import <CoreVideo/CoreVideo.h>
#include "ijksdl_vout_overlay_videotoolbox.h"
typedef struct IJK_GLES2_Renderer_Opaque
{
CVOpenGLESTextureCacheRef cv_texture_cache;
CVOpenGLESTextureRef cv_texture[2];
CFTypeRef color_attachments;
} IJK_GLES2_Renderer_Opaque;
static GLboolean yuv420sp_vtb_use(IJK_GLES2_Renderer *renderer)
{
ALOGI("use render yuv420sp_vtb\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glUseProgram(renderer->program); IJK_GLES2_checkError_TRACE("glUseProgram");
if (0 == renderer->plane_textures[0])
glGenTextures(2, renderer->plane_textures);
for (int i = 0; i < 2; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, renderer->plane_textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniform1i(renderer->us2_sampler[i], i);
}
glUniformMatrix3fv(renderer->um3_color_conversion, 1, GL_FALSE, IJK_GLES2_getColorMatrix_bt709());
return GL_TRUE;
}
static GLvoid yuv420sp_vtb_clean_textures(IJK_GLES2_Renderer *renderer)
{
if (renderer || !renderer->opaque)
return;
IJK_GLES2_Renderer_Opaque *opaque = renderer->opaque;
for (int i = 0; i < 2; ++i) {
if (opaque->cv_texture[i]) {
CFRelease(opaque->cv_texture[i]);
opaque->cv_texture[i] = nil;
}
}
if (opaque->cv_texture_cache) {
CFRelease(&opaque->cv_texture_cache);
opaque->cv_texture_cache = nil;
}
// Periodic texture cache flush every frame
if (opaque->cv_texture_cache)
CVOpenGLESTextureCacheFlush(opaque->cv_texture_cache, 0);
}
static GLboolean yuv420sp_vtb_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)
{
if (!renderer || !renderer->opaque || !overlay)
return GL_FALSE;
if (!overlay->is_private)
return GL_FALSE;
switch (overlay->format) {
case SDL_FCC__VTB:
break;
default:
ALOGE("[yuv420sp_vtb] unexpected format %x\n", overlay->format);
return GL_FALSE;
}
IJK_GLES2_Renderer_Opaque *opaque = renderer->opaque;
if (!opaque->cv_texture_cache) {
ALOGE("nil textureCache\n");
return GL_FALSE;
}
CVPixelBufferRef pixel_buffer = SDL_VoutOverlayVideoToolBox_GetCVPixelBufferRef(overlay);
if (!pixel_buffer) {
ALOGE("nil pixelBuffer in overlay\n");
return GL_FALSE;
}
CFTypeRef color_attachments = CVBufferGetAttachment(pixel_buffer, kCVImageBufferYCbCrMatrixKey, NULL);
if (color_attachments != opaque->color_attachments) {
if (color_attachments == nil) {
glUniformMatrix3fv(renderer->um3_color_conversion, 1, GL_FALSE, IJK_GLES2_getColorMatrix_bt709());
} else if (opaque->color_attachments != nil &&
CFStringCompare(color_attachments, opaque->color_attachments, 0) == kCFCompareEqualTo) {
// remain prvious color attachment
} else if (CFStringCompare(color_attachments, kCVImageBufferYCbCrMatrix_ITU_R_709_2, 0) == kCFCompareEqualTo) {
glUniformMatrix3fv(renderer->um3_color_conversion, 1, GL_FALSE, IJK_GLES2_getColorMatrix_bt709());
} else if (CFStringCompare(color_attachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4, 0) == kCFCompareEqualTo) {
glUniformMatrix3fv(renderer->um3_color_conversion, 1, GL_FALSE, IJK_GLES2_getColorMatrix_bt601());
} else {
glUniformMatrix3fv(renderer->um3_color_conversion, 1, GL_FALSE, IJK_GLES2_getColorMatrix_bt709());
}
opaque->color_attachments = color_attachments;
}
yuv420sp_vtb_clean_textures(renderer);
if (renderer->plane_textures[0])
glDeleteTextures(2, renderer->plane_textures);
GLsizei frame_width = (GLsizei)CVPixelBufferGetWidth(pixel_buffer);
GLsizei frame_height = (GLsizei)CVPixelBufferGetHeight(pixel_buffer);
glActiveTexture(GL_TEXTURE0);
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
opaque->cv_texture_cache,
pixel_buffer,
NULL,
GL_TEXTURE_2D,
GL_RED_EXT,
(GLsizei)frame_width,
(GLsizei)frame_height,
GL_RED_EXT,
GL_UNSIGNED_BYTE,
0,
&opaque->cv_texture[0]);
renderer->plane_textures[0] = CVOpenGLESTextureGetName(opaque->cv_texture[0]);
glBindTexture(CVOpenGLESTextureGetTarget(opaque->cv_texture[0]), renderer->plane_textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE1);
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
opaque->cv_texture_cache,
pixel_buffer,
NULL,
GL_TEXTURE_2D,
GL_RG_EXT,
(GLsizei)frame_width / 2,
(GLsizei)frame_height / 2,
GL_RG_EXT,
GL_UNSIGNED_BYTE,
1,
&opaque->cv_texture[1]);
renderer->plane_textures[1] = CVOpenGLESTextureGetName(opaque->cv_texture[1]);
glBindTexture(CVOpenGLESTextureGetTarget(opaque->cv_texture[1]), renderer->plane_textures[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return GL_TRUE;
}
static GLvoid yuv420sp_vtb_destroy(IJK_GLES2_Renderer *renderer)
{
if (renderer || !renderer->opaque)
return;
yuv420sp_vtb_clean_textures(renderer);
IJK_GLES2_Renderer_Opaque *opaque = renderer->opaque;
if (opaque->cv_texture_cache) {
CFRelease(opaque->cv_texture_cache);
opaque->cv_texture_cache = nil;
}
}
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv420sp_vtb(SDL_VoutOverlay *overlay)
{
CVReturn err = 0;
EAGLContext *context = [EAGLContext currentContext];
if (!overlay) {
ALOGW("invalid overlay, fall back to yuv420sp renderer\n");
return IJK_GLES2_Renderer_create_yuv420sp();
}
if (!overlay) {
ALOGW("non-private overlay, fall back to yuv420sp renderer\n");
return IJK_GLES2_Renderer_create_yuv420sp();
}
if (!context) {
ALOGW("nil EAGLContext, fall back to yuv420sp renderer\n");
return IJK_GLES2_Renderer_create_yuv420sp();
}
ALOGI("create render yuv420sp_vtb\n");
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_yuv420sp());
if (!renderer)
goto fail;
renderer->us2_sampler[0] = glGetUniformLocation(renderer->program, "us2_SamplerX"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerX)");
renderer->us2_sampler[1] = glGetUniformLocation(renderer->program, "us2_SamplerY"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(us2_SamplerY)");
renderer->um3_color_conversion = glGetUniformLocation(renderer->program, "um3_ColorConversion"); IJK_GLES2_checkError_TRACE("glGetUniformLocation(um3_ColorConversionMatrix)");
renderer->func_use = yuv420sp_vtb_use;
renderer->func_uploadTexture = yuv420sp_vtb_uploadTexture;
renderer->func_destroy = yuv420sp_vtb_destroy;
renderer->opaque = calloc(1, sizeof(IJK_GLES2_Renderer_Opaque));
if (!renderer->opaque)
goto fail;
err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, context, NULL, &renderer->opaque->cv_texture_cache);
if (err || renderer->opaque->cv_texture_cache == nil) {
ALOGE("Error at CVOpenGLESTextureCacheCreate %d\n", err);
goto fail;
}
renderer->opaque->color_attachments = kCVImageBufferYCbCrMatrix_ITU_R_709_2;
return renderer;
fail:
IJK_GLES2_Renderer_free(renderer);
return NULL;
}
......@@ -22,6 +22,7 @@
static GLboolean yuv444p10le_use(IJK_GLES2_Renderer *renderer)
{
ALOGI("use render yuv420p10le\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glUseProgram(renderer->program); IJK_GLES2_checkError_TRACE("glUseProgram");
......@@ -93,6 +94,7 @@ static GLboolean yuv444p10le_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_Vou
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create_yuv444p10le()
{
ALOGI("create render yuv444p10le\n");
IJK_GLES2_Renderer *renderer = IJK_GLES2_Renderer_create_base(IJK_GLES2_getFragmentShader_yuv444p10le());
if (!renderer)
goto fail;
......
......@@ -35,7 +35,7 @@ static void IJK_GLES2_printShaderInfo(GLuint shader)
char buf_stack[32];
char *buf_heap = NULL;
char *buf = buf_stack;
size_t buf_len = sizeof(buf_stack) - 1;
GLsizei buf_len = sizeof(buf_stack) - 1;
if (info_len > sizeof(buf_stack)) {
buf_heap = (char*) malloc(info_len + 1);
if (buf_heap) {
......@@ -53,7 +53,7 @@ static void IJK_GLES2_printShaderInfo(GLuint shader)
GLuint IJK_GLES2_loadShader(GLenum shader_type, const char *shader_source)
{
assert(shader);
assert(shader_source);
GLuint shader = glCreateShader(shader_type); IJK_GLES2_checkError("glCreateShader");
if (!shader)
......
......@@ -18,15 +18,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __APPLE__
#include "ijksdl_egl.h"
#include <stdlib.h>
#include <stdbool.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include "ijksdl/ijksdl_gles2.h"
#include "ijksdl/ijksdl_log.h"
#include "ijksdl/ijksdl_vout.h"
......@@ -274,8 +271,16 @@ static EGLBoolean IJK_EGL_prepareRenderer(IJK_EGL* egl, SDL_VoutOverlay *overlay
IJK_EGL_Opaque *opaque = egl->opaque;
// FIXME: check render against overlay
if (!IJK_GLES2_Renderer_isValid(opaque->renderer)) {
if (!IJK_GLES2_Renderer_isFormat(opaque->renderer, overlay->format)) {
}
if (!IJK_GLES2_Renderer_isValid(opaque->renderer) ||
!IJK_GLES2_Renderer_isFormat(opaque->renderer, overlay->format)) {
IJK_GLES2_Renderer_reset(opaque->renderer);
IJK_GLES2_Renderer_freeP(&opaque->renderer);
opaque->renderer = IJK_GLES2_Renderer_create(overlay);
if (!opaque->renderer) {
ALOGE("[EGL] Could not create render.");
......@@ -383,3 +388,5 @@ IJK_EGL *IJK_EGL_create()
return egl;
}
#endif
......@@ -21,9 +21,14 @@
#ifndef IJKSDL__IJKSDL_EGL_H
#define IJKSDL__IJKSDL_EGL_H
#ifdef __APPLE__
#include "ijksdl/ios/EGL/egl.h"
#include "ijksdl/ios/EGL/eglplatform.h"
#else
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#endif
#include "ijksdl_class.h"
typedef struct SDL_VoutOverlay SDL_VoutOverlay;
......
......@@ -55,6 +55,8 @@
#define SDL_FCC_UYVY SDL_FOURCC('U', 'Y', 'V', 'Y') /**< bpp=16, Packed mode: U0+Y0+V0+Y1 (1 plane) */
#define SDL_FCC_YVYU SDL_FOURCC('Y', 'V', 'Y', 'U') /**< bpp=16, Packed mode: Y0+V0+Y1+U0 (1 plane) */
#define SDL_FCC_NV12 SDL_FOURCC('N', 'V', '1', '2')
// RGB formats
#define SDL_FCC_RV16 SDL_FOURCC('R', 'V', '1', '6') /**< bpp=16, RGB565 */
#define SDL_FCC_RV24 SDL_FOURCC('R', 'V', '2', '4') /**< bpp=24, RGBX8888 */
......
......@@ -21,9 +21,14 @@
#ifndef IJKSDL__IJKSDL_GLES2_H
#define IJKSDL__IJKSDL_GLES2_H
#ifdef __APPLE__
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2platform.h>
#endif
typedef struct SDL_VoutOverlay SDL_VoutOverlay;
......@@ -45,29 +50,6 @@ GLuint IJK_GLES2_loadShader(GLenum shader_type, const char *shader_source);
*/
#define IJK_GLES2_MAX_PLANE 3
typedef struct IJK_GLES2_Renderer IJK_GLES2_Renderer;
typedef struct IJK_GLES2_Renderer
{
GLuint program;
GLuint vertex_shader;
GLuint fragment_shader;
GLuint plane_textures[IJK_GLES2_MAX_PLANE];
GLuint av4_position;
GLuint av2_texcoord;
GLuint um4_mvp;
GLuint us2_sampler[IJK_GLES2_MAX_PLANE];
GLuint um3_color_conversion;
GLboolean (*func_use)(IJK_GLES2_Renderer *renderer);
GLsizei (*func_getBufferWidth)(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay);
GLboolean (*func_uploadTexture)(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay);
GLsizei buffer_width;
GLsizei visible_width;
GLfloat texcoords[8];
} IJK_GLES2_Renderer;
IJK_GLES2_Renderer *IJK_GLES2_Renderer_create(SDL_VoutOverlay *overlay);
void IJK_GLES2_Renderer_reset(IJK_GLES2_Renderer *renderer);
......@@ -76,7 +58,13 @@ void IJK_GLES2_Renderer_freeP(IJK_GLES2_Renderer **renderer);
GLboolean IJK_GLES2_Renderer_setupGLES();
GLboolean IJK_GLES2_Renderer_isValid(IJK_GLES2_Renderer *renderer);
GLboolean IJK_GLES2_Renderer_isFormat(IJK_GLES2_Renderer *renderer, int format);
GLboolean IJK_GLES2_Renderer_use(IJK_GLES2_Renderer *renderer);
GLboolean IJK_GLES2_Renderer_renderOverlay(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay);
#define IJK_GLES2_GRAVITY_RESIZE (0) // Stretch to fill view bounds.
#define IJK_GLES2_GRAVITY_RESIZE_ASPECT (1) // Preserve aspect ratio; fit within view bounds.
#define IJK_GLES2_GRAVITY_RESIZE_ASPECT_FILL (2) // Preserve aspect ratio; fill view bounds.
GLboolean IJK_GLES2_Renderer_setGravity(IJK_GLES2_Renderer *renderer, int gravity, GLsizei view_width, GLsizei view_height);
#endif
......@@ -208,7 +208,7 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
self.shouldShowHudView = options.showHudView;
ijkmp_ios_set_glview(_mediaPlayer, _glView);
ijkmp_set_option(_mediaPlayer, IJKMP_OPT_CATEGORY_PLAYER, "overlay-format", "fcc-i420");
ijkmp_set_option(_mediaPlayer, IJKMP_OPT_CATEGORY_PLAYER, "overlay-format", "fcc-_es2");
#ifdef DEBUG
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
#else
......
/*
* IJKSDLGLRender.h
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import <Foundation/Foundation.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#include "ijksdl/ijksdl_vout.h"
@protocol IJKSDLGLRender
- (BOOL) isValid;
- (NSString *) fragmentShader;
- (void) resolveUniforms: (GLuint) program;
- (void) render: (SDL_VoutOverlay *) overlay;
- (BOOL) prepareDisplay;
@end
// BT.709, which is the standard for HDTV.
static const GLfloat kColorConversion709[] = {
1.164, 1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533, 0.0,
};
// BT.601, which is the standard for SDTV.
static const GLfloat kColorConversion601[] = {
1.164, 1.164, 1.164,
0.0, -0.392, 2.017,
1.596, -0.813, 0.0,
};
/*
* IJKSDLGLRenderI420.h
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import <Foundation/Foundation.h>
#import "IJKSDLGLRender.h"
@interface IJKSDLGLRenderI420 : NSObject<IJKSDLGLRender>
@end
/*
* IJKSDLGLRenderI420.m
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "IJKSDLGLRenderI420.h"
#import "IJKSDLGLShader.h"
static NSString *const g_yuvFragmentShaderString = IJK_SHADER_STRING
(
varying highp vec2 v_texcoord;
precision mediump float;
uniform sampler2D SamplerY;
uniform sampler2D SamplerU;
uniform sampler2D SamplerV;
uniform mat3 colorConversionMatrix;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
// Subtract constants to map the video range start at 0
yuv.x = (texture2D(SamplerY, v_texcoord).r - (16.0/255.0));
yuv.y = (texture2D(SamplerU, v_texcoord).r - 0.5);
yuv.z = (texture2D(SamplerV, v_texcoord).r - 0.5);
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb,1);
}
);
@implementation IJKSDLGLRenderI420 {
GLint _uniform[1];
GLint _uniformSamplers[3];
GLuint _textures[3];
const GLfloat *_preferredConversion;
}
- (BOOL) isValid
{
return (_textures[0] != 0);
}
- (NSString *) fragmentShader
{
return g_yuvFragmentShaderString;
}
- (void) resolveUniforms: (GLuint) program
{
_uniformSamplers[0] = glGetUniformLocation(program, "SamplerY");
_uniformSamplers[1] = glGetUniformLocation(program, "SamplerU");
_uniformSamplers[2] = glGetUniformLocation(program, "SamplerV");
_uniform[0] = glGetUniformLocation(program, "colorConversionMatrix");
}
- (void) render: (SDL_VoutOverlay *) overlay
{
assert(overlay->planes);
assert(overlay->format == SDL_FCC_I420);
assert(overlay->planes == 3);
assert(overlay->planes == 3);
// assert(yuvFrame.luma.length == yuvFrame.width * yuvFrame.height);
// assert(yuvFrame.chromaB.length == (yuvFrame.width * yuvFrame.height) / 4);
// assert(yuvFrame.chromaR.length == (yuvFrame.width * yuvFrame.height) / 4);
const NSUInteger frameHeight = overlay->h;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (0 == _textures[0])
glGenTextures(3, _textures);
_preferredConversion = kColorConversion709;
const UInt8 *pixels[3] = { overlay->pixels[0], overlay->pixels[1], overlay->pixels[2] };
const NSUInteger widths[3] = { overlay->pitches[0], overlay->pitches[1], overlay->pitches[2] };
const NSUInteger heights[3] = { frameHeight, frameHeight / 2, frameHeight / 2 };
for (int i = 0; i < 3; ++i) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_LUMINANCE,
(int)widths[i],
(int)heights[i],
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
pixels[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
- (BOOL) prepareDisplay
{
if (_textures[0] == 0)
return NO;
for (int i = 0; i < 3; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glUniform1i(_uniformSamplers[i], i);
}
glUniformMatrix3fv(_uniform[0], 1, GL_FALSE, _preferredConversion);
return YES;
}
- (void) dealloc
{
if (_textures[0])
glDeleteTextures(3, _textures);
}
@end
/*
* IJKSDLGLRenderI444P10LE.h
*
* Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import <Foundation/Foundation.h>
#import "IJKSDLGLRender.h"
@interface IJKSDLGLRenderI444P10LE : NSObject<IJKSDLGLRender>
@end
/*
* IJKSDLGLRenderI444P10LE.m
*
* Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "IJKSDLGLRenderI444P10LE.h"
#import "IJKSDLGLShader.h"
static NSString *const g_yuvFragmentShaderString = IJK_SHADER_STRING
(
varying highp vec2 v_texcoord;
precision mediump float;
uniform sampler2D SamplerY;
uniform sampler2D SamplerU;
uniform sampler2D SamplerV;
uniform mat3 colorConversionMatrix;
void main()
{
highp vec3 yuvr;
highp vec3 yuvg;
highp vec3 yuv;
lowp vec3 rgb;
// Subtract constants to map the video range start at 0
yuvr.x = texture2D(SamplerY, v_texcoord).r;
yuvr.y = texture2D(SamplerU, v_texcoord).r;
yuvr.z = texture2D(SamplerV, v_texcoord).r;
yuvg.x = texture2D(SamplerY, v_texcoord).g;
yuvg.y = texture2D(SamplerU, v_texcoord).g;
yuvg.z = texture2D(SamplerV, v_texcoord).g;
yuv = (yuvr * 255.0 + yuvg * 255.0 * 256.0) / (1023.0);
yuv.x = yuv.x - 16.0 / 255.0;
yuv.yz = yuv.yz - vec2(0.5, 0.5);
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb,1);
}
);
@implementation IJKSDLGLRenderI444P10LE {
GLint _uniform[1];
GLint _uniformSamplers[3];
GLuint _textures[3];
const GLfloat *_preferredConversion;
}
- (BOOL) isValid
{
return (_textures[0] != 0);
}
- (NSString *) fragmentShader
{
return g_yuvFragmentShaderString;
}
- (void) resolveUniforms: (GLuint) program
{
_uniformSamplers[0] = glGetUniformLocation(program, "SamplerY");
_uniformSamplers[1] = glGetUniformLocation(program, "SamplerU");
_uniformSamplers[2] = glGetUniformLocation(program, "SamplerV");
_uniform[0] = glGetUniformLocation(program, "colorConversionMatrix");
}
- (void) render: (SDL_VoutOverlay *) overlay
{
assert(overlay->planes);
assert(overlay->format == SDL_FCC_I444P10LE);
assert(overlay->planes == 3);
// assert(yuvFrame.luma.length == yuvFrame.width * yuvFrame.height);
// assert(yuvFrame.chromaB.length == (yuvFrame.width * yuvFrame.height) / 4);
// assert(yuvFrame.chromaR.length == (yuvFrame.width * yuvFrame.height) / 4);
const NSUInteger frameHeight = overlay->h;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (0 == _textures[0])
glGenTextures(3, _textures);
_preferredConversion = kColorConversion709;
const UInt8 *pixels[3] = { overlay->pixels[0], overlay->pixels[1], overlay->pixels[2] };
const NSUInteger widths[3] = { overlay->pitches[0] / 2, overlay->pitches[1] / 2, overlay->pitches[2] / 2 };
const NSUInteger heights[3] = { frameHeight, frameHeight, frameHeight };
for (int i = 0; i < 3; ++i) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RG_EXT,
(int)widths[i],
(int)heights[i],
0,
GL_RG_EXT,
GL_UNSIGNED_BYTE,
pixels[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
- (BOOL) prepareDisplay
{
if (_textures[0] == 0)
return NO;
for (int i = 0; i < 3; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glUniform1i(_uniformSamplers[i], i);
}
glUniformMatrix3fv(_uniform[0], 1, GL_FALSE, _preferredConversion);
return YES;
}
- (void) dealloc
{
if (_textures[0])
glDeleteTextures(3, _textures);
}
@end
/*
* IJKSDLGLRenderNV12.m
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "IJKSDLGLRenderNV12.h"
#import "IJKSDLGLShader.h"
#include "ijksdl_vout_overlay_videotoolbox.h"
static NSString *const g_nv12FragmentShaderString = IJK_SHADER_STRING
(
varying highp vec2 v_texcoord;
precision mediump float;
uniform sampler2D SamplerY;
uniform sampler2D SamplerUV;
uniform mat3 colorConversionMatrix;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
// Subtract constants to map the video range start at 0
yuv.x = (texture2D(SamplerY, v_texcoord).r - (16.0/255.0));
yuv.yz = (texture2D(SamplerUV, v_texcoord).rg - vec2(0.5, 0.5));
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb,1);
}
);
@implementation IJKSDLGLRenderNV12 {
GLint _uniform[1];
GLint _uniformSamplers[2];
GLuint _textures[2];
CVOpenGLESTextureCacheRef _textureCache;
CVOpenGLESTextureRef _cvTexturesRef[2];
const GLfloat *_preferredConversion;
}
-(id)initWithTextureCache:(CVOpenGLESTextureCacheRef) textureCache
{
self = [super init];
if (self) {
_textureCache = textureCache;
}
return self;
}
- (BOOL) isValid
{
return (_textures[0] != 0) && (_textures[1] != 0);
}
- (NSString *) fragmentShader
{
return g_nv12FragmentShaderString;
}
- (void) resolveUniforms: (GLuint) program
{
_uniformSamplers[0] = glGetUniformLocation(program, "SamplerY");
_uniformSamplers[1] = glGetUniformLocation(program, "SamplerUV");
_uniform[0] = glGetUniformLocation(program, "colorConversionMatrix");
}
- (void) render: (SDL_VoutOverlay *) overlay
{
assert(overlay->planes);
assert(overlay->format == SDL_FCC__VTB);
assert(overlay->planes == 2);
if (!overlay->is_private)
return;
if (!_textureCache) {
ALOGE("nil textureCache\n");
return;
}
CVPixelBufferRef pixelBuffer = SDL_VoutOverlayVideoToolBox_GetCVPixelBufferRef(overlay);
if (!pixelBuffer) {
ALOGE("nil pixelBuffer in overlay\n");
return;
}
CFTypeRef colorAttachments = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL);
if (colorAttachments == kCVImageBufferYCbCrMatrix_ITU_R_601_4) {
_preferredConversion = kColorConversion601;
} else if (colorAttachments == kCVImageBufferYCbCrMatrix_ITU_R_709_2){
_preferredConversion = kColorConversion709;
} else {
_preferredConversion = kColorConversion709;
}
for (int i = 0; i < 2; ++i) {
if (_cvTexturesRef[i]) {
CFRelease(_cvTexturesRef[i]);
_cvTexturesRef[i] = 0;
_textures[i] = 0;
}
}
// Periodic texture cache flush every frame
if (_textureCache)
CVOpenGLESTextureCacheFlush(_textureCache, 0);
if (_textures[0])
glDeleteTextures(2, _textures);
size_t frameWidth = CVPixelBufferGetWidth(pixelBuffer);
size_t frameHeight = CVPixelBufferGetHeight(pixelBuffer);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_textureCache,
pixelBuffer,
NULL,
GL_TEXTURE_2D,
GL_RED_EXT,
(GLsizei)frameWidth,
(GLsizei)frameHeight,
GL_RED_EXT,
GL_UNSIGNED_BYTE,
0,
&_cvTexturesRef[0]);
_textures[0] = CVOpenGLESTextureGetName(_cvTexturesRef[0]);
glBindTexture(CVOpenGLESTextureGetTarget(_cvTexturesRef[0]), _textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_textureCache,
pixelBuffer,
NULL,
GL_TEXTURE_2D,
GL_RG_EXT,
(GLsizei)frameWidth / 2,
(GLsizei)frameHeight / 2,
GL_RG_EXT,
GL_UNSIGNED_BYTE,
1,
&_cvTexturesRef[1]);
_textures[1] = CVOpenGLESTextureGetName(_cvTexturesRef[1]);
glBindTexture(CVOpenGLESTextureGetTarget(_cvTexturesRef[1]), _textures[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
- (BOOL) prepareDisplay
{
if (_textures[0] == 0)
return NO;
for (int i = 0; i < 2; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glUniform1i(_uniformSamplers[i], i);
}
glUniformMatrix3fv(_uniform[0], 1, GL_FALSE, _preferredConversion);
return YES;
}
- (void) dealloc
{
for (int i = 0; i < 2; ++i) {
if (_cvTexturesRef[i]) {
CFRelease(_cvTexturesRef[i]);
_cvTexturesRef[i] = 0;
_textures[i] = 0;
}
}
if (_textures[0])
glDeleteTextures(2, _textures);
}
@end
/*
* IJKSDLGLRenderRV24.h
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import <Foundation/Foundation.h>
#import "IJKSDLGLRender.h"
@interface IJKSDLGLRenderRV24 : NSObject<IJKSDLGLRender>
@end
/*
* IJKSDLGLRenderRV24.m
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "IJKSDLGLRenderRV24.h"
#import "IJKSDLGLShader.h"
static NSString *const g_rgbFragmentShaderString = IJK_SHADER_STRING
(
varying highp vec2 v_texcoord;
uniform sampler2D s_texture;
void main()
{
gl_FragColor = texture2D(s_texture, v_texcoord);
}
);
@implementation IJKSDLGLRenderRV24 {
GLint _uniformSamplers[1];
GLuint _textures[1];
}
- (BOOL) isValid
{
return (_textures[0] != 0);
}
- (NSString *) fragmentShader
{
return g_rgbFragmentShaderString;
}
- (void) resolveUniforms: (GLuint) program
{
_uniformSamplers[0] = glGetUniformLocation(program, "s_texture");
}
- (void) render: (SDL_VoutOverlay *) overlay
{
assert(overlay->planes);
assert(overlay->format == SDL_FCC_RV24);
assert(overlay->planes == 1);
assert(overlay->planes == 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (0 == _textures[0])
glGenTextures(1, _textures);
const UInt8 *pixels[1] = { overlay->pixels[0] };
const NSUInteger widths[1] = { overlay->pitches[0] / 3};
const NSUInteger heights[1] = { overlay->h };
for (int i = 0; i < 1; ++i) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
(int)widths[i],
(int)heights[i],
0,
GL_RGB,
GL_UNSIGNED_BYTE,
pixels[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
- (BOOL) prepareDisplay
{
if (_textures[0] == 0)
return NO;
for (int i = 0; i < 1; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glUniform1i(_uniformSamplers[i], i);
}
return YES;
}
- (void) dealloc
{
if (_textures[0])
glDeleteTextures(1, _textures);
}
@end
/*
* IJKSDLGLShader.h
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import <Foundation/Foundation.h>
#define IJK_STRINGIZE(x) #x
#define IJK_STRINGIZE2(x) IJK_STRINGIZE(x)
#define IJK_SHADER_STRING(text) @ IJK_STRINGIZE2(text)
......@@ -47,10 +47,10 @@ static SDL_VoutOverlay *vout_create_overlay_l(int width, int height, int frame_f
}
}
static SDL_VoutOverlay *vout_create_overlay(int width, int height, Uint32 format, SDL_Vout *vout)
static SDL_VoutOverlay *vout_create_overlay(int width, int height, int frame_format, SDL_Vout *vout)
{
SDL_LockMutex(vout->mutex);
SDL_VoutOverlay *overlay = vout_create_overlay_l(width, height, format, vout);
SDL_VoutOverlay *overlay = vout_create_overlay_l(width, height, frame_format, vout);
SDL_UnlockMutex(vout->mutex);
return overlay;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册