[vlc-devel] [PATCH 1/8] Add CALayer module
Pierre d'Herbemont
pdherbemont at free.fr
Fri Sep 10 10:03:34 CEST 2010
Seems fine.
About the coding style, could you pick one, ie:
> + if( self = [super init] )
and
> + if (currentpic != NULL)
...
Also:
> +- (void) setPic: (picture_t *) p_pic
We generally would not put spaces after "(void)", ":" and |(picture_t *)"
> + if( self = [super init] )
> + {
> + currentpic = NULL;
> + vd = p_vd;
> + pthread_mutex_init(&mutex, NULL);
NSLock?
Thanks! This is a very simple vout in the end which is nice.
Pierre.
> +/**
> + * This function draws the current image into the layer with a size
> + * and position based on the layer's current bounds.
> + */
> +- (void) drawLayer: (CALayer *)layer inContext: (CGContextRef) theContext
> +{
> + // Determine where to draw the image.
> + vout_display_cfg_t place_cfg = *vd->cfg;
> + CGRect bounds = layer.bounds;
> + place_cfg.display.width = bounds.size.width;
> + place_cfg.display.height = bounds.size.height;
> + vout_display_place_t place;
> + vout_display_PlacePicture(&place, &vd->source, &place_cfg, FALSE);
> +
> + CGRect imagePosition = CGRectMake(place.x, place.y, place.width, place.height);
> +
> + pthread_mutex_lock(&mutex);
> + if (currentpic != NULL)
> + {
> + // Create a CGImage to put in the layer
> + CGImageRef image = CGImageCreate(currentpic->format.i_width, currentpic->format.i_height,
> + 8, 32, currentpic->p[0].i_pitch, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipLast |
> + kCGBitmapByteOrder32Big, currentpic->p_sys->p_provider, NULL, TRUE,
> + kCGRenderingIntentDefault);
> + CGContextDrawImage(theContext, imagePosition, image);
> + CGImageRelease(image);
> + }
> + pthread_mutex_unlock(&mutex);
> +
> +}
> +/**
> + * This function is called by the vout display's Display() function to deliver
> + * the most recent frame to the delegate. This function will release the old
> + * (if any) picture_t back to the pool. The provided picture_t pointer may be
> + * NULL.
> + */
> +- (void) setPic: (picture_t *) p_pic
> +{
> + pthread_mutex_lock(&mutex);
> +
> + if (currentpic != NULL)
> + picture_Release(currentpic);
> +
> + currentpic = p_pic;
> +
> + if (currentpic != NULL)
> + picture_Hold(currentpic);
> +
> + pthread_mutex_unlock(&mutex);
> +}
> +- (void) dealloc
> +{
> + vd = NULL;
> + [self setPic: NULL];
> + pthread_mutex_destroy(&mutex);
> + [super dealloc];
> +}
> + at end
> +
> +static CALayer *getDrawable(vout_display_t *vd)
> +{
> + CALayer *layer = var_CreateGetAddress(vd, "drawable-nsobject");
> + var_Destroy(vd, "drawable-nsobject");
> + return layer;
> +}
> +
> +static int Open(vlc_object_t *this)
> +{
> + vout_display_t *vd = (vout_display_t *)this;
> + vout_display_sys_t *sys = calloc(1, sizeof(*sys));
> + vd->sys = sys;
> +
> + if( !sys )
> + return VLC_ENOMEM;
> +
> + CALayer *layer = getDrawable(vd);
> + if( !layer )
> + {
> + msg_Dbg(vd, "No drawable-nsobject, passing over.");
> + goto error;
> + }
> +
> + // Store a pointer to the layer, construct and assign the delegate
> + sys->p_calayer = [layer retain];
> + sys->p_delegate = [[VLCLayerDelegate alloc] initWithVd:vd];
> + sys->p_calayer.delegate = sys->p_delegate;
> +
> + // Apple docs mention RGBA-32, so we'll do that.
> + video_format_t fmt = vd->fmt;
> + fmt.i_chroma = VLC_CODEC_RGBA;
> +
> + vout_display_info_t info = vd->info;
> + info.has_pictures_invalid = false;
> +
> + // Setup fields in vd
> + vd->pool = Pool;
> + vd->prepare = NULL;
> + vd->display = Display;
> + vd->control = Control;
> + vd->manage = NULL;
> + vd->info = info;
> + vd->fmt = fmt;
> +
> + return VLC_SUCCESS;
> +
> +error:
> + Close(this);
> + return VLC_EGENERIC;
> +}
> +
> +/*****************************************************************************
> + * vout display callbacks
> + *****************************************************************************/
> +
> +/**
> + * This function adds module specific "sys" data to the given picture_t.
> + * We cache a CGDataProvider for each picture_t.
> + */
> +static void fillPictureSysData(picture_t *pic)
> +{
> + calayer_picture_sys_t *picsys = pic->p_sys = calloc(1, sizeof(calayer_picture_sys_t));
> +
> + // Create the data provider/CGImage
> + CGDataProviderRef data = CGDataProviderCreateWithData(NULL,
> + pic->p[0].p_pixels, pic->p[0].i_pitch * pic->p[0].i_lines, NULL);
> +
> + picsys->p_provider = data;
> +}
> +
> +/**
> + * This funtion frees the module specific data (created by fillPictureSysData)
> + * in the given picture_t.
> + */
> +static void freePictureSysData(picture_t *pic)
> +{
> + if( pic->p_sys )
> + {
> + CGDataProviderRelease(pic->p_sys->p_provider);
> + free(pic->p_sys);
> + pic->p_sys = NULL;
> + }
> +}
> +
> +/**
> + * This function creates our picture pool and stores it in our sys structure.
> + */
> +static void fillPool(vout_display_t *vd, unsigned count)
> +{
> + picture_t **picture = calloc(count, sizeof *picture);
> + if( !picture )
> + return;
> +
> + // Create count pictures, and add sys data to each one.
> + for( int i = 0; i < count; i++ ) {
> + picture[i] = picture_NewFromFormat(&vd->fmt);
> + if( !picture[i] )
> + goto error;
> + fillPictureSysData(picture[i]);
> + }
> +
> + // Create the pool from the picture array
> + picture_pool_t *pool = picture_pool_New(count, picture);
> + if( !pool )
> + goto error;
> +
> + // Store the relevant information in our sys structure.
> + vd->sys->p_pool = pool;
> + vd->sys->p_pictures = picture;
> + vd->sys->picture_count = count;
> + return;
> +
> +error:
> + for( int i = 0; i < count; i++ ) {
> + if( !picture[i] )
> + break;
> + picture_Release(picture[i]);
> + }
> + free(picture);
> + return;
> +}
> +
> +/**
> + * This function frees the picture pool created by fillPool().
> + */
> +static void freePool(vout_display_sys_t *sys)
> +{
> + picture_pool_t *pool = sys->p_pool;
> + if( !pool )
> + return;
> +
> + // free the sys data from each picture
> + for( int i = 0; i < sys->picture_count; i++ )
> + freePictureSysData(sys->p_pictures[i]);
> +
> + // free the pool itself
> + picture_pool_Delete(pool);
> +
> + sys->p_pool = NULL;
> +
> + if( sys->p_pictures )
> + free(sys->p_pictures);
> + sys->p_pictures = NULL;
> +}
> +
> +static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
> +{
> + vout_display_sys_t *sys = vd->sys;
> +
> + if( !sys->p_pool )
> + {
> + // We always request an extra picture_t in the pool because
> + // the VLCLayerDelegate holds its picture_t out of the pool
> + fillPool(vd, count + 1);
> + }
> + assert(sys->p_pool);
> + return sys->p_pool;
> +}
> +
> +static void Display(vout_display_t *vd, picture_t *pic)
> +{
> + vout_display_sys_t *sys = vd->sys;
> + assert(pic->i_planes == 1);
> + assert(pic->format.i_bits_per_pixel == 32);
> +
> + assert(sys != NULL);
> + assert(sys->p_calayer != NULL);
> +
> + // send the picture to the delegate and ask the main thread to redraw the layer.
> + [sys->p_delegate setPic:pic];
> + [sys->p_calayer performSelectorOnMainThread: @selector(setNeedsDisplay) withObject:nil waitUntilDone:false];
> +
> + // We release our reference to the picture_t here, but the delegate still holds
> + // a reference that will not be released until the next picture_t is handed to it.
> + picture_Release (pic);
> +}
> +
> +static int Control (vout_display_t *vd, int query, va_list ap)
> +{
> + vout_display_sys_t *sys = vd->sys;
> +
> + switch (query)
> + {
> + case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
> + case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
> + case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
> + case VOUT_DISPLAY_CHANGE_ZOOM:
> + case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
> + {
> + /* todo */
> + return VLC_EGENERIC;
> + }
> + case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
> + {
> + const vout_display_cfg_t *cfg = vd->cfg;
> + const video_format_t *source = va_arg(ap, const video_format_t *);
> +
> + // Aspect ratio changes are handled by drawing the picture in the new
> + // aspect ratio in the VLCLayerDelegate. So we just return success here.
> + return VLC_SUCCESS;
> + }
> +
> + case VOUT_DISPLAY_HIDE_MOUSE:
> + return VLC_SUCCESS;
> +
> + case VOUT_DISPLAY_GET_OPENGL:
> + {
> + return VLC_EGENERIC;
> + }
> + case VOUT_DISPLAY_RESET_PICTURES:
> + assert (0);
> + default:
> + msg_Err (vd, "Unknown request in Mac OS X CALayer vout display");
> + return VLC_EGENERIC;
> + }
> +}
> +
> +void Close(vlc_object_t *this)
> +{
> + vout_display_t *vd = (vout_display_t *)this;
> +
> + if( vd->sys )
> + {
> + vout_display_sys_t *sys = vd->sys;
> +
> + [sys->p_delegate setPic:NULL];
> + sys->p_calayer.delegate = NULL;
> + [sys->p_delegate release];
> + [sys->p_calayer release];
> +
> + freePool(sys);
> + free(sys);
> + vd->sys = NULL;
> + }
> +}
> --
> 1.7.0.3
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> http://mailman.videolan.org/listinfo/vlc-devel
>
More information about the vlc-devel
mailing list