Пример #1
0
/*****************************************************************************
 * Display: Map p_image onto the screen
 *****************************************************************************/
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
    uint32_t i_width, i_height, i_x, i_y;
    uint32_t i_offset = 0;
    
    vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
                       p_vout->p_sys->i_height,
                       &i_x, &i_y, &i_width, &i_height );
    msg_Dbg( p_vout, "PlacePicture at x_left = %d, y_left = %d, x_bottom = %d, y_bottom = %d",
                i_x, i_y, i_width, i_height );

    /* Currently the only pixel format supported is 32bpp RGBA.*/
    p_vout->p_sys->p_screen->LockScreen();
    
    /* Unlock the shared memory region first. */
    if( p_pic->p_sys->p_image->Unlock() ) 
    {
        msg_Err( p_vout, "unlocking shared memory failed. Expect threading problems." );
    }
    
    p_vout->p_sys->p_screen->Blit( CascadePoint( (u32) i_x, (u32) i_y ), /* Place bitmap at */
            (*p_pic->p_sys->p_image)   ,                                      /* Image data */
            (u32) i_offset,                                   /* Offset in SharedMemoryZone */
            (u32) i_width,                                           /* Source bitmap width */
            (u32) i_height,                                         /* Source bitmap height */
            (u32) p_vout->p_sys->i_screen_depth,                      /* Source pixel depth */
            CascadeRect( (u32) i_x, (u32) i_y, (u32) i_width, (u32) i_height ) );
            
    p_vout->p_sys->p_screen->UnlockScreen();
}
Пример #2
0
/*****************************************************************************
 * Display: displays previously rendered output
 *****************************************************************************
 * This function sends the currently rendered image to the display.
 *****************************************************************************/
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
    unsigned int x, y, w, h;
    SDL_Rect disp;

    vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
                       &x, &y, &w, &h );
    disp.x = x;
    disp.y = y;
    disp.w = w;
    disp.h = h;

    if( p_vout->p_sys->p_overlay == NULL )
    {
        /* RGB picture */
        SDL_Flip( p_vout->p_sys->p_display );
    }
    else
    {
        /* Overlay picture */
        SDL_UnlockYUVOverlay( p_pic->p_sys->p_overlay);
        SDL_DisplayYUVOverlay( p_pic->p_sys->p_overlay , &disp );
        SDL_LockYUVOverlay( p_pic->p_sys->p_overlay);
    }
}
Пример #3
0
Файл: qte.cpp Проект: Kafay/vlc
/*****************************************************************************
 * Display: displays previously rendered output
 *****************************************************************************
 * This function sends the currently rendered image to screen.
 *****************************************************************************/
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
    unsigned int x, y, w, h;

    vout_PlacePicture( p_vout, p_vout->output.i_width, p_vout->output.i_height,
                       &x, &y, &w, &h );
#if 0
    msg_Dbg(p_vout, "+qte::Display( p_vout, i_width=%d, i_height=%d, x=%u, y=%u, w=%u, h=%u",
        p_vout->output.i_width, p_vout->output.i_height, x, y, w, h );
#endif

    if(p_vout->p_sys->p_VideoWidget)
    {
// shameless borrowed from opie mediaplayer....
#ifndef USE_DIRECT_PAINTER
        msg_Dbg(p_vout, "not using direct painter");
        QPainter p(p_vout->p_sys->p_VideoWidget);

        /* rotate frame */
        int dd      = QPixmap::defaultDepth();
        int bytes   = ( dd == 16 ) ? 2 : 4;
        int rw = h, rh = w;

        QImage rotatedFrame( rw, rh, bytes << 3 );

        ushort* in  = (ushort*)p_pic->p_sys->pQImage->bits();
        ushort* out = (ushort*)rotatedFrame.bits();

        int spl = rotatedFrame.bytesPerLine() / bytes;
        for (int x=0; x<h; x++)
        {
            if ( bytes == 2 )
            {
                ushort* lout = out++ + (w - 1)*spl;
                for (int y=0; y<w; y++)
                {
                    *lout=*in++;
                    lout-=spl;
                }
            }
            else
            {
                ulong* lout = ((ulong *)out)++ + (w - 1)*spl;
                for (int y=0; y<w; y++)
                {
                    *lout=*((ulong*)in)++;
                    lout-=spl;
                }
            }
        }

        p.drawImage( x, y, rotatedFrame, 0, 0, rw, rh );
#else
        QDirectPainter p(p_vout->p_sys->p_VideoWidget);
        p.transformOrientation();
        // just copy the image to the frame buffer...
        memcpy(p.frameBuffer(), (p_pic->p_sys->pQImage->jumpTable())[0], h * p.lineStep());
#endif
    }
}
Пример #4
0
/*****************************************************************************
 * Display: displays previously rendered output
 *****************************************************************************/
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
    /* No need to do anything, the fake direct buffers stay as they are */
    int i_width, i_height, i_x, i_y;

    vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
                       &i_x, &i_y, &i_width, &i_height );

    aa_flush(p_vout->p_sys->aa_context);
}
Пример #5
0
/*****************************************************************************
 * SwapBuffers: swap front/back buffers
 *****************************************************************************/
