1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

Probe Tracks section of header to identify the video track.

We'll sync keyframes on that track next commit.
This commit is contained in:
Joseph Wallace 2015-11-21 12:59:14 -05:00
parent 9899413839
commit 6e11db5de2

View File

@ -89,7 +89,10 @@ struct ebml_st {
int header_position; int header_position;
int header_read_position; int header_read_position;
unsigned char *header; unsigned char *header;
unsigned long long keyframe_track_number;
unsigned long long parsing_track_number;
int parsing_track_is_video;
}; };
static void ebml_free_plugin(format_plugin_t *plugin); static void ebml_free_plugin(format_plugin_t *plugin);
@ -116,6 +119,7 @@ static int ebml_parse_sized_int(unsigned char *buffer,
int len, int len,
int is_signed, int is_signed,
unsigned long long *out_value); unsigned long long *out_value);
static inline void ebml_check_track(ebml_t *ebml);
int format_ebml_get_plugin(source_t *source) int format_ebml_get_plugin(source_t *source)
{ {
@ -352,6 +356,10 @@ static ebml_t *ebml_create()
ebml->input_buffer = calloc(1, EBML_SLICE_SIZE); ebml->input_buffer = calloc(1, EBML_SLICE_SIZE);
ebml->cluster_start = -1; ebml->cluster_start = -1;
ebml->keyframe_track_number = EBML_UNKNOWN;
ebml->parsing_track_number = EBML_UNKNOWN;
ebml->parsing_track_is_video = 0;
return ebml; return ebml;
@ -522,11 +530,17 @@ static int ebml_wrote(ebml_t *ebml, int len)
unsigned char *end_of_buffer; unsigned char *end_of_buffer;
int tag_length; int tag_length;
int value_length;
unsigned long long payload_length; unsigned long long payload_length;
unsigned long long data_value;
int copy_state; int copy_state;
char *segment_id = "\x18\x53\x80\x67"; char *segment_id = "\x18\x53\x80\x67";
char *cluster_id = "\x1F\x43\xB6\x75"; char *cluster_id = "\x1F\x43\xB6\x75";
char *tracks_id = "\x16\x54\xAE\x6B";
char *track_entry_id = "\xAE";
char *track_number_id = "\xD7";
char *track_type_id = "\x83";
ebml->input_position += len; ebml->input_position += len;
end_of_buffer = ebml->input_buffer + ebml->input_position; end_of_buffer = ebml->input_buffer + ebml->input_position;
@ -556,16 +570,69 @@ static int ebml_wrote(ebml_t *ebml, int len)
payload_length = 0; payload_length = 0;
} }
/* Recognize tags of interest */
if (tag_length > 4) {
if (!memcmp(ebml->input_buffer + cursor, segment_id, 4)) {
/* Parse all Segment children */
payload_length = 0;
} else if (!memcmp(ebml->input_buffer + cursor, tracks_id, 4)) {
/* Parse all Tracks children */
payload_length = 0;
}
}
if (tag_length > 1) {
if (!memcmp(ebml->input_buffer + cursor, track_entry_id, 1)) {
/* Parse all TrackEntry children; reset the state */
payload_length = 0;
ebml->parsing_track_number = EBML_UNKNOWN;
ebml->parsing_track_is_video = 0;
} else if (!memcmp(ebml->input_buffer + cursor, track_number_id, 1)) {
/* Probe TrackNumber for value */
value_length = ebml_parse_sized_int(ebml->input_buffer + cursor + tag_length,
end_of_buffer, payload_length, 0, &data_value);
if (value_length == 0) {
/* Wait for more data */
processing = 0;
} else if (value_length < 0) {
return -1;
} else {
ebml->parsing_track_number = data_value;
ebml_check_track(ebml);
}
} else if (!memcmp(ebml->input_buffer + cursor, track_type_id, 1)) {
/* Probe TrackType for a video flag */
value_length = ebml_parse_sized_int(ebml->input_buffer + cursor + tag_length,
end_of_buffer, payload_length, 0, &data_value);
if (value_length == 0) {
/* Wait for more data */
processing = 0;
} else if (value_length < 0) {
return -1;
} else {
if (data_value & 0x01) {
/* This is a video track (0x01 flag = video) */
ebml->parsing_track_is_video = 1;
ebml_check_track(ebml);
}
}
}
}
/* Take appropriate next action */
if (!memcmp(ebml->input_buffer + cursor, cluster_id, 4)) { if (!memcmp(ebml->input_buffer + cursor, cluster_id, 4)) {
/* Found a cluster */ /* Found a cluster */
ebml->parse_state = EBML_STATE_START_CLUSTER; ebml->parse_state = EBML_STATE_START_CLUSTER;
} else if (!memcmp(ebml->input_buffer + cursor, segment_id, 4)) { } else if (processing) {
/* Segment tag, copy tag to buffer but parse children */
ebml->copy_len = tag_length;
ebml->parse_state = copy_state;
} else {
/* Non-cluster tag, copy it & children into buffer */ /* Non-cluster tag, copy it & children into buffer */
ebml->copy_len = tag_length + payload_length; ebml->copy_len = tag_length + payload_length;
ebml->parse_state = copy_state; ebml->parse_state = copy_state;
@ -671,6 +738,17 @@ static int ebml_wrote(ebml_t *ebml, int len)
} }
static inline void ebml_check_track(ebml_t *ebml)
{
if (ebml->keyframe_track_number == EBML_UNKNOWN
&& ebml->parsing_track_is_video
&& ebml->parsing_track_number != EBML_UNKNOWN) {
ebml->keyframe_track_number = ebml->parsing_track_number;
ICECAST_LOG_DEBUG("Identified track #%ffu as the video track", ebml->keyframe_track_number);
}
}
/* Try to parse an EBML tag at the given location, returning the /* Try to parse an EBML tag at the given location, returning the
* length of the tag & the length of the associated payload. * length of the tag & the length of the associated payload.
* *