From 18fd894546492261e3abff8d5d1d7b45c352e4cc Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Mon, 11 Sep 2006 19:55:41 +0000 Subject: Added EOF callback in memory playback port. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@704 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/mem_port.h | 22 ++++++++++++++ pjmedia/src/pjmedia/mem_player.c | 60 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) (limited to 'pjmedia') diff --git a/pjmedia/include/pjmedia/mem_port.h b/pjmedia/include/pjmedia/mem_port.h index 7c62b614..40c85999 100644 --- a/pjmedia/include/pjmedia/mem_port.h +++ b/pjmedia/include/pjmedia/mem_port.h @@ -69,6 +69,28 @@ PJ_DECL(pj_status_t) pjmedia_mem_player_create(pj_pool_t *pool, pjmedia_port **p_port ); +/** + * Register a callback to be called when the buffer reading has reached the + * end of buffer. If the player is set to play repeatedly, then the callback + * will be called multiple times. Note that only one callback can be + * registered for each player port. + * + * @param port The memory player port. + * @param user_data User data to be specified in the callback + * @param cb Callback to be called. If the callback returns non- + * PJ_SUCCESS, the playback will stop. Note that if + * application destroys the player port in the callback, + * it must return non-PJ_SUCCESS here. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_mem_player_set_eof_cb( pjmedia_port *port, + void *user_data, + pj_status_t (*cb)(pjmedia_port *port, + void *usr_data)); + + /** * @} */ diff --git a/pjmedia/src/pjmedia/mem_player.c b/pjmedia/src/pjmedia/mem_player.c index 5bc82caf..a2aec01a 100644 --- a/pjmedia/src/pjmedia/mem_player.c +++ b/pjmedia/src/pjmedia/mem_player.c @@ -37,6 +37,12 @@ struct mem_player char *buffer; pj_size_t buf_size; char *read_pos; + + pj_bool_t eof; + void *user_data; + pj_status_t (*cb)(pjmedia_port *port, + void *user_data); + }; @@ -94,6 +100,30 @@ PJ_DEF(pj_status_t) pjmedia_mem_player_create( pj_pool_t *pool, } + +/* + * Register a callback to be called when the file reading has reached the + * end of buffer. + */ +PJ_DEF(pj_status_t) +pjmedia_mem_player_set_eof_cb( pjmedia_port *port, + void *user_data, + pj_status_t (*cb)(pjmedia_port *port, + void *usr_data)) +{ + struct mem_player *player; + + PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, + PJ_EINVALIDOP); + + player = (struct mem_player*) port; + player->user_data = user_data; + player->cb = cb; + + return PJ_SUCCESS; +} + + static pj_status_t mem_put_frame( pjmedia_port *this_port, const pjmedia_frame *frame) { @@ -116,6 +146,11 @@ static pj_status_t mem_get_frame( pjmedia_port *this_port, player = (struct mem_player*) this_port; + if (player->eof) { + frame->type = PJMEDIA_FRAME_TYPE_NONE; + return PJ_EEOF; + } + size_needed = this_port->info.bytes_per_frame; size_written = 0; endpos = player->buffer + player->buf_size; @@ -134,16 +169,35 @@ static pj_status_t mem_get_frame( pjmedia_port *this_port, pj_assert(player->read_pos <= endpos); - if (player->read_pos == endpos) + if (player->read_pos == endpos) { player->read_pos = player->buffer; - } - player->timestamp.u64 += this_port->info.samples_per_frame; + /* Call callback, if any */ + if (player->cb) { + pj_status_t status; + + player->eof = PJ_TRUE; + status = (*player->cb)(this_port, player->user_data); + if (status != PJ_SUCCESS) { + /* Must not access player from here on. It may be + * destroyed by application. + */ + frame->size = size_written; + frame->timestamp.u64 = player->timestamp.u64; + frame->type = PJMEDIA_FRAME_TYPE_AUDIO; + return status; + } + player->eof = PJ_FALSE; + } + } + } frame->size = this_port->info.bytes_per_frame; frame->timestamp.u64 = player->timestamp.u64; frame->type = PJMEDIA_FRAME_TYPE_AUDIO; + player->timestamp.u64 += this_port->info.samples_per_frame; + return PJ_SUCCESS; } -- cgit v1.2.3