Re: vic information

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



> > Somewhere I still have a command line utility which sends out H.263
> > files (written by the tmn encoder) as RTP streams, which I've used for
> > testing purposes.
>  
>  	If you can find it will help me a lot :)

Found it.  Five years old, and the @cs address doesn't work any more
these days ...

  Gerd

==============================[ rtp.h ]==============================
#define RTCP_TYPE_SR     200
#define RTCP_TYPE_RR     201
#define RTCP_TYPE_SDES   202
#define RTCP_TYPE_BYE    203
#define RTCP_TYPE_APP    204

#define RCTP_F_V_MASK    0xc0
#define RCTP_F_P_MASK    0x20
#define RCTP_F_C_MASK    0x1f

struct RTCP {
    unsigned char   flags;

    unsigned char   pt;           /* packet type         */
    unsigned short  length;
    unsigned long   ssrc;
};

/* --------------------------------------------------------------------- */

#define RTP_F_V_MASK     0xc0
#define RTP_F_P_MASK     0x20
#define RTP_F_X_MASK     0x10
#define RTP_F_C_MASK     0x0f

#define RTP_PT_M_MASK    0x80
#define RTP_PT_PT_MASK   0x7f

struct RTP {
    unsigned char   flags;

    unsigned char   pt;           /* packet type + M-bit */

    unsigned short  seq;
    unsigned long   timestamp;
    unsigned long   ssrc;
    unsigned long   payload[0];
};
==============================[ send-h263.c ]========================
/*
 * (c) 1997 Gerd Knorr <kraxel@xxxxxxxxxxxxxxx>
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/utsname.h>

#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "rtp.h"

extern char *optarg;

#define MAX_PACKET_SIZE  16384

/* ---------------------------------------------------------------------- */

char    *name         = "send-h263 1.0";

int     verbose            = 0;
int     my_port            = 4711;
char    my_addr[128]       = "*";
int     dest_port          = 4711;
char    dest_addr[128]     = "224.0.0.42";
char    *filename          = NULL;

/* size of outgoing pakets */
int     send_psize         = 1400;

/* statistics */
int     paket_count        = 0;
int     octet_count        = 0;

/* ---------------------------------------------------------------------- */

int stop = 0;

void
catch_signal(int sig)
{
    if (SIGINT == sig)
	fprintf(stderr,"^C - one moment please...\n");
    stop = 1;
}

/* ---------------------------------------------------------------------- */

void
usage(char *prog)
{
    char *h;

    h = strrchr(prog,'/');
    fprintf(stderr,
	    "usage: %s [ options ]\n"
	    "\n"
	    "Options:\n"
	    "  -h          print this text\n"
	    "  -f file     read H.263 bitstream from >file<\n"
	    "  -a ipaddr   send RTP pakets to >ipaddr<        [%s]\n"
	    "  -p port     sent RTP pakets to >port<          [%d]\n"
	    "  -s size     set max. packet size               [%d]\n"
	    "  -i ipaddr   bind locally to >ipaddr<           [%s]\n",
	    h ? h+1 : prog,
	    dest_addr,
	    send_psize,
	    dest_port,
	    my_addr);
    exit(1);
}

void
string_to_ipaddr(char *name, struct sockaddr_in *addr)
{
    struct hostent *host;

    /* "*" is any address (for bind) */
    if (0 == strcmp(name,"*")) {
	addr->sin_addr.s_addr = htonl (INADDR_ANY);
	return;
    }
    
    /* try to parse it it dotted number ... */
    if (-1 == (addr->sin_addr.s_addr = inet_addr(name))) {

	/* ... failing that do a DNS lookup */
	if (NULL == (host = gethostbyname(name))) {
	    fprintf(stderr,"can't resolve hostname %s\n",name);
	    exit(1);
	}
	addr->sin_addr = *(struct in_addr *) host->h_addr;
    }
}

void
dump_paket(unsigned char *data, int len)
{
    int x,y;

    for (y = 0; y < len; y += 16) {
	printf("\t");
	for (x = y; x < y+16; x++) {
	    if (x < len)
		printf("%02x ",data[x]);
	    else
		printf("   ");
	}
	printf(" ");
	for (x = y; x < y+16; x++) {
	    if (x < len)
		printf("%c", ((data[x] & 0x7f) < 32) ? '.' : data[x]);
	    else
		printf(" ");
	}
	printf("\n");
    }
}

/* ---------------------------------------------------------------------- */

static char *sdes[] = {
    "",
    "user@host",                        /* cname     */
    "Gerd Knorr",                       /* name      */
    "kraxel@xxxxxxxxxxxxxxx",           /* email     */
    "",                                 /* phone     */
    "",                                 /* location  */
    "",                                 /* tool      */
    "H263v2 RTP payload testing",       /* note      */
    "",                                 /* priv (?)  */
    NULL
};

static char *bye = "end of file";

