vout_pictures.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:39k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * vout_pictures.c : picture management functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2004 the VideoLAN team
  5.  * $Id: ba384c04d69caaa0da5b8182f448ec86f4f23388 $
  6.  *
  7.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <assert.h>
  31. #include <vlc_common.h>
  32. #include <libvlc.h>
  33. #include <vlc_vout.h>
  34. #include <vlc_osd.h>
  35. #include <vlc_filter.h>
  36. #include <vlc_image.h>
  37. #include <vlc_block.h>
  38. #include "vout_pictures.h"
  39. #include "vout_internal.h"
  40. /**
  41.  * Display a picture
  42.  *
  43.  * Remove the reservation flag of a picture, which will cause it to be ready
  44.  * for display.
  45.  */
  46. void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
  47. {
  48.     vlc_mutex_lock( &p_vout->picture_lock );
  49.     if( p_pic->i_status == RESERVED_PICTURE )
  50.     {
  51.         p_pic->i_status = READY_PICTURE;
  52.         vlc_cond_signal( &p_vout->p->picture_wait );
  53.     }
  54.     else
  55.     {
  56.         msg_Err( p_vout, "picture to display %p has invalid status %d",
  57.                          p_pic, p_pic->i_status );
  58.     }
  59.     p_vout->p->i_picture_qtype = p_pic->i_qtype;
  60.     vlc_mutex_unlock( &p_vout->picture_lock );
  61. }
  62. /**
  63.  * Allocate a picture in the video output heap.
  64.  *
  65.  * This function creates a reserved image in the video output heap.
  66.  * A null pointer is returned if the function fails. This method provides an
  67.  * already allocated zone of memory in the picture data fields.
  68.  * It needs locking since several pictures can be created by several producers
  69.  * threads.
  70.  */
  71. int vout_CountPictureAvailable( vout_thread_t *p_vout )
  72. {
  73.     int i_free = 0;
  74.     int i_pic;
  75.     vlc_mutex_lock( &p_vout->picture_lock );
  76.     for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
  77.     {
  78.         picture_t *p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1) % I_RENDERPICTURES];
  79.         switch( p_pic->i_status )
  80.         {
  81.             case DESTROYED_PICTURE:
  82.                 i_free++;
  83.                 break;
  84.             case FREE_PICTURE:
  85.                 i_free++;
  86.                 break;
  87.             default:
  88.                 break;
  89.         }
  90.     }
  91.     vlc_mutex_unlock( &p_vout->picture_lock );
  92.     return i_free;
  93. }
  94. picture_t *vout_CreatePicture( vout_thread_t *p_vout,
  95.                                bool b_progressive,
  96.                                bool b_top_field_first,
  97.                                unsigned int i_nb_fields )
  98. {
  99.     int         i_pic;                                      /* picture index */
  100.     picture_t * p_pic;
  101.     picture_t * p_freepic = NULL;                      /* first free picture */
  102.     /* Get lock */
  103.     vlc_mutex_lock( &p_vout->picture_lock );
  104.     /*
  105.      * Look for an empty place in the picture heap.
  106.      */
  107.     for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
  108.     {
  109.         p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1)
  110.                                  % I_RENDERPICTURES];
  111.         switch( p_pic->i_status )
  112.         {
  113.             case DESTROYED_PICTURE:
  114.                 /* Memory will not be reallocated, and function can end
  115.                  * immediately - this is the best possible case, since no
  116.                  * memory allocation needs to be done */
  117.                 p_pic->i_status   = RESERVED_PICTURE;
  118.                 p_pic->i_refcount = 0;
  119.                 p_pic->b_force    = 0;
  120.                 p_pic->b_progressive        = b_progressive;
  121.                 p_pic->i_nb_fields          = i_nb_fields;
  122.                 p_pic->b_top_field_first    = b_top_field_first;
  123.                 p_vout->i_heap_size++;
  124.                 p_vout->render.i_last_used_pic =
  125.                     ( p_vout->render.i_last_used_pic + i_pic + 1 )
  126.                     % I_RENDERPICTURES;
  127.                 vlc_mutex_unlock( &p_vout->picture_lock );
  128.                 return( p_pic );
  129.             case FREE_PICTURE:
  130.                 /* Picture is empty and ready for allocation */
  131.                 p_vout->render.i_last_used_pic =
  132.                     ( p_vout->render.i_last_used_pic + i_pic + 1 )
  133.                     % I_RENDERPICTURES;
  134.                 p_freepic = p_pic;
  135.                 break;
  136.             default:
  137.                 break;
  138.         }
  139.     }
  140.     /*
  141.      * Prepare picture
  142.      */
  143.     if( p_freepic != NULL )
  144.     {
  145.         vout_AllocatePicture( VLC_OBJECT(p_vout),
  146.                               p_freepic, p_vout->render.i_chroma,
  147.                               p_vout->render.i_width, p_vout->render.i_height,
  148.                               p_vout->render.i_aspect );
  149.         if( p_freepic->i_planes )
  150.         {
  151.             /* Copy picture information, set some default values */
  152.             p_freepic->i_status   = RESERVED_PICTURE;
  153.             p_freepic->i_type     = MEMORY_PICTURE;
  154.             p_freepic->b_slow     = 0;
  155.             p_freepic->i_refcount = 0;
  156.             p_freepic->b_force = 0;
  157.             p_freepic->b_progressive        = b_progressive;
  158.             p_freepic->i_nb_fields          = i_nb_fields;
  159.             p_freepic->b_top_field_first    = b_top_field_first;
  160.             p_vout->i_heap_size++;
  161.         }
  162.         else
  163.         {
  164.             /* Memory allocation failed : set picture as empty */
  165.             p_freepic->i_status = FREE_PICTURE;
  166.             p_freepic = NULL;
  167.             msg_Err( p_vout, "picture allocation failed" );
  168.         }
  169.         vlc_mutex_unlock( &p_vout->picture_lock );
  170.         return( p_freepic );
  171.     }
  172.     /* No free or destroyed picture could be found, but the decoder
  173.      * will try again in a while. */
  174.     vlc_mutex_unlock( &p_vout->picture_lock );
  175.     return( NULL );
  176. }
  177. /* */
  178. static void DestroyPicture( vout_thread_t *p_vout, picture_t *p_picture )
  179. {
  180.     vlc_assert_locked( &p_vout->picture_lock );
  181.     p_picture->i_status = DESTROYED_PICTURE;
  182.     p_vout->i_heap_size--;
  183.     picture_CleanupQuant( p_picture );
  184.     vlc_cond_signal( &p_vout->p->picture_wait );
  185. }
  186. /**
  187.  * Remove a permanent or reserved picture from the heap
  188.  *
  189.  * This function frees a previously reserved picture or a permanent
  190.  * picture. It is meant to be used when the construction of a picture aborted.
  191.  * Note that the picture will be destroyed even if it is linked !
  192.  *
  193.  * TODO remove it, vout_DropPicture should be used instead
  194.  */
  195. void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
  196. {
  197. #ifndef NDEBUG
  198.     /* Check if picture status is valid */
  199.     vlc_mutex_lock( &p_vout->picture_lock );
  200.     if( p_pic->i_status != RESERVED_PICTURE )
  201.     {
  202.         msg_Err( p_vout, "picture to destroy %p has invalid status %d",
  203.                          p_pic, p_pic->i_status );
  204.     }
  205.     vlc_mutex_unlock( &p_vout->picture_lock );
  206. #endif
  207.     vout_DropPicture( p_vout, p_pic );
  208. }
  209. /* */
  210. void vout_UsePictureLocked( vout_thread_t *p_vout, picture_t *p_picture )
  211. {
  212.     vlc_assert_locked( &p_vout->picture_lock );
  213.     if( p_picture->i_refcount > 0 )
  214.     {
  215.         /* Pretend we displayed the picture, but don't destroy
  216.          * it since the decoder might still need it. */
  217.         p_picture->i_status = DISPLAYED_PICTURE;
  218.     }
  219.     else
  220.     {
  221.         /* Destroy the picture without displaying it */
  222.         DestroyPicture( p_vout, p_picture );
  223.     }
  224. }
  225. /* */
  226. void vout_DropPicture( vout_thread_t *p_vout, picture_t *p_pic  )
  227. {
  228.     vlc_mutex_lock( &p_vout->picture_lock );
  229.     if( p_pic->i_status == READY_PICTURE )
  230.     {
  231.         /* Grr cannot destroy ready picture by myself so be sure vout won't like it */
  232.         p_pic->date = 1;
  233.         vlc_cond_signal( &p_vout->p->picture_wait );
  234.     }
  235.     else
  236.     {
  237.         vout_UsePictureLocked( p_vout, p_pic );
  238.     }
  239.     vlc_mutex_unlock( &p_vout->picture_lock );
  240. }
  241. /**
  242.  * Increment reference counter of a picture
  243.  *
  244.  * This function increments the reference counter of a picture in the video
  245.  * heap. It needs a lock since several producer threads can access the picture.
  246.  */
  247. void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
  248. {
  249.     vlc_mutex_lock( &p_vout->picture_lock );
  250.     p_pic->i_refcount++;
  251.     vlc_mutex_unlock( &p_vout->picture_lock );
  252. }
  253. /**
  254.  * Decrement reference counter of a picture
  255.  *
  256.  * This function decrement the reference counter of a picture in the video heap
  257.  */
  258. void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
  259. {
  260.     vlc_mutex_lock( &p_vout->picture_lock );
  261.     if( p_pic->i_refcount > 0 )
  262.         p_pic->i_refcount--;
  263.     else
  264.         msg_Err( p_vout, "Invalid picture reference count (%p, %d)",
  265.                  p_pic, p_pic->i_refcount );
  266.     if( p_pic->i_refcount == 0 && p_pic->i_status == DISPLAYED_PICTURE )
  267.         DestroyPicture( p_vout, p_pic );
  268.     vlc_mutex_unlock( &p_vout->picture_lock );
  269. }
  270. static int vout_LockPicture( vout_thread_t *p_vout, picture_t *p_picture )
  271. {
  272.     if( p_picture->pf_lock )
  273.         return p_picture->pf_lock( p_vout, p_picture );
  274.     return VLC_SUCCESS;
  275. }
  276. static void vout_UnlockPicture( vout_thread_t *p_vout, picture_t *p_picture )
  277. {
  278.     if( p_picture->pf_unlock )
  279.         p_picture->pf_unlock( p_vout, p_picture );
  280. }
  281. /**
  282.  * Render a picture
  283.  *
  284.  * This function chooses whether the current picture needs to be copied
  285.  * before rendering, does the subpicture magic, and tells the video output
  286.  * thread which direct buffer needs to be displayed.
  287.  */
  288. picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
  289.                                subpicture_t *p_subpic, mtime_t render_date )
  290. {
  291.     if( p_pic == NULL )
  292.         return NULL;
  293.     if( p_pic->i_type == DIRECT_PICTURE )
  294.     {
  295.         /* Picture is in a direct buffer. */
  296.         if( p_subpic != NULL )
  297.         {
  298.             /* We have subtitles. First copy the picture to
  299.              * the spare direct buffer, then render the
  300.              * subtitles. */
  301.             if( vout_LockPicture( p_vout, PP_OUTPUTPICTURE[0] ) )
  302.                 return NULL;
  303.             picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
  304.             spu_RenderSubpicturesNew( p_vout->p_spu,
  305.                                       PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
  306.                                       p_subpic, &p_vout->fmt_in, render_date );
  307.             vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
  308.             return PP_OUTPUTPICTURE[0];
  309.         }
  310.         /* No subtitles, picture is in a directbuffer so
  311.          * we can display it directly (even if it is still
  312.          * in use or not). */
  313.         return p_pic;
  314.     }
  315.     /* Not a direct buffer. We either need to copy it to a direct buffer,
  316.      * or render it if the chroma isn't the same. */
  317.     if( p_vout->p->b_direct )
  318.     {
  319.         /* Picture is not in a direct buffer, but is exactly the
  320.          * same size as the direct buffers. A memcpy() is enough,
  321.          * then render the subtitles. */
  322.         if( vout_LockPicture( p_vout, PP_OUTPUTPICTURE[0] ) )
  323.             return NULL;
  324.         picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
  325.         spu_RenderSubpicturesNew( p_vout->p_spu,
  326.                                   PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
  327.                                   p_subpic, &p_vout->fmt_in, render_date );
  328.         vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
  329.         return PP_OUTPUTPICTURE[0];
  330.     }
  331.     /* Picture is not in a direct buffer, and needs to be converted to
  332.      * another size/chroma. Then the subtitles need to be rendered as
  333.      * well. This usually means software YUV, or hardware YUV with a
  334.      * different chroma. */
  335.     if( p_subpic != NULL && p_vout->p_picture[0].b_slow )
  336.     {
  337.         /* The picture buffer is in slow memory. We'll use
  338.          * the "2 * VOUT_MAX_PICTURES + 1" picture as a temporary
  339.          * one for subpictures rendering. */
  340.         picture_t *p_tmp_pic = &p_vout->p_picture[2 * VOUT_MAX_PICTURES];
  341.         if( p_tmp_pic->i_status == FREE_PICTURE )
  342.         {
  343.             vout_AllocatePicture( VLC_OBJECT(p_vout),
  344.                                   p_tmp_pic, p_vout->fmt_out.i_chroma,
  345.                                   p_vout->fmt_out.i_width,
  346.                                   p_vout->fmt_out.i_height,
  347.                                   p_vout->fmt_out.i_aspect );
  348.             p_tmp_pic->i_type = MEMORY_PICTURE;
  349.             p_tmp_pic->i_status = RESERVED_PICTURE;
  350.             /* some modules (such as blend)  needs to know the extra information in picture heap */
  351.             p_tmp_pic->p_heap = &p_vout->output;
  352.         }
  353.         /* Convert image to the first direct buffer */
  354.         p_vout->p->p_chroma->p_owner = (filter_owner_sys_t *)p_tmp_pic;
  355.         p_vout->p->p_chroma->pf_video_filter( p_vout->p->p_chroma, p_pic );
  356.         /* Render subpictures on the first direct buffer */
  357.         spu_RenderSubpicturesNew( p_vout->p_spu,
  358.                                   p_tmp_pic, &p_vout->fmt_out,
  359.                                   p_subpic, &p_vout->fmt_in, render_date );
  360.         if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
  361.             return NULL;
  362.         picture_Copy( &p_vout->p_picture[0], p_tmp_pic );
  363.     }
  364.     else
  365.     {
  366.         if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
  367.             return NULL;
  368.         /* Convert image to the first direct buffer */
  369.         p_vout->p->p_chroma->p_owner = (filter_owner_sys_t *)&p_vout->p_picture[0];
  370.         p_vout->p->p_chroma->pf_video_filter( p_vout->p->p_chroma, p_pic );
  371.         /* Render subpictures on the first direct buffer */
  372.         spu_RenderSubpicturesNew( p_vout->p_spu,
  373.                                   &p_vout->p_picture[0], &p_vout->fmt_out,
  374.                                   p_subpic, &p_vout->fmt_in, render_date );
  375.     }
  376.     vout_UnlockPicture( p_vout, &p_vout->p_picture[0] );
  377.     return &p_vout->p_picture[0];
  378. }
  379. /**
  380.  * Calculate image window coordinates
  381.  *
  382.  * This function will be accessed by plugins. It calculates the relative
  383.  * position of the output window and the image window.
  384.  */
  385. void vout_PlacePicture( const vout_thread_t *p_vout,
  386.                         unsigned int i_width, unsigned int i_height,
  387.                         unsigned int *restrict pi_x,
  388.                         unsigned int *restrict pi_y,
  389.                         unsigned int *restrict pi_width,
  390.                         unsigned int *restrict pi_height )
  391. {
  392.     if( i_width <= 0 || i_height <= 0 )
  393.     {
  394.         *pi_width = *pi_height = *pi_x = *pi_y = 0;
  395.         return;
  396.     }
  397.     if( p_vout->b_autoscale )
  398.     {
  399.         *pi_width = i_width;
  400.         *pi_height = i_height;
  401.     }
  402.     else
  403.     {
  404.         int i_zoom = p_vout->i_zoom;
  405.         /* be realistic, scaling factor confined between .2 and 10. */
  406.         if( i_zoom > 10 * ZOOM_FP_FACTOR )      i_zoom = 10 * ZOOM_FP_FACTOR;
  407.         else if( i_zoom <  ZOOM_FP_FACTOR / 5 ) i_zoom = ZOOM_FP_FACTOR / 5;
  408.         unsigned int i_original_width, i_original_height;
  409.         if( p_vout->fmt_in.i_sar_num >= p_vout->fmt_in.i_sar_den )
  410.         {
  411.             i_original_width = p_vout->fmt_in.i_visible_width *
  412.                                p_vout->fmt_in.i_sar_num / p_vout->fmt_in.i_sar_den;
  413.             i_original_height =  p_vout->fmt_in.i_visible_height;
  414.         }
  415.         else
  416.         {
  417.             i_original_width =  p_vout->fmt_in.i_visible_width;
  418.             i_original_height = p_vout->fmt_in.i_visible_height *
  419.                                 p_vout->fmt_in.i_sar_den / p_vout->fmt_in.i_sar_num;
  420.         }
  421. #ifdef WIN32
  422.         /* On windows, inner video window exceeding container leads to black screen */
  423.         *pi_width = __MIN( i_width, i_original_width * i_zoom / ZOOM_FP_FACTOR );
  424.         *pi_height = __MIN( i_height, i_original_height * i_zoom / ZOOM_FP_FACTOR );
  425. #else
  426.         *pi_width = i_original_width * i_zoom / ZOOM_FP_FACTOR ;
  427.         *pi_height = i_original_height * i_zoom / ZOOM_FP_FACTOR ;
  428. #endif
  429.     }
  430.     int64_t i_scaled_width = p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
  431.                               *pi_height / p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
  432.     int64_t i_scaled_height = p_vout->fmt_in.i_visible_height * (int64_t)p_vout->fmt_in.i_sar_den *
  433.                                *pi_width / p_vout->fmt_in.i_visible_width / p_vout->fmt_in.i_sar_num;
  434.     if( i_scaled_width <= 0 || i_scaled_height <= 0 )
  435.     {
  436.         msg_Warn( p_vout, "ignoring broken aspect ratio" );
  437.         i_scaled_width = *pi_width;
  438.         i_scaled_height = *pi_height;
  439.     }
  440.     if( i_scaled_width > *pi_width )
  441.         *pi_height = i_scaled_height;
  442.     else
  443.         *pi_width = i_scaled_width;
  444.     switch( p_vout->i_alignment & VOUT_ALIGN_HMASK )
  445.     {
  446.     case VOUT_ALIGN_LEFT:
  447.         *pi_x = 0;
  448.         break;
  449.     case VOUT_ALIGN_RIGHT:
  450.         *pi_x = i_width - *pi_width;
  451.         break;
  452.     default:
  453.         *pi_x = ( i_width - *pi_width ) / 2;
  454.     }
  455.     switch( p_vout->i_alignment & VOUT_ALIGN_VMASK )
  456.     {
  457.     case VOUT_ALIGN_TOP:
  458.         *pi_y = 0;
  459.         break;
  460.     case VOUT_ALIGN_BOTTOM:
  461.         *pi_y = i_height - *pi_height;
  462.         break;
  463.     default:
  464.         *pi_y = ( i_height - *pi_height ) / 2;
  465.     }
  466. }
  467. /**
  468.  * Allocate a new picture in the heap.
  469.  *
  470.  * This function allocates a fake direct buffer in memory, which can be
  471.  * used exactly like a video buffer. The video output thread then manages
  472.  * how it gets displayed.
  473.  */
  474. int __vout_AllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
  475.                             vlc_fourcc_t i_chroma,
  476.                             int i_width, int i_height, int i_aspect )
  477. {
  478.     int i_bytes, i_index, i_width_aligned, i_height_aligned;
  479.     /* Make sure the real dimensions are a multiple of 16 */
  480.     i_width_aligned = (i_width + 15) >> 4 << 4;
  481.     i_height_aligned = (i_height + 15) >> 4 << 4;
  482.     if( vout_InitPicture( p_this, p_pic, i_chroma,
  483.                           i_width, i_height, i_aspect ) != VLC_SUCCESS )
  484.     {
  485.         p_pic->i_planes = 0;
  486.         return VLC_EGENERIC;
  487.     }
  488.     /* Calculate how big the new image should be */
  489.     i_bytes = p_pic->format.i_bits_per_pixel *
  490.         i_width_aligned * i_height_aligned / 8;
  491.     p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes );
  492.     if( p_pic->p_data == NULL )
  493.     {
  494.         p_pic->i_planes = 0;
  495.         return VLC_EGENERIC;
  496.     }
  497.     /* Fill the p_pixels field for each plane */
  498.     p_pic->p[ 0 ].p_pixels = p_pic->p_data;
  499.     for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
  500.     {
  501.         p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels +
  502.             p_pic->p[i_index-1].i_lines * p_pic->p[i_index-1].i_pitch;
  503.     }
  504.     return VLC_SUCCESS;
  505. }
  506. /**
  507.  * Initialise the video format fields given chroma/size.
  508.  *
  509.  * This function initializes all the video_frame_format_t fields given the
  510.  * static properties of a picture (chroma and size).
  511.  * param p_format Pointer to the format structure to initialize
  512.  * param i_chroma Chroma to set
  513.  * param i_width Width to set
  514.  * param i_height Height to set
  515.  * param i_aspect Aspect ratio
  516.  */
  517. void vout_InitFormat( video_frame_format_t *p_format, vlc_fourcc_t i_chroma,
  518.                       int i_width, int i_height, int i_aspect )
  519. {
  520.     p_format->i_chroma   = i_chroma;
  521.     p_format->i_width    = p_format->i_visible_width  = i_width;
  522.     p_format->i_height   = p_format->i_visible_height = i_height;
  523.     p_format->i_x_offset = p_format->i_y_offset = 0;
  524.     p_format->i_aspect   = i_aspect;
  525. #if 0
  526.     /* Assume we have square pixels */
  527.     if( i_width && i_height )
  528.         p_format->i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height;
  529.     else
  530.         p_format->i_aspect = 0;
  531. #endif
  532.     switch( i_chroma )
  533.     {
  534.         case FOURCC_YUVA:
  535.             p_format->i_bits_per_pixel = 32;
  536.             break;
  537.         case FOURCC_I444:
  538.         case FOURCC_J444:
  539.             p_format->i_bits_per_pixel = 24;
  540.             break;
  541.         case FOURCC_I422:
  542.         case FOURCC_YUY2:
  543.         case FOURCC_UYVY:
  544.         case FOURCC_J422:
  545.             p_format->i_bits_per_pixel = 16;
  546.             break;
  547.         case FOURCC_I440:
  548.         case FOURCC_J440:
  549.             p_format->i_bits_per_pixel = 16;
  550.             break;
  551.         case FOURCC_I411:
  552.         case FOURCC_YV12:
  553.         case FOURCC_I420:
  554.         case FOURCC_J420:
  555.         case FOURCC_IYUV:
  556.             p_format->i_bits_per_pixel = 12;
  557.             break;
  558.         case FOURCC_I410:
  559.         case FOURCC_YVU9:
  560.             p_format->i_bits_per_pixel = 9;
  561.             break;
  562.         case FOURCC_Y211:
  563.             p_format->i_bits_per_pixel = 8;
  564.             break;
  565.         case FOURCC_YUVP:
  566.             p_format->i_bits_per_pixel = 8;
  567.             break;
  568.         case FOURCC_RV32:
  569.         case FOURCC_RGBA:
  570.             p_format->i_bits_per_pixel = 32;
  571.             break;
  572.         case FOURCC_RV24:
  573.             p_format->i_bits_per_pixel = 24;
  574.             break;
  575.         case FOURCC_RV15:
  576.         case FOURCC_RV16:
  577.             p_format->i_bits_per_pixel = 16;
  578.             break;
  579.         case FOURCC_RGB2:
  580.             p_format->i_bits_per_pixel = 8;
  581.             break;
  582.         case FOURCC_GREY:
  583.         case FOURCC_Y800:
  584.         case FOURCC_Y8:
  585.         case FOURCC_RGBP:
  586.             p_format->i_bits_per_pixel = 8;
  587.             break;
  588.         default:
  589.             p_format->i_bits_per_pixel = 0;
  590.             break;
  591.     }
  592. }
  593. /**
  594.  * Initialise the picture_t fields given chroma/size.
  595.  *
  596.  * This function initializes most of the picture_t fields given a chroma and
  597.  * size. It makes the assumption that stride == width.
  598.  * param p_this The calling object
  599.  * param p_pic Pointer to the picture to initialize
  600.  * param i_chroma The chroma fourcc to set
  601.  * param i_width The width of the picture
  602.  * param i_height The height of the picture
  603.  * param i_aspect The aspect ratio of the picture
  604.  */
  605. int __vout_InitPicture( vlc_object_t *p_this, picture_t *p_pic,
  606.                         vlc_fourcc_t i_chroma,
  607.                         int i_width, int i_height, int i_aspect )
  608. {
  609.     int i_index, i_width_aligned, i_height_aligned;
  610.     /* Store default values */
  611.     for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
  612.     {
  613.         p_pic->p[i_index].p_pixels = NULL;
  614.         p_pic->p[i_index].i_pixel_pitch = 1;
  615.     }
  616.     p_pic->pf_release = NULL;
  617.     p_pic->pf_lock = NULL;
  618.     p_pic->pf_unlock = NULL;
  619.     p_pic->i_refcount = 0;
  620.     p_pic->i_qtype = QTYPE_NONE;
  621.     p_pic->i_qstride = 0;
  622.     p_pic->p_q = NULL;
  623.     vout_InitFormat( &p_pic->format, i_chroma, i_width, i_height, i_aspect );
  624.     /* Make sure the real dimensions are a multiple of 16 */
  625.     i_width_aligned = (i_width + 15) >> 4 << 4;
  626.     i_height_aligned = (i_height + 15) >> 4 << 4;
  627.     /* Calculate coordinates */
  628.     switch( i_chroma )
  629.     {
  630.         case FOURCC_I411:
  631.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  632.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  633.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  634.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  635.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
  636.             p_pic->p[ U_PLANE ].i_visible_lines = i_height;
  637.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
  638.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
  639.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
  640.             p_pic->p[ V_PLANE ].i_visible_lines = i_height;
  641.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
  642.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
  643.             p_pic->i_planes = 3;
  644.             break;
  645.         case FOURCC_I410:
  646.         case FOURCC_YVU9:
  647.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  648.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  649.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  650.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  651.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 4;
  652.             p_pic->p[ U_PLANE ].i_visible_lines = i_height / 4;
  653.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
  654.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
  655.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 4;
  656.             p_pic->p[ V_PLANE ].i_visible_lines = i_height / 4;
  657.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
  658.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
  659.             p_pic->i_planes = 3;
  660.             break;
  661.         case FOURCC_YV12:
  662.         case FOURCC_I420:
  663.         case FOURCC_IYUV:
  664.         case FOURCC_J420:
  665.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  666.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  667.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  668.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  669.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
  670.             p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
  671.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
  672.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
  673.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
  674.             p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
  675.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 2;
  676.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 2;
  677.             p_pic->i_planes = 3;
  678.             break;
  679.         case FOURCC_I422:
  680.         case FOURCC_J422:
  681.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  682.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  683.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  684.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  685.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
  686.             p_pic->p[ U_PLANE ].i_visible_lines = i_height;
  687.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
  688.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
  689.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
  690.             p_pic->p[ V_PLANE ].i_visible_lines = i_height;
  691.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 2;
  692.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 2;
  693.             p_pic->i_planes = 3;
  694.             break;
  695.         case FOURCC_I440:
  696.         case FOURCC_J440:
  697.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  698.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  699.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  700.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  701.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
  702.             p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
  703.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
  704.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
  705.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
  706.             p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
  707.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
  708.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
  709.             p_pic->i_planes = 3;
  710.             break;
  711.         case FOURCC_I444:
  712.         case FOURCC_J444:
  713.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  714.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  715.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  716.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  717.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
  718.             p_pic->p[ U_PLANE ].i_visible_lines = i_height;
  719.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
  720.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
  721.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
  722.             p_pic->p[ V_PLANE ].i_visible_lines = i_height;
  723.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
  724.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
  725.             p_pic->i_planes = 3;
  726.             break;
  727.         case FOURCC_YUVA:
  728.             p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
  729.             p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
  730.             p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
  731.             p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
  732.             p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
  733.             p_pic->p[ U_PLANE ].i_visible_lines = i_height;
  734.             p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
  735.             p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
  736.             p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
  737.             p_pic->p[ V_PLANE ].i_visible_lines = i_height;
  738.             p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
  739.             p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
  740.             p_pic->p[ A_PLANE ].i_lines = i_height_aligned;
  741.             p_pic->p[ A_PLANE ].i_visible_lines = i_height;
  742.             p_pic->p[ A_PLANE ].i_pitch = i_width_aligned;
  743.             p_pic->p[ A_PLANE ].i_visible_pitch = i_width;
  744.             p_pic->i_planes = 4;
  745.             break;
  746.         case FOURCC_YUVP:
  747.             p_pic->p->i_lines = i_height_aligned;
  748.             p_pic->p->i_visible_lines = i_height;
  749.             p_pic->p->i_pitch = i_width_aligned;
  750.             p_pic->p->i_visible_pitch = i_width;
  751.             p_pic->p->i_pixel_pitch = 8;
  752.             p_pic->i_planes = 1;
  753.             break;
  754.         case FOURCC_Y211:
  755.             p_pic->p->i_lines = i_height_aligned;
  756.             p_pic->p->i_visible_lines = i_height;
  757.             p_pic->p->i_pitch = i_width_aligned;
  758.             p_pic->p->i_visible_pitch = i_width;
  759.             p_pic->p->i_pixel_pitch = 4;
  760.             p_pic->i_planes = 1;
  761.             break;
  762.         case FOURCC_UYVY:
  763.         case FOURCC_YUY2:
  764.             p_pic->p->i_lines = i_height_aligned;
  765.             p_pic->p->i_visible_lines = i_height;
  766.             p_pic->p->i_pitch = i_width_aligned * 2;
  767.             p_pic->p->i_visible_pitch = i_width * 2;
  768.             p_pic->p->i_pixel_pitch = 4;
  769.             p_pic->i_planes = 1;
  770.             break;
  771.         case FOURCC_RGB2:
  772.             p_pic->p->i_lines = i_height_aligned;
  773.             p_pic->p->i_visible_lines = i_height;
  774.             p_pic->p->i_pitch = i_width_aligned;
  775.             p_pic->p->i_visible_pitch = i_width;
  776.             p_pic->p->i_pixel_pitch = 1;
  777.             p_pic->i_planes = 1;
  778.             break;
  779.         case FOURCC_RV15:
  780.             p_pic->p->i_lines = i_height_aligned;
  781.             p_pic->p->i_visible_lines = i_height;
  782.             p_pic->p->i_pitch = i_width_aligned * 2;
  783.             p_pic->p->i_visible_pitch = i_width * 2;
  784.             p_pic->p->i_pixel_pitch = 2;
  785.             p_pic->i_planes = 1;
  786.             break;
  787.         case FOURCC_RV16:
  788.             p_pic->p->i_lines = i_height_aligned;
  789.             p_pic->p->i_visible_lines = i_height;
  790.             p_pic->p->i_pitch = i_width_aligned * 2;
  791.             p_pic->p->i_visible_pitch = i_width * 2;
  792.             p_pic->p->i_pixel_pitch = 2;
  793.             p_pic->i_planes = 1;
  794.             break;
  795.         case FOURCC_RV24:
  796.             p_pic->p->i_lines = i_height_aligned;
  797.             p_pic->p->i_visible_lines = i_height;
  798.             p_pic->p->i_pitch = i_width_aligned * 3;
  799.             p_pic->p->i_visible_pitch = i_width * 3;
  800.             p_pic->p->i_pixel_pitch = 3;
  801.             p_pic->i_planes = 1;
  802.             break;
  803.         case FOURCC_RV32:
  804.         case FOURCC_RGBA:
  805.             p_pic->p->i_lines = i_height_aligned;
  806.             p_pic->p->i_visible_lines = i_height;
  807.             p_pic->p->i_pitch = i_width_aligned * 4;
  808.             p_pic->p->i_visible_pitch = i_width * 4;
  809.             p_pic->p->i_pixel_pitch = 4;
  810.             p_pic->i_planes = 1;
  811.             break;
  812.         case FOURCC_GREY:
  813.         case FOURCC_Y800:
  814.         case FOURCC_Y8:
  815.         case FOURCC_RGBP:
  816.             p_pic->p->i_lines = i_height_aligned;
  817.             p_pic->p->i_visible_lines = i_height;
  818.             p_pic->p->i_pitch = i_width_aligned;
  819.             p_pic->p->i_visible_pitch = i_width;
  820.             p_pic->p->i_pixel_pitch = 1;
  821.             p_pic->i_planes = 1;
  822.             break;
  823.         default:
  824.             if( p_this )
  825.                 msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)",
  826.                                  i_chroma, (char*)&i_chroma );
  827.             p_pic->i_planes = 0;
  828.             return VLC_EGENERIC;
  829.     }
  830.     return VLC_SUCCESS;
  831. }
  832. /**
  833.  * Compare two chroma values
  834.  *
  835.  * This function returns 1 if the two fourcc values given as argument are
  836.  * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12)
  837.  */
  838. int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc )
  839. {
  840.     static const vlc_fourcc_t p_I420[] = {
  841.         FOURCC_I420, FOURCC_IYUV, FOURCC_YV12, FOURCC_J420, 0
  842.     };
  843.     static const vlc_fourcc_t p_I422[] = {
  844.         FOURCC_I422, FOURCC_J422, 0
  845.     };
  846.     static const vlc_fourcc_t p_I440[] = {
  847.         FOURCC_I440, FOURCC_J440, 0
  848.     };
  849.     static const vlc_fourcc_t p_I444[] = {
  850.         FOURCC_I444, FOURCC_J444, 0
  851.     };
  852.     static const vlc_fourcc_t p_UYVY[] = {
  853.         FOURCC_UYVY, FOURCC_UYNV, FOURCC_Y422, 0
  854.     };
  855.     static const vlc_fourcc_t p_YUYV[] = {
  856.         FOURCC_YUY2, FOURCC_YUNV, 0
  857.     };
  858.     static const vlc_fourcc_t p_GREY[] = {
  859.         FOURCC_GREY, FOURCC_Y800, FOURCC_Y8, 0
  860.     };
  861.     static const vlc_fourcc_t *pp_fcc[] = {
  862.         p_I420, p_I422, p_I440, p_I444, p_UYVY, p_YUYV, p_GREY, NULL
  863.     };
  864.     /* If they are the same, they are the same ! */
  865.     if( i_chroma == i_amorhc )
  866.         return 1;
  867.     /* Check for equivalence classes */
  868.     for( int i = 0; pp_fcc[i] != NULL; i++ )
  869.     {
  870.         bool b_fcc1 = false;
  871.         bool b_fcc2 = false;
  872.         for( int j = 0; pp_fcc[i][j] != 0; j++ )
  873.         {
  874.             if( i_chroma == pp_fcc[i][j] )
  875.                 b_fcc1 = true;
  876.             if( i_amorhc == pp_fcc[i][j] )
  877.                 b_fcc2 = true;
  878.         }
  879.         if( b_fcc1 && b_fcc2 )
  880.             return 1;
  881.     }
  882.     return 0;
  883. }
  884. /*****************************************************************************
  885.  *
  886.  *****************************************************************************/
  887. static void PictureReleaseCallback( picture_t *p_picture )
  888. {
  889.     if( --p_picture->i_refcount > 0 )
  890.         return;
  891.     picture_Delete( p_picture );
  892. }
  893. /*****************************************************************************
  894.  *
  895.  *****************************************************************************/
  896. picture_t *picture_New( vlc_fourcc_t i_chroma, int i_width, int i_height, int i_aspect )
  897. {
  898.     picture_t *p_picture = calloc( 1, sizeof(*p_picture) );
  899.     if( !p_picture )
  900.         return NULL;
  901.     if( __vout_AllocatePicture( NULL, p_picture,
  902.                                 i_chroma, i_width, i_height, i_aspect ) )
  903.     {
  904.         free( p_picture );
  905.         return NULL;
  906.     }
  907.     p_picture->i_refcount = 1;
  908.     p_picture->pf_release = PictureReleaseCallback;
  909.     p_picture->i_status = RESERVED_PICTURE;
  910.     return p_picture;
  911. }
  912. /*****************************************************************************
  913.  *
  914.  *****************************************************************************/
  915. void picture_Delete( picture_t *p_picture )
  916. {
  917.     assert( p_picture && p_picture->i_refcount == 0 );
  918.     free( p_picture->p_q );
  919.     free( p_picture->p_data_orig );
  920.     free( p_picture->p_sys );
  921.     free( p_picture );
  922. }
  923. /*****************************************************************************
  924.  *
  925.  *****************************************************************************/
  926. void picture_CopyPixels( picture_t *p_dst, const picture_t *p_src )
  927. {
  928.     int i;
  929.     for( i = 0; i < p_src->i_planes ; i++ )
  930.         plane_CopyPixels( p_dst->p+i, p_src->p+i );
  931. }
  932. void plane_CopyPixels( plane_t *p_dst, const plane_t *p_src )
  933. {
  934.     const unsigned i_width  = __MIN( p_dst->i_visible_pitch,
  935.                                      p_src->i_visible_pitch );
  936.     const unsigned i_height = __MIN( p_dst->i_visible_lines,
  937.                                      p_src->i_visible_lines );
  938.     if( p_src->i_pitch == p_dst->i_pitch )
  939.     {
  940.         /* There are margins, but with the same width : perfect ! */
  941.         vlc_memcpy( p_dst->p_pixels, p_src->p_pixels,
  942.                     p_src->i_pitch * i_height );
  943.     }
  944.     else
  945.     {
  946.         /* We need to proceed line by line */
  947.         uint8_t *p_in = p_src->p_pixels;
  948.         uint8_t *p_out = p_dst->p_pixels;
  949.         int i_line;
  950.         assert( p_in );
  951.         assert( p_out );
  952.         for( i_line = i_height; i_line--; )
  953.         {
  954.             vlc_memcpy( p_out, p_in, i_width );
  955.             p_in += p_src->i_pitch;
  956.             p_out += p_dst->i_pitch;
  957.         }
  958.     }
  959. }
  960. /*****************************************************************************
  961.  *
  962.  *****************************************************************************/
  963. int picture_Export( vlc_object_t *p_obj,
  964.                     block_t **pp_image,
  965.                     video_format_t *p_fmt,
  966.                     picture_t *p_picture,
  967.                     vlc_fourcc_t i_format,
  968.                     int i_override_width, int i_override_height )
  969. {
  970.     /* */
  971.     video_format_t fmt_in = p_picture->format;
  972.     if( fmt_in.i_sar_num <= 0 || fmt_in.i_sar_den <= 0 )
  973.     {
  974.         fmt_in.i_sar_num =
  975.         fmt_in.i_sar_den = 1;
  976.     }
  977.     /* */
  978.     video_format_t fmt_out;
  979.     memset( &fmt_out, 0, sizeof(fmt_out) );
  980.     fmt_out.i_sar_num =
  981.     fmt_out.i_sar_den = 1;
  982.     fmt_out.i_chroma  = i_format;
  983.     /* compute original width/height */
  984.     unsigned int i_original_width;
  985.     unsigned int i_original_height;
  986.     if( fmt_in.i_sar_num >= fmt_in.i_sar_den )
  987.     {
  988.         i_original_width = fmt_in.i_width * fmt_in.i_sar_num / fmt_in.i_sar_den;
  989.         i_original_height = fmt_in.i_height;
  990.     }
  991.     else
  992.     {
  993.         i_original_width =  fmt_in.i_width;
  994.         i_original_height = fmt_in.i_height * fmt_in.i_sar_den / fmt_in.i_sar_num;
  995.     }
  996.     /* */
  997.     fmt_out.i_width  = ( i_override_width < 0 ) ?
  998.                        i_original_width : i_override_width;
  999.     fmt_out.i_height = ( i_override_height < 0 ) ?
  1000.                        i_original_height : i_override_height;
  1001.     /* scale if only one direction is provided */
  1002.     if( fmt_out.i_height == 0 && fmt_out.i_width > 0 )
  1003.     {
  1004.         fmt_out.i_height = fmt_in.i_height * fmt_out.i_width
  1005.                      * fmt_in.i_sar_den / fmt_in.i_width / fmt_in.i_sar_num;
  1006.     }
  1007.     else if( fmt_out.i_width == 0 && fmt_out.i_height > 0 )
  1008.     {
  1009.         fmt_out.i_width  = fmt_in.i_width * fmt_out.i_height
  1010.                      * fmt_in.i_sar_num / fmt_in.i_height / fmt_in.i_sar_den;
  1011.     }
  1012.     image_handler_t *p_image = image_HandlerCreate( p_obj );
  1013.     block_t *p_block = image_Write( p_image, p_picture, &fmt_in, &fmt_out );
  1014.     image_HandlerDelete( p_image );
  1015.     if( !p_block )
  1016.         return VLC_EGENERIC;
  1017.     p_block->i_pts =
  1018.     p_block->i_dts = p_picture->date;
  1019.     if( p_fmt )
  1020.         *p_fmt = fmt_out;
  1021.     *pp_image = p_block;
  1022.     return VLC_SUCCESS;
  1023. }
  1024. /*****************************************************************************
  1025.  *
  1026.  *****************************************************************************/