mirror of
https://github.com/libretro/RetroArch
synced 2025-04-11 00:44:20 +00:00
Support different forms of compression from different clients.
This commit is contained in:
parent
84c33634a6
commit
677ffa9ebd
@ -610,6 +610,59 @@ void netplay_post_frame(netplay_t *netplay)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* netplay_send_savestate
|
||||||
|
* @netplay : pointer to netplay object
|
||||||
|
* @serial_info : the savestate being loaded
|
||||||
|
* @cx : compression type
|
||||||
|
* @z : compression backend to use
|
||||||
|
*
|
||||||
|
* Send a loaded savestate to those connected peers using the given compression
|
||||||
|
* scheme.
|
||||||
|
*/
|
||||||
|
void netplay_send_savestate(netplay_t *netplay,
|
||||||
|
retro_ctx_serialize_info_t *serial_info, uint32_t cx,
|
||||||
|
struct compression_transcoder *z)
|
||||||
|
{
|
||||||
|
uint32_t header[4];
|
||||||
|
uint32_t rd, wn;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* Compress it */
|
||||||
|
z->compression_backend->set_in(z->compression_stream,
|
||||||
|
(const uint8_t*)serial_info->data_const, serial_info->size);
|
||||||
|
z->compression_backend->set_out(z->compression_stream,
|
||||||
|
netplay->zbuffer, netplay->zbuffer_size);
|
||||||
|
if (!z->compression_backend->trans(z->compression_stream, true, &rd,
|
||||||
|
&wn, NULL))
|
||||||
|
{
|
||||||
|
/* Catastrophe! */
|
||||||
|
for (i = 0; i < netplay->connections_size; i++)
|
||||||
|
netplay_hangup(netplay, &netplay->connections[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send it to relevant peers */
|
||||||
|
header[0] = htonl(NETPLAY_CMD_LOAD_SAVESTATE);
|
||||||
|
header[1] = htonl(wn + 2*sizeof(uint32_t));
|
||||||
|
header[2] = htonl(netplay->self_frame_count);
|
||||||
|
header[3] = htonl(serial_info->size);
|
||||||
|
|
||||||
|
for (i = 0; i < netplay->connections_size; i++)
|
||||||
|
{
|
||||||
|
struct netplay_connection *connection = &netplay->connections[i];
|
||||||
|
if (!connection->active ||
|
||||||
|
connection->mode < NETPLAY_CONNECTION_CONNECTED ||
|
||||||
|
connection->compression_supported != cx) continue;
|
||||||
|
|
||||||
|
if (!netplay_send(&connection->send_packet_buffer, connection->fd, header,
|
||||||
|
sizeof(header)) ||
|
||||||
|
!netplay_send(&connection->send_packet_buffer, connection->fd,
|
||||||
|
netplay->zbuffer, wn))
|
||||||
|
netplay_hangup(netplay, connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* netplay_load_savestate
|
* netplay_load_savestate
|
||||||
* @netplay : pointer to netplay object
|
* @netplay : pointer to netplay object
|
||||||
@ -623,10 +676,7 @@ void netplay_post_frame(netplay_t *netplay)
|
|||||||
void netplay_load_savestate(netplay_t *netplay,
|
void netplay_load_savestate(netplay_t *netplay,
|
||||||
retro_ctx_serialize_info_t *serial_info, bool save)
|
retro_ctx_serialize_info_t *serial_info, bool save)
|
||||||
{
|
{
|
||||||
uint32_t header[4];
|
|
||||||
retro_ctx_serialize_info_t tmp_serial_info;
|
retro_ctx_serialize_info_t tmp_serial_info;
|
||||||
uint32_t rd, wn;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/* Record it in our own buffer */
|
/* Record it in our own buffer */
|
||||||
if (save || !serial_info)
|
if (save || !serial_info)
|
||||||
@ -693,39 +743,12 @@ void netplay_load_savestate(netplay_t *netplay,
|
|||||||
| NETPLAY_QUIRK_NO_TRANSMISSION))
|
| NETPLAY_QUIRK_NO_TRANSMISSION))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Compress it */
|
/* Send this to every peer */
|
||||||
if (!netplay->compression_backend)
|
if (netplay->compress_nil.compression_backend)
|
||||||
return;
|
netplay_send_savestate(netplay, serial_info, 0, &netplay->compress_nil);
|
||||||
netplay->compression_backend->set_in(netplay->compression_stream,
|
if (netplay->compress_zlib.compression_backend)
|
||||||
(const uint8_t*)serial_info->data_const, serial_info->size);
|
netplay_send_savestate(netplay, serial_info, NETPLAY_COMPRESSION_ZLIB,
|
||||||
netplay->compression_backend->set_out(netplay->compression_stream,
|
&netplay->compress_zlib);
|
||||||
netplay->zbuffer, netplay->zbuffer_size);
|
|
||||||
if (!netplay->compression_backend->trans(netplay->compression_stream,
|
|
||||||
true, &rd, &wn, NULL))
|
|
||||||
{
|
|
||||||
/* Catastrophe! */
|
|
||||||
for (i = 0; i < netplay->connections_size; i++)
|
|
||||||
netplay_hangup(netplay, &netplay->connections[i]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And send it to the peers */
|
|
||||||
header[0] = htonl(NETPLAY_CMD_LOAD_SAVESTATE);
|
|
||||||
header[1] = htonl(wn + 2*sizeof(uint32_t));
|
|
||||||
header[2] = htonl(netplay->self_frame_count);
|
|
||||||
header[3] = htonl(serial_info->size);
|
|
||||||
|
|
||||||
for (i = 0; i < netplay->connections_size; i++)
|
|
||||||
{
|
|
||||||
struct netplay_connection *connection = &netplay->connections[i];
|
|
||||||
if (!connection->active || connection->mode < NETPLAY_CONNECTION_CONNECTED) continue;
|
|
||||||
|
|
||||||
if (!netplay_send(&connection->send_packet_buffer, connection->fd, header,
|
|
||||||
sizeof(header)) ||
|
|
||||||
!netplay_send(&connection->send_packet_buffer, connection->fd,
|
|
||||||
netplay->zbuffer, wn))
|
|
||||||
netplay_hangup(netplay, connection);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,6 +301,7 @@ bool netplay_handshake_init(netplay_t *netplay,
|
|||||||
struct nick_buf_s nick_buf;
|
struct nick_buf_s nick_buf;
|
||||||
uint32_t local_pmagic, remote_pmagic;
|
uint32_t local_pmagic, remote_pmagic;
|
||||||
uint32_t compression;
|
uint32_t compression;
|
||||||
|
struct compression_transcoder *ctrans;
|
||||||
|
|
||||||
dmsg = NULL;
|
dmsg = NULL;
|
||||||
|
|
||||||
@ -334,31 +335,41 @@ bool netplay_handshake_init(netplay_t *netplay,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear any existing compression */
|
|
||||||
if (netplay->compression_stream)
|
|
||||||
netplay->compression_backend->stream_free(netplay->compression_stream);
|
|
||||||
if (netplay->decompression_stream)
|
|
||||||
netplay->decompression_backend->stream_free(netplay->decompression_stream);
|
|
||||||
|
|
||||||
/* Check what compression is supported */
|
/* Check what compression is supported */
|
||||||
compression = ntohl(header[2]);
|
compression = ntohl(header[2]);
|
||||||
compression &= NETPLAY_COMPRESSION_SUPPORTED;
|
compression &= NETPLAY_COMPRESSION_SUPPORTED;
|
||||||
if (compression & NETPLAY_COMPRESSION_ZLIB)
|
if (compression & NETPLAY_COMPRESSION_ZLIB)
|
||||||
{
|
{
|
||||||
netplay->compression_backend = trans_stream_get_zlib_deflate_backend();
|
ctrans = &netplay->compress_zlib;
|
||||||
if (!netplay->compression_backend)
|
if (!ctrans->compression_backend)
|
||||||
netplay->compression_backend = trans_stream_get_pipe_backend();
|
{
|
||||||
|
ctrans->compression_backend =
|
||||||
|
trans_stream_get_zlib_deflate_backend();
|
||||||
|
if (!ctrans->compression_backend)
|
||||||
|
ctrans->compression_backend = trans_stream_get_pipe_backend();
|
||||||
|
}
|
||||||
|
connection->compression_supported = NETPLAY_COMPRESSION_ZLIB;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
netplay->compression_backend = trans_stream_get_pipe_backend();
|
ctrans = &netplay->compress_nil;
|
||||||
|
if (!ctrans->compression_backend)
|
||||||
|
{
|
||||||
|
ctrans->compression_backend =
|
||||||
|
trans_stream_get_pipe_backend();
|
||||||
|
}
|
||||||
|
connection->compression_supported = 0;
|
||||||
}
|
}
|
||||||
netplay->decompression_backend = netplay->compression_backend->reverse;
|
if (!ctrans->decompression_backend)
|
||||||
|
ctrans->decompression_backend = ctrans->compression_backend->reverse;
|
||||||
|
|
||||||
/* Allocate our compression stream */
|
/* Allocate our compression stream */
|
||||||
netplay->compression_stream = netplay->compression_backend->stream_new();
|
if (!ctrans->compression_stream)
|
||||||
netplay->decompression_stream = netplay->decompression_backend->stream_new();
|
{
|
||||||
if (!netplay->compression_stream || !netplay->decompression_stream)
|
ctrans->compression_stream = ctrans->compression_backend->stream_new();
|
||||||
|
ctrans->decompression_stream = ctrans->decompression_backend->stream_new();
|
||||||
|
}
|
||||||
|
if (!ctrans->compression_stream || !ctrans->decompression_stream)
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to allocate compression transcoder!\n");
|
RARCH_ERR("Failed to allocate compression transcoder!\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -540,8 +540,16 @@ void netplay_free(netplay_t *netplay)
|
|||||||
if (netplay->zbuffer)
|
if (netplay->zbuffer)
|
||||||
free(netplay->zbuffer);
|
free(netplay->zbuffer);
|
||||||
|
|
||||||
if (netplay->compression_stream)
|
if (netplay->compress_nil.compression_stream)
|
||||||
netplay->compression_backend->stream_free(netplay->compression_stream);
|
{
|
||||||
|
netplay->compress_nil.compression_backend->stream_free(netplay->compress_nil.compression_stream);
|
||||||
|
netplay->compress_nil.decompression_backend->stream_free(netplay->compress_nil.decompression_stream);
|
||||||
|
}
|
||||||
|
if (netplay->compress_zlib.compression_stream)
|
||||||
|
{
|
||||||
|
netplay->compress_zlib.compression_backend->stream_free(netplay->compress_zlib.compression_stream);
|
||||||
|
netplay->compress_zlib.decompression_backend->stream_free(netplay->compress_zlib.decompression_stream);
|
||||||
|
}
|
||||||
|
|
||||||
if (netplay->addr)
|
if (netplay->addr)
|
||||||
freeaddrinfo_retro(netplay->addr);
|
freeaddrinfo_retro(netplay->addr);
|
||||||
|
@ -1013,6 +1013,7 @@ static bool netplay_get_cmd(netplay_t *netplay,
|
|||||||
uint32_t isize;
|
uint32_t isize;
|
||||||
uint32_t rd, wn;
|
uint32_t rd, wn;
|
||||||
uint32_t player;
|
uint32_t player;
|
||||||
|
struct compression_transcoder *ctrans;
|
||||||
|
|
||||||
/* Make sure we're ready for it */
|
/* Make sure we're ready for it */
|
||||||
if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
|
if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
|
||||||
@ -1101,12 +1102,20 @@ static bool netplay_get_cmd(netplay_t *netplay,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* And decompress it */
|
/* And decompress it */
|
||||||
netplay->decompression_backend->set_in(netplay->decompression_stream,
|
switch (connection->compression_supported)
|
||||||
|
{
|
||||||
|
case NETPLAY_COMPRESSION_ZLIB:
|
||||||
|
ctrans = &netplay->compress_zlib;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ctrans = &netplay->compress_nil;
|
||||||
|
}
|
||||||
|
ctrans->decompression_backend->set_in(ctrans->decompression_stream,
|
||||||
netplay->zbuffer, cmd_size - 2*sizeof(uint32_t));
|
netplay->zbuffer, cmd_size - 2*sizeof(uint32_t));
|
||||||
netplay->decompression_backend->set_out(netplay->decompression_stream,
|
ctrans->decompression_backend->set_out(ctrans->decompression_stream,
|
||||||
(uint8_t*)netplay->buffer[netplay->read_ptr[connection->player]].state,
|
(uint8_t*)netplay->buffer[netplay->read_ptr[connection->player]].state,
|
||||||
netplay->state_size);
|
netplay->state_size);
|
||||||
netplay->decompression_backend->trans(netplay->decompression_stream,
|
ctrans->decompression_backend->trans(ctrans->decompression_stream,
|
||||||
true, &rd, &wn, NULL);
|
true, &rd, &wn, NULL);
|
||||||
|
|
||||||
/* Skip ahead if it's past where we are */
|
/* Skip ahead if it's past where we are */
|
||||||
|
@ -274,6 +274,9 @@ struct netplay_connection
|
|||||||
/* Player # of connected player */
|
/* Player # of connected player */
|
||||||
int player;
|
int player;
|
||||||
|
|
||||||
|
/* What compression does this peer support? */
|
||||||
|
uint32_t compression_supported;
|
||||||
|
|
||||||
/* Is this player paused? */
|
/* Is this player paused? */
|
||||||
bool paused;
|
bool paused;
|
||||||
|
|
||||||
@ -282,6 +285,15 @@ struct netplay_connection
|
|||||||
retro_time_t stall_time;
|
retro_time_t stall_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Compression transcoder */
|
||||||
|
struct compression_transcoder
|
||||||
|
{
|
||||||
|
const struct trans_stream_backend *compression_backend;
|
||||||
|
void *compression_stream;
|
||||||
|
const struct trans_stream_backend *decompression_backend;
|
||||||
|
void *decompression_stream;
|
||||||
|
};
|
||||||
|
|
||||||
struct netplay
|
struct netplay
|
||||||
{
|
{
|
||||||
/* Are we the server? */
|
/* Are we the server? */
|
||||||
@ -330,10 +342,8 @@ struct netplay
|
|||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
|
|
||||||
/* Compression transcoder */
|
/* Compression transcoder */
|
||||||
const struct trans_stream_backend *compression_backend;
|
struct compression_transcoder compress_nil,
|
||||||
void *compression_stream;
|
compress_zlib;
|
||||||
const struct trans_stream_backend *decompression_backend;
|
|
||||||
void *decompression_stream;
|
|
||||||
|
|
||||||
/* A buffer into which to compress frames for transfer */
|
/* A buffer into which to compress frames for transfer */
|
||||||
uint8_t *zbuffer;
|
uint8_t *zbuffer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user