static void SwapBuffers( vout_thread_t *p_vout )
{
    vout_sys_t *p_sys = p_vout->p_sys;
    int i_width, i_height, i_x, i_y;

    vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
                       p_vout->p_sys->p_win->i_height,
                       &i_x, &i_y, &i_width, &i_height );

    glViewport( 0, 0, (GLint)i_width, (GLint)i_height );

    if( p_sys->b_glx13 )
    {
        glXSwapBuffers( p_sys->p_display, p_sys->gwnd );
    }
    else
    {
        glXSwapBuffers( p_sys->p_display, p_sys->p_win->video_window );
    }
}
Пример #6
0
/*****************************************************************************
 * VLCVIew::MouseMoved
 *****************************************************************************/
void
VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
{
    fLastMouseMovedTime = mdate();
    fCursorHidden = false;
    fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );

    if( !fCursorInside )
    {
        return;
    }

    vlc_value_t val;
    unsigned int i_width, i_height, i_x, i_y;
    vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
                       (unsigned int)Bounds().Height(),
                       &i_x, &i_y, &i_width, &i_height );
    val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
    var_Set( p_vout, "mouse-x", val );
    val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
    var_Set( p_vout, "mouse-y", val );
    val.b_bool = true;
    var_Set( p_vout, "mouse-moved", val );
}
Пример #7
0
/*****************************************************************************
 * 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 )
{
    SDL_Event event;                                            /* SDL event */
    vlc_value_t val;
    unsigned int i_width, i_height, i_x, i_y;

    /* Process events */
    while( SDL_PollEvent(&event) )
    {
        switch( event.type )
        {
        case SDL_VIDEORESIZE:                          /* Resizing of window */
            /* Update dimensions */
            p_vout->i_changes |= VOUT_SIZE_CHANGE;
            p_vout->i_window_width = p_vout->p_sys->i_width = event.resize.w;
            p_vout->i_window_height = p_vout->p_sys->i_height = event.resize.h;
            break;

        case SDL_MOUSEMOTION:
            vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
                               p_vout->p_sys->i_height,
                               &i_x, &i_y, &i_width, &i_height );

            val.i_int = ( event.motion.x - i_x )
                         * p_vout->render.i_width / i_width;
            var_Set( p_vout, "mouse-x", val );
            val.i_int = ( event.motion.y - i_y )
                         * p_vout->render.i_height / i_height;
            var_Set( p_vout, "mouse-y", val );

            val.b_bool = VLC_TRUE;
            var_Set( p_vout, "mouse-moved", val );

            if( p_vout->p_sys->b_cursor &&
                (abs(event.motion.xrel) > 2 || abs(event.motion.yrel) > 2) )
            {
                if( p_vout->p_sys->b_cursor_autohidden )
                {
                    p_vout->p_sys->b_cursor_autohidden = 0;
                    SDL_ShowCursor( 1 );
                }
                else
                {
                    p_vout->p_sys->i_lastmoved = mdate();
                }
            }
            break;

        case SDL_MOUSEBUTTONUP:
            switch( event.button.button )
            {
            case SDL_BUTTON_LEFT:
                val.b_bool = VLC_TRUE;
                var_Set( p_vout, "mouse-clicked", val );
                break;

            case SDL_BUTTON_RIGHT:
                {
                    intf_thread_t *p_intf;
                    p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
                                                      FIND_ANYWHERE );
                    if( p_intf )
                    {
                        p_intf->b_menu_change = 1;
                        vlc_object_release( p_intf );
                    }
                }
                break;
            }
            break;

        case SDL_MOUSEBUTTONDOWN:
            switch( event.button.button )
            {
            case SDL_BUTTON_LEFT:
                /* In this part we will eventually manage
                 * clicks for DVD navigation for instance. */

                /* detect double-clicks */
                if( ( mdate() - p_vout->p_sys->i_lastpressed ) < 300000 )
                    p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;

                p_vout->p_sys->i_lastpressed = mdate();
                break;

            case 4:
                break;

            case 5:
                break;
            }
            break;

        case SDL_QUIT:
            p_vout->p_vlc->b_die = 1;
            break;

        case SDL_KEYDOWN:                             /* if a key is pressed */

            switch( event.key.keysym.sym )
            {
            case SDLK_ESCAPE:
                if( p_vout->b_fullscreen )
                {
                    p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
                }
                else
                {
                    p_vout->p_vlc->b_die = 1;
                }
                break;

            case SDLK_q:                                             /* quit */
                p_vout->p_vlc->b_die = 1;
                break;

            case SDLK_f:                             /* switch to fullscreen */
                p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
                break;

            case SDLK_c:                                 /* toggle grayscale */
                p_vout->b_grayscale = ! p_vout->b_grayscale;
                p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
                break;

            case SDLK_i:                                      /* toggle info */
                p_vout->b_info = ! p_vout->b_info;
                p_vout->i_changes |= VOUT_INFO_CHANGE;
                break;

            case SDLK_s:                                   /* toggle scaling */
                p_vout->b_scale = ! p_vout->b_scale;
                p_vout->i_changes |= VOUT_SCALE_CHANGE;
                break;

            case SDLK_SPACE:                             /* toggle interface */
                p_vout->b_interface = ! p_vout->b_interface;
                p_vout->i_changes |= VOUT_INTF_CHANGE;
                break;

            case SDLK_MENU:
                {
                    intf_thread_t *p_intf;
                    p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
                                                      FIND_ANYWHERE );
                    if( p_intf != NULL )
                    {
                        p_intf->b_menu_change = 1;
                        vlc_object_release( p_intf );
                    }
                }
                break;

            case SDLK_LEFT:
                break;

            case SDLK_RIGHT:
                break;

            case SDLK_UP:
                break;

            case SDLK_DOWN:
                break;

            case SDLK_b:
                {
                    audio_volume_t i_volume;
                    if ( !aout_VolumeDown( p_vout, 1, &i_volume ) )
                    {
                        msg_Dbg( p_vout, "audio volume is now %d", i_volume );
                    }
                    else
                    {
                        msg_Dbg( p_vout, "audio volume: operation not supported" );
                    }
                }
                break;

            case SDLK_n:
                {
                    audio_volume_t i_volume;
                    if ( !aout_VolumeUp( p_vout, 1, &i_volume ) )
                    {
                        msg_Dbg( p_vout, "audio volume is now %d", i_volume );
                    }
                    else
                    {
                        msg_Dbg( p_vout, "audio volume: operation not supported" );
                    }
                }
                break;

             default:
                break;
            }
            break;

        default:
            break;
        }
    }

    /* Fullscreen change */
    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
    {
        p_vout->b_fullscreen = ! p_vout->b_fullscreen;

        p_vout->p_sys->b_cursor_autohidden = 0;
        SDL_ShowCursor( p_vout->p_sys->b_cursor &&
                        ! p_vout->p_sys->b_cursor_autohidden );

        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
        p_vout->i_changes |= VOUT_SIZE_CHANGE;
    }

    /*
     * Size change
     */
    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
    {
        msg_Dbg( p_vout, "video display resized (%dx%d)",
                 p_vout->p_sys->i_width, p_vout->p_sys->i_height );

        CloseDisplay( p_vout );
        OpenDisplay( p_vout );

        /* We don't need to signal the vout thread about the size change if
         * we can handle rescaling ourselves */
        if( p_vout->p_sys->p_overlay != NULL )
            p_vout->i_changes &= ~VOUT_SIZE_CHANGE;

    }

    /* Pointer change */
    if( ! p_vout->p_sys->b_cursor_autohidden &&
        ( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) )
    {
        /* Hide the mouse automatically */
        p_vout->p_sys->b_cursor_autohidden = 1;
        SDL_ShowCursor( 0 );
    }

    return VLC_SUCCESS;
}
Пример #8
0
/*****************************************************************************
 * NewPicture: allocate a picture
 *****************************************************************************
 * Returns 0 on success, -1 otherwise
 *****************************************************************************/