int
build_rtcp(char *packet, int type, unsigned int ssrc, unsigned int timestamp)
{
    struct RTCP        *rtcp = (struct RTCP*) packet;
    unsigned int       *l    = (unsigned int*) packet;
    int                length,i,n;

    rtcp->flags  = 0x80;
    rtcp->pt     = type;
    rtcp->ssrc   = ssrc;
    switch (type) {
    case RTCP_TYPE_SR:
	l[2] = 0;	/* FIXME: ntp timestamp goes here */
	l[3] = 0;	/* ntp #2 */
	l[4] = timestamp;
	l[5] = paket_count;
	l[6] = octet_count;
	length = 4*7;	
	break;
    case RTCP_TYPE_SDES:
	rtcp->flags++;
	length = 8;
	for (i = 1; sdes[i] != NULL; i++) {
	    if (0 == (n = strlen(sdes[i])))
		continue;
	    packet[length]   = i;  /* type */
	    packet[length+1] = n;  /* length */
	    memcpy(packet+length+2,sdes[i],n);
	    length += n+2;
	}
	break;
    case RTCP_TYPE_BYE:
	rtcp->flags++;
	length = 8;
	n = strlen(bye);
	packet[length] = n;
	memcpy(packet+length+1,bye,n);
	length += n+1;
	break;
    default:
	length = 8;
	break;
    }

    length = (length+3)&0xfffc;
    rtcp->length = htons((length/4)-1);
    return length;
}

/* ---------------------------------------------------------------------- */

