+ int i_subpic; /* subpicture index */
+ subpicture_t * p_free_subpic = NULL; /* first free subpicture */
+ subpicture_t * p_destroyed_subpic = NULL; /* first destroyed subpic */
+
+ /* Get lock */
+ vlc_mutex_lock( &p_vout->subpicture_lock );
+
+ /*
+ * Look for an empty place
+ */
+ for( i_subpic = 0; i_subpic < VOUT_MAX_PICTURES; i_subpic++ )
+ {
+ if( p_vout->p_subpicture[i_subpic].i_status == DESTROYED_SUBPICTURE )
+ {
+ /* Subpicture is marked for destruction, but is still allocated */
+ if( (p_vout->p_subpicture[i_subpic].i_type == i_type) &&
+ (p_vout->p_subpicture[i_subpic].i_size >= i_size) )
+ {
+ /* Memory size do match or is smaller : memory will not be reallocated,
+ * and function can end immediately - this is the best possible case,
+ * since no memory allocation needs to be done */
+ p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE;
+#ifdef DEBUG_VIDEO
+ intf_DbgMsg("subpicture %p (in destroyed subpicture slot)\n",
+ &p_vout->p_subpicture[i_subpic] );
+#endif
+ vlc_mutex_unlock( &p_vout->subpicture_lock );
+ return( &p_vout->p_subpicture[i_subpic] );
+ }
+ else if( p_destroyed_subpic == NULL )
+ {
+ /* Memory size do not match, but subpicture index will be kept in
+ * case no other place are left */
+ p_destroyed_subpic = &p_vout->p_subpicture[i_subpic];
+ }
+ }
+ else if( (p_free_subpic == NULL) &&
+ (p_vout->p_subpicture[i_subpic].i_status == FREE_SUBPICTURE ))
+ {
+ /* Subpicture is empty and ready for allocation */
+ p_free_subpic = &p_vout->p_subpicture[i_subpic];
+ }
+ }
+
+ /* If no free subpicture is available, use a destroyed subpicture */
+ if( (p_free_subpic == NULL) && (p_destroyed_subpic != NULL ) )
+ {
+ /* No free subpicture or matching destroyed subpicture has been found, but
+ * a destroyed subpicture is still avalaible */
+ free( p_destroyed_subpic->p_data );
+ p_free_subpic = p_destroyed_subpic;
+ }
+
+ /*
+ * Prepare subpicture
+ */
+ if( p_free_subpic != NULL )
+ {
+ /* Allocate memory */
+ switch( i_type )
+ {
+ case TEXT_SUBPICTURE: /* text subpicture */
+ p_free_subpic->p_data = malloc( i_size + 1 );
+ break;
+#ifdef DEBUG
+ default:
+ intf_DbgMsg("error: unknown subpicture type %d\n", i_type );
+ p_free_subpic->p_data = NULL;
+ break;
+#endif
+ }
+
+ if( p_free_subpic->p_data != NULL )
+ { /* Copy subpicture informations, set some default values */
+ p_free_subpic->i_type = i_type;
+ p_free_subpic->i_status = RESERVED_SUBPICTURE;
+ p_free_subpic->i_size = i_size;
+ p_free_subpic->i_x = 0;
+ p_free_subpic->i_y = 0;
+ p_free_subpic->i_width = 0;
+ p_free_subpic->i_height = 0;
+ p_free_subpic->i_horizontal_align = CENTER_RALIGN;
+ p_free_subpic->i_vertical_align = CENTER_RALIGN;
+ }
+ else
+ {
+ /* Memory allocation failed : set subpicture as empty */
+ p_free_subpic->i_type = EMPTY_SUBPICTURE;
+ p_free_subpic->i_status = FREE_SUBPICTURE;
+ p_free_subpic = NULL;
+ intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
+ }
+
+#ifdef DEBUG_VIDEO
+ intf_DbgMsg("subpicture %p (in free subpicture slot)\n", p_free_subpic );
+#endif
+ vlc_mutex_unlock( &p_vout->subpicture_lock );
+ return( p_free_subpic );
+ }
+
+ /* No free or destroyed subpicture could be found */
+ intf_DbgMsg( "warning: heap is full\n" );
+ vlc_mutex_unlock( &p_vout->subpicture_lock );
+ return( NULL );