static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic, int index )
{
    /* 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;
    }

    switch( p_vout->p_sys->i_mode )
    {
    case MODE_NORMAL_MEM:
    case MODE_SHARED_MEM:
        /* create images for [shared] memory blit */
        if( !( p_pic->p_sys->p_image = PhCreateImage( NULL,
                    p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
                    p_vout->p_sys->i_img_type, NULL, 0,
                    p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
            msg_Err( p_vout, "cannot create image" );
            free( p_pic->p_sys );
            return( -1 );
        }

        p_pic->p->p_pixels = p_pic->p_sys->p_image->image;
        p_pic->p->i_lines = p_pic->p_sys->p_image->size.h;
        p_pic->p->i_visible_lines = p_pic->p_sys->p_image->size.h;
        p_pic->p->i_pitch = p_pic->p_sys->p_image->bpl;
        p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
        p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
                                     * p_pic->p_sys->p_image->size.w;
        p_pic->i_planes = 1;
        break;

    case MODE_VIDEO_MEM:
        /* create offscreen contexts for video memory blit */
        if( ( p_pic->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
                        p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
                       Pg_OSC_MEM_PAGE_ALIGN) ) == NULL )
        {
            msg_Err( p_vout, "unable to create offscreen context" );
            free( p_pic->p_sys );
            return( -1 );
        }

        /* get context pointers */
        if( (  p_pic->p_sys->p_buf[0] =
            PdGetOffscreenContextPtr ( p_pic->p_sys->p_ctx[0] ) ) == NULL )
        {
            msg_Err( p_vout, "unable to get offscreen context ptr" );
            PhDCRelease ( p_pic->p_sys->p_ctx[0] );
            p_pic->p_sys->p_ctx[0] = NULL;
            free( p_pic->p_sys );
            return( -1 );
        }

        p_vout->p_sys->i_bytes_per_line = p_pic->p_sys->p_ctx[0]->pitch;
        memset( p_pic->p_sys->p_buf[0], 0,
            p_vout->p_sys->i_bytes_per_line * p_vout->p_sys->dim.h );

        p_pic->p->p_pixels = p_pic->p_sys->p_buf[0];
        p_pic->p->i_lines = p_pic->p_sys->p_ctx[0]->dim.h;
        p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[0]->dim.h;
        p_pic->p->i_pitch = p_pic->p_sys->p_ctx[0]->pitch;
        p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
        p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
                                     * p_pic->p_sys->p_ctx[0]->dim.w;
        p_pic->i_planes = 1;
        break;

    case MODE_VIDEO_OVERLAY:
        if (index == 0)
        {
            p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane1;
            p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane1;
            p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane1;
        }
        else
        {
            p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane2;
            p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane2;
            p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane2;
        }

        p_pic->p_sys->p_buf[Y_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[Y_PLANE] );
        if( p_pic->p_sys->p_buf[Y_PLANE] == NULL )
        {
            msg_Err( p_vout, "unable to get video channel ctx ptr" );
            return( 1 );
        }

        switch (p_vout->p_sys->i_vc_format)
        {
            case Pg_VIDEO_FORMAT_YUV420:
                p_vout->output.i_chroma = VLC_CODEC_I420;

                p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
                p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );

                if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
                    p_pic->p_sys->p_buf[V_PLANE] == NULL )
                {
                    msg_Err( p_vout, "unable to get video channel ctx ptr" );
                    return( 1 );
                }

                p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
                p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
                p_pic->p[Y_PLANE].i_pixel_pitch = 1;
                p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;

                p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
                p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
                p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
                p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
                p_pic->p[U_PLANE].i_pixel_pitch = 1;
                p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;

                p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
                p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
                p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
                p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
                p_pic->p[V_PLANE].i_pixel_pitch = 1;
                p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;

                p_pic->i_planes = 3;
                break;

            case Pg_VIDEO_FORMAT_YV12:
                p_vout->output.i_chroma = VLC_CODEC_YV12;

                p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
                p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );

                if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
                    p_pic->p_sys->p_buf[V_PLANE] == NULL )
                {
                    msg_Err( p_vout, "unable to get video channel ctx ptr" );
                    return( 1 );
                }

                p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
                p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
                p_pic->p[Y_PLANE].i_pixel_pitch = 1;
                p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;

                p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
                p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
                p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
                p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
                p_pic->p[U_PLANE].i_pixel_pitch = 1;
                p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;

                p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
                p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
                p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
                p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
                p_pic->p[V_PLANE].i_pixel_pitch = 1;
                p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;

                p_pic->i_planes = 3;
                break;

            case Pg_VIDEO_FORMAT_UYVY:
            case Pg_VIDEO_FORMAT_YUY2:
                if (p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_UYVY)
                {
                    p_vout->output.i_chroma = VLC_CODEC_UYVY;
                }
                else
                {
                    p_vout->output.i_chroma = VLC_CODEC_YUYV;
                }

                p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
                p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
                p_pic->p->i_pixel_pitch = 4;
                p_pic->p->i_visible_pitch = p_pic->p->i_pitch;

                p_pic->i_planes = 1;
                break;

            case Pg_VIDEO_FORMAT_RGB555:
                p_vout->output.i_chroma = VLC_CODEC_RGB15;
                p_vout->output.i_rmask = 0x001f;
                p_vout->output.i_gmask = 0x03e0;
                p_vout->output.i_bmask = 0x7c00;

                p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
                p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
                p_pic->p->i_pixel_pitch = 2;
                p_pic->p->i_visible_pitch = 2 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;

                p_pic->i_planes = 1;
                break;

            case Pg_VIDEO_FORMAT_RGB565:
                p_vout->output.i_chroma = VLC_CODEC_RGB16;
                p_vout->output.i_rmask = 0x001f;
                p_vout->output.i_gmask = 0x07e0;
                p_vout->output.i_bmask = 0xf800;

                p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
                p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
                p_pic->p->i_pixel_pitch = 4;
                p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;

                p_pic->i_planes = 1;
                break;

            case Pg_VIDEO_FORMAT_RGB8888:
                p_vout->output.i_chroma = VLC_CODEC_RGB32;
                p_vout->output.i_rmask = 0x000000ff;
                p_vout->output.i_gmask = 0x0000ff00;
                p_vout->output.i_bmask = 0x00ff0000;

                p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
                p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
                p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
                p_pic->p->i_pixel_pitch = 4;
                p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;

                p_pic->i_planes = 1;
                break;
        }

