mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-03 04:16:43 +00:00
Merge "abstract/fixed/adpative jitter buffer: disallow frame re-inserts"
This commit is contained in:
@@ -109,6 +109,8 @@ typedef int (*jb_remove_impl)(void *jb, struct ast_frame **fout);
|
|||||||
typedef void (*jb_force_resynch_impl)(void *jb);
|
typedef void (*jb_force_resynch_impl)(void *jb);
|
||||||
/*! \brief Empty and reset jb */
|
/*! \brief Empty and reset jb */
|
||||||
typedef void (*jb_empty_and_reset_impl)(void *jb);
|
typedef void (*jb_empty_and_reset_impl)(void *jb);
|
||||||
|
/*! \brief Check if late */
|
||||||
|
typedef int (*jb_is_late_impl)(void *jb, long ts);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -127,6 +129,7 @@ struct ast_jb_impl
|
|||||||
jb_remove_impl remove;
|
jb_remove_impl remove;
|
||||||
jb_force_resynch_impl force_resync;
|
jb_force_resynch_impl force_resync;
|
||||||
jb_empty_and_reset_impl empty_and_reset;
|
jb_empty_and_reset_impl empty_and_reset;
|
||||||
|
jb_is_late_impl is_late;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ enum ast_frame_type {
|
|||||||
enum {
|
enum {
|
||||||
/*! This frame contains valid timing information */
|
/*! This frame contains valid timing information */
|
||||||
AST_FRFLAG_HAS_TIMING_INFO = (1 << 0),
|
AST_FRFLAG_HAS_TIMING_INFO = (1 << 0),
|
||||||
|
/*! This frame has been requeued */
|
||||||
|
AST_FRFLAG_REQUEUED = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ast_frame_subclass {
|
struct ast_frame_subclass {
|
||||||
|
|||||||
@@ -166,6 +166,9 @@ enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf);
|
|||||||
typedef void __attribute__((format(printf, 1, 2))) (*jb_output_function_t)(const char *fmt, ...);
|
typedef void __attribute__((format(printf, 1, 2))) (*jb_output_function_t)(const char *fmt, ...);
|
||||||
void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg);
|
void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg);
|
||||||
|
|
||||||
|
/*! \brief Checks if the given time stamp is late */
|
||||||
|
int jb_is_late(jitterbuf *jb, long ts);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ static long jb_next_fixed(void *jb);
|
|||||||
static int jb_remove_fixed(void *jb, struct ast_frame **fout);
|
static int jb_remove_fixed(void *jb, struct ast_frame **fout);
|
||||||
static void jb_force_resynch_fixed(void *jb);
|
static void jb_force_resynch_fixed(void *jb);
|
||||||
static void jb_empty_and_reset_fixed(void *jb);
|
static void jb_empty_and_reset_fixed(void *jb);
|
||||||
|
static int jb_is_late_fixed(void *jb, long ts);
|
||||||
/* adaptive */
|
/* adaptive */
|
||||||
static void * jb_create_adaptive(struct ast_jb_conf *general_config);
|
static void * jb_create_adaptive(struct ast_jb_conf *general_config);
|
||||||
static void jb_destroy_adaptive(void *jb);
|
static void jb_destroy_adaptive(void *jb);
|
||||||
@@ -75,6 +76,7 @@ static long jb_next_adaptive(void *jb);
|
|||||||
static int jb_remove_adaptive(void *jb, struct ast_frame **fout);
|
static int jb_remove_adaptive(void *jb, struct ast_frame **fout);
|
||||||
static void jb_force_resynch_adaptive(void *jb);
|
static void jb_force_resynch_adaptive(void *jb);
|
||||||
static void jb_empty_and_reset_adaptive(void *jb);
|
static void jb_empty_and_reset_adaptive(void *jb);
|
||||||
|
static int jb_is_late_adaptive(void *jb, long ts);
|
||||||
|
|
||||||
/* Available jb implementations */
|
/* Available jb implementations */
|
||||||
static const struct ast_jb_impl avail_impl[] = {
|
static const struct ast_jb_impl avail_impl[] = {
|
||||||
@@ -90,6 +92,7 @@ static const struct ast_jb_impl avail_impl[] = {
|
|||||||
.remove = jb_remove_fixed,
|
.remove = jb_remove_fixed,
|
||||||
.force_resync = jb_force_resynch_fixed,
|
.force_resync = jb_force_resynch_fixed,
|
||||||
.empty_and_reset = jb_empty_and_reset_fixed,
|
.empty_and_reset = jb_empty_and_reset_fixed,
|
||||||
|
.is_late = jb_is_late_fixed,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "adaptive",
|
.name = "adaptive",
|
||||||
@@ -103,6 +106,7 @@ static const struct ast_jb_impl avail_impl[] = {
|
|||||||
.remove = jb_remove_adaptive,
|
.remove = jb_remove_adaptive,
|
||||||
.force_resync = jb_force_resynch_adaptive,
|
.force_resync = jb_force_resynch_adaptive,
|
||||||
.empty_and_reset = jb_empty_and_reset_adaptive,
|
.empty_and_reset = jb_empty_and_reset_adaptive,
|
||||||
|
.is_late = jb_is_late_adaptive,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -704,6 +708,11 @@ static void jb_empty_and_reset_fixed(void *jb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int jb_is_late_fixed(void *jb, long ts)
|
||||||
|
{
|
||||||
|
return fixed_jb_is_late(jb, ts);
|
||||||
|
}
|
||||||
|
|
||||||
/* adaptive */
|
/* adaptive */
|
||||||
|
|
||||||
static void *jb_create_adaptive(struct ast_jb_conf *general_config)
|
static void *jb_create_adaptive(struct ast_jb_conf *general_config)
|
||||||
@@ -810,6 +819,11 @@ const struct ast_jb_impl *ast_jb_get_impl(enum ast_jb_type type)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int jb_is_late_adaptive(void *jb, long ts)
|
||||||
|
{
|
||||||
|
return jb_is_late(jb, ts);
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFAULT_TIMER_INTERVAL 20
|
#define DEFAULT_TIMER_INTERVAL 20
|
||||||
#define DEFAULT_SIZE 200
|
#define DEFAULT_SIZE 200
|
||||||
#define DEFAULT_TARGET_EXTRA 40
|
#define DEFAULT_TARGET_EXTRA 40
|
||||||
@@ -893,7 +907,22 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frame) {
|
/*
|
||||||
|
* If the frame has been requeued (for instance when the translate core returns
|
||||||
|
* more than one frame) then if the frame is late we want to immediately return
|
||||||
|
* it. Otherwise attempt to insert it into the jitterbuffer.
|
||||||
|
*
|
||||||
|
* If the frame is requeued and late then in all likely hood it's a frame that
|
||||||
|
* that was previously retrieved from the jitterbuffer, passed to the translate
|
||||||
|
* core, and then put back into the channel read queue. Even if it had not been
|
||||||
|
* in the jitterbuffer prior to now it needs to be the next frame "out".
|
||||||
|
*
|
||||||
|
* However late arriving frames that have not been requeued (i.e. regular frames)
|
||||||
|
* need to be passed to the jitterbuffer so they can be appropriately dropped. As
|
||||||
|
* well any requeued frames that are not late should be put into the jitterbuffer.
|
||||||
|
*/
|
||||||
|
if (!frame || (ast_test_flag(frame, AST_FRFLAG_REQUEUED) &&
|
||||||
|
framedata->jb_impl->is_late(framedata->jb_obj, frame->ts))) {
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4333,12 +4333,19 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
|||||||
* at the end of the queue.
|
* at the end of the queue.
|
||||||
*/
|
*/
|
||||||
if (AST_LIST_NEXT(f, frame_list)) {
|
if (AST_LIST_NEXT(f, frame_list)) {
|
||||||
if (!readq_tail) {
|
struct ast_frame *cur, *multi_frame = AST_LIST_NEXT(f, frame_list);
|
||||||
ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list));
|
|
||||||
} else {
|
/* Mark these frames as being re-queued */
|
||||||
__ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail);
|
for (cur = multi_frame; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||||
|
ast_set_flag(cur, AST_FRFLAG_REQUEUED);
|
||||||
}
|
}
|
||||||
ast_frfree(AST_LIST_NEXT(f, frame_list));
|
|
||||||
|
if (!readq_tail) {
|
||||||
|
ast_queue_frame_head(chan, multi_frame);
|
||||||
|
} else {
|
||||||
|
__ast_queue_frame(chan, multi_frame, 0, readq_tail);
|
||||||
|
}
|
||||||
|
ast_frfree(multi_frame);
|
||||||
AST_LIST_NEXT(f, frame_list) = NULL;
|
AST_LIST_NEXT(f, frame_list) = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,6 @@ int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long n
|
|||||||
return fixed_jb_put(jb, data, ms, ts, now);
|
return fixed_jb_put(jb, data, ms, ts, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
|
int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
|
||||||
{
|
{
|
||||||
struct fixed_jb_frame *frame, *next, *newframe;
|
struct fixed_jb_frame *frame, *next, *newframe;
|
||||||
@@ -347,3 +346,8 @@ int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout)
|
|||||||
|
|
||||||
return FIXED_JB_OK;
|
return FIXED_JB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fixed_jb_is_late(struct fixed_jb *jb, long ts)
|
||||||
|
{
|
||||||
|
return jb->rxcore + jb->delay + ts < jb->next_delivery;
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout);
|
|||||||
|
|
||||||
void fixed_jb_set_force_resynch(struct fixed_jb *jb);
|
void fixed_jb_set_force_resynch(struct fixed_jb *jb);
|
||||||
|
|
||||||
|
/*! \brief Checks if the given time stamp is late */
|
||||||
|
int fixed_jb_is_late(struct fixed_jb *jb, long ts);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -843,4 +843,7 @@ enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
|
|||||||
return JB_OK;
|
return JB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int jb_is_late(jitterbuf *jb, long ts)
|
||||||
|
{
|
||||||
|
return ts + jb->info.current < jb->info.next_voice_ts;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user