Files
libucore/test/ortp-send-simple.c
T
2014-09-11 21:55:57 +02:00

147 lines
3.5 KiB
C

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <ortp/ortp.h>
#include "ucore/iomux.h"
#include "ucore/utils.h"
#include "ucore/string.h"
struct IOMux *mux;
#define errx(x, ...) do { fprintf(stderr, x, __VA_ARGS__); exit(1); } while(0)
struct RTPSender {
FILE *file;
char remote_ip[48];
uint16_t remote_port;
struct UCTimer timer;
uint32_t ts;
struct timespec last_ts;
RtpSession *rtp_sess;
RtpProfile *rtp_profile;
int accum_diff;
uint8_t frame[160];
};
//returns microsec
int diffts(const struct timespec *a, struct timespec *b)
{
struct timespec diff;
diff.tv_sec = b->tv_sec - a->tv_sec;
diff.tv_nsec = b->tv_nsec - a->tv_nsec;
if (diff.tv_nsec < 0) {
diff.tv_sec--;
diff.tv_nsec += 1000000000;
}
return (int) (diff.tv_sec * 1000 + (diff.tv_nsec + 500)/1000);
}
void timer_cb(struct UCTimers *timers, struct UCTimer *timer)
{
struct RTPSender *s = UC_CONTAINER_OF(timer, struct RTPSender, timer);
int rc;
ssize_t r;
struct timespec ts;
int diff;
int adjust;
clock_gettime(CLOCK_MONOTONIC, &ts);
rc = rtp_session_send_with_ts(s->rtp_sess,s->frame, sizeof s->frame, s->ts);
if(rc < sizeof s->frame) {
printf("Error, short send of %d bytes\n", rc);
}
s->ts += 160;
r = fread(s->frame,1, sizeof s->frame, s->file);
if (r <= 0) {
rtp_session_bye(s->rtp_sess, "Finished");
return;
}
diff = diffts(&s->last_ts, &ts);
diff -= 20000;
s->accum_diff += diff;
if (s->accum_diff > 500)
adjust = -1000;
else if (s->accum_diff < -500)
adjust = 1000;
else
adjust = s->accum_diff;
if (s->accum_diff >= 20000 || s->accum_diff <= -20000) {
s->ts += 160;
printf("Skew ! accum_diff %d\n", s->accum_diff);
s->accum_diff -= 20000;
}
uc_timers_add(iomux_get_timers(mux), &s->timer, 0, 20 * 1000 + adjust);
s->last_ts = ts;
}
void init_sender(FILE* file, const char *remote_ip, uint16_t remote_port)
{
struct RTPSender *s = calloc(1, sizeof *s);
RtpSession *rtp_sess = rtp_session_new(RTP_SESSION_SENDONLY);
RtpProfile *rtp_prof = rtp_profile_new("pcmu8000");
rtp_profile_set_payload(rtp_prof, 0, &payload_type_pcmu8000);
rtp_session_set_profile(rtp_sess, rtp_prof);
//rtp_session_set_local_addr("192.168.1.55", 0);
rtp_session_set_remote_addr(rtp_sess, remote_ip, remote_port);
rtp_session_set_blocking_mode(rtp_sess, FALSE);
s->file = file;
strcpy(s->remote_ip, remote_ip);
s->remote_port = remote_port;
s->rtp_sess = rtp_sess;
s->rtp_profile = rtp_prof;
s->timer.callback = timer_cb;
clock_gettime(CLOCK_MONOTONIC, &s->last_ts);
uc_timers_add(iomux_get_timers(mux), &s->timer, 0, 20000);
}
int main(int argc, char *argv[])
{
mux = iomux_create(IOMUX_TYPE_DEFAULT);
FILE *file;
if(argc != 4) {
puts("Specify a file name, remote IP and remote port");
return 1;
}
if(strcmp(argv[1], "-") == 0) {
file = stdin;
} else {
file = fopen(argv[1], "rb");
if(file == NULL) {
perror("Cannot open file");
return 1;
}
}
ortp_init();
ortp_set_log_level_mask(ORTP_DEBUG| ORTP_MESSAGE| ORTP_WARNING| ORTP_ERROR|ORTP_FATAL);
init_sender(file ,argv[2], atoi(argv[3]));
iomux_run(mux);
fclose(file);
ortp_exit();
return 0;
}
//compile:
// gcc -Wall -g -O `pkg-config --cflags --libs ortp` ortp-send-simple.c