int
main(int argc, char *argv[])
{
    struct sockaddr_in  addr,dest;
    int                 c,i,n,ps,length;
    int                 s_rtp = -1,s_rtcp = -1;
    unsigned char      *packet,*buffer,*user;
    struct utsname      uts;
    struct hostent     *he;
    struct RTP         *rtp;
    FILE               *fp;
    unsigned int        tr,tr_last=-1,tr_wrap,tr_diff,tr_long;
    unsigned short      seq;
    unsigned int        timestamp,ssrc;
    struct timeval      start,now;
    int                 delay;

    /* build cname */
    user = getenv("USER");
    if (NULL == user)
	user = getenv("LOGNAME");
    uname(&uts);
    he = gethostbyname(uts.nodename);
    sdes[1] = malloc(256);
    sprintf(sdes[1],"%s@%s",user,inet_ntoa(*(struct in_addr *) he->h_addr));
    strcpy(my_addr,inet_ntoa(*(struct in_addr *) he->h_addr));
    sdes[6] = name;
    
    /* parse options */
    for (;;) {
	if (-1 == (c = getopt(argc, argv, "hf:s:a:p:i:")))
	    break;
	switch (c) {
	case 'f':
	    filename = strdup(optarg);
	    break;
	case 'i':
	    strcpy(my_addr,optarg);
	    break;
	case 'a':
	    strcpy(dest_addr,optarg);
	    break;
	case 'p':
	    dest_port = atoi(optarg);
	    break;
	case 's':
	    send_psize = atoi(optarg);
	    break;
	case 'h':
	default:
	    usage(argv[0]);
	    exit(1);
	}
    }

    /* h263 stream file */
    if (filename) {
	if (NULL == (fp = fopen(filename,"rb"))) {
	    perror(filename);
	    exit(1);
	}
    } else {
	fp = stdin;
	if (isatty(0)) {
	    usage(argv[0]);
	    exit(1);
	}
    }

    signal(SIGINT,catch_signal);
    signal(SIGHUP,catch_signal);
    signal(SIGTERM,catch_signal);
    
    /* network stuff */
    addr.sin_family = AF_INET;
    string_to_ipaddr(my_addr,&addr);
    dest.sin_family = AF_INET;
    dest.sin_port = htons (dest_port);
    string_to_ipaddr(dest_addr,&dest);

retry_bind:
    if (-1 == s_rtcp) close(s_rtcp);
    if (-1 == s_rtp)  close(s_rtp);
    my_port += 2;
    addr.sin_port = htons (my_port);

    /* rtcp socket */
    if (-1 == (s_rtcp = socket (PF_INET, SOCK_DGRAM, 0))) {
	perror("socket rtcp");
        exit(1);
    }
    if (-1 == bind(s_rtcp, (struct sockaddr*) &addr, sizeof(addr))) {
	if (errno == EADDRINUSE)
	    goto retry_bind;
	perror("bind rtcp");
        exit(1);
    }
    
    /* rtp socket */
    addr.sin_port = htons (my_port-1);
    if (-1 == (s_rtp = socket (PF_INET, SOCK_DGRAM, 0))) {
	perror("socket rtp");
        exit(1);
    }
    if (-1 == bind(s_rtp, (struct sockaddr*) &addr, sizeof(addr))) {
	if (errno == EADDRINUSE)
	    goto retry_bind;
	perror("bind rtp");
        exit(1);
    }

    packet = malloc(MAX_PACKET_SIZE);
    rtp = (struct RTP*)packet;

    srand(time(NULL));
    seq = rand();
    timestamp = rand();
    ssrc = rand();
    tr_last = 0;
    tr_wrap = 0;
    gettimeofday(&start,NULL);

    length  = build_rtcp(packet,       RTCP_TYPE_SR,  ssrc,timestamp);
    length += build_rtcp(packet+length,RTCP_TYPE_SDES,ssrc,timestamp);
    dest.sin_port = htons (dest_port);
    if (-1 == (sendto(s_rtcp,packet,length,0,
		      (struct sockaddr*)&dest,sizeof(dest)))) {
	perror("sendto");
	exit(1);
    }
    
    /* main loop */
    buffer = malloc(MAX_PACKET_SIZE);
    send_psize -= 14; /* RTP + Payload */
    i = 0;
    buffer[i++] = fgetc(fp);
    buffer[i++] = fgetc(fp);
    buffer[i++] = fgetc(fp);
    for (;!stop;) {
	for (;;) {
	    c = fgetc(fp);
	    if (c == EOF) {
		printf("eof ");
		i += 3;
		break;
	    }
	    buffer[i++] = c;
	    if (buffer[i-3] == 0 &&
		buffer[i-2] == 0 &&
		(buffer[i-1] & 0xfc) == 0x80) {
		printf("psc ");
		break;
	    }
	}
	fflush(stdout);
	/* fwrite(buffer,1,i-3,out); */

	/* send out frame -- one packet for now */
	tr = ((buffer[2] & 0x03) << 6) | ((buffer[3] & 0xfc) >> 2);
	if (tr < tr_last) {
	    tr_diff = tr+256-tr_last, tr_wrap++;

	    /* send one RTCP packet */
	    length  = build_rtcp(packet,       RTCP_TYPE_SR,  ssrc,timestamp);
	    length += build_rtcp(packet+length,RTCP_TYPE_SDES,ssrc,timestamp);
	    dest.sin_port = htons (dest_port);
	    if (-1 == (sendto(s_rtcp,packet,length,0,
			      (struct sockaddr*)&dest,sizeof(dest)))) {
		perror("sendto");
		exit(1);
	    }

	} else
	    tr_diff = tr-tr_last;
	tr_long = tr_wrap*256+tr;
	timestamp += tr_diff * 3000; /* tr is 30Hz, timestamp 90kHz */
	if (0 == tr_diff)
	    timestamp++;
	tr_last = tr;

	gettimeofday(&now,NULL);
	delay  = tr_long * 1000 / 30;
	delay -= (now.tv_sec - start.tv_sec)*1000;
	delay -= (now.tv_usec - start.tv_usec)/1000;
	if (delay > 0)
	    usleep(delay*1000);
	if (stop)
	    break;
	printf("tr=%3d/%4d, len=%4d ",tr,tr_long,i-3);
#if 0
	dump_paket(buffer,16);
#endif

	rtp->flags      = 0x80;
	rtp->pt         = 42 /* payload type */;
	rtp->timestamp  = htonl(timestamp);
	rtp->ssrc       = ssrc;
	dest.sin_port = htons (dest_port-1);

	for (n = 2; n < i-3; n += ps) {
	    rtp->payload[0] = 0;
	    if (2 == n)
		rtp->payload[0] |= htonl(0x04000000); /* set P bit */
	    ps = (i-3) - n;
	    if (ps > send_psize) {
		if (ps > send_psize + 64)
		    ps = send_psize;
		else
		    ps = send_psize-64;
	    } else
		rtp->pt |= 0x80; /* set M bit */
	    rtp->seq = htons(seq++);
	    memcpy(((char*)(&(rtp->payload[0])))+2,&buffer[n],ps);
	    if (-1 == (sendto(s_rtp,packet,ps+14,0,
			      (struct sockaddr*)&dest,sizeof(dest)))) {
		perror("sendto");
		exit(1);
	    }
	    printf("*");
	    paket_count++;
	    octet_count += ps+14;
	}
	printf("\n");

	if (c == EOF)
	    break;
	buffer[0] = buffer[i-3];
	buffer[1] = buffer[i-2];
	buffer[2] = buffer[i-1];
	i = 3;
    }
    fclose(fp);

    sleep(1);
    length  = build_rtcp(packet, RTCP_TYPE_BYE, ssrc,timestamp);
    dest.sin_port = htons (dest_port);
    if (-1 == (sendto(s_rtcp,packet,length,0,
		      (struct sockaddr*)&dest,sizeof(dest)))) {
	perror("sendto");
	exit(1);
    }

    /* keep compiler happy */
    return 0;
}





[Index of Archives]     [Linux DVB]     [Video Disk Recorder]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [Linux USB]

Powered by Linux