diff options
-rw-r--r-- | pjmedia/include/pjmedia/mem_port.h | 17 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/mem_player.c | 52 |
2 files changed, 48 insertions, 21 deletions
diff --git a/pjmedia/include/pjmedia/mem_port.h b/pjmedia/include/pjmedia/mem_port.h index 63c5f335..47b911f2 100644 --- a/pjmedia/include/pjmedia/mem_port.h +++ b/pjmedia/include/pjmedia/mem_port.h @@ -38,6 +38,21 @@ PJ_BEGIN_DECL * situation where filesystems are not available in the target system. */ + +/** + * Memory player options. + */ +enum pjmedia_mem_player_option +{ + /** + * Tell the memory player to return NULL frame when the whole + * buffer has been played instead of rewinding the buffer back + * to start position. + */ + PJMEDIA_MEM_NO_LOOP = 1 +}; + + /** * Create the buffer based playback to play the media from the specified * buffer. @@ -52,7 +67,7 @@ PJ_BEGIN_DECL * @param channel_count Number of channels. * @param samples_per_frame Number of samples per frame. * @param bits_per_sample Number of bits per sample. - * @param options Option flags. + * @param options Option flags, see #pjmedia_mem_player_option * @param p_port Pointer to receive the port instance. * * @return PJ_SUCCESS on success, or the appropriate diff --git a/pjmedia/src/pjmedia/mem_player.c b/pjmedia/src/pjmedia/mem_player.c index 678391c0..038577ef 100644 --- a/pjmedia/src/pjmedia/mem_player.c +++ b/pjmedia/src/pjmedia/mem_player.c @@ -146,8 +146,22 @@ 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; + pj_status_t status = PJ_SUCCESS; + + /* Call callback, if any */ + if (player->cb) + status = (*player->cb)(this_port, player->user_data); + + /* If callback returns non PJ_SUCCESS or 'no loop' is specified + * return immediately (and don't try to access player port since + * it might have been destroyed by the callback). + */ + if ((status != PJ_SUCCESS) || (player->options & PJMEDIA_MEM_NO_LOOP)) { + frame->type = PJMEDIA_FRAME_TYPE_NONE; + return PJ_EEOF; + } + + player->eof = PJ_FALSE; } size_needed = this_port->info.bytes_per_frame; @@ -169,24 +183,18 @@ static pj_status_t mem_get_frame( pjmedia_port *this_port, pj_assert(player->read_pos <= endpos); if (player->read_pos == endpos) { + /* Set EOF flag */ + player->eof = PJ_TRUE; + /* Reset read pointer */ player->read_pos = player->buffer; - /* 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; + /* Pad with zeroes then return for no looped play */ + if (player->options & PJMEDIA_MEM_NO_LOOP) { + pj_size_t null_len; + + null_len = size_needed - size_written; + pj_bzero(dst + max, null_len); + break; } } } @@ -203,8 +211,12 @@ static pj_status_t mem_get_frame( pjmedia_port *this_port, static pj_status_t mem_on_destroy(pjmedia_port *this_port) { - /* Nothing to do */ - PJ_UNUSED_ARG(this_port); + PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, + PJ_EINVALIDOP); + + /* Destroy signature */ + this_port->info.signature = 0; + return PJ_SUCCESS; } |