#if 0
    switch( p_vout->output.i_chroma )
    {
#ifdef MODULE_NAME_IS_xvideo
        case VLC_CODEC_Y211:

            p_pic->p->p_pixels = p_pic->p_sys->p_image->data
                                  + p_pic->p_sys->p_image->offsets[0];
            p_pic->p->i_lines = p_vout->output.i_height;
            p_pic->p->i_visible_lines = p_vout->output.i_height;
            /* XXX: this just looks so plain wrong... check it out ! */
            p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
            p_pic->p->i_pixel_pitch = 4;
            p_pic->p->i_visible_pitch = p_pic->p->i_pitch;

            p_pic->i_planes = 1;
            break;
#endif

#endif

    default:
        /* This shouldn't happen ! */
        break;
    }

    return 0;
}

/*****************************************************************************
 * FreePicture: destroy a picture allocated with NewPicture
 *****************************************************************************
 * Destroy XImage AND associated data. If using Shm, detach shared memory
 * segment from server and process, then free it. The XDestroyImage manpage
 * says that both the image structure _and_ the data pointed to by the
 * image structure are freed, so no need to free p_image->data.
 *****************************************************************************/
static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
{
    if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
        p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
        p_pic->p_sys->p_image )
    {
        PhReleaseImage( p_pic->p_sys->p_image );
        free( p_pic->p_sys->p_image );
    }
    else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
             p_pic->p_sys->p_ctx[0] )
    {
        PhDCRelease( p_pic->p_sys->p_ctx[0] );
    }

    free( p_pic->p_sys );
}


