Changeset 3402
- Timestamp:
- Dec 30, 2010 4:31:16 PM (14 years ago)
- Location:
- pjproject/branches/projects/2.0-dev
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/avi_stream.h
r3392 r3402 50 50 }; 51 51 52 /** 53 * AVI stream data type. 54 */ 52 55 typedef pjmedia_port pjmedia_avi_stream; 53 56 57 /** 58 * Opaque data type for AVI streams. AVI streams is a collection of 59 * zero or more AVI stream. 60 */ 54 61 typedef struct pjmedia_avi_streams pjmedia_avi_streams; 55 62 … … 72 79 pjmedia_avi_streams **p_streams); 73 80 74 PJ_DECL(pj_uint8_t) 81 /** 82 * Get the number of AVI stream. 83 * 84 * @param streams The AVI streams. 85 * 86 * @return The number of AVI stream. 87 */ 88 PJ_DECL(unsigned) 75 89 pjmedia_avi_streams_get_num_streams(pjmedia_avi_streams *streams); 76 90 91 /** 92 * Return the idx-th stream of the AVI streams. 93 * 94 * @param streams The AVI streams. 95 * @param idx The stream index. 96 * 97 * @return The AVI stream or NULL if it does not exist. 98 */ 77 99 PJ_DECL(pjmedia_avi_stream *) 78 100 pjmedia_avi_streams_get_stream(pjmedia_avi_streams *streams, 79 pj_uint8_tidx);101 unsigned idx); 80 102 103 /** 104 * Return an AVI stream with a certain media type from the AVI streams. 105 * 106 * @param streams The AVI streams. 107 * @param start_idx The starting index. 108 * @param media_type The media type of the stream. 109 * 110 * @return The AVI stream or NULL if it does not exist. 111 */ 81 112 PJ_DECL(pjmedia_avi_stream *) 82 113 pjmedia_avi_streams_get_stream_by_media(pjmedia_avi_streams *streams, 83 pj_uint8_tstart_idx,114 unsigned start_idx, 84 115 pjmedia_type media_type); 85 116 117 /** 118 * Return the media port of an AVI stream. 119 * 120 * @param stream The AVI stream. 121 * 122 * @return The media port. 123 */ 86 124 PJ_INLINE(pjmedia_port *) 87 125 pjmedia_avi_stream_get_port(pjmedia_avi_stream *stream) … … 93 131 * Get the data length, in bytes. 94 132 * 95 * @param portThe AVI stream.133 * @param stream The AVI stream. 96 134 * 97 135 * @return The length of the data, in bytes. Upon error it will … … 107 145 * registered for each AVI stream. 108 146 * 109 * @param portThe AVI stream.147 * @param stream The AVI stream. 110 148 * @param user_data User data to be specified in the callback 111 149 * @param cb Callback to be called. If the callback returns non- -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/clock.h
r3392 r3402 79 79 80 80 PJ_BEGIN_DECL 81 82 /** 83 * Media clock source. 84 */ 85 typedef struct pjmedia_clock_src 86 { 87 pjmedia_type media_type; /**< Media type. */ 88 unsigned clock_rate; /**< Clock rate. */ 89 unsigned ptime_usec; /**< Frame interval (in usec). */ 90 /** 91 * The timestamp field holds an increasing value in samples and its 92 * value is expected to be increased by clock_rate samples per second. 93 */ 94 pj_timestamp timestamp; 95 /** 96 * Timestamp's last update. The last_update field contains a value in 97 * ticks, and it is expected to be increased by pj_get_timestamp_freq() 98 * ticks per second. 99 */ 100 pj_timestamp last_update; 101 } pjmedia_clock_src; 102 103 /** 104 * This is an auxiliary function to initialize the media clock source. 105 * 106 * @param clocksrc The clock source to be initialized. 107 * @param media_type The media type. 108 * @param clock_rate The clock rate. 109 * @param ptime_usec Media frame interval (in usec). 110 * 111 * @return PJ_SUCCESS on success. 112 */ 113 PJ_DECL(pj_status_t) pjmedia_clock_src_init( pjmedia_clock_src *clocksrc, 114 pjmedia_type media_type, 115 unsigned clock_rate, 116 unsigned ptime_usec ); 117 118 /** 119 * This function updates the clock source's timestamp. Application should 120 * use this function instead of updating the timestamp directly since this 121 * function will also update the last_update field of the clock source. 122 * 123 * @param clocksrc The clock source to be updated. 124 * @param timestamp The new timestamp, can be NULL if the current 125 * timestamp does not change (in this case it 126 * will only update the last_update field). 127 * 128 * @return PJ_SUCCESS on success. 129 */ 130 PJ_DECL(pj_status_t) pjmedia_clock_src_update( pjmedia_clock_src *clocksrc, 131 const pj_timestamp *timestamp ); 132 133 /** 134 * This function gets the clock source's current timestamp. Application 135 * should use this function instead of accessing the timestamp directly 136 * since this function will calculate the predicted timestamp for current 137 * time, based on the values of timestamp, last_update, and clock_rate. 138 * 139 * @param clocksrc The clock source. 140 * @param timestamp Argument to receive the current timestamp 141 * 142 * @return PJ_SUCCESS on success. 143 */ 144 PJ_DECL(pj_status_t) 145 pjmedia_clock_src_get_current_timestamp( const pjmedia_clock_src *clocksrc, 146 pj_timestamp *timestamp); 147 148 /** 149 * This function gets the clock source's time in msec. 150 * 151 * @param clocksrc The clock source. 152 * 153 * @return The clock source's time (in msec). 154 */ 155 PJ_DECL(pj_uint32_t) 156 pjmedia_clock_src_get_time_msec( const pjmedia_clock_src *clocksrc ); 81 157 82 158 -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/config.h
r3392 r3402 967 967 #endif 968 968 969 /** 970 * Specify the maximum time difference (in ms) for synchronization between 971 * two medias. If the synchronization media source is ahead of time 972 * greater than this duration, it is considered to make a very large jump 973 * and the synchronization will be reset. 974 * 975 * Default: 20000 976 */ 977 #ifndef PJMEDIA_CLOCK_SYNC_MAX_SYNC_MSEC 978 # define PJMEDIA_CLOCK_SYNC_MAX_SYNC_MSEC 20000 979 #endif 980 981 /** 982 * Specify the maximum duration (in ms) for resynchronization. When a media 983 * is late to another media it is supposed to be synchronized to, it is 984 * guaranteed to be synchronized again after this duration. While if the 985 * media is ahead/early by t ms, it is guaranteed to be synchronized after 986 * t + this duration. This timing only applies if there is no additional 987 * resynchronization required during the specified duration. 988 * 989 * Default: 2000 990 */ 991 #ifndef PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION 992 # define PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION 2000 993 #endif 994 969 995 970 996 /** -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/port.h
r3392 r3402 25 25 * @brief Port interface declaration 26 26 */ 27 #include <pjmedia/clock.h> 27 28 #include <pjmedia/format.h> 28 29 #include <pjmedia/frame.h> … … 373 374 374 375 /** 376 * Get clock source. 377 * This should only be called by #pjmedia_port_get_clock_src(). 378 */ 379 pjmedia_clock_src* (*get_clock_src)(struct pjmedia_port *this_port, 380 pjmedia_dir dir); 381 382 /** 375 383 * Sink interface. 376 384 * This should only be called by #pjmedia_port_put_frame(). … … 399 407 * 400 408 * @param info The port info to be initialized. 401 * @param pool Pool to allocate memory from.402 409 * @param name Port name. 403 410 * @param signature Port signature. … … 437 444 438 445 /** 446 * Get a clock source from the port. 447 * 448 * @param port The media port. 449 * @param dir Media port's direction. 450 * 451 * @return The clock source or NULL if clock source is not present 452 * in the port. 453 */ 454 PJ_DECL(pjmedia_clock_src *) pjmedia_port_get_clock_src( pjmedia_port *port, 455 pjmedia_dir dir ); 456 457 458 /** 439 459 * Get a frame from the port (and subsequent downstream ports). 440 460 * -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/sound_port.h
r2506 r3402 26 26 */ 27 27 #include <pjmedia-audiodev/audiodev.h> 28 #include <pjmedia/clock.h> 28 29 #include <pjmedia/port.h> 29 30 … … 243 244 244 245 /** 246 * Get a clock source from the sound port. 247 * 248 * @param snd_port The sound port. 249 * @param dir Sound port's direction. 250 * 251 * @return The clock source. 252 */ 253 PJ_DECL(pjmedia_clock_src *) 254 pjmedia_snd_port_get_clock_src( pjmedia_snd_port *snd_port, 255 pjmedia_dir dir ); 256 257 258 /** 245 259 * Connect a port to the sound device port. If the sound device port has a 246 260 * sound recorder device, then this will start periodic function call to -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/videoport.h
r3392 r3402 126 126 127 127 /** 128 * Get a clock source from the video port. 129 * 130 * @param vid_port The video port. 131 * @param dir Video port's direction. 132 * 133 * @return The clock source. 134 */ 135 PJ_DECL(pjmedia_clock_src *) 136 pjmedia_vid_port_get_clock_src( pjmedia_vid_port *vid_port, 137 pjmedia_dir dir ); 138 139 /** 140 * Set a clock source for the video port. 141 * 142 * @param vid_port The video port. 143 * @param dir Video port's direction. 144 * @param clocksrc The clock source. 145 * 146 * @return PJ_SUCCESS on success or the appropriate error code. 147 */ 148 PJ_DECL(pj_status_t) 149 pjmedia_vid_port_set_clock_src( pjmedia_vid_port *vid_port, 150 pjmedia_dir dir, 151 pjmedia_clock_src *clocksrc ); 152 153 /** 128 154 * Connect the video port to a downstream (slave) media port. This operation 129 155 * is only valid for video ports created with active interface selected. -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/dshow_dev.c
r3392 r3402 41 41 42 42 #define THIS_FILE "dshow_dev.c" 43 #define DEFAULT_CLOCK_RATE 90000 43 44 #define DEFAULT_WIDTH 640 44 45 #define DEFAULT_HEIGHT 480 … … 394 395 395 396 /* Set the device capabilities here */ 396 param->clock_rate = 9000;397 param->frame_rate.num = 14;397 param->clock_rate = DEFAULT_CLOCK_RATE; 398 param->frame_rate.num = DEFAULT_FPS; 398 399 param->frame_rate.denum = 1; 399 400 param->flags = PJMEDIA_VID_DEV_CAP_FORMAT; -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/avi_player.c
r3392 r3402 87 87 struct pjmedia_avi_streams 88 88 { 89 pj_uint8_tnum_streams;89 unsigned num_streams; 90 90 pjmedia_port **streams; 91 91 }; … … 94 94 { 95 95 pjmedia_port base; 96 pj_uint8_tstream_id;96 unsigned stream_id; 97 97 unsigned options; 98 98 pj_uint16_t bits_per_sample; … … 172 172 struct avi_reader_port *fport[PJMEDIA_AVI_MAX_NUM_STREAMS]; 173 173 pj_off_t pos; 174 pj_uint8_ti, nstr = 0;174 unsigned i, nstr = 0; 175 175 pj_status_t status = PJ_SUCCESS; 176 176 … … 468 468 } 469 469 470 PJ_DEF( pj_uint8_t)470 PJ_DEF(unsigned) 471 471 pjmedia_avi_streams_get_num_streams(pjmedia_avi_streams *streams) 472 472 { … … 477 477 PJ_DEF(pjmedia_avi_stream *) 478 478 pjmedia_avi_streams_get_stream(pjmedia_avi_streams *streams, 479 pj_uint8_tidx)479 unsigned idx) 480 480 { 481 481 pj_assert(streams); … … 486 486 PJ_DEF(pjmedia_avi_stream *) 487 487 pjmedia_avi_streams_get_stream_by_media(pjmedia_avi_streams *streams, 488 pj_uint8_tstart_idx,488 unsigned start_idx, 489 489 pjmedia_type media_type) 490 490 { 491 pj_uint8_ti;491 unsigned i; 492 492 493 493 pj_assert(streams); … … 594 594 pjmedia_avi_subchunk ch = {0, 0}; 595 595 char *cid; 596 pj_uint8_tstream_id;596 unsigned stream_id; 597 597 598 598 /* We need to read data from the file past the chunk boundary */ -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/clock_thread.c
r3392 r3402 24 24 #include <pj/os.h> 25 25 #include <pj/pool.h> 26 #include <pj/string.h> 27 #include <pj/compat/high_precision.h> 28 29 /* API: Init clock source */ 30 PJ_DEF(pj_status_t) pjmedia_clock_src_init( pjmedia_clock_src *clocksrc, 31 pjmedia_type media_type, 32 unsigned clock_rate, 33 unsigned ptime_usec ) 34 { 35 PJ_ASSERT_RETURN(clocksrc, PJ_EINVAL); 36 37 clocksrc->media_type = media_type; 38 clocksrc->clock_rate = clock_rate; 39 clocksrc->ptime_usec = ptime_usec; 40 pj_set_timestamp32(&clocksrc->timestamp, 0, 0); 41 pj_get_timestamp(&clocksrc->last_update); 42 43 return PJ_SUCCESS; 44 } 45 46 /* API: Update clock source */ 47 PJ_DECL(pj_status_t) pjmedia_clock_src_update( pjmedia_clock_src *clocksrc, 48 const pj_timestamp *timestamp ) 49 { 50 PJ_ASSERT_RETURN(clocksrc, PJ_EINVAL); 51 52 if (timestamp) 53 pj_memcpy(&clocksrc->timestamp, timestamp, sizeof(pj_timestamp)); 54 pj_get_timestamp(&clocksrc->last_update); 55 56 return PJ_SUCCESS; 57 } 58 59 /* API: Get clock source's current timestamp */ 60 PJ_DEF(pj_status_t) 61 pjmedia_clock_src_get_current_timestamp( const pjmedia_clock_src *clocksrc, 62 pj_timestamp *timestamp) 63 { 64 pj_timestamp now; 65 unsigned elapsed_ms; 66 67 PJ_ASSERT_RETURN(clocksrc && timestamp, PJ_EINVAL); 68 69 pj_get_timestamp(&now); 70 elapsed_ms = pj_elapsed_msec(&clocksrc->last_update, &now); 71 pj_memcpy(timestamp, &clocksrc->timestamp, sizeof(pj_timestamp)); 72 pj_add_timestamp32(timestamp, elapsed_ms * clocksrc->clock_rate / 1000); 73 74 return PJ_SUCCESS; 75 } 76 77 /* API: Get clock source's time (in ms) */ 78 PJ_DEF(pj_uint32_t) 79 pjmedia_clock_src_get_time_msec( const pjmedia_clock_src *clocksrc ) 80 { 81 pj_timestamp ts; 82 83 pjmedia_clock_src_get_current_timestamp(clocksrc, &ts); 84 85 #if PJ_HAS_INT64 86 if (ts.u64 > 0x3FFFFFFFFFFFFFUL) 87 return (pj_uint32_t)(ts.u64 / clocksrc->clock_rate * 1000); 88 else 89 return (pj_uint32_t)(ts.u64 * 1000 / clocksrc->clock_rate); 90 #elif PJ_HAS_FLOATING_POINT 91 return (pj_uint32_t)((1.0 * ts.u32.hi * 0xFFFFFFFFUL + ts.u32.lo) 92 * 1000.0 / clocksrc->clock_rate); 93 #else 94 if (ts.u32.lo > 0x3FFFFFUL) 95 return (pj_uint32_t)(0xFFFFFFFFUL / clocksrc->clock_rate * ts.u32.hi 96 * 1000UL + ts.u32.lo / clocksrc->clock_rate * 97 1000UL); 98 else 99 return (pj_uint32_t)(0xFFFFFFFFUL / clocksrc->clock_rate * ts.u32.hi 100 * 1000UL + ts.u32.lo * 1000UL / 101 clocksrc->clock_rate); 102 #endif 103 } 26 104 27 105 -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/port.c
r3392 r3402 76 76 77 77 /** 78 * Get a clock source from the port. 79 */ 80 PJ_DEF(pjmedia_clock_src *) pjmedia_port_get_clock_src( pjmedia_port *port, 81 pjmedia_dir dir ) 82 { 83 if (port && port->get_clock_src) 84 return port->get_clock_src(port, dir); 85 else 86 return NULL; 87 } 88 89 /** 78 90 * Get a frame from the port (and subsequent downstream ports). 79 91 */ -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/sound_port.c
r3392 r3402 45 45 pjmedia_port *port; 46 46 47 pjmedia_clock_src cap_clocksrc, 48 play_clocksrc; 49 47 50 unsigned clock_rate; 48 51 unsigned channel_count; … … 70 73 pj_status_t status; 71 74 75 pjmedia_clock_src_update(&snd_port->play_clocksrc, &frame->timestamp); 76 72 77 port = snd_port->port; 73 78 if (port == NULL) … … 127 132 pjmedia_port *port; 128 133 134 pjmedia_clock_src_update(&snd_port->cap_clocksrc, &frame->timestamp); 135 129 136 port = snd_port->port; 130 137 if (port == NULL) … … 137 144 138 145 pjmedia_port_put_frame(port, frame); 146 139 147 140 148 return PJ_SUCCESS; … … 418 426 pjmedia_snd_port *snd_port; 419 427 pj_status_t status; 428 unsigned ptime_usec; 420 429 421 430 PJ_ASSERT_RETURN(pool && prm && p_port, PJ_EINVAL); … … 433 442 snd_port->bits_per_sample = prm->bits_per_sample; 434 443 pj_memcpy(&snd_port->aud_param, prm, sizeof(*prm)); 444 445 ptime_usec = prm->samples_per_frame * 1000 / prm->channel_count / 446 prm->clock_rate * 1000; 447 pjmedia_clock_src_init(&snd_port->cap_clocksrc, PJMEDIA_TYPE_AUDIO, 448 snd_port->clock_rate, ptime_usec); 449 pjmedia_clock_src_init(&snd_port->play_clocksrc, PJMEDIA_TYPE_AUDIO, 450 snd_port->clock_rate, ptime_usec); 435 451 436 452 /* Start sound device immediately. … … 633 649 634 650 /* 651 * Get clock source. 652 */ 653 PJ_DEF(pjmedia_clock_src *) 654 pjmedia_snd_port_get_clock_src( pjmedia_snd_port *snd_port, 655 pjmedia_dir dir ) 656 { 657 return (dir == PJMEDIA_DIR_CAPTURE? &snd_port->cap_clocksrc: 658 &snd_port->play_clocksrc); 659 } 660 661 662 /* 635 663 * Connect a port. 636 664 */ -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c
r3401 r3402 50 50 *dec_clock; 51 51 52 pjmedia_clock_src cap_clocksrc, 53 rend_clocksrc; 54 55 struct sync_clock_src_t 56 { 57 pjmedia_clock_src *sync_clocksrc; 58 pj_int32_t sync_delta; 59 unsigned max_sync_ticks; 60 unsigned nsync_frame; 61 unsigned nsync_progress; 62 } cap_sync_clocksrc, rend_sync_clocksrc; 63 52 64 pjmedia_frame *enc_frm_buf, 53 65 *dec_frm_buf; … … 99 111 pj_bool_t need_frame_buf = PJ_FALSE; 100 112 pj_status_t status; 113 unsigned ptime_usec; 101 114 102 115 PJ_ASSERT_RETURN(pool && prm && p_vid_port, PJ_EINVAL); … … 140 153 vp->stream_role = di.has_callback ? ROLE_ACTIVE : ROLE_PASSIVE; 141 154 155 ptime_usec = PJMEDIA_PTIME(&vfd->fps); 156 pjmedia_clock_src_init(&vp->cap_clocksrc, PJMEDIA_TYPE_VIDEO, 157 prm->vidparam.clock_rate, ptime_usec); 158 pjmedia_clock_src_init(&vp->rend_clocksrc, PJMEDIA_TYPE_VIDEO, 159 prm->vidparam.clock_rate, ptime_usec); 160 vp->cap_sync_clocksrc.max_sync_ticks = 161 PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION * 162 1000 / vp->cap_clocksrc.ptime_usec; 163 vp->rend_sync_clocksrc.max_sync_ticks = 164 PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION * 165 1000 / vp->rend_clocksrc.ptime_usec; 166 142 167 /* Create the video stream */ 143 168 pj_bzero(&vid_cb, sizeof(vid_cb)); … … 269 294 270 295 296 297 PJ_DEF(pjmedia_clock_src *) 298 pjmedia_vid_port_get_clock_src( pjmedia_vid_port *vid_port, 299 pjmedia_dir dir ) 300 { 301 return (dir == PJMEDIA_DIR_CAPTURE? &vid_port->cap_clocksrc: 302 &vid_port->rend_clocksrc); 303 } 304 305 PJ_DECL(pj_status_t) 306 pjmedia_vid_port_set_clock_src( pjmedia_vid_port *vid_port, 307 pjmedia_dir dir, 308 pjmedia_clock_src *clocksrc) 309 { 310 pjmedia_clock_src *vclocksrc; 311 struct sync_clock_src_t *sync_src; 312 313 PJ_ASSERT_RETURN(vid_port && clocksrc, PJ_EINVAL); 314 315 vclocksrc = (dir == PJMEDIA_DIR_CAPTURE? &vid_port->cap_clocksrc: 316 &vid_port->rend_clocksrc); 317 sync_src = (dir == PJMEDIA_DIR_CAPTURE? &vid_port->cap_sync_clocksrc: 318 &vid_port->rend_sync_clocksrc); 319 sync_src->sync_clocksrc = clocksrc; 320 sync_src->sync_delta = pjmedia_clock_src_get_time_msec(vclocksrc) - 321 pjmedia_clock_src_get_time_msec(clocksrc); 322 323 return PJ_SUCCESS; 324 } 325 326 271 327 PJ_DEF(pj_status_t) pjmedia_vid_port_connect(pjmedia_vid_port *vp, 272 328 pjmedia_port *port, … … 438 494 pjmedia_vid_port *vp = (pjmedia_vid_port*)user_data; 439 495 pj_status_t status; 496 unsigned frame_ts = vp->rend_clocksrc.clock_rate / 1000 * 497 vp->rend_clocksrc.ptime_usec / 1000; 440 498 441 499 pj_assert(vp->role==ROLE_ACTIVE && vp->stream_role==ROLE_PASSIVE); … … 446 504 return; 447 505 506 if (vp->rend_sync_clocksrc.sync_clocksrc) { 507 pjmedia_clock_src *src = vp->rend_sync_clocksrc.sync_clocksrc; 508 pj_int32_t diff; 509 unsigned nsync_frame; 510 511 /* Synchronization */ 512 /* Calculate the time difference (in ms) with the sync source */ 513 diff = pjmedia_clock_src_get_time_msec(&vp->rend_clocksrc) - 514 pjmedia_clock_src_get_time_msec(src) - 515 vp->rend_sync_clocksrc.sync_delta; 516 517 /* Check whether sync source made a large jump */ 518 if (diff < 0 && -diff > PJMEDIA_CLOCK_SYNC_MAX_SYNC_MSEC) { 519 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 520 vp->rend_sync_clocksrc.sync_delta = 521 pjmedia_clock_src_get_time_msec(src) - 522 pjmedia_clock_src_get_time_msec(&vp->rend_clocksrc); 523 vp->rend_sync_clocksrc.nsync_frame = 0; 524 return; 525 } 526 527 /* Calculate the difference (in frames) with the sync source */ 528 nsync_frame = abs(diff) * 1000 / vp->rend_clocksrc.ptime_usec; 529 if (nsync_frame == 0) { 530 /* Nothing to sync */ 531 vp->rend_sync_clocksrc.nsync_frame = 0; 532 } else { 533 pj_int32_t init_sync_frame = nsync_frame; 534 535 /* Check whether it's a new sync or whether we need to reset 536 * the sync 537 */ 538 if (vp->rend_sync_clocksrc.nsync_frame == 0 || 539 (vp->rend_sync_clocksrc.nsync_frame > 0 && 540 nsync_frame > vp->rend_sync_clocksrc.nsync_frame)) 541 { 542 vp->rend_sync_clocksrc.nsync_frame = nsync_frame; 543 vp->rend_sync_clocksrc.nsync_progress = 0; 544 } else { 545 init_sync_frame = vp->rend_sync_clocksrc.nsync_frame; 546 } 547 548 if (diff >= 0) { 549 unsigned skip_mod; 550 551 /* We are too fast */ 552 if (vp->rend_sync_clocksrc.max_sync_ticks > 0) { 553 skip_mod = init_sync_frame / 554 vp->rend_sync_clocksrc.max_sync_ticks + 2; 555 } else 556 skip_mod = init_sync_frame + 2; 557 558 PJ_LOG(5, (THIS_FILE, "synchronization: early by %d ms", 559 diff)); 560 /* We'll play a frame every skip_mod-th tick instead of 561 * a complete pause 562 */ 563 if (++vp->rend_sync_clocksrc.nsync_progress % skip_mod > 0) { 564 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 565 return; 566 } 567 } else { 568 unsigned i, ndrop = init_sync_frame; 569 570 /* We are too late, drop the frame */ 571 if (vp->rend_sync_clocksrc.max_sync_ticks > 0) { 572 ndrop /= vp->rend_sync_clocksrc.max_sync_ticks; 573 ndrop++; 574 } 575 PJ_LOG(5, (THIS_FILE, "synchronization: late, " 576 "dropping %d frame(s)", ndrop)); 577 578 if (ndrop >= nsync_frame) { 579 vp->rend_sync_clocksrc.nsync_frame = 0; 580 ndrop = nsync_frame; 581 } else 582 vp->rend_sync_clocksrc.nsync_progress += ndrop; 583 for (i = 0; i < ndrop; i++) { 584 status = pjmedia_port_get_frame(vp->client_port, 585 vp->dec_frm_buf); 586 if (status != PJ_SUCCESS) { 587 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 588 return; 589 } 590 pj_add_timestamp32(&vp->rend_clocksrc.timestamp, 591 frame_ts); 592 } 593 } 594 } 595 } 596 448 597 status = pjmedia_port_get_frame(vp->client_port, vp->dec_frm_buf); 449 if (status != PJ_SUCCESS) 598 if (status != PJ_SUCCESS) { 599 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 450 600 return; 601 } 602 pj_add_timestamp32(&vp->rend_clocksrc.timestamp, frame_ts); 603 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 451 604 452 605 status = pjmedia_vid_stream_put_frame(vp->strm, vp->dec_frm_buf); -
pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/aviplay.c
r3401 r3402 91 91 { 92 92 pjmedia_vid_port *vid_port; 93 pjmedia_ aud_stream *aud_stream;93 pjmedia_snd_port *snd_port; 94 94 pj_bool_t is_running; 95 95 pj_bool_t is_quitting; … … 105 105 pjmedia_converter *conv; 106 106 } codec_port_data_t; 107 108 static pj_status_t avi_play_cb(void *user_data, pjmedia_frame *frame)109 {110 return pjmedia_port_get_frame((pjmedia_port*)user_data, frame);111 }112 107 113 108 static pj_status_t avi_event_cb(pjmedia_vid_stream *stream, … … 126 121 if (ap->is_running) { 127 122 pjmedia_vid_port_stop(ap->vid_port); 128 if (ap->aud_stream) 129 pjmedia_aud_stream_stop(ap->aud_stream); 123 if (ap->snd_port) 124 pjmedia_aud_stream_stop( 125 pjmedia_snd_port_get_snd_stream(ap->snd_port)); 130 126 } else { 131 127 pjmedia_vid_port_start(ap->vid_port); 132 if (ap->aud_stream) 133 pjmedia_aud_stream_start(ap->aud_stream); 128 if (ap->snd_port) 129 pjmedia_aud_stream_start( 130 pjmedia_snd_port_get_snd_stream(ap->snd_port)); 134 131 } 135 132 ap->is_running = !ap->is_running; … … 187 184 pjmedia_vid_port *renderer=NULL; 188 185 pjmedia_vid_port_param param; 189 pjmedia_aud_param aparam;190 186 const pjmedia_video_format_info *vfi; 191 187 pjmedia_video_format_detail *vfd; 192 pjmedia_audio_format_detail *afd; 193 pjmedia_aud_stream *strm = NULL; 188 pjmedia_snd_port *snd_port = NULL; 194 189 pj_status_t status; 195 190 int rc = 0; … … 376 371 377 372 if (aud_port) { 378 status = pjmedia_aud_dev_default_param( 379 PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV, 380 &aparam); 373 /* Create sound player port. */ 374 status = pjmedia_snd_port_create_player( 375 pool, /* pool */ 376 -1, /* use default dev. */ 377 PJMEDIA_PIA_SRATE(&aud_port->info),/* clock rate. */ 378 PJMEDIA_PIA_CCNT(&aud_port->info), /* # of channels. */ 379 PJMEDIA_PIA_SPF(&aud_port->info), /* samples per frame. */ 380 PJMEDIA_PIA_BITS(&aud_port->info), /* bits per sample. */ 381 0, /* options */ 382 &snd_port /* returned port */ 383 ); 381 384 if (status != PJ_SUCCESS) { 382 385 rc = 310; goto on_return; 383 386 } 384 387 385 aparam.dir = PJMEDIA_DIR_PLAYBACK; 386 afd = pjmedia_format_get_audio_format_detail(&aud_port->info.fmt, 387 PJ_TRUE); 388 aparam.clock_rate = afd->clock_rate; 389 aparam.channel_count = afd->channel_count; 390 aparam.bits_per_sample = afd->bits_per_sample; 391 aparam.samples_per_frame = afd->frame_time_usec * aparam.clock_rate * 392 aparam.channel_count / 1000000; 393 394 status = pjmedia_aud_stream_create(&aparam, NULL, &avi_play_cb, 395 aud_port, 396 &strm); 397 if (status != PJ_SUCCESS) { 398 rc = 320; goto on_return; 399 } 400 401 /* Start audio streaming.. */ 402 status = pjmedia_aud_stream_start(strm); 388 /* Connect file port to the sound player. 389 * Stream playing will commence immediately. 390 */ 391 status = pjmedia_snd_port_connect(snd_port, aud_port); 403 392 if (status != PJ_SUCCESS) { 404 393 rc = 330; goto on_return; … … 411 400 pj_bzero(&cb, sizeof(cb)); 412 401 cb.on_event_cb = avi_event_cb; 413 avi_port. aud_stream = strm;402 avi_port.snd_port = snd_port; 414 403 avi_port.vid_port = renderer; 415 404 avi_port.is_running = PJ_TRUE; 416 405 pjmedia_vid_port_set_cb(renderer, &cb, &avi_port); 406 407 if (snd_port) { 408 /* Synchronize video rendering and audio playback */ 409 pjmedia_vid_port_set_clock_src( 410 renderer, PJMEDIA_DIR_RENDER, 411 pjmedia_snd_port_get_clock_src( 412 snd_port, PJMEDIA_DIR_PLAYBACK)); 413 } 414 417 415 418 416 /* Start video streaming.. */ … … 428 426 429 427 on_return: 430 if (strm) { 431 pjmedia_aud_stream_stop(strm); 432 pjmedia_aud_stream_destroy(strm); 428 if (snd_port) { 429 pjmedia_snd_port_disconnect(snd_port); 430 /* Without this sleep, Windows/DirectSound will repeteadly 431 * play the last frame during destroy. 432 */ 433 pj_thread_sleep(100); 434 pjmedia_snd_port_destroy(snd_port); 433 435 } 434 436 if (renderer) 435 437 pjmedia_vid_port_destroy(renderer); 438 if (aud_port) 439 pjmedia_port_destroy(aud_port); 436 440 if (vid_port) 437 441 pjmedia_port_destroy(vid_port);
Note: See TracChangeset
for help on using the changeset viewer.