|
|
|
@ -526,18 +526,17 @@ struct rtp_parsed { |
|
|
|
|
|
|
|
#ifdef KERNEL_PLAYER |
|
|
|
|
|
|
|
struct play_stream_packet { |
|
|
|
struct re_play_stream_packet { |
|
|
|
struct list_head list; |
|
|
|
ktime_t delay; |
|
|
|
uint32_t ts; |
|
|
|
uint32_t duration_ts; |
|
|
|
uint16_t seq; |
|
|
|
//struct sk_buff *skb; |
|
|
|
char *data; |
|
|
|
size_t len; |
|
|
|
}; |
|
|
|
|
|
|
|
struct play_stream_packets { |
|
|
|
struct re_play_stream_packets { |
|
|
|
atomic_t refcnt; |
|
|
|
rwlock_t lock; |
|
|
|
struct list_head packets; |
|
|
|
@ -547,22 +546,22 @@ struct play_stream_packets { |
|
|
|
unsigned int idx; |
|
|
|
}; |
|
|
|
|
|
|
|
struct play_stream { |
|
|
|
struct re_play_stream { |
|
|
|
spinlock_t lock; |
|
|
|
atomic_t refcnt; |
|
|
|
unsigned int idx; |
|
|
|
struct rtpengine_play_stream_info info; |
|
|
|
struct re_crypto_context encrypt; |
|
|
|
struct play_stream_packets *packets; |
|
|
|
struct re_play_stream_packets *packets; |
|
|
|
ktime_t start_time; |
|
|
|
struct play_stream_packet *position; |
|
|
|
struct timer_thread *timer_thread; |
|
|
|
struct re_play_stream_packet *position; |
|
|
|
struct re_timer_thread *timer_thread; |
|
|
|
uint64_t tree_index; |
|
|
|
unsigned int table_id; |
|
|
|
struct list_head table_entry; |
|
|
|
}; |
|
|
|
|
|
|
|
struct timer_thread { |
|
|
|
struct re_timer_thread { |
|
|
|
struct list_head list; |
|
|
|
unsigned int idx; |
|
|
|
struct task_struct *task; |
|
|
|
@ -573,15 +572,15 @@ struct timer_thread { |
|
|
|
spinlock_t tree_lock; // XXX use mutex? |
|
|
|
struct btree_head64 tree; // timer entries // XXX use rbtree? |
|
|
|
bool tree_added; |
|
|
|
struct play_stream *scheduled; |
|
|
|
struct re_play_stream *scheduled; |
|
|
|
ktime_t scheduled_at; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void free_packet_stream(struct play_stream_packets *stream); |
|
|
|
static void free_play_stream_packet(struct play_stream_packet *p); |
|
|
|
static void free_play_stream(struct play_stream *s); |
|
|
|
static void do_stop_stream(struct play_stream *stream); |
|
|
|
static void free_packet_stream(struct re_play_stream_packets *stream); |
|
|
|
static void free_play_stream_packet(struct re_play_stream_packet *p); |
|
|
|
static void free_play_stream(struct re_play_stream *s); |
|
|
|
static void do_stop_stream(struct re_play_stream *stream); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
@ -598,15 +597,15 @@ static struct re_auto_array streams; |
|
|
|
|
|
|
|
#ifdef KERNEL_PLAYER |
|
|
|
static rwlock_t media_player_lock; |
|
|
|
static struct play_stream_packets **stream_packets; |
|
|
|
static struct re_play_stream_packets **stream_packets; |
|
|
|
static unsigned int num_stream_packets; |
|
|
|
static atomic_t last_stream_packets_idx; |
|
|
|
|
|
|
|
static struct play_stream **play_streams; |
|
|
|
static struct re_play_stream **play_streams; |
|
|
|
static unsigned int num_play_streams; |
|
|
|
static atomic_t last_play_stream_idx; |
|
|
|
|
|
|
|
static struct timer_thread **timer_threads; |
|
|
|
static struct re_timer_thread **timer_threads; |
|
|
|
static unsigned int num_timer_threads; |
|
|
|
static atomic_t last_timer_thread_idx; |
|
|
|
#endif |
|
|
|
@ -1041,9 +1040,9 @@ static void clear_proc(struct proc_dir_entry **e) { |
|
|
|
|
|
|
|
#ifdef KERNEL_PLAYER |
|
|
|
|
|
|
|
static void __unref_play_stream(struct play_stream *s); |
|
|
|
static void __unref_packet_stream(struct play_stream_packets *stream); |
|
|
|
static void end_of_stream(struct play_stream *stream); |
|
|
|
static void __unref_play_stream(struct re_play_stream *s); |
|
|
|
static void __unref_packet_stream(struct re_play_stream_packets *stream); |
|
|
|
static void end_of_stream(struct re_play_stream *stream); |
|
|
|
|
|
|
|
#define unref_play_stream(s) do { \ |
|
|
|
/* printk(KERN_WARNING "unref play stream %p (%i--) @ %s:%i\n", s, atomic_read(&(s)->refcnt), __FILE__, __LINE__); */ \ |
|
|
|
@ -1078,8 +1077,8 @@ static void clear_table_proc_files(struct rtpengine_table *t) { |
|
|
|
#ifdef KERNEL_PLAYER |
|
|
|
|
|
|
|
static void clear_table_player(struct rtpengine_table *t) { |
|
|
|
struct play_stream *stream, *ts; |
|
|
|
struct play_stream_packets *packets, *tp; |
|
|
|
struct re_play_stream *stream, *ts; |
|
|
|
struct re_play_stream_packets *packets, *tp; |
|
|
|
unsigned int idx; |
|
|
|
|
|
|
|
list_for_each_entry_safe(stream, ts, &t->play_streams, table_entry) { |
|
|
|
@ -3842,14 +3841,14 @@ static int cmd_pin_memory(struct rtpengine_table *t, struct rtpengine_pin_memory |
|
|
|
|
|
|
|
#ifdef KERNEL_PLAYER |
|
|
|
|
|
|
|
static void shut_threads(struct timer_thread **thr, unsigned int nt) { |
|
|
|
static void shut_threads(struct re_timer_thread **thr, unsigned int nt) { |
|
|
|
unsigned int i; |
|
|
|
|
|
|
|
if (!thr) |
|
|
|
return; |
|
|
|
|
|
|
|
for (i = 0; i < nt; i++) { |
|
|
|
struct timer_thread *tt = thr[i]; |
|
|
|
struct re_timer_thread *tt = thr[i]; |
|
|
|
if (!tt) |
|
|
|
continue; |
|
|
|
//printk(KERN_WARNING "stopping %u\n", i); |
|
|
|
@ -3864,7 +3863,7 @@ static void shut_threads(struct timer_thread **thr, unsigned int nt) { |
|
|
|
static void shut_all_threads(void) { |
|
|
|
LIST_HEAD(list); |
|
|
|
unsigned int nt; |
|
|
|
struct timer_thread **thr; |
|
|
|
struct re_timer_thread **thr; |
|
|
|
|
|
|
|
write_lock(&media_player_lock); |
|
|
|
|
|
|
|
@ -3877,8 +3876,8 @@ static void shut_all_threads(void) { |
|
|
|
shut_threads(thr, nt); |
|
|
|
} |
|
|
|
|
|
|
|
static void free_packet_stream(struct play_stream_packets *stream) { |
|
|
|
struct play_stream_packet *packet, *tp; |
|
|
|
static void free_packet_stream(struct re_play_stream_packets *stream) { |
|
|
|
struct re_play_stream_packet *packet, *tp; |
|
|
|
struct rtpengine_table *t; |
|
|
|
|
|
|
|
//printk(KERN_WARNING "freeing packet stream %p\n", stream); |
|
|
|
@ -3899,27 +3898,27 @@ static void free_packet_stream(struct play_stream_packets *stream) { |
|
|
|
kfree(stream); |
|
|
|
} |
|
|
|
|
|
|
|
static void __unref_packet_stream(struct play_stream_packets *stream) { |
|
|
|
static void __unref_packet_stream(struct re_play_stream_packets *stream) { |
|
|
|
if (atomic_dec_and_test(&stream->refcnt)) |
|
|
|
free_packet_stream(stream); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// stream must be locked and started |
|
|
|
static ktime_t play_stream_packet_time(struct play_stream *stream, struct play_stream_packet *packet) { |
|
|
|
static ktime_t play_stream_packet_time(struct re_play_stream *stream, struct re_play_stream_packet *packet) { |
|
|
|
return ktime_add(stream->start_time, packet->delay); |
|
|
|
} |
|
|
|
|
|
|
|
// stream must be locked, started, and non-empty |
|
|
|
static void play_stream_next_packet(struct play_stream *stream) { |
|
|
|
struct play_stream_packet *packet = stream->position; |
|
|
|
struct play_stream_packets *packets = stream->packets; |
|
|
|
static void play_stream_next_packet(struct re_play_stream *stream) { |
|
|
|
struct re_play_stream_packet *packet = stream->position; |
|
|
|
struct re_play_stream_packets *packets = stream->packets; |
|
|
|
read_lock(&packets->lock); |
|
|
|
stream->position = list_is_last(&packet->list, &packets->packets) ? NULL : list_next_entry(packet, list); |
|
|
|
if (!stream->position) { |
|
|
|
if (stream->info.repeat > 1) { |
|
|
|
stream->info.repeat--; |
|
|
|
stream->position = list_first_entry(&packets->packets, struct play_stream_packet, list); |
|
|
|
stream->position = list_first_entry(&packets->packets, struct re_play_stream_packet, list); |
|
|
|
stream->start_time = play_stream_packet_time(stream, packet); |
|
|
|
stream->info.ts += packet->ts + packet->duration_ts; |
|
|
|
stream->info.seq += packet->seq + 1; |
|
|
|
@ -3930,7 +3929,7 @@ static void play_stream_next_packet(struct play_stream *stream) { |
|
|
|
|
|
|
|
// stream must be locked, started, and non-empty |
|
|
|
// tt->tree_lock must be locked |
|
|
|
static void play_stream_insert_packet_to_tree(struct play_stream *stream, struct timer_thread *tt, ktime_t scheduled) { |
|
|
|
static void play_stream_insert_packet_to_tree(struct re_play_stream *stream, struct re_timer_thread *tt, ktime_t scheduled) { |
|
|
|
int64_t offset; |
|
|
|
|
|
|
|
// make sure key is unique |
|
|
|
@ -3943,11 +3942,11 @@ static void play_stream_insert_packet_to_tree(struct play_stream *stream, struct |
|
|
|
|
|
|
|
// stream must be locked, started, and non-empty |
|
|
|
// tree must not be locked |
|
|
|
static void play_stream_schedule_packet_to_thread(struct play_stream *stream, struct timer_thread *tt, |
|
|
|
static void play_stream_schedule_packet_to_thread(struct re_play_stream *stream, struct re_timer_thread *tt, |
|
|
|
bool reschedule) |
|
|
|
{ |
|
|
|
ktime_t scheduled; |
|
|
|
struct play_stream_packet *packet; |
|
|
|
struct re_play_stream_packet *packet; |
|
|
|
|
|
|
|
packet = stream->position; |
|
|
|
scheduled = play_stream_packet_time(stream, packet); |
|
|
|
@ -3990,8 +3989,8 @@ static void play_stream_schedule_packet_to_thread(struct play_stream *stream, st |
|
|
|
// threads->tree_lock must be unlocked (one will be locked) |
|
|
|
// lock order: stream lock first, thread->tree_lock second |
|
|
|
// num_timer_threads must be >0 |
|
|
|
static void play_stream_schedule_packet(struct play_stream *stream) { |
|
|
|
struct timer_thread *tt; |
|
|
|
static void play_stream_schedule_packet(struct re_play_stream *stream) { |
|
|
|
struct re_timer_thread *tt; |
|
|
|
unsigned int idx; |
|
|
|
|
|
|
|
// XXX check if already scheduled |
|
|
|
@ -4005,7 +4004,7 @@ static void play_stream_schedule_packet(struct play_stream *stream) { |
|
|
|
wake_up_interruptible(&tt->queue); // XXX need to refcount tt? for shutdown/free race? |
|
|
|
} |
|
|
|
|
|
|
|
static void play_stream_send_packet(struct play_stream *stream, struct play_stream_packet *packet) { |
|
|
|
static void play_stream_send_packet(struct re_play_stream *stream, struct re_play_stream_packet *packet) { |
|
|
|
struct sk_buff *skb; |
|
|
|
struct rtp_parsed rtp; |
|
|
|
|
|
|
|
@ -4045,7 +4044,7 @@ static void play_stream_send_packet(struct play_stream *stream, struct play_stre |
|
|
|
atomic64_add(packet->len, &stream->info.iface_stats->out.bytes); |
|
|
|
} |
|
|
|
|
|
|
|
static void free_play_stream(struct play_stream *s) { |
|
|
|
static void free_play_stream(struct re_play_stream *s) { |
|
|
|
//printk(KERN_WARNING "freeing play stream %p\n", s); |
|
|
|
free_crypto_context(&s->encrypt); |
|
|
|
if (s->packets) |
|
|
|
@ -4053,22 +4052,22 @@ static void free_play_stream(struct play_stream *s) { |
|
|
|
kfree(s); |
|
|
|
} |
|
|
|
|
|
|
|
static void __unref_play_stream(struct play_stream *s) { |
|
|
|
static void __unref_play_stream(struct re_play_stream *s) { |
|
|
|
if (atomic_dec_and_test(&s->refcnt)) |
|
|
|
free_play_stream(s); |
|
|
|
} |
|
|
|
|
|
|
|
static int timer_worker(void *p) { |
|
|
|
struct timer_thread *tt = p; |
|
|
|
struct re_timer_thread *tt = p; |
|
|
|
|
|
|
|
//printk(KERN_WARNING "cpu %u running\n", smp_processor_id()); |
|
|
|
while (!atomic_read(&tt->shutdown)) { |
|
|
|
int64_t timer_scheduled; |
|
|
|
struct play_stream *stream; |
|
|
|
struct re_play_stream *stream; |
|
|
|
ktime_t now, packet_scheduled; |
|
|
|
int64_t sleeptime_ns; |
|
|
|
struct play_stream_packet *packet; |
|
|
|
struct play_stream_packets *packets; |
|
|
|
struct re_play_stream_packet *packet; |
|
|
|
struct re_play_stream_packets *packets; |
|
|
|
|
|
|
|
//printk(KERN_WARNING "cpu %u (%p) loop enter\n", smp_processor_id(), tt); |
|
|
|
|
|
|
|
@ -4200,8 +4199,8 @@ static int timer_worker(void *p) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static struct timer_thread *launch_thread(unsigned int cpu) { |
|
|
|
struct timer_thread *tt; |
|
|
|
static struct re_timer_thread *launch_thread(unsigned int cpu) { |
|
|
|
struct re_timer_thread *tt; |
|
|
|
int ret; |
|
|
|
//printk(KERN_WARNING "try to launch %u\n", cpu); |
|
|
|
tt = kzalloc(sizeof(*tt), GFP_KERNEL); |
|
|
|
@ -4232,11 +4231,11 @@ static struct timer_thread *launch_thread(unsigned int cpu) { |
|
|
|
|
|
|
|
static int init_play_streams(unsigned int n_play_streams, unsigned int n_stream_packets) { |
|
|
|
int ret = 0; |
|
|
|
struct timer_thread **threads_new = NULL; |
|
|
|
struct re_timer_thread **threads_new = NULL; |
|
|
|
unsigned int new_num_threads = 0; |
|
|
|
bool need_threads; |
|
|
|
struct play_stream **new_play_streams, **old_play_streams = NULL; |
|
|
|
struct play_stream_packets **new_stream_packets, **old_stream_packets = NULL; |
|
|
|
struct re_play_stream **new_play_streams, **old_play_streams = NULL; |
|
|
|
struct re_play_stream_packets **new_stream_packets, **old_stream_packets = NULL; |
|
|
|
unsigned int cpu; |
|
|
|
|
|
|
|
write_lock(&media_player_lock); |
|
|
|
@ -4314,7 +4313,7 @@ err: |
|
|
|
} |
|
|
|
|
|
|
|
static int get_packet_stream(struct rtpengine_table *t, unsigned int *num) { |
|
|
|
struct play_stream_packets *new_stream; |
|
|
|
struct re_play_stream_packets *new_stream; |
|
|
|
unsigned int idx = -1; |
|
|
|
unsigned int i; |
|
|
|
|
|
|
|
@ -4360,7 +4359,7 @@ static int get_packet_stream(struct rtpengine_table *t, unsigned int *num) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void free_play_stream_packet(struct play_stream_packet *p) { |
|
|
|
static void free_play_stream_packet(struct re_play_stream_packet *p) { |
|
|
|
//printk(KERN_WARNING "freeing stream packet %u\n", p->seq); |
|
|
|
kfree(p->data); |
|
|
|
kfree(p); |
|
|
|
@ -4368,9 +4367,9 @@ static void free_play_stream_packet(struct play_stream_packet *p) { |
|
|
|
|
|
|
|
static int play_stream_packet(const struct rtpengine_play_stream_packet_info *info, size_t len) { |
|
|
|
const char *data = info->data; |
|
|
|
struct play_stream_packets *stream; |
|
|
|
struct re_play_stream_packets *stream; |
|
|
|
int ret = 0; |
|
|
|
struct play_stream_packet *packet = NULL, *last; |
|
|
|
struct re_play_stream_packet *packet = NULL, *last; |
|
|
|
|
|
|
|
//printk(KERN_WARNING "size %zu\n", len); |
|
|
|
|
|
|
|
@ -4404,7 +4403,7 @@ static int play_stream_packet(const struct rtpengine_play_stream_packet_info *in |
|
|
|
write_lock(&stream->lock); |
|
|
|
|
|
|
|
if (!list_empty(&stream->packets)) { |
|
|
|
last = list_last_entry(&stream->packets, struct play_stream_packet, list); |
|
|
|
last = list_last_entry(&stream->packets, struct re_play_stream_packet, list); |
|
|
|
if (ktime_after(last->delay, packet->delay)) { |
|
|
|
write_unlock(&stream->lock); |
|
|
|
ret = -ELOOP; |
|
|
|
@ -4427,8 +4426,8 @@ out: |
|
|
|
} |
|
|
|
|
|
|
|
static int play_stream(struct rtpengine_table *t, const struct rtpengine_play_stream_info *info, unsigned int *num) { |
|
|
|
struct play_stream *play_stream; |
|
|
|
struct play_stream_packets *packets = NULL; |
|
|
|
struct re_play_stream *play_stream; |
|
|
|
struct re_play_stream_packets *packets = NULL; |
|
|
|
int ret; |
|
|
|
unsigned int idx = -1; |
|
|
|
unsigned int i; |
|
|
|
@ -4497,7 +4496,7 @@ static int play_stream(struct rtpengine_table *t, const struct rtpengine_play_st |
|
|
|
} |
|
|
|
|
|
|
|
play_stream->packets = packets; |
|
|
|
play_stream->position = list_first_entry(&packets->packets, struct play_stream_packet, list); |
|
|
|
play_stream->position = list_first_entry(&packets->packets, struct re_play_stream_packet, list); |
|
|
|
|
|
|
|
read_unlock(&packets->lock); |
|
|
|
|
|
|
|
@ -4556,7 +4555,7 @@ out: |
|
|
|
} |
|
|
|
|
|
|
|
// stream must be locked, reference must be held |
|
|
|
static void end_of_stream(struct play_stream *stream) { |
|
|
|
static void end_of_stream(struct re_play_stream *stream) { |
|
|
|
struct rtpengine_table *t; |
|
|
|
|
|
|
|
if (stream->table_id != -1 && !list_empty(&stream->table_entry)) { |
|
|
|
@ -4575,9 +4574,9 @@ static void end_of_stream(struct play_stream *stream) { |
|
|
|
} |
|
|
|
|
|
|
|
// stream lock is not held, reference must be held |
|
|
|
static void do_stop_stream(struct play_stream *stream) { |
|
|
|
struct timer_thread *tt; |
|
|
|
struct play_stream *old_stream; |
|
|
|
static void do_stop_stream(struct re_play_stream *stream) { |
|
|
|
struct re_timer_thread *tt; |
|
|
|
struct re_play_stream *old_stream; |
|
|
|
|
|
|
|
//printk(KERN_WARNING "stop stream %p\n", stream); |
|
|
|
|
|
|
|
@ -4615,7 +4614,7 @@ static void do_stop_stream(struct play_stream *stream) { |
|
|
|
} |
|
|
|
|
|
|
|
static int stop_stream(struct rtpengine_table *t, unsigned int num) { |
|
|
|
struct play_stream *stream; |
|
|
|
struct re_play_stream *stream; |
|
|
|
int ret; |
|
|
|
|
|
|
|
ret = 0; |
|
|
|
@ -4655,7 +4654,7 @@ static int stop_stream(struct rtpengine_table *t, unsigned int num) { |
|
|
|
} |
|
|
|
|
|
|
|
static int cmd_free_packet_stream(struct rtpengine_table *t, unsigned int idx) { |
|
|
|
struct play_stream_packets *stream = NULL; |
|
|
|
struct re_play_stream_packets *stream = NULL; |
|
|
|
int ret; |
|
|
|
|
|
|
|
write_lock(&media_player_lock); |
|
|
|
|