static int ResizeOverlayOutput(vout_thread_t *p_vout)
{
    int i_width, i_height, i_x, i_y;
    int i_ret;
    PgScalerProps_t props;

    props.size   = sizeof( props );
    props.format = p_vout->p_sys->i_vc_format;
    props.flags  = Pg_SCALER_PROP_SCALER_ENABLE |
                          Pg_SCALER_PROP_DOUBLE_BUFFER;

    /* enable chroma keying if available */
    if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
    {
        props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
    }

    /* set viewport position */
    props.viewport.ul.x = p_vout->p_sys->pos.x;
    props.viewport.ul.y = p_vout->p_sys->pos.y;
    if( !p_vout->b_fullscreen )
    {
        props.viewport.ul.x += p_vout->p_sys->frame.ul.x;
        props.viewport.ul.y += p_vout->p_sys->frame.ul.y;
    }

    /* set viewport dimension */
    vout_PlacePicture( p_vout, p_vout->p_sys->dim.w,
                           p_vout->p_sys->dim.h,
                           &i_x, &i_y, &i_width, &i_height );

    props.viewport.ul.x += i_x;
    props.viewport.ul.y += i_y;
    props.viewport.lr.x = i_width + props.viewport.ul.x;
    props.viewport.lr.y = i_height + props.viewport.ul.y;

    /* set source dimension */
    props.src_dim.w = p_vout->output.i_width;
    props.src_dim.h = p_vout->output.i_height;

    /* configure scaler channel */
    i_ret = PgConfigScalerChannel( p_vout->p_sys->p_channel, &props );

    if( i_ret == -1 )
    {
        msg_Err( p_vout, "unable to configure video channel" );
        return( 1 );
    }

    return ( 0 );
}
Пример #9
0
/*****************************************************************************
 * UpdateRects: update clipping rectangles
 *****************************************************************************
 * This function is called when the window position or size are changed, and
 * its job is to update the source and destination RECTs used to display the
 * picture.
 *****************************************************************************/
