📄 opengllayer.m
字号:
* Destroy: destroy GLX video thread output method ***************************************************************************** * Terminate an output method created by CreateVout *****************************************************************************/static void DestroyVout( vlc_object_t *p_this ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; vout_sys_t *p_sys = p_vout->p_sys; free( p_sys );}/***************************************************************************** * Manage: handle Sys events ***************************************************************************** * This function should be called regularly by video output thread. It returns * a non null value if an error occurred. *****************************************************************************/static int Manage( vout_thread_t *p_vout ){ vout_sys_t *p_sys = p_vout->p_sys; return VLC_SUCCESS;}/***************************************************************************** * Render: render previously calculated output *****************************************************************************/static void Render( vout_thread_t *p_vout, picture_t *p_pic ){ vout_sys_t *p_sys = p_vout->p_sys; @synchronized( p_sys->o_layer ) /* Make sure the p_sys->glContext isn't edited */ { if( p_sys->glContext ) { CGLLockContext(p_sys->glContext); CGLSetCurrentContext(p_sys->glContext); int i_new_index; i_new_index = ( p_sys->i_index + 1 ) & 1; /* Update the texture */ glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_new_index] ); glTexSubImage2D( VLCGL_TARGET, 0, 0, 0, p_vout->fmt_out.i_width, p_vout->fmt_out.i_height, VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[i_new_index] ); /* Bind to the previous texture for drawing */ glBindTexture( VLCGL_TARGET, p_sys->p_textures[p_sys->i_index] ); /* Switch buffers */ p_sys->i_index = i_new_index; p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index]; CGLUnlockContext(p_sys->glContext); p_sys->b_frame_available = true; } } /* Give a buffer where the image will be rendered */ p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index];}/***************************************************************************** * DisplayVideo: displays previously rendered output *****************************************************************************/static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ){ vout_sys_t *p_sys = p_vout->p_sys; [p_sys->o_layer performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:YES];}/***************************************************************************** * Control: control facility for the vout *****************************************************************************/static int Control( vout_thread_t *p_vout, int i_query, va_list args ){ vout_sys_t *p_sys = p_vout->p_sys; switch( i_query ) { case VOUT_SNAPSHOT: return vout_vaControlDefault( p_vout, i_query, args ); default: if( p_sys->p_vout->pf_control ) return p_sys->p_vout->pf_control( p_sys->p_vout, i_query, args ); else return vout_vaControlDefault( p_vout, i_query, args ); }}/***************************************************************************** * InitTextures *****************************************************************************/static int InitTextures( vout_thread_t *p_vout ){ vout_sys_t *p_sys = p_vout->p_sys; int i_index; glDeleteTextures( 2, p_sys->p_textures ); glGenTextures( 2, p_sys->p_textures ); for( i_index = 0; i_index < 2; i_index++ ) { glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_index] ); /* Set the texture parameters */ glTexParameterf( VLCGL_TARGET, GL_TEXTURE_PRIORITY, 1.0 ); glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); /* Note: It seems that we can't bypass those, and even * disabled they are used. They are the cause of the flickering */ /* Tell the driver not to make a copy of the texture but to use our buffer */ glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE ); glPixelStorei( GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE ); /* Use AGP texturing */ glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE ); /* Call glTexImage2D only once, and use glTexSubImage2D later */ glTexImage2D( VLCGL_TARGET, 0, 4, p_sys->i_tex_width, p_sys->i_tex_height, 0, VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[i_index] ); } return 0;}/***************************************************************************** * @implementation VLCVoutLayer */@implementation VLCVoutLayer/***************************************************************************** * autoinitInVout: Called from the video thread to create a layer. * The created layer is stored in the p_vout. We do that way because, cocoa * doesn't support layer creation on non-main thread. *****************************************************************************/+ (void)autoinitInVout:(NSValue*)arg{ vout_thread_t * p_vout = [arg pointerValue]; p_vout->p_sys->o_layer = [[VLCVoutLayer layerWithVout:p_vout] retain]; [p_vout->p_sys->o_cocoa_container addVoutLayer:p_vout->p_sys->o_layer];}+ (id)layerWithVout:(vout_thread_t*)_p_vout { VLCVoutLayer* me = [[[self alloc] init] autorelease]; if( me ) { me->p_vout = _p_vout; me.asynchronous = NO; me.bounds = CGRectMake( 0.0, 0.0, (float)_p_vout->fmt_in.i_visible_width * _p_vout->fmt_in.i_sar_num, (float)_p_vout->fmt_in.i_visible_height * _p_vout->fmt_in.i_sar_den ); } return me;}- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp{ /* Only draw the frame if we have a frame that was previously rendered */ return p_vout->p_sys->b_frame_available; // Flag is cleared by drawInCGLContext:pixelFormat:forLayerTime:displayTime:}- (void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp{ CGLLockContext( glContext ); CGLSetCurrentContext( glContext ); float f_width, f_height, f_x, f_y; f_x = (float)p_vout->fmt_out.i_x_offset; f_y = (float)p_vout->fmt_out.i_y_offset; f_width = (float)p_vout->fmt_out.i_x_offset + (float)p_vout->fmt_out.i_visible_width; f_height = (float)p_vout->fmt_out.i_y_offset + (float)p_vout->fmt_out.i_visible_height; glClear( GL_COLOR_BUFFER_BIT ); glEnable( VLCGL_TARGET ); glBegin( GL_POLYGON ); glTexCoord2f( f_x, f_y ); glVertex2f( -1.0, 1.0 ); glTexCoord2f( f_width, f_y ); glVertex2f( 1.0, 1.0 ); glTexCoord2f( f_width, f_height ); glVertex2f( 1.0, -1.0 ); glTexCoord2f( f_x, f_height ); glVertex2f( -1.0, -1.0 ); glEnd(); glDisable( VLCGL_TARGET ); glFlush(); CGLUnlockContext( glContext );}- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat{ CGLContextObj context = [super copyCGLContextForPixelFormat:pixelFormat]; CGLLockContext( context ); CGLSetCurrentContext( context ); /* Swap buffers only during the vertical retrace of the monitor. http://developer.apple.com/documentation/GraphicsImaging/ Conceptual/OpenGL/chap5/chapter_5_section_44.html */ GLint params = 1; CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval, ¶ms ); InitTextures( p_vout ); glDisable( GL_BLEND ); glDisable( GL_DEPTH_TEST ); glDepthMask( GL_FALSE ); glDisable( GL_CULL_FACE) ; glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT ); CGLUnlockContext( context ); @synchronized( self ) { p_vout->p_sys->glContext = context; } return context;}- (void)releaseCGLContext:(CGLContextObj)glContext{ @synchronized( self ) { p_vout->p_sys->glContext = nil; } CGLLockContext( glContext ); CGLSetCurrentContext( glContext ); glDeleteTextures( 2, p_vout->p_sys->p_textures ); CGLUnlockContext( glContext );}@end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -