OSUOSL/Nero are experiencing Internet connectivity problems. This affects us as we're hosted with OSUOSL. We apologize for the inconvenience.

Commit 744b66c4 authored by Joseph Wallace's avatar Joseph Wallace

Make the state-machine nature of the EBML parser more evident.

parent 15e7fc6e
......@@ -39,6 +39,10 @@
#define EBML_HEADER_MAX_SIZE 131072
#define EBML_SLICE_SIZE 4096
typedef enum ebml_read_mode {
EBML_STATE_READING_HEADER = 0,
EBML_STATE_READING_CLUSTERS
} ebml_read_mode;
typedef struct ebml_client_data_st ebml_client_data_t;
......@@ -51,14 +55,15 @@ struct ebml_client_data_st {
struct ebml_st {
ebml_read_mode output_state;
char *cluster_id;
int cluster_start;
int position;
unsigned char *input_buffer;
unsigned char *buffer;
int header_read;
int header_size;
int header_position;
int header_read_position;
......@@ -302,6 +307,8 @@ static ebml_t *ebml_create()
ebml_t *ebml = calloc(1, sizeof(ebml_t));
ebml->output_state = EBML_STATE_READING_HEADER;
ebml->header = calloc(1, EBML_HEADER_MAX_SIZE);
ebml->buffer = calloc(1, EBML_SLICE_SIZE * 4);
ebml->input_buffer = calloc(1, EBML_SLICE_SIZE);
......@@ -322,35 +329,39 @@ static int ebml_read_space(ebml_t *ebml)
int read_space;
if (ebml->header_read == 1)
{
/* The header has previously been read */
if (ebml->cluster_start > 0) {
/* return up until just before a new cluster starts */
read_space = ebml->cluster_start;
} else {
/* return most of what we have, but leave enough unread
* to detect the next cluster.
*/
read_space = ebml->position - 4;
}
switch (ebml->output_state) {
case EBML_STATE_READING_HEADER:
if (ebml->header_size != 0) {
/* The header can be read */
return ebml->header_size;
} else {
/* The header's not ready yet */
return 0;
}
break;
case EBML_STATE_READING_CLUSTERS:
if (ebml->cluster_start > 0) {
/* return up until just before a new cluster starts */
read_space = ebml->cluster_start;
} else {
/* return most of what we have, but leave enough unread
* to detect the next cluster.
*/
read_space = ebml->position - 4;
}
return read_space;
}
else
{
if (ebml->header_size != 0) {
/* The header can be read */
return ebml->header_size;
} else {
/* The header's not ready yet */
return 0;
}
return read_space;
}
ICECAST_LOG_ERROR("EBML: Invalid parser read state");
return 0;
}
/* Return a chunk of the EBML/MKV/WebM stream.
* The header will be buffered until it can be returned as one chunk.
* A cluster element's opening tag will always start a new chunk.
*/
static int ebml_read(ebml_t *ebml, char *buffer, int len)
......@@ -363,61 +374,63 @@ static int ebml_read(ebml_t *ebml, char *buffer, int len)
return 0;
}
if (ebml->header_read == 1)
{
/* The header has previously been read */
if (ebml->cluster_start > 0) {
/* return up until just before a new cluster starts */
read_space = ebml->cluster_start;
} else {
read_space = ebml->position - 4;
}
switch (ebml->output_state) {
case EBML_STATE_READING_HEADER:
if (ebml->header_size != 0)
{
/* Can read a chunk of the header */
read_space = ebml->header_size - ebml->header_read_position;
if (read_space < 1) {
return 0;
}
if (read_space >= len) {
to_read = len;
} else {
to_read = read_space;
}
if (read_space >= len ) {
to_read = len;
} else {
to_read = read_space;
}
memcpy(buffer, ebml->header, to_read);
ebml->header_read_position += to_read;
memcpy(buffer, ebml->buffer, to_read);
if (ebml->header_read_position == ebml->header_size) {
ebml->output_state = EBML_STATE_READING_CLUSTERS;
}
} else {
/* The header's not ready yet */
return 0;
}
break;
case EBML_STATE_READING_CLUSTERS:
/* Shift unread data down to the start of the buffer */
memmove(ebml->buffer, ebml->buffer + to_read, ebml->position - to_read);
ebml->position -= to_read;
if (ebml->cluster_start > 0) {
/* return up until just before a new cluster starts */
read_space = ebml->cluster_start;
} else {
read_space = ebml->position - 4;
}
if (ebml->cluster_start > 0) {
ebml->cluster_start -= to_read;
}
}
else
{
if (ebml->header_size != 0)
{
/* Can read a chunk of the header */
read_space = ebml->header_size - ebml->header_read_position;
if (read_space < 1) {
return 0;
}
if (read_space >= len) {
if (read_space >= len ) {
to_read = len;
} else {
to_read = read_space;
}
memcpy(buffer, ebml->header, to_read);
ebml->header_read_position += to_read;
memcpy(buffer, ebml->buffer, to_read);
/* Shift unread data down to the start of the buffer */
memmove(ebml->buffer, ebml->buffer + to_read, ebml->position - to_read);
ebml->position -= to_read;
if (ebml->header_read_position == ebml->header_size) {
ebml->header_read = 1;
if (ebml->cluster_start > 0) {
ebml->cluster_start -= to_read;
}
}
else
{
/* The header's not ready yet */
return 0;
}
break;
}
return to_read;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment