Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous conference bridge operation #3928

Merged
merged 13 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pjmedia/include/pjmedia/conference.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ PJ_DECL(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
* Disconnect unidirectional audio from the specified source to the specified
* sink slot.
*
* Note that the operation will be done asynchronously, so application
* should not assume that the port will no longer receive/send audio frame
* after this function has returned.
*
* @param conf The conference bridge.
* @param src_slot Source slot.
* @param sink_slot Sink slot.
Expand All @@ -362,6 +366,10 @@ PJ_DECL(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
/**
* Disconnect unidirectional audio from all sources to the specified sink slot.
*
* Note that the operation will be done asynchronously, so application
* should not assume that the port will no longer receive/send audio frame
* after this function has returned.
*
* @param conf The conference bridge.
* @param sink_slot Sink slot.
*
Expand All @@ -375,6 +383,10 @@ pjmedia_conf_disconnect_port_from_sources( pjmedia_conf *conf,
/**
* Disconnect unidirectional audio from the specified source to all sink slots.
*
* Note that the operation will be done asynchronously, so application
* should not assume that the port will no longer receive/send audio frame
* after this function has returned.
*
* @param conf The conference bridge.
* @param src_slot Source slot.
*
Expand Down Expand Up @@ -409,6 +421,10 @@ PJ_DECL(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf);
/**
* Remove the specified port from the conference bridge.
*
* Note that the operation will be done asynchronously, so application
* should not assume that the port will no longer receive/send audio frame
* after this function has returned.
*
* @param conf The conference bridge.
* @param slot The port index to be removed.
*
Expand Down
14 changes: 11 additions & 3 deletions pjmedia/include/pjmedia/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,8 @@ typedef struct pjmedia_port
pjmedia_frame *frame);

/**
* Called to destroy this port.
* Destructor.
* This should only be called by #pjmedia_port_destroy().
*/
pj_status_t (*on_destroy)(struct pjmedia_port *this_port);

Expand Down Expand Up @@ -512,14 +513,21 @@ PJ_DECL(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port,
PJ_DECL(pj_status_t) pjmedia_port_destroy( pjmedia_port *port );



/*
*******************************************************************
* Helper functions.
*******************************************************************
*/

/**
* This is a helper function to initialize the port's group lock. This
* function will create a group lock if NULL is passed, initialize the group
* lock by adding the port's destructor to the group lock handler list, and
* increment the reference counter.
*
* This function should only be called by a media port implementation and
* after port's on_destroy() function has been assigned.
* This function should only be called by media port implementation. The port
* must have its own pool which will be released in its on_destroy() function.
*
* @param port The pjmedia port to be initialized.
* @param pool The pool, this can be a temporary pool as
Expand Down
3 changes: 2 additions & 1 deletion pjmedia/include/pjmedia/splitcomb.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ PJ_DECL(pj_status_t) pjmedia_splitcomb_set_channel(pjmedia_port *splitcomb,
* media port. So this effectively reverse the phase of the media port.
*
* @param pool The pool to allocate memory for the port and
* buffers.
* buffers. This is deprecated, the channel will be
* created using splitter/combiner's pool.
* @param splitcomb The splitter/combiner.
* @param ch_num Audio channel starting number (zero based).
* @param options Normally is zero, but the lower 8-bit of the
Expand Down
63 changes: 51 additions & 12 deletions pjmedia/src/pjmedia/avi_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ static avi_fmt_info avi_fmts[] =

struct pjmedia_avi_streams
{
pj_pool_t *pool;
unsigned num_streams;
pjmedia_port **streams;
};
Expand All @@ -142,12 +143,12 @@ struct avi_reader_port
void (*cb2)(pjmedia_port*, void*);
};


static pj_status_t avi_get_frame(pjmedia_port *this_port,
pjmedia_frame *frame);
static pj_status_t avi_on_destroy(pjmedia_port *this_port);

static struct avi_reader_port *create_avi_port(pj_pool_t *pool)
static struct avi_reader_port *create_avi_port(pj_pool_t *pool,
pj_grp_lock_t *grp_lock)
{
const pj_str_t name = pj_str("file");
struct avi_reader_port *port;
Expand All @@ -166,6 +167,8 @@ static struct avi_reader_port *create_avi_port(pj_pool_t *pool)
port->base.get_frame = &avi_get_frame;
port->base.on_destroy = &avi_on_destroy;

pjmedia_port_init_grp_lock(&port->base, pool, grp_lock);

return port;
}

Expand Down Expand Up @@ -196,11 +199,19 @@ static pj_status_t file_read3(pj_oshandle_t fd, void *data, pj_ssize_t size,
return status;
}


static void streams_on_destroy(void *arg)
{
pjmedia_avi_streams *streams = (pjmedia_avi_streams*)arg;
pj_pool_safe_release(&streams->pool);
}


/*
* Create AVI player port.
*/
PJ_DEF(pj_status_t)
pjmedia_avi_player_create_streams(pj_pool_t *pool,
pjmedia_avi_player_create_streams(pj_pool_t *pool_,
const char *filename,
unsigned options,
pjmedia_avi_streams **p_streams)
Expand All @@ -209,20 +220,36 @@ pjmedia_avi_player_create_streams(pj_pool_t *pool,
struct avi_reader_port *fport[PJMEDIA_AVI_MAX_NUM_STREAMS];
pj_off_t pos;
unsigned i, nstr = 0;
pj_pool_t *pool = NULL;
pj_grp_lock_t *grp_lock = NULL;
pj_status_t status = PJ_SUCCESS;

/* Check arguments. */
PJ_ASSERT_RETURN(pool && filename && p_streams, PJ_EINVAL);
PJ_ASSERT_RETURN(pool_ && filename && p_streams, PJ_EINVAL);

/* Check the file really exists. */
if (!pj_file_exists(filename)) {
return PJ_ENOTFOUND;
}

/* Create own pool */
pool = pj_pool_create(pool_->factory, "aviplayer", 500, 500, NULL);
PJ_ASSERT_RETURN(pool, PJ_ENOMEM);

/* Create group lock */
status = pj_grp_lock_create(pool, NULL, &grp_lock);
if (status != PJ_SUCCESS)
goto on_error;

/* Create fport instance. */
fport[0] = create_avi_port(pool);
fport[0] = create_avi_port(pool, grp_lock);
if (!fport[0]) {
return PJ_ENOMEM;
/* Destroy group lock here to avoid leak */
pj_grp_lock_destroy(grp_lock);
grp_lock = NULL;

status = PJ_ENOMEM;
goto on_error;
}

/* Get the file size. */
Expand All @@ -232,14 +259,15 @@ pjmedia_avi_player_create_streams(pj_pool_t *pool,
if (fport[0]->fsize <= (pj_off_t)(sizeof(riff_hdr_t) + sizeof(avih_hdr_t) +
sizeof(strl_hdr_t)))
{
return PJMEDIA_EINVALIMEDIATYPE;
status = PJMEDIA_EINVALIMEDIATYPE;
goto on_error;
}

/* Open file. */
status = pj_file_open(pool, filename, PJ_O_RDONLY | PJ_O_CLOEXEC,
&fport[0]->fd);
if (status != PJ_SUCCESS)
return status;
goto on_error;

/* Read the RIFF + AVIH header. */
status = file_read(fport[0]->fd, &avi_hdr,
Expand Down Expand Up @@ -435,7 +463,7 @@ pjmedia_avi_player_create_streams(pj_pool_t *pool,

if (nstr > 0) {
/* Create fport instance. */
fport[nstr] = create_avi_port(pool);
fport[nstr] = create_avi_port(pool, grp_lock);
if (!fport[nstr]) {
status = PJ_ENOMEM;
goto on_error;
Expand Down Expand Up @@ -542,6 +570,13 @@ pjmedia_avi_player_create_streams(pj_pool_t *pool,
for (i = 0; i < nstr; i++)
(*p_streams)->streams[i] = &fport[i]->base;

status = pj_grp_lock_add_handler(grp_lock, NULL, *p_streams,
&streams_on_destroy);
if (status != PJ_SUCCESS)
goto on_error;

(*p_streams)->pool = pool;

PJ_LOG(4,(THIS_FILE,
"AVI file player '%.*s' created with "
"%d media ports",
Expand All @@ -552,9 +587,13 @@ pjmedia_avi_player_create_streams(pj_pool_t *pool,
return PJ_SUCCESS;

on_error:
fport[0]->base.on_destroy(&fport[0]->base);
for (i = 1; i < nstr; i++)
fport[i]->base.on_destroy(&fport[i]->base);
if (grp_lock) {
pjmedia_port_destroy(&fport[0]->base);
for (i = 1; i < nstr; i++)
pjmedia_port_destroy(&fport[i]->base);
}
pj_pool_release(pool);

if (status == AVI_EOF)
return PJMEDIA_EINVALIMEDIATYPE;
return status;
Expand Down
Loading
Loading