Changeset 3893 for pjproject/trunk


Ignore:
Timestamp:
Dec 1, 2011 10:49:07 AM (13 years ago)
Author:
ming
Message:

Closed #1420: Add support for event manager

Location:
pjproject/trunk
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev.h

    r3864 r3893  
    752752 
    753753/** 
    754  * Get the event publisher object for the video stream. Caller typically use 
    755  * the returned object to subscribe or unsubscribe events from the video 
    756  * stream. 
    757  * 
    758  * @param strm      The video stream. 
    759  * 
    760  * @return          The event publisher object. 
    761  */ 
    762 PJ_DECL(pjmedia_event_publisher*) 
    763 pjmedia_vid_dev_stream_get_event_publisher(pjmedia_vid_dev_stream *strm); 
    764  
    765  
    766 /** 
    767754 * Request one frame from the stream. Application needs to call this function 
    768755 * periodically only if the stream doesn't support "active interface", i.e. 
  • pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev_imp.h

    r3758 r3893  
    189189    /** Operations */ 
    190190    pjmedia_vid_dev_stream_op *op; 
    191  
    192     /** Event producer */ 
    193     pjmedia_event_publisher     epub; 
    194191}; 
    195192 
  • pjproject/trunk/pjmedia/include/pjmedia/event.h

    r3774 r3893  
    2626#include <pjmedia/format.h> 
    2727#include <pjmedia/signatures.h> 
    28 #include <pj/list.h> 
    2928 
    3029PJ_BEGIN_DECL 
     
    8988 
    9089/** 
    91  * Forward declaration for event subscription. 
    92  */ 
    93 typedef struct pjmedia_event_subscription pjmedia_event_subscription; 
    94  
    95 /** 
    96  * Forward declaration for event publisher. 
    97  */ 
    98 typedef struct pjmedia_event_publisher pjmedia_event_publisher; 
    99  
    100 /** 
    10190 * Additional data/parameters for media format changed event 
    10291 * (PJMEDIA_EVENT_FMT_CHANGED). 
     
    163152/** 
    164153 * This structure describes a media event. It consists mainly of the event 
    165  * type and additional data/parameters for the event. Event publishers need 
    166  * to use #pjmedia_event_init() to initialize this event structure with 
     154 * type and additional data/parameters for the event. Applications can 
     155 * use #pjmedia_event_init() to initialize this event structure with 
    167156 * basic information about the event. 
    168157 */ 
     
    180169 
    181170    /** 
    182      * This keeps count on the number of subscribers that have 
    183      * processed this event. 
    184      */ 
    185     unsigned                             proc_cnt; 
    186  
    187     /** 
    188      * The object signature of the event publisher. Application may use 
    189      * this to check which publisher published the event. 
    190      */ 
    191     pjmedia_obj_sig                      epub_sig; 
    192  
    193     /** 
    194171     * Pointer information about the source of this event. This field 
    195      * is provided mainly so that the event subscribers can compare it 
    196      * against the publisher that it subscribed the events from initially, 
    197      * a publisher can republish events from other publisher. Event 
    198      * subscription must be careful when using this pointer other than for 
    199      * comparison purpose, since access to the publisher may require special 
    200      * care (e.g. mutex locking). 
    201      */ 
    202     const pjmedia_event_publisher       *epub; 
     172     * is provided mainly for comparison purpose so that event subscribers 
     173     * can check which source the event originated from. Usage of this 
     174     * pointer for other purpose may require special care such as mutex 
     175     * locking or checking whether the object is already destroyed. 
     176     */ 
     177    const void                          *src; 
     178 
     179    /** 
     180     * Pointer information about the publisher of this event. This field 
     181     * is provided mainly for comparison purpose so that event subscribers 
     182     * can check which object published the event. Usage of this 
     183     * pointer for other purpose may require special care such as mutex 
     184     * locking or checking whether the object is already destroyed. 
     185     */ 
     186    const void                          *epub; 
    203187 
    204188    /** 
     
    239223 
    240224/** 
    241  * The callback to receive media events. The callback should increase 
    242  * \a proc_cnt field of the event if it processes the event. 
    243  * 
    244  * @param esub          The subscription that was made initially to receive 
    245  *                      this event. 
    246  * @param event         The media event itself. 
     225 * The callback to receive media events. 
     226 * 
     227 * @param event         The media event. 
     228 * @param user_data     The user data associated with the callback. 
    247229 * 
    248230 * @return              If the callback returns non-PJ_SUCCESS, this return 
    249  *                      code may be propagated back to the producer. 
    250  */ 
    251 typedef pj_status_t pjmedia_event_cb(pjmedia_event_subscription *esub, 
    252                                      pjmedia_event *event); 
    253  
    254 /** 
    255  * This structure keeps the data needed to maintain an event subscription. 
    256  * This data is normally kept by event publishers. 
    257  */ 
    258 struct pjmedia_event_subscription 
    259 { 
    260     /** Standard list members */ 
    261     PJ_DECL_LIST_MEMBER(pjmedia_event_subscription); 
    262  
    263     /** Callback that will be called by publisher to report events. */ 
    264     pjmedia_event_cb    *cb; 
    265  
    266     /** User data for this subscription */ 
    267     void                *user_data; 
    268  
    269     /** Current publisher it is subscribed to */ 
    270     pjmedia_event_publisher *subscribe_to; 
    271 }; 
    272  
    273 /** 
    274  * This describes an event publisher. An event publisher is an object that 
    275  * maintains event subscriptions. When an event is published on behalf of 
    276  * a publisher with #pjmedia_event_publish(), that event will be propagated 
    277  * to all of the subscribers registered to the publisher. 
    278  */ 
    279 struct pjmedia_event_publisher 
    280 { 
    281     /** The object signature of the publisher */ 
    282     pjmedia_obj_sig             sig; 
    283  
    284     /** List of subscriptions for this event publisher */ 
    285     pjmedia_event_subscription  subscription_list; 
    286 }; 
     231 *                      code may be propagated back to the caller. 
     232 */ 
     233typedef pj_status_t pjmedia_event_cb(pjmedia_event *event, 
     234                                     void *user_data); 
     235 
     236/** 
     237 * This enumeration describes flags for event publication via 
     238 * #pjmedia_event_publish(). 
     239 */ 
     240typedef enum pjmedia_event_publish_flag 
     241{ 
     242    /** 
     243     * Publisher will only post the event to the event manager. It is the 
     244     * event manager that will later notify all the publisher's subscribers. 
     245     */ 
     246    PJMEDIA_EVENT_PUBLISH_POST_EVENT = 1 
     247 
     248} pjmedia_event_publish_flag; 
     249 
     250/** 
     251 * Event manager flag. 
     252 */ 
     253typedef enum pjmedia_event_mgr_flag 
     254{ 
     255    /** 
     256     * Tell the event manager not to create any event worker thread. 
     257     */ 
     258    PJMEDIA_EVENT_MGR_NO_THREAD = 1 
     259 
     260} pjmedia_event_mgr_flag; 
     261 
     262/** 
     263 * Opaque data type for event manager. Typically, the event manager 
     264 * is a singleton instance, although application may instantiate more than one 
     265 * instances of this if required. 
     266 */ 
     267typedef struct pjmedia_event_mgr pjmedia_event_mgr; 
     268 
     269/** 
     270 * Create a new event manager instance. This will also set the pointer 
     271 * to the singleton instance if the value is still NULL. 
     272 * 
     273 * @param pool          Pool to allocate memory from. 
     274 * @param options       Options. Bitmask flags from #pjmedia_event_mgr_flag 
     275 * @param mgr           Pointer to hold the created instance of the 
     276 *                      event manager. 
     277 * 
     278 * @return              PJ_SUCCESS on success or the appropriate error code. 
     279 */ 
     280PJ_DECL(pj_status_t) pjmedia_event_mgr_create(pj_pool_t *pool, 
     281                                              unsigned options, 
     282                                              pjmedia_event_mgr **mgr); 
     283 
     284/** 
     285 * Get the singleton instance of the event manager. 
     286 * 
     287 * @return              The instance. 
     288 */ 
     289PJ_DECL(pjmedia_event_mgr*) pjmedia_event_mgr_instance(void); 
     290 
     291/** 
     292 * Manually assign a specific event manager instance as the singleton 
     293 * instance. Normally this is not needed if only one instance is ever 
     294 * going to be created, as the library automatically assign the singleton 
     295 * instance. 
     296 * 
     297 * @param mgr           The instance to be used as the singleton instance. 
     298 *                      Application may specify NULL to clear the singleton 
     299 *                      singleton instance. 
     300 */ 
     301PJ_DECL(void) pjmedia_event_mgr_set_instance(pjmedia_event_mgr *mgr); 
     302 
     303/** 
     304 * Destroy an event manager. If the manager happens to be the singleton 
     305 * instance, the singleton instance will be set to NULL. 
     306 * 
     307 * @param mgr           The eventmanager. Specify NULL to use 
     308 *                      the singleton instance. 
     309 */ 
     310PJ_DECL(void) pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr); 
    287311 
    288312/** 
     
    293317 * @param ts            Event timestamp. May be set to NULL to set the event 
    294318 *                      timestamp to zero. 
    295  * @param epub          Event publisher. 
     319 * @param src           Event source. 
    296320 */ 
    297321PJ_DECL(void) pjmedia_event_init(pjmedia_event *event, 
    298322                                 pjmedia_event_type type, 
    299323                                 const pj_timestamp *ts, 
    300                                  const pjmedia_event_publisher *epub); 
    301  
    302 /** 
    303  * Initialize an event publisher structure. 
    304  * 
    305  * @param epub          The event publisher. 
    306  * @param sig           The object signature of the publisher. 
    307  */ 
    308 PJ_DECL(void) pjmedia_event_publisher_init(pjmedia_event_publisher *epub, 
    309                                            pjmedia_obj_sig sig); 
    310  
    311 /** 
    312  * Initialize subscription data. 
    313  * 
    314  * @param esub          The event subscription. 
    315  * @param cb            The callback to receive events. 
    316  * @param user_data     Arbitrary user data to be associated with the 
    317  *                      subscription. 
    318  */ 
    319 PJ_DECL(void) pjmedia_event_subscription_init(pjmedia_event_subscription *esub, 
    320                                               pjmedia_event_cb *cb, 
    321                                               void *user_data); 
    322  
    323 /** 
    324  * Subscribe to events published by the specified publisher using the 
    325  * specified subscription object. The callback and user data fields of 
    326  * the subscription object must have been initialized prior to calling 
    327  * this function, and the subscription object must be kept alive throughout 
    328  * the duration of the subscription (e.g. it must not be allocated from 
    329  * the stack). 
    330  * 
    331  * Note that the subscriber may receive not only events emitted by 
     324                                 const void *src); 
     325 
     326/** 
     327 * Subscribe a callback function to events published by the specified 
     328 * publisher. Note that the subscriber may receive not only events emitted by 
    332329 * the specific publisher specified in the argument, but also from other 
    333330 * publishers contained by the publisher, if the publisher is republishing 
    334331 * events from other publishers. 
    335332 * 
     333 * @param mgr           The event manager. 
     334 * @param pool          Pool to allocate memory from. 
     335 * @param cb            The callback function to receive the event. 
     336 * @param user_data     The user data to be associated with the callback 
     337 *                      function. 
    336338 * @param epub          The event publisher. 
    337  * @param esub          The event subscription object. 
    338339 * 
    339340 * @return              PJ_SUCCESS on success or the appropriate error code. 
    340341 */ 
    341 PJ_DECL(pj_status_t) pjmedia_event_subscribe(pjmedia_event_publisher *epub, 
    342                                              pjmedia_event_subscription *esub); 
    343  
    344 /** 
    345  * Unsubscribe the specified subscription object from publisher it is 
    346  * currently subscribed to. If the subscription object is not currently 
    347  * subscribed to anything, the function will do nothing. 
    348  * 
    349  * @param esub          The event subscription object, which must be the same 
    350  *                      object that was given to #pjmedia_event_subscribe(). 
     342PJ_DECL(pj_status_t) pjmedia_event_subscribe(pjmedia_event_mgr *mgr, 
     343                                             pj_pool_t *pool, 
     344                                             pjmedia_event_cb *cb, 
     345                                             void *user_data, 
     346                                             void *epub); 
     347 
     348/** 
     349 * Unsubscribe the callback associated with the user data from a publisher. 
     350 * If the user data is not specified, this function will do the 
     351 * unsubscription for all user data. If the publisher, epub, is not 
     352 * specified, this function will do the unsubscription from all publishers. 
     353 * 
     354 * @param mgr           The event manager. 
     355 * @param cb            The callback function. 
     356 * @param user_data     The user data associated with the callback 
     357 *                      function, can be NULL. 
     358 * @param epub          The event publisher, can be NULL. 
    351359 * 
    352360 * @return              PJ_SUCCESS on success or the appropriate error code. 
    353361 */ 
    354362PJ_DECL(pj_status_t) 
    355 pjmedia_event_unsubscribe(pjmedia_event_subscription *esub); 
    356  
    357 /** 
    358  * Check if the specified publisher has subscribers. 
    359  * 
    360  * @param epub          The event publisher. 
    361  * 
    362  * @return              PJ_TRUE if the publisher has at least one subscriber. 
    363  */ 
    364 PJ_DECL(pj_bool_t) 
    365 pjmedia_event_publisher_has_sub(pjmedia_event_publisher *epub); 
     363pjmedia_event_unsubscribe(pjmedia_event_mgr *mgr, 
     364                          pjmedia_event_cb *cb, 
     365                          void *user_data, 
     366                          void *epub); 
    366367 
    367368/** 
    368369 * Publish the specified event to all subscribers of the specified event 
    369  * publisher. 
    370  * 
     370 * publisher. By default, the function will call all the subcribers' 
     371 * callbacks immediately. If the publisher uses the flag 
     372 * PJMEDIA_EVENT_PUBLISH_POST_EVENT, publisher will only post the event 
     373 * to the event manager and return immediately. It is the event manager 
     374 * that will later notify all the publisher's subscribers. 
     375 * 
     376 * @param mgr           The event manager. 
    371377 * @param epub          The event publisher. 
    372378 * @param event         The event to be published. 
     379 * @param flag          Publication flag. 
    373380 * 
    374381 * @return              PJ_SUCCESS only if all subscription callbacks returned 
    375382 *                      PJ_SUCCESS. 
    376383 */ 
    377 PJ_DECL(pj_status_t) pjmedia_event_publish(pjmedia_event_publisher *epub, 
    378                                            pjmedia_event *event); 
    379  
    380 /** 
    381  * Subscribe to events produced by the source publisher in \a esrc and 
    382  * republish the events to all subscribers in \a epub publisher. 
    383  * 
    384  * @param esrc          The event source from which events will be 
    385  *                      republished. 
    386  * @param epub          Events from the event source above will be 
    387  *                      republished to subscribers of this publisher. 
    388  * @param esub          The subscription object to be used to subscribe 
    389  *                      to \a esrc. This doesn't need to be initialized, 
    390  *                      but it must be kept alive throughout the lifetime 
    391  *                      of the subsciption. 
    392  * 
    393  * @return              PJ_SUCCESS only if all subscription callbacks returned 
    394  *                      PJ_SUCCESS. 
    395  */ 
    396 PJ_DECL(pj_status_t) pjmedia_event_republish(pjmedia_event_publisher *esrc, 
    397                                              pjmedia_event_publisher *epub, 
    398                                              pjmedia_event_subscription *esub); 
     384PJ_DECL(pj_status_t) pjmedia_event_publish(pjmedia_event_mgr *mgr, 
     385                                           void *epub, 
     386                                           pjmedia_event *event, 
     387                                           pjmedia_event_publish_flag flag); 
     388 
    399389 
    400390/** 
  • pjproject/trunk/pjmedia/include/pjmedia/port.h

    r3664 r3893  
    400400    pj_status_t (*on_destroy)(struct pjmedia_port *this_port); 
    401401 
    402     /** 
    403      * Get event publisher for this media port, if any. 
    404      */ 
    405     pjmedia_event_publisher *(*get_event_pub)(struct pjmedia_port *this_port); 
    406  
    407402} pjmedia_port; 
    408403 
     
    485480 
    486481/** 
    487  * Get the event publisher for the media port, if any. 
     482 * Destroy port (and subsequent downstream ports) 
    488483 * 
    489484 * @param port      The media port. 
    490485 * 
    491  * @return          The event publisher, or NULL if the port does not publish 
    492  *                  events. 
    493  */ 
    494 PJ_DECL(pjmedia_event_publisher*) 
    495 pjmedia_port_get_event_publisher(pjmedia_port *port); 
    496  
    497 /** 
    498  * Destroy port (and subsequent downstream ports) 
    499  * 
    500  * @param port      The media port. 
    501  * 
    502486 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    503487 */ 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h

    r3795 r3893  
    250250    /** Operations to codec. */ 
    251251    pjmedia_vid_codec_op        *op; 
    252  
    253     /** Event publisher object */ 
    254     pjmedia_event_publisher      epub; 
    255252}; 
    256253 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_port.h

    r3758 r3893  
    106106 
    107107/** 
    108  * Get the event publisher instance of the video port. 
    109  * 
    110  * @param vid_port      The video port. 
    111  * 
    112  * @return              The event publisher of the video port. 
    113  */ 
    114 PJ_DECL(pjmedia_event_publisher*) 
    115 pjmedia_vid_port_get_event_publisher(pjmedia_vid_port *vid_port); 
    116  
    117 /** 
    118108 * Return the underlying video stream of the video port. 
    119109 * 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c

    r3861 r3893  
    16101610 
    16111611            /* Broadcast event */ 
    1612             if (pjmedia_event_publisher_has_sub(&codec->epub)) { 
     1612            { 
    16131613                pjmedia_event event; 
    16141614 
    16151615                pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, 
    1616                                    &input->timestamp, &codec->epub); 
     1616                                   &input->timestamp, codec); 
    16171617                event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 
    16181618                pj_memcpy(&event.data.fmt_changed.new_fmt, &ff->param.dec_fmt, 
    16191619                          sizeof(ff->param.dec_fmt)); 
    1620                 pjmedia_event_publish(&codec->epub, &event); 
     1620                pjmedia_event_publish(NULL, codec, &event, 0); 
    16211621            } 
    16221622        } 
     
    16521652 
    16531653        /* Check if we got key frame */ 
    1654         if (avframe.key_frame && pjmedia_event_publisher_has_sub(&codec->epub)) 
     1654        if (avframe.key_frame) 
    16551655        { 
    16561656            pjmedia_event event; 
    16571657 
    16581658            pjmedia_event_init(&event, PJMEDIA_EVENT_KEY_FRAME_FOUND, 
    1659                                &output->timestamp, &codec->epub); 
    1660             pjmedia_event_publish(&codec->epub, &event); 
     1659                               &output->timestamp, codec); 
     1660            pjmedia_event_publish(NULL, codec, &event, 0); 
    16611661        } 
    16621662    } else { 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c

    r3715 r3893  
    417417    pj_memcpy(&strm->vafp, &vafp, sizeof(vafp)); 
    418418    strm->ts_inc = PJMEDIA_SPF2(param->clock_rate, &vfd->fps, 1); 
    419     pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_COLORBAR); 
    420419 
    421420    for (i = 0; i < vfi->plane_cnt; ++i) { 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/dshow_dev.c

    r3803 r3893  
    870870    pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 
    871871    strm->user_data = user_data; 
    872     pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_DSHOW); 
    873872 
    874873    if (param->dir & PJMEDIA_DIR_CAPTURE) { 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c

    r3715 r3893  
    384384    strm->pool = pool; 
    385385    pj_memcpy(&strm->param, param, sizeof(*param)); 
    386     pjmedia_event_publisher_init(&strm->base.epub); 
    387386 
    388387    /* Done */ 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/sdl_dev.c

    r3864 r3893  
    309309    if (strm) 
    310310        pjmedia_event_init(pevent, PJMEDIA_EVENT_NONE, &strm->last_ts, 
    311                            &strm->base.epub); 
     311                           strm); 
    312312 
    313313    return strm; 
     
    355355            pj_status_t status; 
    356356 
    357             pjmedia_event_publish(&strm->base.epub, &pevent); 
     357            pjmedia_event_publish(NULL, strm, &pevent, 0); 
    358358 
    359359            switch (pevent.type) { 
     
    376376                sdl_destroy_all(strm); 
    377377                pjmedia_event_init(&pevent, PJMEDIA_EVENT_WND_CLOSED, 
    378                                    &strm->last_ts, 
    379                                    &strm->base.epub); 
    380                 pjmedia_event_publish(&strm->base.epub, &pevent); 
     378                                   &strm->last_ts, strm); 
     379                pjmedia_event_publish(NULL, strm, &pevent, 0); 
    381380 
    382381                /* 
     
    917916    pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 
    918917    strm->user_data = user_data; 
    919     pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_SDL); 
    920918 
    921919    /* Create render stream here */ 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c

    r3864 r3893  
    786786} 
    787787 
    788 PJ_DEF(pjmedia_event_publisher*) 
    789 pjmedia_vid_dev_stream_get_event_publisher(pjmedia_vid_dev_stream *strm) 
    790 { 
    791     return &strm->epub; 
    792 } 
    793  
    794788/* API: Start the stream. */ 
    795789PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm) 
  • pjproject/trunk/pjmedia/src/pjmedia/event.c

    r3782 r3893  
    2020#include <pjmedia/errno.h> 
    2121#include <pj/assert.h> 
     22#include <pj/list.h> 
    2223#include <pj/log.h> 
     24#include <pj/os.h> 
     25#include <pj/pool.h> 
    2326#include <pj/string.h> 
    2427 
    2528#define THIS_FILE       "event.c" 
    2629 
    27 #if 1 
    28 #   define TRACE_(x)    PJ_LOG(6,x) 
    29 #else 
    30 #   define TRACE_(x) 
    31 #endif 
     30#define MAX_EVENTS 16 
     31 
     32typedef struct esub esub; 
     33 
     34struct esub 
     35{ 
     36    PJ_DECL_LIST_MEMBER(esub); 
     37 
     38    pjmedia_event_cb    *cb; 
     39    void                *user_data; 
     40    void                *epub; 
     41}; 
     42 
     43typedef struct event_queue 
     44{ 
     45    pjmedia_event   events[MAX_EVENTS]; /**< array of events.           */ 
     46    int             head, tail; 
     47    pj_bool_t       is_full; 
     48} event_queue; 
     49 
     50struct pjmedia_event_mgr 
     51{ 
     52    pj_thread_t    *thread;             /**< worker thread.             */ 
     53    pj_bool_t       is_quitting; 
     54    pj_sem_t       *sem; 
     55    pj_mutex_t     *mutex; 
     56    event_queue     ev_queue; 
     57    event_queue    *pub_ev_queue;       /**< publish() event queue.     */ 
     58    esub            esub_list;          /**< list of subscribers.       */ 
     59    esub           *th_next_sub,        /**< worker thread's next sub.  */ 
     60                   *pub_next_sub;       /**< publish() next sub.        */ 
     61}; 
     62 
     63static pjmedia_event_mgr *event_manager_instance; 
     64 
     65static pj_status_t event_queue_add_event(event_queue* ev_queue, 
     66                                         pjmedia_event *event) 
     67{ 
     68    if (ev_queue->is_full) { 
     69        char ev_name[5]; 
     70 
     71        /* This event will be ignored. */ 
     72        PJ_LOG(4, (THIS_FILE, "Lost event %s from publisher [0x%p] " 
     73                              "due to full queue.", 
     74                              pjmedia_fourcc_name(event->type, ev_name), 
     75                              event->epub)); 
     76 
     77        return PJ_ETOOMANY; 
     78    } 
     79 
     80    pj_memcpy(&ev_queue->events[ev_queue->tail], event, sizeof(*event)); 
     81    ev_queue->tail = (ev_queue->tail + 1) % MAX_EVENTS; 
     82    if (ev_queue->tail == ev_queue->head) 
     83        ev_queue->is_full = PJ_TRUE; 
     84 
     85    return PJ_SUCCESS; 
     86} 
     87 
     88static pj_status_t event_mgr_distribute_events(pjmedia_event_mgr *mgr, 
     89                                               event_queue *ev_queue, 
     90                                               esub **next_sub) 
     91{ 
     92    pj_status_t err = PJ_SUCCESS; 
     93    esub * sub = mgr->esub_list.next; 
     94    pjmedia_event *ev = &ev_queue->events[ev_queue->head]; 
     95 
     96    while (sub != &mgr->esub_list) { 
     97        *next_sub = sub->next; 
     98 
     99        /* Check if the subscriber is interested in  
     100         * receiving the event from the publisher. 
     101         */ 
     102        if (sub->epub == ev->epub || !sub->epub) { 
     103            pj_status_t status = (*sub->cb)(ev, sub->user_data); 
     104            if (status != PJ_SUCCESS && err == PJ_SUCCESS) 
     105                err = status; 
     106        } 
     107        sub = *next_sub; 
     108    } 
     109    *next_sub = NULL; 
     110 
     111    ev_queue->head = (ev_queue->head + 1) % MAX_EVENTS; 
     112    ev_queue->is_full = PJ_FALSE; 
     113 
     114    return err; 
     115} 
     116 
     117/* Event worker thread function. */ 
     118static int event_worker_thread(void *arg) 
     119{ 
     120    pjmedia_event_mgr *mgr = (pjmedia_event_mgr *)arg; 
     121 
     122    while (1) { 
     123        /* Wait until there is an event. */ 
     124        pj_sem_wait(mgr->sem); 
     125 
     126        if (mgr->is_quitting) 
     127            break; 
     128 
     129        pj_mutex_lock(mgr->mutex); 
     130        event_mgr_distribute_events(mgr, &mgr->ev_queue, &mgr->th_next_sub); 
     131        pj_mutex_unlock(mgr->mutex); 
     132    } 
     133 
     134    return 0; 
     135} 
     136 
     137PJ_DEF(pj_status_t) pjmedia_event_mgr_create(pj_pool_t *pool, 
     138                                             unsigned options, 
     139                                             pjmedia_event_mgr **p_mgr) 
     140{ 
     141    pjmedia_event_mgr *mgr; 
     142    pj_status_t status; 
     143 
     144    mgr = PJ_POOL_ZALLOC_T(pool, pjmedia_event_mgr); 
     145    pj_list_init(&mgr->esub_list); 
     146 
     147    if (!(options & PJMEDIA_EVENT_MGR_NO_THREAD)) { 
     148        status = pj_sem_create(pool, "ev_sem", 0, MAX_EVENTS + 1, &mgr->sem); 
     149        if (status != PJ_SUCCESS) 
     150            return status; 
     151 
     152        status = pj_thread_create(pool, "ev_thread", &event_worker_thread, 
     153                                  mgr, 0, 0, &mgr->thread); 
     154        if (status != PJ_SUCCESS) { 
     155            pjmedia_event_mgr_destroy(mgr); 
     156            return status; 
     157        } 
     158    } 
     159 
     160    status = pj_mutex_create_recursive(pool, "ev_mutex", &mgr->mutex); 
     161    if (status != PJ_SUCCESS) { 
     162        pjmedia_event_mgr_destroy(mgr); 
     163        return status; 
     164    } 
     165 
     166    if (!event_manager_instance) 
     167        event_manager_instance = mgr; 
     168 
     169    if (p_mgr) 
     170        *p_mgr = mgr; 
     171 
     172    return PJ_SUCCESS; 
     173} 
     174 
     175PJ_DEF(pjmedia_event_mgr*) pjmedia_event_mgr_instance(void) 
     176{ 
     177    return event_manager_instance; 
     178} 
     179 
     180PJ_DEF(void) pjmedia_event_mgr_set_instance(pjmedia_event_mgr *mgr) 
     181{ 
     182    event_manager_instance = mgr; 
     183} 
     184 
     185PJ_DEF(void) pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr) 
     186{ 
     187    esub *sub; 
     188 
     189    if (!mgr) mgr = pjmedia_event_mgr_instance(); 
     190    PJ_ASSERT_ON_FAIL(mgr != NULL, return); 
     191 
     192    if (mgr->thread) { 
     193        mgr->is_quitting = PJ_TRUE; 
     194        pj_sem_post(mgr->sem); 
     195        pj_thread_join(mgr->thread); 
     196    } 
     197 
     198    if (mgr->sem) { 
     199        pj_sem_destroy(mgr->sem); 
     200        mgr->sem = NULL; 
     201    } 
     202 
     203    if (mgr->mutex) { 
     204        pj_mutex_destroy(mgr->mutex); 
     205        mgr->mutex = NULL; 
     206    } 
     207 
     208    sub = mgr->esub_list.next; 
     209    while (sub != &mgr->esub_list) { 
     210        esub *next = sub->next; 
     211        pj_list_erase(sub); 
     212        sub = next; 
     213    } 
     214 
     215    if (event_manager_instance == mgr) 
     216        event_manager_instance = NULL; 
     217} 
    32218 
    33219PJ_DEF(void) pjmedia_event_init( pjmedia_event *event, 
    34220                                 pjmedia_event_type type, 
    35221                                 const pj_timestamp *ts, 
    36                                  const pjmedia_event_publisher *epub) 
     222                                 const void *src) 
    37223{ 
    38224    pj_bzero(event, sizeof(*event)); 
     
    40226    if (ts) 
    41227        event->timestamp.u64 = ts->u64; 
     228    event->epub = event->src = src; 
     229} 
     230 
     231PJ_DEF(pj_status_t) pjmedia_event_subscribe( pjmedia_event_mgr *mgr, 
     232                                             pj_pool_t *pool, 
     233                                             pjmedia_event_cb *cb, 
     234                                             void *user_data, 
     235                                             void *epub) 
     236{ 
     237    esub *sub; 
     238 
     239    PJ_ASSERT_RETURN(pool && cb, PJ_EINVAL); 
     240 
     241    if (!mgr) mgr = pjmedia_event_mgr_instance(); 
     242    PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 
     243 
     244    pj_mutex_lock(mgr->mutex); 
     245    /* Check whether callback function with the same user data is already 
     246     * subscribed to the publisher. This is to prevent the callback function 
     247     * receiving the same event from the same publisher more than once. 
     248     */ 
     249    sub = mgr->esub_list.next; 
     250    while (sub != &mgr->esub_list) { 
     251        esub *next = sub->next; 
     252        if (sub->cb == cb && sub->user_data == user_data && 
     253            sub->epub == epub) 
     254        { 
     255            pj_mutex_unlock(mgr->mutex); 
     256            return PJ_SUCCESS; 
     257        } 
     258        sub = next; 
     259    } 
     260 
     261    sub = PJ_POOL_ZALLOC_T(pool, esub); 
     262    sub->cb = cb; 
     263    sub->user_data = user_data; 
     264    sub->epub = epub; 
     265    pj_list_push_back(&mgr->esub_list, sub); 
     266    pj_mutex_unlock(mgr->mutex); 
     267 
     268    return PJ_SUCCESS; 
     269} 
     270 
     271PJ_DEF(pj_status_t) 
     272pjmedia_event_unsubscribe(pjmedia_event_mgr *mgr, 
     273                          pjmedia_event_cb *cb, 
     274                          void *user_data, 
     275                          void *epub) 
     276{ 
     277    esub *sub; 
     278 
     279    PJ_ASSERT_RETURN(cb, PJ_EINVAL); 
     280 
     281    if (!mgr) mgr = pjmedia_event_mgr_instance(); 
     282    PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 
     283 
     284    pj_mutex_lock(mgr->mutex); 
     285    sub = mgr->esub_list.next; 
     286    while (sub != &mgr->esub_list) { 
     287        esub *next = sub->next; 
     288        if (sub->cb == cb && (sub->user_data == user_data || !user_data) && 
     289            (sub->epub == epub || !epub)) 
     290        { 
     291            /* If the worker thread or pjmedia_event_publish() API is 
     292             * in the process of distributing events, make sure that 
     293             * its pointer to the next subscriber stays valid. 
     294             */ 
     295            if (mgr->th_next_sub == sub) 
     296                mgr->th_next_sub = sub->next; 
     297            if (mgr->pub_next_sub == sub) 
     298                mgr->pub_next_sub = sub->next; 
     299            pj_list_erase(sub); 
     300            if (user_data && epub) 
     301                break; 
     302        } 
     303        sub = next; 
     304    } 
     305    pj_mutex_unlock(mgr->mutex); 
     306 
     307    return PJ_SUCCESS; 
     308} 
     309 
     310PJ_DEF(pj_status_t) pjmedia_event_publish( pjmedia_event_mgr *mgr, 
     311                                           void *epub, 
     312                                           pjmedia_event *event, 
     313                                           pjmedia_event_publish_flag flag) 
     314{ 
     315    pj_status_t err = PJ_SUCCESS; 
     316 
     317    PJ_ASSERT_RETURN(epub && event, PJ_EINVAL); 
     318 
     319    if (!mgr) mgr = pjmedia_event_mgr_instance(); 
     320    PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 
     321 
    42322    event->epub = epub; 
    43     if (epub) 
    44         event->epub_sig = epub->sig; 
    45 } 
    46  
    47 PJ_DEF(void) pjmedia_event_publisher_init(pjmedia_event_publisher *epub, 
    48                                           pjmedia_obj_sig sig) 
    49 { 
    50     pj_bzero(epub, sizeof(*epub)); 
    51     pj_list_init(&epub->subscription_list); 
    52     epub->sig = sig; 
    53 } 
    54  
    55 PJ_DEF(void) pjmedia_event_subscription_init( pjmedia_event_subscription *esub, 
    56                                               pjmedia_event_cb *cb, 
    57                                               void *user_data) 
    58 { 
    59     pj_bzero(esub, sizeof(*esub)); 
    60     esub->cb = cb; 
    61     esub->user_data = user_data; 
    62 } 
    63  
    64 PJ_DEF(pj_bool_t) 
    65 pjmedia_event_publisher_has_sub(pjmedia_event_publisher *epub) 
    66 { 
    67     PJ_ASSERT_RETURN(epub, PJ_FALSE); 
    68     return epub->subscription_list.next && 
    69             (!pj_list_empty(&epub->subscription_list)); 
    70 } 
    71  
    72 PJ_DEF(pj_status_t) pjmedia_event_subscribe( pjmedia_event_publisher *epub, 
    73                                              pjmedia_event_subscription *esub) 
    74 { 
    75     char epub_name[5]; 
    76  
    77     PJ_ASSERT_RETURN(epub && esub && esub->cb, PJ_EINVAL); 
    78     /* Must not currently subscribe to anything */ 
    79     PJ_ASSERT_RETURN(esub->subscribe_to == NULL, PJ_EINVALIDOP); 
    80  
    81     TRACE_((THIS_FILE, "Subscription [0x%p] to publisher %s", 
    82                        esub, 
    83                        pjmedia_fourcc_name(epub->sig, epub_name))); 
    84     /* Suppress compiler warning if trace is disabled */ 
    85     PJ_UNUSED_ARG(epub_name); 
    86  
    87     pj_list_push_back(&epub->subscription_list, esub); 
    88     esub->subscribe_to = epub; 
    89     return PJ_SUCCESS; 
    90 } 
    91  
    92 PJ_DEF(pj_status_t) pjmedia_event_unsubscribe(pjmedia_event_subscription *esub) 
    93 { 
    94     PJ_ASSERT_RETURN(esub, PJ_EINVAL); 
    95  
    96     if (esub->subscribe_to) { 
    97         char epub_name[5]; 
    98         TRACE_((THIS_FILE, "Unsubscription [0x%p] to publisher %s", 
    99                            esub, 
    100                            pjmedia_fourcc_name(esub->subscribe_to->sig, 
    101                                                epub_name))); 
    102         /* Suppress compiler warning if trace is disabled */ 
    103         PJ_UNUSED_ARG(epub_name); 
    104  
    105         PJ_ASSERT_RETURN( 
    106             pj_list_find_node(&esub->subscribe_to->subscription_list, 
    107                               esub)==esub, PJ_ENOTFOUND); 
    108         pj_list_erase(esub); 
    109         esub->subscribe_to = NULL; 
    110     } 
    111     return PJ_SUCCESS; 
    112 } 
    113  
    114 PJ_DEF(pj_status_t) pjmedia_event_publish( pjmedia_event_publisher *epub, 
    115                                            pjmedia_event *event) 
    116 { 
    117     pjmedia_event_subscription *esub; 
    118     char event_name[5]; 
    119     char epub_name[5]; 
    120     pj_status_t err = PJ_SUCCESS; 
    121  
    122     PJ_ASSERT_RETURN(epub && event, PJ_EINVAL); 
    123  
    124     TRACE_((THIS_FILE, "Event %s is published by publisher %s", 
    125                        pjmedia_fourcc_name(event->type, event_name), 
    126                        pjmedia_fourcc_name(epub->sig, epub_name))); 
    127     /* Suppress compiler warning if trace is disabled */ 
    128     PJ_UNUSED_ARG(event_name); 
    129     PJ_UNUSED_ARG(epub_name); 
    130  
    131     esub = epub->subscription_list.next; 
    132     if (!esub) 
    133         return err; 
    134  
    135     while (esub != &epub->subscription_list) { 
    136         pjmedia_event_subscription *next; 
    137         pj_status_t status; 
    138  
    139         /* just in case esub is destroyed in the callback */ 
    140         next = esub->next; 
    141  
    142         status = (*esub->cb)(esub, event); 
    143         if (status != PJ_SUCCESS && err == PJ_SUCCESS) 
    144             err = status; 
    145  
    146         esub = next; 
    147     } 
     323 
     324    pj_mutex_lock(mgr->mutex); 
     325    if (flag & PJMEDIA_EVENT_PUBLISH_POST_EVENT) { 
     326        if (event_queue_add_event(&mgr->ev_queue, event) == PJ_SUCCESS) 
     327            pj_sem_post(mgr->sem); 
     328    } else { 
     329        /* For nested pjmedia_event_publish() calls, i.e. calling publish() 
     330         * inside the subscriber's callback, the function will only add 
     331         * the event to the event queue of the first publish() call. It 
     332         * is the first publish() call that will be responsible to 
     333         * distribute the events. 
     334         */ 
     335        if (mgr->pub_ev_queue) { 
     336            event_queue_add_event(mgr->pub_ev_queue, event); 
     337        } else { 
     338            static event_queue ev_queue; 
     339            pj_status_t status; 
     340 
     341            ev_queue.head = ev_queue.tail = 0; 
     342            ev_queue.is_full = PJ_FALSE; 
     343            mgr->pub_ev_queue = &ev_queue; 
     344 
     345            event_queue_add_event(mgr->pub_ev_queue, event); 
     346 
     347            do { 
     348                status = event_mgr_distribute_events(mgr, mgr->pub_ev_queue, 
     349                                                     &mgr->pub_next_sub); 
     350                if (status != PJ_SUCCESS && err == PJ_SUCCESS) 
     351                    err = status; 
     352            } while(ev_queue.head != ev_queue.tail || ev_queue.is_full); 
     353 
     354            mgr->pub_ev_queue = NULL; 
     355        } 
     356    } 
     357    pj_mutex_unlock(mgr->mutex); 
    148358 
    149359    return err; 
    150360} 
    151  
    152 static pj_status_t republisher_cb(pjmedia_event_subscription *esub, 
    153                                   pjmedia_event *event) 
    154 { 
    155     return pjmedia_event_publish((pjmedia_event_publisher*)esub->user_data, 
    156                                  event); 
    157 } 
    158  
    159 PJ_DEF(pj_status_t) pjmedia_event_republish(pjmedia_event_publisher *esrc, 
    160                                              pjmedia_event_publisher *epub, 
    161                                              pjmedia_event_subscription *esub) 
    162 { 
    163     PJ_ASSERT_RETURN(esrc && epub && esub, PJ_EINVAL); 
    164  
    165     pjmedia_event_subscription_init(esub, &republisher_cb, epub); 
    166     return pjmedia_event_subscribe(esrc, esub); 
    167 } 
    168  
  • pjproject/trunk/pjmedia/src/pjmedia/port.c

    r3664 r3893  
    118118} 
    119119 
    120 /* 
    121  * Get event publisher 
    122  */ 
    123 PJ_DEF(pjmedia_event_publisher*) 
    124 pjmedia_port_get_event_publisher(pjmedia_port *port) 
    125 { 
    126     PJ_ASSERT_RETURN(port, NULL); 
    127  
    128     if (port->get_event_pub) 
    129         return (*port->get_event_pub)(port); 
    130  
    131     return NULL; 
    132 } 
    133  
    134120/** 
    135121 * Destroy port (and subsequent downstream ports) 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_codec.c

    r3715 r3893  
    7878{ 
    7979    pj_bzero(codec, sizeof(*codec)); 
    80     pjmedia_event_publisher_init(&codec->epub, sig); 
    8180} 
    8281 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_port.c

    r3758 r3893  
    6262    pjmedia_conversion_param conv_param; 
    6363 
    64     pjmedia_event_publisher    epub; 
    65     pjmedia_event_subscription esub_dev; 
    66     pjmedia_event_subscription esub_client_port; 
    67  
    6864    pjmedia_clock           *clock; 
    6965    pjmedia_clock_src        clocksrc; 
     
    9591                                       void *user_data, 
    9692                                       pjmedia_frame *frame); 
    97 static pj_status_t vidstream_event_cb(pjmedia_event_subscription *esub, 
    98                                       pjmedia_event *event); 
    99 static pj_status_t client_port_event_cb(pjmedia_event_subscription *esub, 
    100                                         pjmedia_event *event); 
     93static pj_status_t vidstream_event_cb(pjmedia_event *event, 
     94                                      void *user_data); 
     95static pj_status_t client_port_event_cb(pjmedia_event *event, 
     96                                        void *user_data); 
    10197 
    10298static void enc_clock_cb(const pj_timestamp *ts, void *user_data); 
     
    207203    vp->dir = prm->vidparam.dir; 
    208204//    vp->cap_size = vfd->size; 
    209     pjmedia_event_publisher_init(&vp->epub, SIGNATURE); 
    210205 
    211206    vparam = prm->vidparam; 
     
    273268 
    274269    /* Subscribe to device's events */ 
    275     pjmedia_event_subscription_init(&vp->esub_dev, vidstream_event_cb, vp); 
    276     pjmedia_event_subscribe( 
    277             pjmedia_vid_dev_stream_get_event_publisher(vp->strm), 
    278             &vp->esub_dev); 
     270    pjmedia_event_subscribe(NULL, vp->pool, &vidstream_event_cb, 
     271                            vp, vp->strm); 
    279272 
    280273    if (vp->dir & PJMEDIA_DIR_CAPTURE) { 
     
    371364} 
    372365 
    373 PJ_DEF(pjmedia_event_publisher*) 
    374 pjmedia_vid_port_get_event_publisher(pjmedia_vid_port *vid_port) 
    375 { 
    376     PJ_ASSERT_RETURN(vid_port, NULL); 
    377     return &vid_port->epub; 
    378 } 
    379  
    380366PJ_DEF(pjmedia_vid_dev_stream*) 
    381367pjmedia_vid_port_get_stream(pjmedia_vid_port *vp) 
     
    420406                                              pj_bool_t destroy) 
    421407{ 
    422     pjmedia_event_publisher *epub; 
    423  
    424408    PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL); 
    425409    vp->destroy_client_port = destroy; 
     
    427411 
    428412    /* Subscribe to client port's events */ 
    429     epub = pjmedia_port_get_event_publisher(port); 
    430     if (epub) { 
    431         pjmedia_event_subscription_init(&vp->esub_client_port, 
    432                                         &client_port_event_cb, 
    433                                         vp); 
    434         pjmedia_event_subscribe(epub, &vp->esub_client_port); 
    435     } 
     413    pjmedia_event_subscribe(NULL, vp->pool, &client_port_event_cb, vp, 
     414                            vp->client_port); 
     415 
    436416    return PJ_SUCCESS; 
    437417} 
     
    442422    PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL); 
    443423 
    444     if (vp->client_port) { 
    445         pjmedia_event_unsubscribe(&vp->esub_client_port); 
    446         vp->client_port = NULL; 
    447     } 
     424    pjmedia_event_unsubscribe(NULL, &client_port_event_cb, vp, 
     425                              vp->client_port); 
     426    vp->client_port = NULL; 
     427 
    448428    return PJ_SUCCESS; 
    449429} 
     
    511491    } 
    512492    if (vp->strm) { 
     493        pjmedia_event_unsubscribe(NULL, &vidstream_event_cb, vp, vp->strm); 
    513494        pjmedia_vid_dev_stream_destroy(vp->strm); 
    514495        vp->strm = NULL; 
    515496    } 
    516497    if (vp->client_port) { 
     498        pjmedia_event_unsubscribe(NULL, &client_port_event_cb, vp, 
     499                                  vp->client_port); 
    517500        if (vp->destroy_client_port) 
    518501            pjmedia_port_destroy(vp->client_port); 
     
    561544 
    562545/* Handle event from vidstream */ 
    563 static pj_status_t vidstream_event_cb(pjmedia_event_subscription *esub, 
    564                                       pjmedia_event *event) 
    565 { 
    566     pjmedia_vid_port *vp = (pjmedia_vid_port*)esub->user_data; 
     546static pj_status_t vidstream_event_cb(pjmedia_event *event, 
     547                                      void *user_data) 
     548{ 
     549    pjmedia_vid_port *vp = (pjmedia_vid_port*)user_data; 
    567550     
    568551    /* Just republish the event to our client */ 
    569     return pjmedia_event_publish(&vp->epub, event); 
    570 } 
    571  
    572 static pj_status_t client_port_event_cb(pjmedia_event_subscription *esub, 
    573                                         pjmedia_event *event) 
    574 { 
    575     pjmedia_vid_port *vp = (pjmedia_vid_port*)esub->user_data; 
     552    return pjmedia_event_publish(NULL, vp, event, 0); 
     553} 
     554 
     555static pj_status_t client_port_event_cb(pjmedia_event *event, 
     556                                        void *user_data) 
     557{ 
     558    pjmedia_vid_port *vp = (pjmedia_vid_port*)user_data; 
    576559 
    577560    if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { 
     
    579562        pj_status_t status; 
    580563         
    581         ++event->proc_cnt; 
    582  
    583564        pjmedia_vid_port_stop(vp); 
    584565         
     
    634615    } 
    635616     
    636     /* Republish the event */ 
    637     return pjmedia_event_publish(&vp->epub, event); 
     617    /* Republish the event, post the event to the event manager 
     618     * to avoid deadlock if vidport is trying to stop the clock. 
     619     */ 
     620    return pjmedia_event_publish(NULL, vp, event, 
     621                                 PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
    638622} 
    639623 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r3848 r3893  
    148148    pj_uint32_t              last_dec_ts;    /**< Last decoded timestamp.   */ 
    149149    int                      last_dec_seq;   /**< Last decoded sequence.    */ 
    150  
    151     pjmedia_event_subscription esub_codec;   /**< To subscribe codec events */ 
    152     pjmedia_event_publisher    epub;         /**< To publish events         */ 
    153150}; 
    154151 
     
    340337 * Handle events from stream components. 
    341338 */ 
    342 static pj_status_t stream_event_cb(pjmedia_event_subscription *esub, 
    343                                    pjmedia_event *event) 
    344 { 
    345     pjmedia_vid_stream *stream = (pjmedia_vid_stream*)esub->user_data; 
    346  
    347     if (esub == &stream->esub_codec) { 
     339static pj_status_t stream_event_cb(pjmedia_event *event, 
     340                                   void *user_data) 
     341{ 
     342    pjmedia_vid_stream *stream = (pjmedia_vid_stream*)user_data; 
     343 
     344    if (event->epub == stream->codec) { 
    348345        /* This is codec event */ 
    349346        switch (event->type) { 
    350347        case PJMEDIA_EVENT_FMT_CHANGED: 
    351             /* we process the event */ 
    352             ++event->proc_cnt; 
    353  
    354348            /* Copy the event to avoid deadlock if we publish the event 
    355349             * now. This happens because fmt_event may trigger restart 
     
    363357    } 
    364358 
    365     return pjmedia_event_publish(&stream->epub, event); 
    366 } 
    367  
    368 static pjmedia_event_publisher *port_get_epub(pjmedia_port *port) 
    369 { 
    370     pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata; 
    371     return &stream->epub; 
     359    return pjmedia_event_publish(NULL, stream, event, 0); 
    372360} 
    373361 
     
    10321020 
    10331021                /* Publish PJMEDIA_EVENT_FMT_CHANGED event */ 
    1034                 if (pjmedia_event_publisher_has_sub(&stream->epub)) { 
     1022                { 
    10351023                    pjmedia_event event; 
    10361024 
     
    10381026 
    10391027                    pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, 
    1040                                        &frame->timestamp, &stream->epub); 
     1028                                       &frame->timestamp, &stream); 
    10411029                    event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 
    10421030                    pj_memcpy(&event.data.fmt_changed.new_fmt, 
    10431031                              &stream->info.codec_param->dec_fmt, 
    10441032                              sizeof(pjmedia_format)); 
    1045                     pjmedia_event_publish(&stream->epub, &event); 
     1033                    pjmedia_event_publish(NULL, stream, &event, 0); 
    10461034                } 
    10471035            } 
     
    10871075                      "changed"); 
    10881076 
    1089         pjmedia_event_publish(&stream->epub, &stream->fmt_event); 
     1077        pjmedia_event_publish(NULL, stream, &stream->fmt_event, 0); 
    10901078 
    10911079        stream->fmt_event.type = PJMEDIA_EVENT_NONE; 
     
    12121200    /* Init port. */ 
    12131201    channel->port.port_data.pdata = stream; 
    1214     channel->port.get_event_pub = &port_get_epub; 
    12151202 
    12161203    PJ_LOG(5, (name.ptr, 
     
    13461333        return status; 
    13471334 
    1348     /* Init event publisher and subscribe to codec events */ 
    1349     pjmedia_event_publisher_init(&stream->epub, SIGNATURE); 
    1350     pjmedia_event_subscription_init(&stream->esub_codec, &stream_event_cb, 
    1351                                     stream); 
    1352     pjmedia_event_subscribe(&stream->codec->epub, &stream->esub_codec); 
     1335    /* Subscribe to codec events */ 
     1336    pjmedia_event_subscribe(NULL, pool, &stream_event_cb, stream, 
     1337                            stream->codec); 
    13531338 
    13541339    /* Estimate the maximum frame size */ 
     
    15571542    /* Free codec. */ 
    15581543    if (stream->codec) { 
     1544        pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream, 
     1545                                  stream->codec); 
    15591546        pjmedia_vid_codec_close(stream->codec); 
    15601547        pjmedia_vid_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); 
  • pjproject/trunk/pjmedia/src/test/test.c

    r3841 r3893  
    7373    pjmedia_video_format_mgr_create(pool, 64, 0, NULL); 
    7474    pjmedia_converter_mgr_create(pool, NULL); 
     75    pjmedia_event_mgr_create(pool, 0, NULL); 
    7576    pjmedia_vid_codec_mgr_create(pool, NULL); 
    7677#endif 
     
    116117    pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance()); 
    117118    pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance()); 
     119    pjmedia_event_mgr_destroy(pjmedia_event_mgr_instance()); 
    118120    pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance()); 
    119121#endif 
  • pjproject/trunk/pjmedia/src/test/vid_codec_test.c

    r3776 r3893  
    4848} codec_port_data_t; 
    4949 
    50 static pj_status_t codec_on_event(pjmedia_event_subscription *esub, 
    51                                   pjmedia_event *event) 
    52 { 
    53     codec_port_data_t *port_data = (codec_port_data_t*)esub->user_data; 
     50static pj_status_t codec_on_event(pjmedia_event *event, 
     51                                  void *user_data) 
     52{ 
     53    codec_port_data_t *port_data = (codec_port_data_t*)user_data; 
    5454 
    5555    if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { 
     
    5757        pjmedia_vid_codec_param codec_param; 
    5858        pj_status_t status; 
    59  
    60         ++event->proc_cnt; 
    6159 
    6260        status = pjmedia_vid_codec_get_param(codec, &codec_param); 
     
    201199    pjmedia_vid_port_param vport_param; 
    202200    pjmedia_video_format_detail *vfd; 
    203     pjmedia_event_subscription esub; 
    204201    char codec_name[5]; 
    205202    pj_status_t status; 
     
    324321 
    325322        /* Subscribe to codec events */ 
    326         pjmedia_event_subscription_init(&esub, &codec_on_event, 
    327                                         &codec_port_data); 
    328         pjmedia_event_subscribe(&codec->epub, &esub); 
     323        pjmedia_event_subscribe(NULL, pool, &codec_on_event, &codec_port_data, 
     324                                codec); 
    329325    } 
    330326 
     
    431427    } 
    432428    if (codec) { 
     429        pjmedia_event_unsubscribe(NULL, &codec_on_event, &codec_port_data, 
     430                                  codec); 
    433431        pjmedia_vid_codec_close(codec); 
    434432        pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); 
  • pjproject/trunk/pjmedia/src/test/vid_dev_test.c

    r3715 r3893  
    7777} 
    7878 
    79 static pj_status_t vid_event_cb(pjmedia_event_subscription *esub, 
    80                                 pjmedia_event *event) 
    81 { 
    82     PJ_UNUSED_ARG(esub); 
     79static pj_status_t vid_event_cb(pjmedia_event *event, 
     80                                void *user_data) 
     81{ 
     82    PJ_UNUSED_ARG(user_data); 
    8383 
    8484    if (event->type == PJMEDIA_EVENT_WND_CLOSED) 
     
    9696    pjmedia_vid_port_param param; 
    9797    pjmedia_video_format_detail *vfd; 
    98     pjmedia_event_subscription esub; 
    9998    pj_status_t status; 
    10099    int rc = 0, i; 
     
    162161 
    163162    /* Set event handler */ 
    164     pjmedia_event_subscription_init(&esub, &vid_event_cb, NULL); 
    165     pjmedia_event_subscribe( 
    166             pjmedia_vid_port_get_event_publisher(renderer), 
    167             &esub); 
     163    pjmedia_event_subscribe(NULL, pool, &vid_event_cb, NULL, renderer); 
    168164 
    169165    /* Connect capture to renderer */ 
     
    197193    if (capture) 
    198194        pjmedia_vid_port_destroy(capture); 
    199     if (renderer) 
     195    if (renderer) { 
     196        pjmedia_event_unsubscribe(NULL, &vid_event_cb, NULL, renderer); 
    200197        pjmedia_vid_port_destroy(renderer); 
     198    } 
    201199 
    202200    pj_pool_release(pool); 
  • pjproject/trunk/pjmedia/src/test/vid_port_test.c

    r3715 r3893  
    3333static pj_bool_t is_quitting = PJ_FALSE; 
    3434 
    35 static pj_status_t vid_event_cb(pjmedia_event_subscription *esub, 
    36                                 pjmedia_event *event) 
    37 { 
    38     PJ_UNUSED_ARG(esub); 
     35static pj_status_t vid_event_cb(pjmedia_event *event, 
     36                                void *user_data) 
     37{ 
     38    PJ_UNUSED_ARG(user_data); 
    3939 
    4040    if (event->type == PJMEDIA_EVENT_WND_CLOSED) 
     
    5353    pjmedia_vid_port_param param; 
    5454    pjmedia_video_format_detail *vfd; 
    55     pjmedia_event_subscription esub; 
    5655    pj_status_t status; 
    5756    int rc = 0, i; 
     
    119118 
    120119    /* Set event handler */ 
    121     pjmedia_event_subscription_init(&esub, &vid_event_cb, NULL); 
    122     pjmedia_event_subscribe( 
    123             pjmedia_vid_port_get_event_publisher(renderer), 
    124             &esub); 
     120    pjmedia_event_subscribe(NULL, pool, &vid_event_cb, NULL, renderer); 
    125121 
    126122    /* Connect capture to renderer */ 
     
    154150    if (capture) 
    155151        pjmedia_vid_port_destroy(capture); 
    156     if (renderer) 
     152    if (renderer) { 
     153        pjmedia_event_unsubscribe(NULL, &vid_event_cb, NULL, renderer); 
    157154        pjmedia_vid_port_destroy(renderer); 
     155    } 
    158156 
    159157    pj_pool_release(pool); 
  • pjproject/trunk/pjsip-apps/src/samples/aviplay.c

    r3776 r3893  
    106106} codec_port_data_t; 
    107107 
    108 static pj_status_t avi_event_cb(pjmedia_event_subscription *esub, 
    109                                 pjmedia_event *event) 
    110 { 
    111     avi_port_t *ap = (avi_port_t *)esub->user_data; 
     108static pj_status_t avi_event_cb(pjmedia_event *event, 
     109                                void *user_data) 
     110{ 
     111    avi_port_t *ap = (avi_port_t *)user_data; 
    112112     
    113113    switch (event->type) { 
     
    192192    pjmedia_port *vid_port = NULL, *aud_port = NULL; 
    193193    pjmedia_vid_codec *codec=NULL; 
    194     pjmedia_event_subscription esub; 
    195194    avi_port_t avi_port; 
    196195     
     
    403402 
    404403        /* subscribe events */ 
    405         pjmedia_event_subscription_init(&esub, &avi_event_cb, &avi_port); 
    406         pjmedia_event_subscribe( 
    407                 pjmedia_vid_port_get_event_publisher(renderer), 
    408                 &esub); 
     404        pjmedia_event_subscribe(NULL, pool, &avi_event_cb, &avi_port, 
     405                                renderer); 
    409406 
    410407        if (snd_port) { 
     
    437434        pjmedia_snd_port_destroy(snd_port); 
    438435    } 
    439     if (renderer) 
     436    if (renderer) { 
     437        pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port, 
     438                                  renderer); 
    440439        pjmedia_vid_port_destroy(renderer); 
     440    } 
    441441    if (aud_port) 
    442442        pjmedia_port_destroy(aud_port); 
     
    483483    pjmedia_video_format_mgr_create(pool, 64, 0, NULL); 
    484484    pjmedia_converter_mgr_create(pool, NULL); 
     485    pjmedia_event_mgr_create(pool, 0, NULL); 
    485486    pjmedia_vid_codec_mgr_create(pool, NULL); 
    486487     
     
    520521    pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance()); 
    521522    pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance()); 
     523    pjmedia_event_mgr_destroy(pjmedia_event_mgr_instance()); 
    522524    pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance());     
    523525     
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r3891 r3893  
    8686    pjmedia_srtp_use     rem_srtp_use; /**< Remote's SRTP usage policy.     */ 
    8787 
    88     pjmedia_event_subscription esub_rend;/**< Subscribe renderer events.    */ 
    89     pjmedia_event_subscription esub_cap;/**< Subscribe capture events.      */ 
    90  
    9188    pjsua_med_tp_state_cb      med_init_cb;/**< Media transport 
    9289                                                initialization callback.    */ 
     
    566563void set_media_tp_state(pjsua_call_media *call_med, pjsua_med_tp_st tp_st); 
    567564 
     565/* Callback to receive media events */ 
     566pj_status_t call_media_on_event(pjmedia_event *event, 
     567                                void *user_data); 
    568568 
    569569/** 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r3892 r3893  
    12541254 
    12551255/* Callback to receive media events */ 
    1256 static pj_status_t call_media_on_event(pjmedia_event_subscription *esub, 
    1257                                        pjmedia_event *event) 
    1258 { 
    1259     pjsua_call_media *call_med = (pjsua_call_media*)esub->user_data; 
     1256pj_status_t call_media_on_event(pjmedia_event *event, 
     1257                                void *user_data) 
     1258{ 
     1259    pjsua_call_media *call_med = (pjsua_call_media*)user_data; 
    12601260    pjsua_call *call = call_med->call; 
    12611261 
    12621262    if (pjsua_var.ua_cfg.cb.on_call_media_event && call) { 
    1263         ++event->proc_cnt; 
    12641263        (*pjsua_var.ua_cfg.cb.on_call_media_event)(call->index, 
    12651264                                                   call_med->idx, event); 
     
    14251424                call_med->strm.v.cap_dev = info.id; 
    14261425            } 
    1427  
    1428             /* Init event subscribtion */ 
    1429             pjmedia_event_subscription_init(&call_med->esub_rend, &call_media_on_event, 
    1430                                             call_med); 
    1431             pjmedia_event_subscription_init(&call_med->esub_cap, &call_media_on_event, 
    1432                                             call_med); 
    14331426        } 
    14341427#endif 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c

    r3891 r3893  
    5858    } 
    5959 
     60    status = pjmedia_event_mgr_create(pjsua_var.pool, 0, NULL); 
     61    if (status != PJ_SUCCESS) { 
     62        PJ_PERROR(1,(THIS_FILE, status, 
     63                     "Error creating PJMEDIA event manager")); 
     64        goto on_error; 
     65    } 
     66 
    6067    status = pjmedia_vid_codec_mgr_create(pjsua_var.pool, NULL); 
    6168    if (status != PJ_SUCCESS) { 
     
    130137    if (pjmedia_converter_mgr_instance()) 
    131138        pjmedia_converter_mgr_destroy(NULL); 
     139 
     140    if (pjmedia_event_mgr_instance()) 
     141        pjmedia_event_mgr_destroy(NULL); 
    132142 
    133143    if (pjmedia_video_format_mgr_instance()) 
     
    614624 
    615625    if (w->vp_cap) { 
     626        pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 
     627                                  w->vp_cap); 
    616628        pjmedia_vid_port_stop(w->vp_cap); 
    617629        pjmedia_vid_port_disconnect(w->vp_cap); 
     
    619631    } 
    620632    if (w->vp_rend) { 
     633        pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 
     634                                  w->vp_rend); 
    621635        pjmedia_vid_port_stop(w->vp_rend); 
    622636        pjmedia_vid_port_destroy(w->vp_rend); 
     
    816830#if ENABLE_EVENT 
    817831            /* Register to video events */ 
    818             pjmedia_event_subscribe( 
    819                     pjmedia_vid_port_get_event_publisher(w->vp_rend), 
    820                     &call_med->esub_rend); 
     832            pjmedia_event_subscribe(NULL, w->pool, &call_media_on_event, 
     833                                    call_med, w->vp_rend); 
    821834#endif 
    822835             
     
    887900            w = &pjsua_var.win[wid]; 
    888901#if ENABLE_EVENT 
    889             pjmedia_event_subscribe( 
    890                     pjmedia_vid_port_get_event_publisher(w->vp_cap), 
    891                     &call_med->esub_cap); 
     902            pjmedia_event_subscribe(NULL, w->pool, &call_media_on_event, 
     903                                    call_med, w->vp_cap); 
    892904#endif 
    893905             
     
    10071019 
    10081020        /* Unsubscribe event */ 
    1009         pjmedia_event_unsubscribe(&call_med->esub_cap); 
     1021        pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 
     1022                                  w->vp_cap); 
    10101023 
    10111024        /* Re-start capture again, if it is used by other stream */ 
     
    10221035        /* Stop the render before unsubscribing event */ 
    10231036        pjmedia_vid_port_stop(w->vp_rend); 
    1024         pjmedia_event_unsubscribe(&call_med->esub_rend); 
     1037        pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 
     1038                                  w->vp_rend); 
    10251039 
    10261040        dec_vid_win(call_med->strm.v.rdr_win_id); 
     
    18361850        return status; 
    18371851 
    1838     pjmedia_event_unsubscribe(&call_med->esub_cap); 
     1852    pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 
     1853                              w->vp_cap); 
    18391854     
    18401855    /* temporarily disconnect while we operate on the tee. */ 
     
    18941909 
    18951910#if ENABLE_EVENT 
    1896     pjmedia_event_subscribe( 
    1897             pjmedia_vid_port_get_event_publisher(new_w->vp_cap), 
    1898             &call_med->esub_cap); 
     1911    pjmedia_event_subscribe(NULL, new_w->pool, &call_media_on_event, 
     1912                            call_med, new_w->vp_cap); 
    18991913#endif 
    19001914 
     
    19201934    if (new_w) { 
    19211935        /* Unsubscribe, just in case */ 
    1922         pjmedia_event_unsubscribe(&call_med->esub_cap); 
     1936        pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 
     1937                                  new_w->vp_cap); 
    19231938        /* Disconnect media port from the new capturer */ 
    19241939        pjmedia_vid_tee_remove_dst_port(new_w->tee, media_port); 
     
    19361951#if ENABLE_EVENT 
    19371952    /* Resubscribe */ 
    1938     pjmedia_event_subscribe( 
    1939             pjmedia_vid_port_get_event_publisher(w->vp_cap), 
    1940             &call_med->esub_cap); 
     1953    pjmedia_event_subscribe(NULL, w->pool, &call_media_on_event, 
     1954                            call_med, w->vp_cap); 
    19411955#endif 
    19421956 
Note: See TracChangeset for help on using the changeset viewer.