void UpdateRects( vout_thread_t *p_vout, bool b_force )
{
#define rect_src p_vout->p_sys->rect_src
#define rect_src_clipped p_vout->p_sys->rect_src_clipped
#define rect_dest p_vout->p_sys->rect_dest
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped

    unsigned int i_width, i_height, i_x, i_y;

    RECT  rect;
    POINT point;

    /* Retrieve the window size */
    GetClientRect( p_vout->p_sys->hwnd, &rect );

    /* Retrieve the window position */
    point.x = point.y = 0;
    ClientToScreen( p_vout->p_sys->hwnd, &point );

    /* If nothing changed, we can return */
    if( !b_force
         && p_vout->p_sys->i_window_width == rect.right
         && p_vout->p_sys->i_window_height == rect.bottom
         && p_vout->p_sys->i_window_x == point.x
         && p_vout->p_sys->i_window_y == point.y )
    {
        return;
    }

    /* Update the window position and size */
    p_vout->p_sys->i_window_x = point.x;
    p_vout->p_sys->i_window_y = point.y;
    p_vout->p_sys->i_window_width = rect.right;
    p_vout->p_sys->i_window_height = rect.bottom;

    vout_PlacePicture( p_vout, rect.right, rect.bottom,
                       &i_x, &i_y, &i_width, &i_height );

    if( p_vout->p_sys->hvideownd )
        SetWindowPos( p_vout->p_sys->hvideownd, 0,
                      i_x, i_y, i_width, i_height,
                      SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS );

    /* Destination image position and dimensions */
    rect_dest.left = point.x + i_x;
    rect_dest.right = rect_dest.left + i_width;
    rect_dest.top = point.y + i_y;
    rect_dest.bottom = rect_dest.top + i_height;

#ifdef MODULE_NAME_IS_directx
    /* Apply overlay hardware constraints */
    if( p_vout->p_sys->b_using_overlay )
    {
        if( p_vout->p_sys->i_align_dest_boundary )
            rect_dest.left = ( rect_dest.left +
                p_vout->p_sys->i_align_dest_boundary / 2 ) &
                ~p_vout->p_sys->i_align_dest_boundary;

        if( p_vout->p_sys->i_align_dest_size )
            rect_dest.right = (( rect_dest.right - rect_dest.left +
                p_vout->p_sys->i_align_dest_size / 2 ) &
                ~p_vout->p_sys->i_align_dest_size) + rect_dest.left;
    }

    /* UpdateOverlay directdraw function doesn't automatically clip to the
     * display size so we need to do it otherwise it will fail */

    /* Clip the destination window */
    if( !IntersectRect( &rect_dest_clipped, &rect_dest,
                        &p_vout->p_sys->rect_display ) )
    {
        SetRectEmpty( &rect_src_clipped );
        return;
    }

#ifndef NDEBUG
    msg_Dbg( p_vout, "DirectXUpdateRects image_dst_clipped coords:"
                     " %li,%li,%li,%li",
                     rect_dest_clipped.left, rect_dest_clipped.top,
                     rect_dest_clipped.right, rect_dest_clipped.bottom );
#endif

#else /* MODULE_NAME_IS_directx */

    /* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */
    rect_dest_clipped = rect_dest;

#endif

    /* the 2 following lines are to fix a bug when clicking on the desktop */
    if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
        (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
    {
        SetRectEmpty( &rect_src_clipped );
        return;
    }

    /* src image dimensions */
    rect_src.left = 0;
    rect_src.top = 0;
    rect_src.right = p_vout->render.i_width;
    rect_src.bottom = p_vout->render.i_height;

    /* Clip the source image */
    rect_src_clipped.left = p_vout->fmt_out.i_x_offset +
      (rect_dest_clipped.left - rect_dest.left) *
      p_vout->fmt_out.i_visible_width / (rect_dest.right - rect_dest.left);
    rect_src_clipped.right = p_vout->fmt_out.i_x_offset +
      p_vout->fmt_out.i_visible_width -
      (rect_dest.right - rect_dest_clipped.right) *
      p_vout->fmt_out.i_visible_width / (rect_dest.right - rect_dest.left);
    rect_src_clipped.top = p_vout->fmt_out.i_y_offset +
      (rect_dest_clipped.top - rect_dest.top) *
      p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);
    rect_src_clipped.bottom = p_vout->fmt_out.i_y_offset +
      p_vout->fmt_out.i_visible_height -
      (rect_dest.bottom - rect_dest_clipped.bottom) *
      p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);

#ifdef MODULE_NAME_IS_directx
    /* Apply overlay hardware constraints */
    if( p_vout->p_sys->b_using_overlay )
    {
        if( p_vout->p_sys->i_align_src_boundary )
            rect_src_clipped.left = ( rect_src_clipped.left +
                p_vout->p_sys->i_align_src_boundary / 2 ) &
                ~p_vout->p_sys->i_align_src_boundary;

        if( p_vout->p_sys->i_align_src_size )
            rect_src_clipped.right = (( rect_src_clipped.right -
                rect_src_clipped.left +
                p_vout->p_sys->i_align_src_size / 2 ) &
                ~p_vout->p_sys->i_align_src_size) + rect_src_clipped.left;
    }
#endif

#ifndef NDEBUG
    msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped"
                     " coords: %li,%li,%li,%li",
                     rect_src_clipped.left, rect_src_clipped.top,
                     rect_src_clipped.right, rect_src_clipped.bottom );
#endif

#ifdef MODULE_NAME_IS_directx
    /* The destination coordinates need to be relative to the current
     * directdraw primary surface (display) */
    rect_dest_clipped.left -= p_vout->p_sys->rect_display.left;
    rect_dest_clipped.right -= p_vout->p_sys->rect_display.left;
    rect_dest_clipped.top -= p_vout->p_sys->rect_display.top;
    rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top;

    if( p_vout->p_sys->b_using_overlay )
        DirectDrawUpdateOverlay( p_vout );
#endif

#ifndef UNDER_CE
    /* Windows 7 taskbar thumbnail code */
    LPTASKBARLIST3 p_taskbl;
    OSVERSIONINFO winVer;
    winVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if( GetVersionEx(&winVer) && winVer.dwMajorVersion > 5 )
    {
        CoInitialize( 0 );

        if( S_OK == CoCreateInstance( &clsid_ITaskbarList,
                    NULL, CLSCTX_INPROC_SERVER,
                    &IID_ITaskbarList3,
                    &p_taskbl) )
        {
            RECT rect_video, rect_parent, rect_relative;
            HWND hroot = GetAncestor(p_vout->p_sys->hwnd,GA_ROOT);

            p_taskbl->vt->HrInit(p_taskbl);
            GetWindowRect(p_vout->p_sys->hvideownd, &rect_video);
            GetWindowRect(hroot, &rect_parent);
            rect_relative.left = rect_video.left - rect_parent.left - 8;
            rect_relative.right = rect_video.right - rect_video.left + rect_relative.left;
            rect_relative.top = rect_video.top - rect_parent.top - 10;
            rect_relative.bottom = rect_video.bottom - rect_video.top + rect_relative.top - 25;

            if (S_OK != p_taskbl->vt->SetThumbnailClip(p_taskbl, hroot, &rect_relative))
                msg_Err( p_vout, "SetThumbNailClip failed");

            p_taskbl->vt->Release(p_taskbl);
        }
        CoUninitialize();
    }
#endif
    /* Signal the change in size/position */
    p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;

#undef rect_src
#undef rect_src_clipped
#undef rect_dest
#undef rect_dest_clipped
}
Пример #10
0
void CommonManage( vout_thread_t *p_vout )
{
    /* If we do not control our window, we check for geometry changes
     * ourselves because the parent might not send us its events. */
    vlc_mutex_lock( &p_vout->p_sys->lock );
    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
    {
        RECT rect_parent;
        POINT point;

        vlc_mutex_unlock( &p_vout->p_sys->lock );

        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
        point.x = point.y = 0;
        ClientToScreen( p_vout->p_sys->hparent, &point );
        OffsetRect( &rect_parent, point.x, point.y );

        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
        {
            p_vout->p_sys->rect_parent = rect_parent;

            /* FIXME I find such #ifdef quite weirds. Are they really needed ? */

#if defined(MODULE_NAME_IS_direct3d)
            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
                          rect_parent.right - rect_parent.left,
                          rect_parent.bottom - rect_parent.top,
                          SWP_NOZORDER );
            UpdateRects( p_vout, true );
#else
            /* This one is to force the update even if only
             * the position has changed */
            SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
                          rect_parent.right - rect_parent.left,
                          rect_parent.bottom - rect_parent.top, 0 );

            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
                          rect_parent.right - rect_parent.left,
                          rect_parent.bottom - rect_parent.top, 0 );

#if defined(MODULE_NAME_IS_wingdi) || defined(MODULE_NAME_IS_wingapi)
            unsigned int i_x, i_y, i_width, i_height;
            vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left,
                               rect_parent.bottom - rect_parent.top,
                               &i_x, &i_y, &i_width, &i_height );

            SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
                          i_x, i_y, i_width, i_height, 0 );
