mirror of
https://github.com/jndean/IPUDOOM.git
synced 2026-04-22 14:41:23 +00:00
Implement frame streaming-> and event streaming<- over UDP
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "d_event.h"
|
||||
|
||||
#define MAXEVENTS 64
|
||||
|
||||
@@ -100,4 +100,7 @@ void I_GetWindowPosition(int *x, int *y, int w, int h);
|
||||
// Joystic/gamepad hysteresis
|
||||
extern unsigned int joywait;
|
||||
|
||||
// JOSEF
|
||||
void I_GetEvent(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "d_event.h"
|
||||
@@ -17,9 +18,10 @@ static int sockfd;
|
||||
static struct sockaddr_in servaddr;
|
||||
static unsigned int serveraddr_len;
|
||||
|
||||
void connect_to_server() {
|
||||
|
||||
void connect_to_server(void) {
|
||||
// Creating socket file descriptor
|
||||
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
|
||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
|
||||
perror("socket creation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -32,20 +34,16 @@ void connect_to_server() {
|
||||
|
||||
HelloMsg msg;
|
||||
msg.type = MSGT_HELLO;
|
||||
sendto(
|
||||
sockfd,
|
||||
(const char *)(&msg), sizeof(msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &servaddr, sizeof(servaddr)
|
||||
);
|
||||
sendto(sockfd,
|
||||
(const char *)(&msg), sizeof(msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &servaddr, sizeof(servaddr));
|
||||
|
||||
LargestMsgType rcv[1];
|
||||
recvfrom(
|
||||
sockfd,
|
||||
(char *)(rcv), sizeof(rcv),
|
||||
MSG_WAITALL,
|
||||
(struct sockaddr *) &servaddr, &serveraddr_len
|
||||
);
|
||||
recvfrom(sockfd,
|
||||
(char *)(rcv), sizeof(rcv),
|
||||
MSG_WAITALL,
|
||||
(struct sockaddr *) &servaddr, &serveraddr_len);
|
||||
if (rcv->type == MSGT_HELLO) {
|
||||
printf("Server says hello\n");
|
||||
} else {
|
||||
@@ -56,7 +54,9 @@ void connect_to_server() {
|
||||
}
|
||||
|
||||
|
||||
void send_events() {
|
||||
void send_events(void) {
|
||||
I_GetEvent();
|
||||
|
||||
EventMsg msg;
|
||||
msg.type = MSGT_EVENT;
|
||||
msg.count = 0;
|
||||
@@ -68,7 +68,7 @@ void send_events() {
|
||||
((event_t*) msg.events)[msg.count] = *ev;
|
||||
} else if (msg.count == 255) {
|
||||
printf("\nmsg.count was about to overflow! Too many events?\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
printf("WARNING: exceeding %d events per frame, dropping some key presses\n",
|
||||
STREAMEVENTSPERMESSAGE);
|
||||
@@ -78,28 +78,53 @@ void send_events() {
|
||||
|
||||
// Send the packet
|
||||
if (msg.count > 0) {
|
||||
sendto(
|
||||
sockfd,
|
||||
(const char *)(&msg), sizeof(msg),
|
||||
0,
|
||||
(const struct sockaddr *) &servaddr, sizeof(servaddr)
|
||||
);
|
||||
sendto(sockfd,
|
||||
(const char *)(&msg), sizeof(msg),
|
||||
0,
|
||||
(const struct sockaddr *) &servaddr, sizeof(servaddr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void recv_loop() {
|
||||
void ping(void) {
|
||||
const int frequency = 64;
|
||||
static int call_count = 0;
|
||||
|
||||
call_count = (call_count + 1) % frequency;
|
||||
if (call_count) return;
|
||||
|
||||
PingMsg msg;
|
||||
msg.type = MSGT_PING;
|
||||
gettimeofday(&msg.sent_time, NULL);
|
||||
sendto(sockfd,
|
||||
(const char *)(&msg), sizeof(msg),
|
||||
0,
|
||||
(const struct sockaddr *) &servaddr, sizeof(servaddr)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void flush_incoming(void) {
|
||||
while (1) {
|
||||
LargestMsgType rcv[1];
|
||||
ssize_t n = recvfrom(sockfd,
|
||||
(char *)rcv, sizeof(rcv),
|
||||
MSG_DONTWAIT,
|
||||
NULL, NULL);
|
||||
if (n == -1) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void recv_loop(void) {
|
||||
unsigned char last_scanline = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
LargestMsgType rcv[1];
|
||||
ssize_t n = recvfrom(
|
||||
sockfd,
|
||||
(char *)rcv, sizeof(rcv),
|
||||
MSG_DONTWAIT,
|
||||
(struct sockaddr *) &servaddr, &serveraddr_len
|
||||
);
|
||||
ssize_t n = recvfrom(sockfd,
|
||||
(char *)rcv, sizeof(rcv),
|
||||
MSG_DONTWAIT,
|
||||
(struct sockaddr *) &servaddr, &serveraddr_len);
|
||||
|
||||
if (n == -1) {
|
||||
struct timespec ts;
|
||||
@@ -107,26 +132,43 @@ void recv_loop() {
|
||||
ts.tv_nsec = 1000;
|
||||
if(nanosleep(&ts, &ts)) {
|
||||
printf("Nanosleep failed\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (rcv->type) {
|
||||
case MSGT_SCANLINE:;
|
||||
case MSGT_SCANLINE: {
|
||||
ScanlineMsg *msg = (ScanlineMsg*) rcv;
|
||||
memcpy(&I_VideoBuffer[msg->idx*STREAMWIDTH], msg->data, STREAMSCANSIZE);
|
||||
if (msg->idx > 190) {
|
||||
printf(">%d ", msg->idx);
|
||||
}
|
||||
if (msg->idx < last_scanline) {
|
||||
if (msg->idx < last_scanline - 100) {
|
||||
send_events();
|
||||
ping();
|
||||
I_FinishUpdate();
|
||||
|
||||
/*static int tmp_count = 0;
|
||||
if (tmp_count++ == 128) {
|
||||
printf("----FLUSH!----\n");
|
||||
tmp_count = 0;
|
||||
flush_incoming();
|
||||
}*/
|
||||
}
|
||||
last_scanline = msg->idx;
|
||||
break;
|
||||
}
|
||||
|
||||
case MSGT_PING: {
|
||||
PingMsg *msg = (PingMsg*) rcv;
|
||||
struct timeval T;
|
||||
gettimeofday(&T, NULL);
|
||||
double delta = (T.tv_usec - msg->sent_time.tv_usec) / 1000.;
|
||||
delta += (T.tv_sec - msg->sent_time.tv_sec) * 1000.;
|
||||
printf("PING: %.1lf\n", delta);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
perror("Received unknown msg type\n");
|
||||
printf("Received unknown msg type %d\n", (int)rcv->type);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#ifndef __COMMON_STREAMING__
|
||||
#define __COMMON_STREAMING__
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
#define STREAMPORT (6666)
|
||||
#define STREAMWIDTH (320)
|
||||
#define STREAMLINESPERMESSAGE (1)
|
||||
#define STREAMEVENTSPERMESSAGE (5)
|
||||
|
||||
#define STREAMSCANSIZE (STREAMLINESPERMESSAGE * STREAMWIDTH)
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned char type;
|
||||
} HelloMsg;
|
||||
@@ -25,11 +27,18 @@ typedef struct {
|
||||
unsigned char events[20 * STREAMEVENTSPERMESSAGE];
|
||||
} EventMsg;
|
||||
|
||||
typedef struct {
|
||||
unsigned char type;
|
||||
struct timeval sent_time;
|
||||
} PingMsg;
|
||||
|
||||
typedef ScanlineMsg LargestMsgType;
|
||||
|
||||
|
||||
#define MSGT_HELLO (0)
|
||||
#define MSGT_SCANLINE (1)
|
||||
#define MSGT_EVENT (2)
|
||||
#define MSGT_PING (3)
|
||||
|
||||
|
||||
#endif // __COMMON_STREAMING__
|
||||
@@ -790,15 +790,8 @@ void I_FinishUpdate (void)
|
||||
}
|
||||
|
||||
// JOSEF: Streaming
|
||||
const int stride = 1;
|
||||
static int offset = 0;
|
||||
for (int i = offset; i < SCREENHEIGHT; i += STREAMLINESPERMESSAGE * stride) {
|
||||
if (i > 190) {
|
||||
printf(">%d ", i);
|
||||
}
|
||||
send_scanline(I_VideoBuffer, i);
|
||||
}
|
||||
offset = (offset + 1) % stride;
|
||||
stream_send_receive(I_VideoBuffer);
|
||||
|
||||
|
||||
if (palette_to_set)
|
||||
{
|
||||
|
||||
101
src/streaming.c
101
src/streaming.c
@@ -7,6 +7,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "d_event.h"
|
||||
#include "i_video.h"
|
||||
#include "streaming.h"
|
||||
|
||||
|
||||
@@ -16,13 +18,13 @@ static unsigned int clientaddr_len;
|
||||
|
||||
|
||||
// Driver code
|
||||
void wait_for_client_connect() {
|
||||
void wait_for_client_connect(void) {
|
||||
|
||||
LargestMsgType rcv[1];
|
||||
struct sockaddr_in servaddr;
|
||||
|
||||
// Creating socket file descriptor
|
||||
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
|
||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
|
||||
perror("socket creation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -43,12 +45,10 @@ void wait_for_client_connect() {
|
||||
}
|
||||
|
||||
clientaddr_len = sizeof(cliaddr);
|
||||
recvfrom(
|
||||
sockfd,
|
||||
(char *)(rcv), sizeof(rcv),
|
||||
MSG_WAITALL,
|
||||
(struct sockaddr *) &cliaddr, &clientaddr_len
|
||||
);
|
||||
recvfrom(sockfd,
|
||||
(char *)(rcv), sizeof(rcv),
|
||||
MSG_WAITALL,
|
||||
(struct sockaddr *) &cliaddr, &clientaddr_len);
|
||||
if (rcv->type != MSGT_HELLO) {
|
||||
perror("Client said something other than hello?");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -57,12 +57,10 @@ void wait_for_client_connect() {
|
||||
|
||||
HelloMsg msg;
|
||||
msg.type = MSGT_HELLO;
|
||||
sendto(
|
||||
sockfd,
|
||||
(char *)(&msg), sizeof(msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &cliaddr, clientaddr_len
|
||||
);
|
||||
sendto(sockfd,
|
||||
(char *)(&msg), sizeof(msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &cliaddr, clientaddr_len);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -73,15 +71,78 @@ void send_scanline(unsigned char *data, unsigned char linenum) {
|
||||
msg.type = MSGT_SCANLINE;
|
||||
msg.idx = linenum;
|
||||
memcpy(msg.data, &data[linenum * STREAMWIDTH], STREAMSCANSIZE);
|
||||
ssize_t sent = sendto(
|
||||
sockfd,
|
||||
(char *)(&msg), sizeof(msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &cliaddr, clientaddr_len
|
||||
);
|
||||
ssize_t sent = sendto(sockfd,
|
||||
(char *)(&msg), sizeof(msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &cliaddr, clientaddr_len);
|
||||
if (sent == -1) {
|
||||
perror("Failed to send scanline");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void recv_events(void) {
|
||||
while (1) {
|
||||
LargestMsgType rcv[1];
|
||||
ssize_t n = recvfrom(sockfd,
|
||||
(char *)rcv, sizeof(rcv),
|
||||
MSG_DONTWAIT,
|
||||
(struct sockaddr *) &cliaddr, &clientaddr_len);
|
||||
if (n == -1) break;
|
||||
|
||||
if (rcv->type != MSGT_EVENT) {
|
||||
printf("Expected to receive MSGT_EVENT(%d), but got %d\n", MSGT_EVENT, rcv->type);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
EventMsg *msg = (EventMsg*) rcv;
|
||||
for (int i = 0; i < msg->count; ++i) {
|
||||
D_PostEvent(&((event_t*)msg->events)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stream_send_receive(unsigned char *data) {
|
||||
const int stride = 1; // Controls interlacing, 1 = no-interlacing
|
||||
static int offset = 0;
|
||||
for (int i = offset; i < SCREENHEIGHT; i += STREAMLINESPERMESSAGE * stride) {
|
||||
send_scanline(data, i);
|
||||
}
|
||||
offset = (offset + 1) % stride;
|
||||
|
||||
while (1) {
|
||||
LargestMsgType rcv[1];
|
||||
ssize_t n = recvfrom(sockfd,
|
||||
(char *)rcv, sizeof(rcv),
|
||||
MSG_DONTWAIT,
|
||||
(struct sockaddr *) &cliaddr, &clientaddr_len);
|
||||
if (n == -1) break;
|
||||
|
||||
switch(rcv->type) {
|
||||
case MSGT_EVENT: {
|
||||
EventMsg *msg = (EventMsg*) rcv;
|
||||
for (int i = 0; i < msg->count; ++i) {
|
||||
D_PostEvent(&((event_t*)msg->events)[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSGT_PING: {
|
||||
PingMsg *msg = (PingMsg*) rcv;
|
||||
sendto(sockfd,
|
||||
(char *)(msg), sizeof(*msg),
|
||||
MSG_CONFIRM,
|
||||
(const struct sockaddr *) &cliaddr, clientaddr_len);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("Unexpected message type %d\n", (int) rcv->type);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../common/streaming.h"
|
||||
|
||||
void wait_for_client_connect();
|
||||
void stream_send_receive(unsigned char *data);
|
||||
void send_scanline(unsigned char *data, unsigned char linenum);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user