mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +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); | ||||
| /*! \brief Empty and reset 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_force_resynch_impl force_resync; | ||||
| 	jb_empty_and_reset_impl empty_and_reset; | ||||
| 	jb_is_late_impl is_late; | ||||
| }; | ||||
|  | ||||
| /*! | ||||
|   | ||||
| @@ -133,6 +133,8 @@ enum ast_frame_type { | ||||
| enum { | ||||
| 	/*! This frame contains valid timing information */ | ||||
| 	AST_FRFLAG_HAS_TIMING_INFO = (1 << 0), | ||||
| 	/*! This frame has been requeued */ | ||||
| 	AST_FRFLAG_REQUEUED = (1 << 1), | ||||
| }; | ||||
|  | ||||
| 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, ...); | ||||
| 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 | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -65,6 +65,7 @@ static long jb_next_fixed(void *jb); | ||||
| static int jb_remove_fixed(void *jb, struct ast_frame **fout); | ||||
| static void jb_force_resynch_fixed(void *jb); | ||||
| static void jb_empty_and_reset_fixed(void *jb); | ||||
| static int jb_is_late_fixed(void *jb, long ts); | ||||
| /* adaptive */ | ||||
| static void * jb_create_adaptive(struct ast_jb_conf *general_config); | ||||
| 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 void jb_force_resynch_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 */ | ||||
| static const struct ast_jb_impl avail_impl[] = { | ||||
| @@ -90,6 +92,7 @@ static const struct ast_jb_impl avail_impl[] = { | ||||
| 		.remove = jb_remove_fixed, | ||||
| 		.force_resync = jb_force_resynch_fixed, | ||||
| 		.empty_and_reset = jb_empty_and_reset_fixed, | ||||
| 		.is_late = jb_is_late_fixed, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.name = "adaptive", | ||||
| @@ -103,6 +106,7 @@ static const struct ast_jb_impl avail_impl[] = { | ||||
| 		.remove = jb_remove_adaptive, | ||||
| 		.force_resync = jb_force_resynch_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 */ | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| static int jb_is_late_adaptive(void *jb, long ts) | ||||
| { | ||||
| 	return jb_is_late(jb, ts); | ||||
| } | ||||
|  | ||||
| #define DEFAULT_TIMER_INTERVAL 20 | ||||
| #define DEFAULT_SIZE  200 | ||||
| #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; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -4333,12 +4333,19 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) | ||||
| 			 * at the end of the queue. | ||||
| 			 */ | ||||
| 			if (AST_LIST_NEXT(f, frame_list)) { | ||||
| 				if (!readq_tail) { | ||||
| 					ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list)); | ||||
| 				} else { | ||||
| 					__ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail); | ||||
| 				struct ast_frame *cur, *multi_frame = AST_LIST_NEXT(f, frame_list); | ||||
|  | ||||
| 				/* Mark these frames as being re-queued */ | ||||
| 				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; | ||||
| 			} | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
| int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now) | ||||
| { | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| 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); | ||||
|  | ||||
| /*! \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) | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -843,4 +843,7 @@ enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf) | ||||
| 	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