📄 voutqt.m
字号:
/* Save the origin and clipping rectangle used by the host application * (e.g. Mozilla), so we can restore it later */ GetPortBounds( p_vout->p_sys->p_qdport, &saved_rect ); GetClip( saved_clip ); /* The port gets unlocked at the end of this function */ LockPortBits( p_vout->p_sys->p_qdport ); /* Change the origin and clipping to the coordinates that the embedded * window wants to draw at */ SetPort( p_vout->p_sys->p_qdport ); SetOrigin( p_vout->p_sys->portx , p_vout->p_sys->porty ); ClipRect( &p_vout->p_sys->clipping_rect ); } if( ( err = DecompressSequenceFrameWhen( p_vout->p_sys->i_seq, p_pic->p_sys->p_data, p_pic->p_sys->i_size, codecFlagUseImageBuffer, &flags, NULL, NULL ) != noErr ) ) { msg_Warn( p_vout, "DecompressSequenceFrameWhen failed: %d", err ); } else { if( !p_vout->p_sys->b_embedded ) QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil ); } if( p_vout->p_sys->b_embedded ) { /* Restore the origin and clipping rectangle to the settings used * by the host application */ SetOrigin( saved_rect.left, saved_rect.top ); SetClip( saved_clip ); UnlockPortBits( p_vout->p_sys->p_qdport ); }}/***************************************************************************** * ControlVideo: control facility for the vout *****************************************************************************/static int ControlVideo( vout_thread_t *p_vout, int i_query, va_list args ){ vlc_bool_t b_arg; switch( i_query ) { case VOUT_SET_STAY_ON_TOP: b_arg = va_arg( args, vlc_bool_t ); [p_vout->p_sys->o_window setOnTop: b_arg]; return VLC_SUCCESS; case VOUT_CLOSE: case VOUT_REPARENT: default: return vout_vaControlDefault( p_vout, i_query, args ); }}/***************************************************************************** * CoToggleFullscreen: toggle fullscreen ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int CoToggleFullscreen( vout_thread_t *p_vout ){ NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; QTDestroySequence( p_vout ); if( !p_vout->b_fullscreen ) { /* Save window size and position */ p_vout->p_sys->s_frame.size = [[p_vout->p_sys->o_window contentView] frame].size; p_vout->p_sys->s_frame.origin = [p_vout->p_sys->o_window frame].origin; p_vout->p_sys->b_saved_frame = VLC_TRUE; } [p_vout->p_sys->o_window close]; p_vout->b_fullscreen = !p_vout->b_fullscreen;#define o_qtview p_vout->p_sys->o_qtview o_qtview = [[VLCQTView alloc] initWithVout: p_vout]; [o_qtview autorelease]; if( p_vout->p_sys->b_saved_frame ) { p_vout->p_sys->o_window = [[VLCWindow alloc] initWithVout: p_vout view: o_qtview frame: &p_vout->p_sys->s_frame]; } else { p_vout->p_sys->o_window = [[VLCWindow alloc] initWithVout: p_vout view: o_qtview frame: nil]; } /* Retrieve the QuickDraw port */ [o_qtview lockFocus]; p_vout->p_sys->p_qdport = [o_qtview qdPort]; [o_qtview unlockFocus];#undef o_qtview SetPort( p_vout->p_sys->p_qdport ); QTScaleMatrix( p_vout ); if( QTCreateSequence( p_vout ) ) { msg_Err( p_vout, "unable to create sequence" ); return( 1 ); } [o_pool release]; return 0;}/***************************************************************************** * QTScaleMatrix: scale matrix *****************************************************************************/static void QTScaleMatrix( vout_thread_t *p_vout ){ Rect s_rect; vlc_value_t val; unsigned int i_width, i_height; Fixed factor_x, factor_y; unsigned int i_offset_x = 0; unsigned int i_offset_y = 0; GetPortBounds( p_vout->p_sys->p_qdport, &s_rect ); i_width = s_rect.right - s_rect.left; i_height = s_rect.bottom - s_rect.top; if( p_vout->p_sys->b_embedded ) { /* Embedded video get their drawing region from the host application * by the drawable values here. Read those variables, and store them * in the p_vout->p_sys structure so that other functions (such as * DisplayVideo and ManageVideo) can use them later. */ vlc_value_t valt, vall, valb, valr, valx, valy, valw, valh, valportx, valporty; var_Get( p_vout->p_vlc, "drawable", &val ); var_Get( p_vout->p_vlc, "drawablet", &valt ); var_Get( p_vout->p_vlc, "drawablel", &vall ); var_Get( p_vout->p_vlc, "drawableb", &valb ); var_Get( p_vout->p_vlc, "drawabler", &valr ); var_Get( p_vout->p_vlc, "drawablex", &valx ); var_Get( p_vout->p_vlc, "drawabley", &valy ); var_Get( p_vout->p_vlc, "drawablew", &valw ); var_Get( p_vout->p_vlc, "drawableh", &valh ); var_Get( p_vout->p_vlc, "drawableportx", &valportx ); var_Get( p_vout->p_vlc, "drawableporty", &valporty ); p_vout->p_sys->portx = valportx.i_int; p_vout->p_sys->porty = valporty.i_int; p_vout->p_sys->p_qdport = (CGrafPtr) val.i_int; i_width = valw.i_int; i_height = valh.i_int; p_vout->p_sys->clipping_rect.top = 0; p_vout->p_sys->clipping_rect.left = 0; p_vout->p_sys->clipping_rect.bottom = valb.i_int - valt.i_int; p_vout->p_sys->clipping_rect.right = valr.i_int - vall.i_int; } var_Get( p_vout, "macosx-stretch", &val ); if( val.b_bool ) { factor_x = FixDiv( Long2Fix( i_width ), Long2Fix( p_vout->output.i_width ) ); factor_y = FixDiv( Long2Fix( i_height ), Long2Fix( p_vout->output.i_height ) ); } else if( i_height * p_vout->output.i_aspect < i_width * VOUT_ASPECT_FACTOR ) { int i_adj_width = i_height * p_vout->output.i_aspect / VOUT_ASPECT_FACTOR; factor_x = FixDiv( Long2Fix( i_adj_width ), Long2Fix( p_vout->output.i_width ) ); factor_y = FixDiv( Long2Fix( i_height ), Long2Fix( p_vout->output.i_height ) ); i_offset_x = (i_width - i_adj_width) / 2; } else { int i_adj_height = i_width * VOUT_ASPECT_FACTOR / p_vout->output.i_aspect; factor_x = FixDiv( Long2Fix( i_width ), Long2Fix( p_vout->output.i_width ) ); factor_y = FixDiv( Long2Fix( i_adj_height ), Long2Fix( p_vout->output.i_height ) ); i_offset_y = (i_height - i_adj_height) / 2; } SetIdentityMatrix( p_vout->p_sys->p_matrix ); ScaleMatrix( p_vout->p_sys->p_matrix, factor_x, factor_y, Long2Fix(0), Long2Fix(0) ); TranslateMatrix( p_vout->p_sys->p_matrix, Long2Fix(i_offset_x), Long2Fix(i_offset_y) );}/***************************************************************************** * QTCreateSequence: create a new sequence ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int QTCreateSequence( vout_thread_t *p_vout ){ OSErr err; ImageDescriptionPtr p_descr; HLock( (Handle)p_vout->p_sys->h_img_descr ); p_descr = *p_vout->p_sys->h_img_descr; p_descr->idSize = sizeof(ImageDescription); p_descr->cType = p_vout->p_sys->i_codec; p_descr->version = 2; p_descr->revisionLevel = 0; p_descr->vendor = 'mpla'; p_descr->width = p_vout->output.i_width; p_descr->height = p_vout->output.i_height; p_descr->hRes = Long2Fix(72); p_descr->vRes = Long2Fix(72); p_descr->spatialQuality = codecLosslessQuality; p_descr->frameCount = 1; p_descr->clutID = -1; p_descr->dataSize = 0; p_descr->depth = 24; HUnlock( (Handle)p_vout->p_sys->h_img_descr ); if( ( err = DecompressSequenceBeginS( &p_vout->p_sys->i_seq, p_vout->p_sys->h_img_descr, NULL, (p_descr->width * p_descr->height * 16) / 8, p_vout->p_sys->p_qdport, NULL, NULL, p_vout->p_sys->p_matrix, srcCopy, NULL, codecFlagUseImageBuffer, codecLosslessQuality, bestSpeedCodec ) ) ) { msg_Err( p_vout, "DecompressSequenceBeginS failed: %d", err ); return( 1 ); } return( 0 );}/***************************************************************************** * QTDestroySequence: destroy sequence *****************************************************************************/static void QTDestroySequence( vout_thread_t *p_vout ){ CDSequenceEnd( p_vout->p_sys->i_seq );}/***************************************************************************** * QTNewPicture: allocate a picture ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int QTNewPicture( vout_thread_t *p_vout, picture_t *p_pic ){ /* We know the chroma, allocate a buffer which will be used * directly by the decoder */ p_pic->p_sys = malloc( sizeof( picture_sys_t ) ); if( p_pic->p_sys == NULL ) { return( -1 ); } vout_InitPicture( VLC_OBJECT( p_vout), p_pic, p_vout->output.i_chroma, p_vout->output.i_width, p_vout->output.i_height, p_vout->output.i_aspect ); switch( p_vout->output.i_chroma ) { case VLC_FOURCC('Y','U','Y','2'): p_pic->p_sys->i_size = p_vout->output.i_width * p_vout->output.i_height * 2; /* Allocate the memory buffer */ p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, p_pic->p_sys->i_size ); p_pic->p[0].p_pixels = p_pic->p_data; p_pic->p[0].i_lines = p_vout->output.i_height; p_pic->p[0].i_visible_lines = p_vout->output.i_height; p_pic->p[0].i_pitch = p_vout->output.i_width * 2; p_pic->p[0].i_pixel_pitch = 1; p_pic->p[0].i_visible_pitch = p_vout->output.i_width * 2; p_pic->i_planes = 1; p_pic->p_sys->p_data = (void *)p_pic->p[0].p_pixels; break; case VLC_FOURCC('I','4','2','0'): p_pic->p_sys->p_data = (void *)&p_pic->p_sys->pixmap_i420; p_pic->p_sys->i_size = sizeof(PlanarPixmapInfoYUV420); /* Allocate the memory buffer */ p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, p_vout->output.i_width * p_vout->output.i_height * 3 / 2 ); /* Y buffer */ p_pic->Y_PIXELS = p_pic->p_data; p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height; p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height; p_pic->p[Y_PLANE].i_pitch = p_vout->output.i_width; p_pic->p[Y_PLANE].i_pixel_pitch = 1; p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width; /* U buffer */ p_pic->U_PIXELS = p_pic->Y_PIXELS + p_vout->output.i_height * p_vout->output.i_width; p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2; p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2; p_pic->p[U_PLANE].i_pitch = p_vout->output.i_width / 2; p_pic->p[U_PLANE].i_pixel_pitch = 1; p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2; /* V buffer */ p_pic->V_PIXELS = p_pic->U_PIXELS + p_vout->output.i_height * p_vout->output.i_width / 4; p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2; p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2; p_pic->p[V_PLANE].i_pitch = p_vout->output.i_width / 2; p_pic->p[V_PLANE].i_pixel_pitch = 1; p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2; /* We allocated 3 planes */ p_pic->i_planes = 3;#define P p_pic->p_sys->pixmap_i420 P.componentInfoY.offset = (void *)p_pic->Y_PIXELS - p_pic->p_sys->p_data; P.componentInfoCb.offset = (void *)p_pic->U_PIXELS - p_pic->p_sys->p_data; P.componentInfoCr.offset = (void *)p_pic->V_PIXELS - p_pic->p_sys->p_data; P.componentInfoY.rowBytes = p_vout->output.i_width; P.componentInfoCb.rowBytes = p_vout->output.i_width / 2; P.componentInfoCr.rowBytes = p_vout->output.i_width / 2;#undef P break; default: /* Unknown chroma, tell the guy to get lost */ free( p_pic->p_sys ); msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)", p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma ); p_pic->i_planes = 0; return( -1 ); } return( 0 );}/***************************************************************************** * QTFreePicture: destroy a picture allocated with QTNewPicture *****************************************************************************/static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ){ switch( p_vout->output.i_chroma ) { case VLC_FOURCC('I','4','2','0'): free( p_pic->p_data_orig ); break; } free( p_pic->p_sys );}/***************************************************************************** * VLCQTView implementation *****************************************************************************/@implementation VLCQTView- (id) initWithVout:(vout_thread_t *)_p_vout{ p_vout = _p_vout; return [super init];}- (void)drawRect:(NSRect)rect{ [[NSColor blackColor] set]; NSRectFill( rect ); [super drawRect: rect]; p_vout->i_changes |= VOUT_SIZE_CHANGE;}@end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -