Changeset 3893
- Timestamp:
- Dec 1, 2011 10:49:07 AM (13 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev.h
r3864 r3893 752 752 753 753 /** 754 * Get the event publisher object for the video stream. Caller typically use755 * the returned object to subscribe or unsubscribe events from the video756 * 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 /**767 754 * Request one frame from the stream. Application needs to call this function 768 755 * periodically only if the stream doesn't support "active interface", i.e. -
pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev_imp.h
r3758 r3893 189 189 /** Operations */ 190 190 pjmedia_vid_dev_stream_op *op; 191 192 /** Event producer */193 pjmedia_event_publisher epub;194 191 }; 195 192 -
pjproject/trunk/pjmedia/include/pjmedia/event.h
r3774 r3893 26 26 #include <pjmedia/format.h> 27 27 #include <pjmedia/signatures.h> 28 #include <pj/list.h>29 28 30 29 PJ_BEGIN_DECL … … 89 88 90 89 /** 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 /**101 90 * Additional data/parameters for media format changed event 102 91 * (PJMEDIA_EVENT_FMT_CHANGED). … … 163 152 /** 164 153 * This structure describes a media event. It consists mainly of the event 165 * type and additional data/parameters for the event. Event publishers need166 * touse #pjmedia_event_init() to initialize this event structure with154 * type and additional data/parameters for the event. Applications can 155 * use #pjmedia_event_init() to initialize this event structure with 167 156 * basic information about the event. 168 157 */ … … 180 169 181 170 /** 182 * This keeps count on the number of subscribers that have183 * processed this event.184 */185 unsigned proc_cnt;186 187 /**188 * The object signature of the event publisher. Application may use189 * this to check which publisher published the event.190 */191 pjmedia_obj_sig epub_sig;192 193 /**194 171 * 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; 203 187 204 188 /** … … 239 223 240 224 /** 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. 247 229 * 248 230 * @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 */ 233 typedef 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 */ 240 typedef 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 */ 253 typedef 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 */ 267 typedef 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 */ 280 PJ_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 */ 289 PJ_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 */ 301 PJ_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 */ 310 PJ_DECL(void) pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr); 287 311 288 312 /** … … 293 317 * @param ts Event timestamp. May be set to NULL to set the event 294 318 * timestamp to zero. 295 * @param epub Event publisher.319 * @param src Event source. 296 320 */ 297 321 PJ_DECL(void) pjmedia_event_init(pjmedia_event *event, 298 322 pjmedia_event_type type, 299 323 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 332 329 * the specific publisher specified in the argument, but also from other 333 330 * publishers contained by the publisher, if the publisher is republishing 334 331 * events from other publishers. 335 332 * 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. 336 338 * @param epub The event publisher. 337 * @param esub The event subscription object.338 339 * 339 340 * @return PJ_SUCCESS on success or the appropriate error code. 340 341 */ 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(). 342 PJ_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. 351 359 * 352 360 * @return PJ_SUCCESS on success or the appropriate error code. 353 361 */ 354 362 PJ_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); 363 pjmedia_event_unsubscribe(pjmedia_event_mgr *mgr, 364 pjmedia_event_cb *cb, 365 void *user_data, 366 void *epub); 366 367 367 368 /** 368 369 * 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. 371 377 * @param epub The event publisher. 372 378 * @param event The event to be published. 379 * @param flag Publication flag. 373 380 * 374 381 * @return PJ_SUCCESS only if all subscription callbacks returned 375 382 * PJ_SUCCESS. 376 383 */ 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); 384 PJ_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 399 389 400 390 /** -
pjproject/trunk/pjmedia/include/pjmedia/port.h
r3664 r3893 400 400 pj_status_t (*on_destroy)(struct pjmedia_port *this_port); 401 401 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 407 402 } pjmedia_port; 408 403 … … 485 480 486 481 /** 487 * Get the event publisher for the media port, if any.482 * Destroy port (and subsequent downstream ports) 488 483 * 489 484 * @param port The media port. 490 485 * 491 * @return The event publisher, or NULL if the port does not publish492 * 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 *502 486 * @return PJ_SUCCESS on success, or the appropriate error code. 503 487 */ -
pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h
r3795 r3893 250 250 /** Operations to codec. */ 251 251 pjmedia_vid_codec_op *op; 252 253 /** Event publisher object */254 pjmedia_event_publisher epub;255 252 }; 256 253 -
pjproject/trunk/pjmedia/include/pjmedia/vid_port.h
r3758 r3893 106 106 107 107 /** 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 /**118 108 * Return the underlying video stream of the video port. 119 109 * -
pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c
r3861 r3893 1610 1610 1611 1611 /* Broadcast event */ 1612 if (pjmedia_event_publisher_has_sub(&codec->epub)){1612 { 1613 1613 pjmedia_event event; 1614 1614 1615 1615 pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, 1616 &input->timestamp, &codec->epub);1616 &input->timestamp, codec); 1617 1617 event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 1618 1618 pj_memcpy(&event.data.fmt_changed.new_fmt, &ff->param.dec_fmt, 1619 1619 sizeof(ff->param.dec_fmt)); 1620 pjmedia_event_publish( &codec->epub, &event);1620 pjmedia_event_publish(NULL, codec, &event, 0); 1621 1621 } 1622 1622 } … … 1652 1652 1653 1653 /* Check if we got key frame */ 1654 if (avframe.key_frame && pjmedia_event_publisher_has_sub(&codec->epub))1654 if (avframe.key_frame) 1655 1655 { 1656 1656 pjmedia_event event; 1657 1657 1658 1658 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); 1661 1661 } 1662 1662 } else { -
pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c
r3715 r3893 417 417 pj_memcpy(&strm->vafp, &vafp, sizeof(vafp)); 418 418 strm->ts_inc = PJMEDIA_SPF2(param->clock_rate, &vfd->fps, 1); 419 pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_COLORBAR);420 419 421 420 for (i = 0; i < vfi->plane_cnt; ++i) { -
pjproject/trunk/pjmedia/src/pjmedia-videodev/dshow_dev.c
r3803 r3893 870 870 pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 871 871 strm->user_data = user_data; 872 pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_DSHOW);873 872 874 873 if (param->dir & PJMEDIA_DIR_CAPTURE) { -
pjproject/trunk/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c
r3715 r3893 384 384 strm->pool = pool; 385 385 pj_memcpy(&strm->param, param, sizeof(*param)); 386 pjmedia_event_publisher_init(&strm->base.epub);387 386 388 387 /* Done */ -
pjproject/trunk/pjmedia/src/pjmedia-videodev/sdl_dev.c
r3864 r3893 309 309 if (strm) 310 310 pjmedia_event_init(pevent, PJMEDIA_EVENT_NONE, &strm->last_ts, 311 &strm->base.epub);311 strm); 312 312 313 313 return strm; … … 355 355 pj_status_t status; 356 356 357 pjmedia_event_publish( &strm->base.epub, &pevent);357 pjmedia_event_publish(NULL, strm, &pevent, 0); 358 358 359 359 switch (pevent.type) { … … 376 376 sdl_destroy_all(strm); 377 377 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); 381 380 382 381 /* … … 917 916 pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 918 917 strm->user_data = user_data; 919 pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_SDL);920 918 921 919 /* Create render stream here */ -
pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c
r3864 r3893 786 786 } 787 787 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 794 788 /* API: Start the stream. */ 795 789 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm) -
pjproject/trunk/pjmedia/src/pjmedia/event.c
r3782 r3893 20 20 #include <pjmedia/errno.h> 21 21 #include <pj/assert.h> 22 #include <pj/list.h> 22 23 #include <pj/log.h> 24 #include <pj/os.h> 25 #include <pj/pool.h> 23 26 #include <pj/string.h> 24 27 25 28 #define THIS_FILE "event.c" 26 29 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 32 typedef struct esub esub; 33 34 struct esub 35 { 36 PJ_DECL_LIST_MEMBER(esub); 37 38 pjmedia_event_cb *cb; 39 void *user_data; 40 void *epub; 41 }; 42 43 typedef 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 50 struct 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 63 static pjmedia_event_mgr *event_manager_instance; 64 65 static 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 88 static 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. */ 118 static 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 137 PJ_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 175 PJ_DEF(pjmedia_event_mgr*) pjmedia_event_mgr_instance(void) 176 { 177 return event_manager_instance; 178 } 179 180 PJ_DEF(void) pjmedia_event_mgr_set_instance(pjmedia_event_mgr *mgr) 181 { 182 event_manager_instance = mgr; 183 } 184 185 PJ_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 } 32 218 33 219 PJ_DEF(void) pjmedia_event_init( pjmedia_event *event, 34 220 pjmedia_event_type type, 35 221 const pj_timestamp *ts, 36 const pjmedia_event_publisher *epub)222 const void *src) 37 223 { 38 224 pj_bzero(event, sizeof(*event)); … … 40 226 if (ts) 41 227 event->timestamp.u64 = ts->u64; 228 event->epub = event->src = src; 229 } 230 231 PJ_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 271 PJ_DEF(pj_status_t) 272 pjmedia_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 310 PJ_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 42 322 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); 148 358 149 359 return err; 150 360 } 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 118 118 } 119 119 120 /*121 * Get event publisher122 */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 134 120 /** 135 121 * Destroy port (and subsequent downstream ports) -
pjproject/trunk/pjmedia/src/pjmedia/vid_codec.c
r3715 r3893 78 78 { 79 79 pj_bzero(codec, sizeof(*codec)); 80 pjmedia_event_publisher_init(&codec->epub, sig);81 80 } 82 81 -
pjproject/trunk/pjmedia/src/pjmedia/vid_port.c
r3758 r3893 62 62 pjmedia_conversion_param conv_param; 63 63 64 pjmedia_event_publisher epub;65 pjmedia_event_subscription esub_dev;66 pjmedia_event_subscription esub_client_port;67 68 64 pjmedia_clock *clock; 69 65 pjmedia_clock_src clocksrc; … … 95 91 void *user_data, 96 92 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);93 static pj_status_t vidstream_event_cb(pjmedia_event *event, 94 void *user_data); 95 static pj_status_t client_port_event_cb(pjmedia_event *event, 96 void *user_data); 101 97 102 98 static void enc_clock_cb(const pj_timestamp *ts, void *user_data); … … 207 203 vp->dir = prm->vidparam.dir; 208 204 // vp->cap_size = vfd->size; 209 pjmedia_event_publisher_init(&vp->epub, SIGNATURE);210 205 211 206 vparam = prm->vidparam; … … 273 268 274 269 /* 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); 279 272 280 273 if (vp->dir & PJMEDIA_DIR_CAPTURE) { … … 371 364 } 372 365 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 380 366 PJ_DEF(pjmedia_vid_dev_stream*) 381 367 pjmedia_vid_port_get_stream(pjmedia_vid_port *vp) … … 420 406 pj_bool_t destroy) 421 407 { 422 pjmedia_event_publisher *epub;423 424 408 PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL); 425 409 vp->destroy_client_port = destroy; … … 427 411 428 412 /* 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 436 416 return PJ_SUCCESS; 437 417 } … … 442 422 PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL); 443 423 444 if (vp->client_port) {445 pjmedia_event_unsubscribe(&vp->esub_client_port);446 447 } 424 pjmedia_event_unsubscribe(NULL, &client_port_event_cb, vp, 425 vp->client_port); 426 vp->client_port = NULL; 427 448 428 return PJ_SUCCESS; 449 429 } … … 511 491 } 512 492 if (vp->strm) { 493 pjmedia_event_unsubscribe(NULL, &vidstream_event_cb, vp, vp->strm); 513 494 pjmedia_vid_dev_stream_destroy(vp->strm); 514 495 vp->strm = NULL; 515 496 } 516 497 if (vp->client_port) { 498 pjmedia_event_unsubscribe(NULL, &client_port_event_cb, vp, 499 vp->client_port); 517 500 if (vp->destroy_client_port) 518 501 pjmedia_port_destroy(vp->client_port); … … 561 544 562 545 /* 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;546 static pj_status_t vidstream_event_cb(pjmedia_event *event, 547 void *user_data) 548 { 549 pjmedia_vid_port *vp = (pjmedia_vid_port*)user_data; 567 550 568 551 /* 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 555 static 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; 576 559 577 560 if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { … … 579 562 pj_status_t status; 580 563 581 ++event->proc_cnt;582 583 564 pjmedia_vid_port_stop(vp); 584 565 … … 634 615 } 635 616 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); 638 622 } 639 623 -
pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
r3848 r3893 148 148 pj_uint32_t last_dec_ts; /**< Last decoded timestamp. */ 149 149 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 */153 150 }; 154 151 … … 340 337 * Handle events from stream components. 341 338 */ 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 (e sub == &stream->esub_codec) {339 static 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) { 348 345 /* This is codec event */ 349 346 switch (event->type) { 350 347 case PJMEDIA_EVENT_FMT_CHANGED: 351 /* we process the event */352 ++event->proc_cnt;353 354 348 /* Copy the event to avoid deadlock if we publish the event 355 349 * now. This happens because fmt_event may trigger restart … … 363 357 } 364 358 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); 372 360 } 373 361 … … 1032 1020 1033 1021 /* Publish PJMEDIA_EVENT_FMT_CHANGED event */ 1034 if (pjmedia_event_publisher_has_sub(&stream->epub)){1022 { 1035 1023 pjmedia_event event; 1036 1024 … … 1038 1026 1039 1027 pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, 1040 &frame->timestamp, &stream ->epub);1028 &frame->timestamp, &stream); 1041 1029 event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 1042 1030 pj_memcpy(&event.data.fmt_changed.new_fmt, 1043 1031 &stream->info.codec_param->dec_fmt, 1044 1032 sizeof(pjmedia_format)); 1045 pjmedia_event_publish( &stream->epub, &event);1033 pjmedia_event_publish(NULL, stream, &event, 0); 1046 1034 } 1047 1035 } … … 1087 1075 "changed"); 1088 1076 1089 pjmedia_event_publish( &stream->epub, &stream->fmt_event);1077 pjmedia_event_publish(NULL, stream, &stream->fmt_event, 0); 1090 1078 1091 1079 stream->fmt_event.type = PJMEDIA_EVENT_NONE; … … 1212 1200 /* Init port. */ 1213 1201 channel->port.port_data.pdata = stream; 1214 channel->port.get_event_pub = &port_get_epub;1215 1202 1216 1203 PJ_LOG(5, (name.ptr, … … 1346 1333 return status; 1347 1334 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); 1353 1338 1354 1339 /* Estimate the maximum frame size */ … … 1557 1542 /* Free codec. */ 1558 1543 if (stream->codec) { 1544 pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream, 1545 stream->codec); 1559 1546 pjmedia_vid_codec_close(stream->codec); 1560 1547 pjmedia_vid_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); -
pjproject/trunk/pjmedia/src/test/test.c
r3841 r3893 73 73 pjmedia_video_format_mgr_create(pool, 64, 0, NULL); 74 74 pjmedia_converter_mgr_create(pool, NULL); 75 pjmedia_event_mgr_create(pool, 0, NULL); 75 76 pjmedia_vid_codec_mgr_create(pool, NULL); 76 77 #endif … … 116 117 pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance()); 117 118 pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance()); 119 pjmedia_event_mgr_destroy(pjmedia_event_mgr_instance()); 118 120 pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance()); 119 121 #endif -
pjproject/trunk/pjmedia/src/test/vid_codec_test.c
r3776 r3893 48 48 } codec_port_data_t; 49 49 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;50 static 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; 54 54 55 55 if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { … … 57 57 pjmedia_vid_codec_param codec_param; 58 58 pj_status_t status; 59 60 ++event->proc_cnt;61 59 62 60 status = pjmedia_vid_codec_get_param(codec, &codec_param); … … 201 199 pjmedia_vid_port_param vport_param; 202 200 pjmedia_video_format_detail *vfd; 203 pjmedia_event_subscription esub;204 201 char codec_name[5]; 205 202 pj_status_t status; … … 324 321 325 322 /* 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); 329 325 } 330 326 … … 431 427 } 432 428 if (codec) { 429 pjmedia_event_unsubscribe(NULL, &codec_on_event, &codec_port_data, 430 codec); 433 431 pjmedia_vid_codec_close(codec); 434 432 pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); -
pjproject/trunk/pjmedia/src/test/vid_dev_test.c
r3715 r3893 77 77 } 78 78 79 static pj_status_t vid_event_cb(pjmedia_event _subscription *esub,80 pjmedia_event *event)81 { 82 PJ_UNUSED_ARG( esub);79 static pj_status_t vid_event_cb(pjmedia_event *event, 80 void *user_data) 81 { 82 PJ_UNUSED_ARG(user_data); 83 83 84 84 if (event->type == PJMEDIA_EVENT_WND_CLOSED) … … 96 96 pjmedia_vid_port_param param; 97 97 pjmedia_video_format_detail *vfd; 98 pjmedia_event_subscription esub;99 98 pj_status_t status; 100 99 int rc = 0, i; … … 162 161 163 162 /* 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); 168 164 169 165 /* Connect capture to renderer */ … … 197 193 if (capture) 198 194 pjmedia_vid_port_destroy(capture); 199 if (renderer) 195 if (renderer) { 196 pjmedia_event_unsubscribe(NULL, &vid_event_cb, NULL, renderer); 200 197 pjmedia_vid_port_destroy(renderer); 198 } 201 199 202 200 pj_pool_release(pool); -
pjproject/trunk/pjmedia/src/test/vid_port_test.c
r3715 r3893 33 33 static pj_bool_t is_quitting = PJ_FALSE; 34 34 35 static pj_status_t vid_event_cb(pjmedia_event _subscription *esub,36 pjmedia_event *event)37 { 38 PJ_UNUSED_ARG( esub);35 static pj_status_t vid_event_cb(pjmedia_event *event, 36 void *user_data) 37 { 38 PJ_UNUSED_ARG(user_data); 39 39 40 40 if (event->type == PJMEDIA_EVENT_WND_CLOSED) … … 53 53 pjmedia_vid_port_param param; 54 54 pjmedia_video_format_detail *vfd; 55 pjmedia_event_subscription esub;56 55 pj_status_t status; 57 56 int rc = 0, i; … … 119 118 120 119 /* 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); 125 121 126 122 /* Connect capture to renderer */ … … 154 150 if (capture) 155 151 pjmedia_vid_port_destroy(capture); 156 if (renderer) 152 if (renderer) { 153 pjmedia_event_unsubscribe(NULL, &vid_event_cb, NULL, renderer); 157 154 pjmedia_vid_port_destroy(renderer); 155 } 158 156 159 157 pj_pool_release(pool); -
pjproject/trunk/pjsip-apps/src/samples/aviplay.c
r3776 r3893 106 106 } codec_port_data_t; 107 107 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;108 static pj_status_t avi_event_cb(pjmedia_event *event, 109 void *user_data) 110 { 111 avi_port_t *ap = (avi_port_t *)user_data; 112 112 113 113 switch (event->type) { … … 192 192 pjmedia_port *vid_port = NULL, *aud_port = NULL; 193 193 pjmedia_vid_codec *codec=NULL; 194 pjmedia_event_subscription esub;195 194 avi_port_t avi_port; 196 195 … … 403 402 404 403 /* 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); 409 406 410 407 if (snd_port) { … … 437 434 pjmedia_snd_port_destroy(snd_port); 438 435 } 439 if (renderer) 436 if (renderer) { 437 pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port, 438 renderer); 440 439 pjmedia_vid_port_destroy(renderer); 440 } 441 441 if (aud_port) 442 442 pjmedia_port_destroy(aud_port); … … 483 483 pjmedia_video_format_mgr_create(pool, 64, 0, NULL); 484 484 pjmedia_converter_mgr_create(pool, NULL); 485 pjmedia_event_mgr_create(pool, 0, NULL); 485 486 pjmedia_vid_codec_mgr_create(pool, NULL); 486 487 … … 520 521 pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance()); 521 522 pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance()); 523 pjmedia_event_mgr_destroy(pjmedia_event_mgr_instance()); 522 524 pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance()); 523 525 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r3891 r3893 86 86 pjmedia_srtp_use rem_srtp_use; /**< Remote's SRTP usage policy. */ 87 87 88 pjmedia_event_subscription esub_rend;/**< Subscribe renderer events. */89 pjmedia_event_subscription esub_cap;/**< Subscribe capture events. */90 91 88 pjsua_med_tp_state_cb med_init_cb;/**< Media transport 92 89 initialization callback. */ … … 566 563 void set_media_tp_state(pjsua_call_media *call_med, pjsua_med_tp_st tp_st); 567 564 565 /* Callback to receive media events */ 566 pj_status_t call_media_on_event(pjmedia_event *event, 567 void *user_data); 568 568 569 569 /** -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r3892 r3893 1254 1254 1255 1255 /* 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;1256 pj_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; 1260 1260 pjsua_call *call = call_med->call; 1261 1261 1262 1262 if (pjsua_var.ua_cfg.cb.on_call_media_event && call) { 1263 ++event->proc_cnt;1264 1263 (*pjsua_var.ua_cfg.cb.on_call_media_event)(call->index, 1265 1264 call_med->idx, event); … … 1425 1424 call_med->strm.v.cap_dev = info.id; 1426 1425 } 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);1433 1426 } 1434 1427 #endif -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
r3891 r3893 58 58 } 59 59 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 60 67 status = pjmedia_vid_codec_mgr_create(pjsua_var.pool, NULL); 61 68 if (status != PJ_SUCCESS) { … … 130 137 if (pjmedia_converter_mgr_instance()) 131 138 pjmedia_converter_mgr_destroy(NULL); 139 140 if (pjmedia_event_mgr_instance()) 141 pjmedia_event_mgr_destroy(NULL); 132 142 133 143 if (pjmedia_video_format_mgr_instance()) … … 614 624 615 625 if (w->vp_cap) { 626 pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 627 w->vp_cap); 616 628 pjmedia_vid_port_stop(w->vp_cap); 617 629 pjmedia_vid_port_disconnect(w->vp_cap); … … 619 631 } 620 632 if (w->vp_rend) { 633 pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 634 w->vp_rend); 621 635 pjmedia_vid_port_stop(w->vp_rend); 622 636 pjmedia_vid_port_destroy(w->vp_rend); … … 816 830 #if ENABLE_EVENT 817 831 /* 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); 821 834 #endif 822 835 … … 887 900 w = &pjsua_var.win[wid]; 888 901 #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); 892 904 #endif 893 905 … … 1007 1019 1008 1020 /* 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); 1010 1023 1011 1024 /* Re-start capture again, if it is used by other stream */ … … 1022 1035 /* Stop the render before unsubscribing event */ 1023 1036 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); 1025 1039 1026 1040 dec_vid_win(call_med->strm.v.rdr_win_id); … … 1836 1850 return status; 1837 1851 1838 pjmedia_event_unsubscribe(&call_med->esub_cap); 1852 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 1853 w->vp_cap); 1839 1854 1840 1855 /* temporarily disconnect while we operate on the tee. */ … … 1894 1909 1895 1910 #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); 1899 1913 #endif 1900 1914 … … 1920 1934 if (new_w) { 1921 1935 /* 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); 1923 1938 /* Disconnect media port from the new capturer */ 1924 1939 pjmedia_vid_tee_remove_dst_port(new_w->tee, media_port); … … 1936 1951 #if ENABLE_EVENT 1937 1952 /* 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); 1941 1955 #endif 1942 1956
Note: See TracChangeset
for help on using the changeset viewer.