#endif
#endif
        }
    }
    else
    {
        vlc_mutex_unlock( &p_vout->p_sys->lock );
    }

    /* autoscale toggle */
    if( p_vout->i_changes & VOUT_SCALE_CHANGE )
    {
        p_vout->i_changes &= ~VOUT_SCALE_CHANGE;

        p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
        p_vout->i_zoom = (int) ZOOM_FP_FACTOR;

        UpdateRects( p_vout, true );
    }

    /* scaling factor */
    if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
    {
        p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;

        p_vout->b_autoscale = false;
        p_vout->i_zoom =
            (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
        UpdateRects( p_vout, true );
    }

    /* Check for cropping / aspect changes */
    if( p_vout->i_changes & VOUT_CROP_CHANGE ||
        p_vout->i_changes & VOUT_ASPECT_CHANGE )
    {
        p_vout->i_changes &= ~VOUT_CROP_CHANGE;
        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;

        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
        UpdateRects( p_vout, true );
    }

    /* We used to call the Win32 PeekMessage function here to read the window
     * messages. But since window can stay blocked into this function for a
     * long time (for example when you move your window on the screen), I
     * decided to isolate PeekMessage in another thread. */

    /*
     * Fullscreen change
     */
    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
    {
        Win32ToggleFullscreen( p_vout );

        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
    }

    /*
     * Pointer change
     */
    EventThreadMouseAutoHide( p_vout->p_sys->p_event );

    /*
     * "Always on top" status change
     */
    if( p_vout->p_sys->b_on_top_change )
    {
        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
        bool b = var_GetBool( p_vout, "video-on-top" );

        /* Set the window on top if necessary */
        if( b && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
                           & WS_EX_TOPMOST ) )
        {
            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
                           MF_BYCOMMAND | MFS_CHECKED );
            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
                          SWP_NOSIZE | SWP_NOMOVE );
        }
        else
        /* The window shouldn't be on top */
        if( !b && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
                           & WS_EX_TOPMOST ) )
        {
            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
                           MF_BYCOMMAND | MFS_UNCHECKED );
            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
                          SWP_NOSIZE | SWP_NOMOVE );
        }

        p_vout->p_sys->b_on_top_change = false;
    }
}
Пример #11
0
Файл: omapfb.c Проект: Kafay/vlc
/*****************************************************************************
 * Init: initialize omap framebuffer video thread output method
 *****************************************************************************/
static int Init( vout_thread_t *p_vout )
{
    vout_sys_t *p_sys = (vout_sys_t *)p_vout->p_sys;

    // We want to keep the same aspect
    p_vout->fmt_out.i_aspect = p_vout->output.i_aspect = p_vout->render.i_aspect;
    // We ask where the video should be displayed in the video area
    vout_PlacePicture( p_vout, p_sys->main_window.i_width,
                       p_sys->main_window.i_height,
                       &p_sys->output_window.i_x,
                       &p_sys->output_window.i_y,
                       &p_sys->output_window.i_width,
                       &p_sys->output_window.i_height );
    p_sys->output_window.i_x = ( p_sys->output_window.i_x +
                                 p_sys->main_window.i_x ) & ~1;
    p_sys->output_window.i_y = ( p_sys->output_window.i_y +
                                 p_sys->main_window.i_y ) & ~1;

    // Hardware upscaling better than software
    if( p_vout->fmt_render.i_width <= p_sys->main_window.i_width &&
        p_vout->fmt_render.i_height <= p_sys->main_window.i_height )
    {
        p_sys->i_video_width =
        p_vout->output.i_width =
        p_vout->fmt_out.i_width =
        p_vout->fmt_out.i_visible_width = p_vout->fmt_render.i_width;
        p_sys->i_video_height =
        p_vout->output.i_height =
        p_vout->fmt_out.i_height =
        p_vout->fmt_out.i_visible_height = p_vout->fmt_render.i_height;
    }
    else
    {
        p_sys->i_video_width =
        p_vout->output.i_width =
        p_vout->fmt_out.i_width =
        p_vout->fmt_out.i_visible_width = p_sys->output_window.i_width;
        p_sys->i_video_height =
        p_vout->output.i_height =
        p_vout->fmt_out.i_height =
        p_vout->fmt_out.i_visible_height = p_sys->output_window.i_height;
    }

    p_vout->output.i_chroma =
    p_vout->fmt_out.i_chroma = VLC_CODEC_I420;
    p_sys->i_color_format = OMAPFB_COLOR_YUV420;

    // place in the framebuffer where we have to write
    p_sys->p_center = p_sys->p_video + p_sys->output_window.i_x*p_sys->i_bytes_per_pixel
                      + p_sys->output_window.i_y*p_sys->i_line_len;

    // We get and set a direct render vlc picture
    I_OUTPUTPICTURES = 0;
    picture_t *p_pic = NULL;
    int i_index;

    for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
    {
        if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
        {
            p_pic = p_vout->p_picture + i_index;
            break;
        }
    }

    /* Allocate the picture */
    if( p_pic == NULL )
    {
        return VLC_EGENERIC;
    }

    p_sys->p_output_picture = p_pic;
    p_pic->p->p_pixels = p_vout->p_sys->p_center;
    p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
    p_pic->p->i_lines = p_sys->i_video_height;
    p_pic->p->i_visible_lines = p_sys->i_video_height;
    p_pic->p->i_pitch = p_sys->i_line_len;
    p_pic->p->i_visible_pitch = p_sys->i_line_len;
    p_pic->i_planes = 1;
    p_pic->i_status = DESTROYED_PICTURE;
    p_pic->i_type   = DIRECT_PICTURE;

    PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;

    I_OUTPUTPICTURES++;

    return VLC_SUCCESS;
}