Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xiph.Org
Icecast-Server
Commits
744b66c4
Commit
744b66c4
authored
Nov 21, 2015
by
Joseph Wallace
Browse files
Make the state-machine nature of the EBML parser more evident.
parent
15e7fc6e
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/format_ebml.c
View file @
744b66c4
...
...
@@ -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
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment