iOS: rework opengl display

parent 0481d7d1
......@@ -126,14 +126,18 @@ didOutputSampleBuffer:(CMSampleBufferRef) sampleBuffer
case 0:
case 180:
if (mOutputVideoSize.width*factor>plane_width || mOutputVideoSize.height*factor>plane_height) {
ms_warning("IOS capture discarding frame because wrong dimensions");
ms_warning("[1]IOS capture discarding frame because wrong dimensions (%d > %d || %d > %d)",
mOutputVideoSize.width*factor, plane_width,
mOutputVideoSize.height*factor, plane_height);
return;
}
break;
case 90:
case 270:
if (mOutputVideoSize.width*factor>plane_height || mOutputVideoSize.height*factor>plane_width) {
ms_warning("IOS capture discarding frame because wrong dimensions");
ms_warning("[2] IOS capture discarding frame because wrong dimensions (%d > %d || %d > %d)",
mOutputVideoSize.width*factor, plane_height,
mOutputVideoSize.height*factor, plane_width);
return;
}
break;
......@@ -210,7 +214,7 @@ didOutputSampleBuffer:(CMSampleBufferRef) sampleBuffer
dispatch_release(queue);
captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
//captureVideoPreviewLayer.orientation = AVCaptureVideoOrientationLandscapeRight;
captureVideoPreviewLayer.orientation = AVCaptureVideoOrientationPortrait; //AVCaptureVideoOrientationLandscapeRight;
start_time=0;
frame_count=-1;
fps=0;
......@@ -251,23 +255,21 @@ didOutputSampleBuffer:(CMSampleBufferRef) sampleBuffer
return 0;
}
static AVCaptureVideoOrientation devideOrientation2AVCaptureVideoOrientation(int deviceOrientation) {
switch (deviceOrientation) {
case 0: return AVCaptureVideoOrientationPortrait;
case 90: return AVCaptureVideoOrientationLandscapeLeft;
case -180:
case 180: return AVCaptureVideoOrientationPortraitUpsideDown;
case -90:
case 270: return AVCaptureVideoOrientationLandscapeRight;
default:
ms_error("Unexpected device orientation [%i] expected value are 0, 90, 180, 270",deviceOrientation);
break;
}
return AVCaptureVideoOrientationPortrait;
switch (deviceOrientation) {
case 0: return AVCaptureVideoOrientationPortrait;
case 90: return AVCaptureVideoOrientationLandscapeLeft;
case -180:
case 180: return AVCaptureVideoOrientationPortraitUpsideDown;
case -90:
case 270: return AVCaptureVideoOrientationLandscapeRight;
default:
ms_error("Unexpected device orientation [%i] expected value are 0, 90, 180, 270",deviceOrientation);
break;
}
return AVCaptureVideoOrientationPortrait;
}
-(void) setSize:(MSVideoSize) size {
@synchronized(self) {
[session beginConfiguration];
......@@ -292,31 +294,31 @@ static AVCaptureVideoOrientation devideOrientation2AVCaptureVideoOrientation(int
mOutputVideoSize=mCameraVideoSize;
mDownScalingRequired=false;
}
NSArray *connections = output.connections;
if ([connections count] > 0 && [[connections objectAtIndex:0] isVideoOrientationSupported]) {
switch (mDeviceOrientation) {
case 0:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationPortrait];
ms_message("Configuring camera in AVCaptureVideoOrientationPortrait mode ");
break;
case 180:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
ms_message("Configuring camera in AVCaptureVideoOrientationPortraitUpsideDown mode ");
break;
case 90:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
ms_message("Configuring camera in AVCaptureVideoOrientationLandscapeLeft mode ");
break;
case 270:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
ms_message("Configuring camera in AVCaptureVideoOrientationLandscapeRight mode ");
default:
break;
}
}
NSArray *connections = output.connections;
if ([connections count] > 0 && [[connections objectAtIndex:0] isVideoOrientationSupported]) {
switch (mDeviceOrientation) {
case 0:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationPortrait];
ms_message("Configuring camera in AVCaptureVideoOrientationPortrait mode ");
break;
case 180:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
ms_message("Configuring camera in AVCaptureVideoOrientationPortraitUpsideDown mode ");
break;
case 90:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
ms_message("Configuring camera in AVCaptureVideoOrientationLandscapeLeft mode ");
break;
case 270:
[[connections objectAtIndex:0] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
ms_message("Configuring camera in AVCaptureVideoOrientationLandscapeRight mode ");
default:
break;
}
}
if (mDeviceOrientation == 0 || mDeviceOrientation == 180) {
MSVideoSize tmpSize = mOutputVideoSize;
mOutputVideoSize.width=tmpSize.height;
......@@ -446,8 +448,16 @@ static int v4ios_set_device_orientation (MSFilter *f, void *arg) {
IOSMsWebCam *webcam=(IOSMsWebCam*)f->data;
if ( webcam->mDeviceOrientation != *(int*)(arg)) {
webcam->mDeviceOrientation = *(int*)(arg);
webcam->captureVideoPreviewLayer.orientation = devideOrientation2AVCaptureVideoOrientation(webcam->mDeviceOrientation);
[webcam setSize:webcam->mOutputVideoSize]; //to update size from orientation
//if ([webcam->captureVideoPreviewLayer isOrientationSupported])
// webcam->captureVideoPreviewLayer.orientation = devideOrientation2AVCaptureVideoOrientation(webcam->mDeviceOrientation);
ms_mutex_lock(&webcam->mutex);
if (webcam->msframe) {
// delete frame if any
freemsg(webcam->msframe);
webcam->msframe = 0;
}
ms_mutex_unlock(&webcam->mutex);
}
return 0;
}
......
......@@ -84,6 +84,8 @@
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderBuffer);
glClear(GL_COLOR_BUFFER_BIT);
// release GL context for this thread
[EAGLContext setCurrentContext:nil];
......@@ -104,10 +106,16 @@
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer);
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
int angle = 0;
if (orientation == UIInterfaceOrientationLandscapeRight)
angle = 270;
else if (orientation == UIInterfaceOrientationLandscapeLeft)
angle = 90;
if (!glInitDone) {
glClear(GL_COLOR_BUFFER_BIT);
} else {
ogl_display_render(helper);
ogl_display_render(helper, angle);
}
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
......@@ -132,6 +140,8 @@
storageAllocationDone = TRUE;
ogl_display_init(helper, self.superview.frame.size.width, self.superview.frame.size.height);
glClear(GL_COLOR_BUFFER_BIT);
//ogl_display_init(helper, width, height);
} else {
ogl_display_init(helper, self.superview.frame.size.width, self.superview.frame.size.height);
......@@ -151,9 +161,6 @@
}
// we use a square view, so we need to offset it
// the GL code draws in the bottom-left corner
[self setCenter: CGPointMake(
self.frame.size.width * 0.5,
self.frame.size.height * 0.5 - (self.frame.size.height - self.superview.frame.size.height))];
[self layoutSubviews];
displayLink = [self.window.screen displayLinkWithTarget:self selector:@selector(drawView:)];
......@@ -239,10 +246,7 @@ static int iosdisplay_set_native_window(MSFilter *f, void *arg) {
} else if (parentView == nil) {
return 0;
} else {
// we need to allocate a square view as it'll be used in portrait/landscape mode
// (in landscape mode, height become width etc...)
int maxDim = MAX(parentView.frame.size.width, parentView.frame.size.height);
thiz = f->data = [[IOSDisplay alloc] initWithFrame:CGRectMake(0, 0, maxDim, maxDim)];
thiz = f->data = [[IOSDisplay alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
}
thiz.imageView = parentView;
[thiz performSelectorOnMainThread:@selector(startRendering:) withObject:nil waitUntilDone:NO];
......
......@@ -34,12 +34,6 @@ static void load_orthographic_matrix(float left, float right, float bottom, floa
static unsigned int align_on_power_of_2(unsigned int value);
static bool_t update_textures_with_yuv(struct opengles_display* gldisp, enum ImageType type);
static const GLfloat squareVertices[] = {
0, 0,
1, 0,
0, 1,
1, 1
};
#define CHECK_GL_ERROR
......@@ -53,7 +47,8 @@ static const GLfloat squareVertices[] = {
#endif
enum {
UNIFORM_MATRIX = 0,
UNIFORM_PROJ_MATRIX = 0,
UNIFORM_ROTATION,
UNIFORM_TEXTURE_Y,
UNIFORM_TEXTURE_U,
UNIFORM_TEXTURE_V,
......@@ -209,7 +204,7 @@ void ogl_display_set_preview_yuv_to_display(struct opengles_display* gldisp, mbl
ogl_display_set_yuv(gldisp, yuv, PREVIEW_IMAGE);
}
static void ogl_display_render_type(struct opengles_display* gldisp, enum ImageType type, bool_t clear, float vpx, float vpy, float vpw, float vph) {
static void ogl_display_render_type(struct opengles_display* gldisp, enum ImageType type, bool_t clear, float vpx, float vpy, float vpw, float vph, int orientation) {
if (!gldisp) {
ms_error("%s called with null struct opengles_display", __FUNCTION__);
return;
......@@ -240,25 +235,47 @@ static void ogl_display_render_type(struct opengles_display* gldisp, enum ImageT
GL_OPERATION(glClear(GL_COLOR_BUFFER_BIT))
}
int x,y,w,h;
if (gldisp->backingHeight * vph > gldisp->backingWidth * vpw) {
GLfloat squareVertices[8];
int screenW, screenH;
int x,y,w,h;
if (orientation == 0) {
float ratio = (gldisp->yuv_size[type].height) / (float)(gldisp->yuv_size[type].width);
screenW = gldisp->backingWidth;
screenH = gldisp->backingHeight;
w = gldisp->backingWidth * vpw;
h = w * ratio;
x = vpx * gldisp->backingWidth;
y = vpy * gldisp->backingHeight + (gldisp->backingHeight * vph - h) * 0.5f;
y = vpy * gldisp->backingHeight;
} else {
float ratio = gldisp->yuv_size[type].width / (float)gldisp->yuv_size[type].height;
h = gldisp->backingHeight * vph;
screenW = gldisp->backingHeight;
screenH = gldisp->backingWidth;
h = screenH * vph;
w = h * ratio;
x = vpx * gldisp->backingWidth + (gldisp->backingWidth * vpw - w) * 0.5f;
y = vpy * gldisp->backingHeight;
x = vpx * screenW;
y = vpy * screenH;
}
GL_OPERATION(glViewport(x, y, w, h))
squareVertices[0] = (x - w * 0.5) / screenW - 0.;
squareVertices[1] = (y - h * 0.5) / screenH - 0.;
squareVertices[2] = (x + w * 0.5) / screenW - 0.;
squareVertices[3] = (y - h * 0.5) / screenH - 0.;
squareVertices[4] = (x - w * 0.5) / screenW - 0.;
squareVertices[5] = (y + h * 0.5) / screenH - 0.;
squareVertices[6] = (x + w * 0.5) / screenW - 0.;
squareVertices[7] = (y + h * 0.5) / screenH - 0.;
GL_OPERATION(glViewport(0, 0, gldisp->backingWidth, gldisp->backingHeight))
GLfloat mat[16];
load_orthographic_matrix(0, 1, 0, 1, 0, 1, mat);
GL_OPERATION(glUniformMatrix4fv(gldisp->uniforms[UNIFORM_MATRIX], 1, GL_FALSE, mat))
load_orthographic_matrix(-0.5, 0.5, -0.5, 0.5, 0, 0.5, mat);
GL_OPERATION(glUniformMatrix4fv(gldisp->uniforms[UNIFORM_PROJ_MATRIX], 1, GL_FALSE, mat))
#define degreesToRadians(d) (2.0 * 3.14157 * d / 360.0)
float rad = degreesToRadians(orientation);
GL_OPERATION(glUniform1f(gldisp->uniforms[UNIFORM_ROTATION], rad))
GL_OPERATION(glActiveTexture(GL_TEXTURE0))
GL_OPERATION(glBindTexture(GL_TEXTURE_2D, gldisp->textures[type][Y]))
......@@ -279,9 +296,9 @@ static void ogl_display_render_type(struct opengles_display* gldisp, enum ImageT
}
void ogl_display_render(struct opengles_display* gldisp) {
ogl_display_render_type(gldisp, REMOTE_IMAGE, TRUE, 0, 0, 1, 1);
ogl_display_render_type(gldisp, PREVIEW_IMAGE, FALSE, 0.8f, 0.0f, 0.2f, 0.2f);
void ogl_display_render(struct opengles_display* gldisp, int orientation) {
ogl_display_render_type(gldisp, REMOTE_IMAGE, TRUE, 0, 0, 1, 1, orientation);
ogl_display_render_type(gldisp, PREVIEW_IMAGE, FALSE, 0.8f, 0.0f, 0.2f, 0.2f, orientation);
}
static void check_GL_errors(const char* context) {
......@@ -323,7 +340,8 @@ static bool_t load_shaders(GLuint* program, GLint* uniforms) {
if (!linkProgram(*program))
return FALSE;
uniforms[UNIFORM_MATRIX] = glGetUniformLocation(*program, "matrix");
uniforms[UNIFORM_PROJ_MATRIX] = glGetUniformLocation(*program, "proj_matrix");
uniforms[UNIFORM_ROTATION] = glGetUniformLocation(*program, "rotation");
uniforms[UNIFORM_TEXTURE_Y] = glGetUniformLocation(*program, "t_texture_y");
uniforms[UNIFORM_TEXTURE_U] = glGetUniformLocation(*program, "t_texture_u");
uniforms[UNIFORM_TEXTURE_V] = glGetUniformLocation(*program, "t_texture_v");
......@@ -343,11 +361,11 @@ static void load_orthographic_matrix(float left, float right, float bottom, floa
float ty = - (top + bottom) / (top - bottom);
float tz = - (far + near) / (far - near);
mat[0] = 2.0f / r_l;
mat[0] = (2.0f / r_l);
mat[1] = mat[2] = mat[3] = 0.0f;
mat[4] = 0.0f;
mat[5] = 2.0f / t_b;
mat[5] = (2.0f / t_b);
mat[6] = mat[7] = 0.0f;
mat[8] = mat[9] = 0.0f;
......
......@@ -64,7 +64,7 @@ void ogl_display_set_yuv_to_display(struct opengles_display* gldisp, mblk_t *yuv
*/
void ogl_display_set_preview_yuv_to_display(struct opengles_display* gldisp, mblk_t *yuv);
void ogl_display_render(struct opengles_display* gldisp);
void ogl_display_render(struct opengles_display* gldisp, int deviceAngleFromPortrait);
#ifdef ANDROID
#include <jni.h>
......
......@@ -32,14 +32,14 @@ GLint compileShader(GLuint *shader, GLenum type, const char *sources)
{
char *log = (char *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
ms_debug("Shader compile log:\n%s", log);
ms_error("Shader compile log:\n%s", log);
free(log);
}
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
ms_error("Failed to compile shader:\n");
ms_error("Failed to compile shader\n");
}
return status;
......
#define YUV2RGB_VERTEX_SHADER "attribute vec4 position;\n" \
#if TARGET_OS_IPHONE || defined(ANDROID)
#define PRECISION_DECL "precision mediump float;\n"
#else
#define PRECISION_DECL ""
#endif
#define YUV2RGB_VERTEX_SHADER "attribute vec2 position;\n" \
"attribute vec2 uv;\n" \
"uniform mat4 matrix;\n" \
"uniform mat4 proj_matrix;\n" \
"uniform float rotation;\n" \
"varying vec2 uvVarying;\n" \
"\n" \
"void main()\n" \
"{\n" \
" gl_Position = matrix * position;\n" \
" mat3 rot = mat3(vec3(cos(rotation), sin(rotation),0.0), vec3(-sin(rotation), cos(rotation), 0.0), vec3(0.0, 0.0, 1.0));\n" \
" gl_Position = proj_matrix * vec4(rot * vec3(position.xy, 0.0), 1.0);\n" \
" uvVarying = uv;\n" \
"}\n"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment