[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