📄 objects.c
字号:
/***************************************************************************** * objects.c: vlc_object_t handling ***************************************************************************** * Copyright (C) 2004-2008 the VideoLAN team * * Authors: Samuel Hocevar <sam@zoy.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//** * \file * This file contains the functions to handle the vlc_object_t type *//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include "../libvlc.h"#include <vlc_vout.h>#include <vlc_aout.h>#include "audio_output/aout_internal.h"#include <vlc_access.h>#include <vlc_demux.h>#include <vlc_stream.h>#include <vlc_sout.h>#include "stream_output/stream_output.h"#include "vlc_interface.h"#include "vlc_codec.h"#include "vlc_filter.h"#include "variables.h"#ifndef WIN32# include <unistd.h>#else# include <io.h># include <fcntl.h># include <errno.h> /* ENOSYS */#endif#include <assert.h>/***************************************************************************** * Local prototypes *****************************************************************************/static int DumpCommand( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static vlc_object_t * FindObject ( vlc_object_t *, int, int );static vlc_object_t * FindObjectName( vlc_object_t *, const char *, int );static void PrintObject ( vlc_object_t *, const char * );static void DumpStructure ( vlc_object_t *, int, char * );static vlc_list_t * NewList ( int );static void ListReplace ( vlc_list_t *, vlc_object_t *, int );/*static void ListAppend ( vlc_list_t *, vlc_object_t * );*/static int CountChildren ( vlc_object_t *, int );static void ListChildren ( vlc_list_t *, vlc_object_t *, int );static void vlc_object_destroy( vlc_object_t *p_this );static void vlc_object_detach_unlocked (vlc_object_t *p_this);#ifdef LIBVLC_REFCHECKstatic vlc_threadvar_t held_objects;typedef struct held_list_t{ struct held_list_t *next; vlc_object_t *obj;} held_list_t;static void held_objects_destroy (void *);#endif/***************************************************************************** * Local structure lock *****************************************************************************/static vlc_mutex_t structure_lock;static unsigned object_counter = 0;void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size, int i_type, const char *psz_type ){ vlc_object_t *p_new; vlc_object_internals_t *p_priv; /* NOTE: * VLC objects are laid out as follow: * - first the LibVLC-private per-object data, * - then VLC_COMMON members from vlc_object_t, * - finally, the type-specific data (if any). * * This function initializes the LibVLC and common data, * and zeroes the rest. */ p_priv = calloc( 1, sizeof( *p_priv ) + i_size ); if( p_priv == NULL ) return NULL; assert (i_size >= sizeof (vlc_object_t)); p_new = (vlc_object_t *)(p_priv + 1); p_new->i_object_type = i_type; p_new->psz_object_type = psz_type; p_new->psz_object_name = NULL; p_new->b_die = false; p_new->b_error = false; p_new->b_dead = false; p_new->b_force = false; p_new->psz_header = NULL; if (p_this) p_new->i_flags = p_this->i_flags & (OBJECT_FLAGS_NODBG|OBJECT_FLAGS_QUIET|OBJECT_FLAGS_NOINTERACT); p_priv->p_vars = calloc( sizeof( variable_t ), 16 ); if( !p_priv->p_vars ) { free( p_priv ); return NULL; } libvlc_global_data_t *p_libvlc_global; if( p_this == NULL ) { /* Only the global root object is created out of the blue */ p_libvlc_global = (libvlc_global_data_t *)p_new; p_new->p_libvlc = NULL; object_counter = 0; /* reset */ p_priv->next = p_priv->prev = p_new; vlc_mutex_init( &structure_lock );#ifdef LIBVLC_REFCHECK /* TODO: use the destruction callback to track ref leaks */ vlc_threadvar_create( &held_objects, held_objects_destroy );#endif } else { p_libvlc_global = vlc_global(); if( i_type == VLC_OBJECT_LIBVLC ) p_new->p_libvlc = (libvlc_int_t*)p_new; else p_new->p_libvlc = p_this->p_libvlc; } vlc_spin_init( &p_priv->ref_spin ); p_priv->i_refcount = 1; p_priv->pf_destructor = NULL; p_priv->b_thread = false; p_new->p_parent = NULL; p_priv->pp_children = NULL; p_priv->i_children = 0; p_new->p_private = NULL; /* Initialize mutexes and condvars */ vlc_mutex_init( &p_priv->lock ); vlc_cond_init( p_new, &p_priv->wait ); vlc_mutex_init( &p_priv->var_lock ); vlc_spin_init( &p_priv->spin ); p_priv->pipes[0] = p_priv->pipes[1] = -1; p_priv->next = VLC_OBJECT (p_libvlc_global);#if !defined (LIBVLC_REFCHECK) /* ... */#elif defined (LIBVLC_USE_PTHREAD) p_priv->creator_id = pthread_self ();#elif defined (WIN32) p_priv->creator_id = GetCurrentThreadId ();#endif vlc_mutex_lock( &structure_lock ); p_priv->prev = vlc_internals (p_libvlc_global)->prev; vlc_internals (p_libvlc_global)->prev = p_new; vlc_internals (p_priv->prev)->next = p_new; p_new->i_object_id = object_counter++; /* fetch THEN increment */ vlc_mutex_unlock( &structure_lock ); if( i_type == VLC_OBJECT_LIBVLC ) { var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_new, "list", DumpCommand, NULL ); var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_new, "tree", DumpCommand, NULL ); var_Create( p_new, "vars", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_AddCallback( p_new, "vars", DumpCommand, NULL ); } return p_new;}/** * Allocates and initializes a vlc object. * * @param i_type known object type (all of them are negative integer values), * or object byte size (always positive). * * @return the new object, or NULL on error. */void * __vlc_object_create( vlc_object_t *p_this, int i_type ){ const char * psz_type; size_t i_size; switch( i_type ) { case VLC_OBJECT_INTF: i_size = sizeof(intf_thread_t); psz_type = "interface"; break; case VLC_OBJECT_DECODER: i_size = sizeof(decoder_t); psz_type = "decoder"; break; case VLC_OBJECT_PACKETIZER: i_size = sizeof(decoder_t); psz_type = "packetizer"; break; case VLC_OBJECT_ENCODER: i_size = sizeof(encoder_t); psz_type = "encoder"; break; case VLC_OBJECT_AOUT: i_size = sizeof(aout_instance_t); psz_type = "audio output"; break; case VLC_OBJECT_OPENGL: i_size = sizeof( vout_thread_t ); psz_type = "opengl"; break; case VLC_OBJECT_ANNOUNCE: i_size = sizeof( announce_handler_t ); psz_type = "announce"; break; default: assert( i_type > 0 ); /* unknown type?! */ i_size = i_type; i_type = VLC_OBJECT_GENERIC; psz_type = "generic"; break; } return vlc_custom_create( p_this, i_size, i_type, psz_type );}/** **************************************************************************** * Set the destructor of a vlc object * * This function sets the destructor of the vlc object. It will be called * when the object is destroyed when the its refcount reaches 0. * (It is called by the internal function vlc_object_destroy()) *****************************************************************************/void __vlc_object_set_destructor( vlc_object_t *p_this, vlc_destructor_t pf_destructor ){ vlc_object_internals_t *p_priv = vlc_internals(p_this ); p_priv->pf_destructor = pf_destructor;}/** **************************************************************************** * Destroy a vlc object (Internal) * * This function destroys an object that has been previously allocated with * vlc_object_create. The object's refcount must be zero and it must not be * attached to other objects in any way. *****************************************************************************/static void vlc_object_destroy( vlc_object_t *p_this ){ vlc_object_internals_t *p_priv = vlc_internals( p_this ); /* Objects are always detached beforehand */ assert( !p_this->p_parent ); /* Send a kill to the object's thread if applicable */ vlc_object_kill( p_this ); /* If we are running on a thread, wait until it ends */ if( p_priv->b_thread ) { msg_Warn (p_this->p_libvlc, /* do NOT use a dead object for logging! */ "%s %d destroyed while thread alive (VLC might crash)", p_this->psz_object_type, p_this->i_object_id); vlc_thread_join( p_this ); } /* Call the custom "subclass" destructor */ if( p_priv->pf_destructor ) p_priv->pf_destructor( p_this ); /* Destroy the associated variables, starting from the end so that * no memmove calls have to be done. */ while( p_priv->i_vars ) { var_Destroy( p_this, p_priv->p_vars[p_priv->i_vars - 1].psz_name ); } free( p_priv->p_vars ); vlc_mutex_destroy( &p_priv->var_lock ); free( p_this->psz_header ); if( p_this->p_libvlc == NULL ) {#ifndef NDEBUG libvlc_global_data_t *p_global = (libvlc_global_data_t *)p_this; assert( p_global == vlc_global() ); /* Test for leaks */ if (p_priv->next != p_this) { vlc_object_t *leaked = p_priv->next, *first = leaked; do { /* We are leaking this object */ fprintf( stderr, "ERROR: leaking object (id:%i, type:%s, name:%s)\n", leaked->i_object_id, leaked->psz_object_type, leaked->psz_object_name ); /* Dump libvlc object to ease debugging */ vlc_object_dump( leaked ); fflush(stderr); leaked = vlc_internals (leaked)->next; } while (leaked != first); /* Dump global object to ease debugging */ vlc_object_dump( p_this ); /* Strongly abort, cause we want these to be fixed */ abort(); }#endif /* We are the global object ... no need to lock. */ vlc_mutex_destroy( &structure_lock );#ifdef LIBVLC_REFCHECK held_objects_destroy( vlc_threadvar_get( &held_objects ) ); vlc_threadvar_delete( &held_objects );#endif } FREENULL( p_this->psz_object_name );#if defined(WIN32) || defined(UNDER_CE) /* if object has an associated thread, close it now */ if( p_priv->thread_id ) CloseHandle(p_priv->thread_id);#endif vlc_spin_destroy( &p_priv->ref_spin ); vlc_mutex_destroy( &p_priv->lock ); vlc_cond_destroy( &p_priv->wait ); vlc_spin_destroy( &p_priv->spin ); if( p_priv->pipes[1] != -1 ) close( p_priv->pipes[1] ); if( p_priv->pipes[0] != -1 ) close( p_priv->pipes[0] ); free( p_priv );}/** Inter-object signaling */void __vlc_object_lock( vlc_object_t *obj )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -