summaryrefslogtreecommitdiff
path: root/src/libmpeg2/decode.c
diff options
context:
space:
mode:
authorReinhard Nißl <rnissl@gmx.de>2007-04-12 00:02:45 +0200
committerReinhard Nißl <rnissl@gmx.de>2007-04-12 00:02:45 +0200
commita76aacd69fa3512c3c566c93248bc6c41bb00e97 (patch)
treed68c90df740a00b561a5a90844dbb0d7d35ead3f /src/libmpeg2/decode.c
parent5e58a3c2f6a02dbd198369d1132366c49f5345fe (diff)
downloadxine-lib-a76aacd69fa3512c3c566c93248bc6c41bb00e97.tar.gz
xine-lib-a76aacd69fa3512c3c566c93248bc6c41bb00e97.tar.bz2
Speed up start code scanning.
The current code implements hardware (a shift register) in software just to find the byte pattern 00 00 01 xx, which causes remarkable CPU load on less powerful machines. The new approach uses memchr() to find the 01 in the buffer, which most often hits a start code. memchr() seems to be even faster then implementing a real pattern search (i. e. by just looking at every third byte to find 01). The new implementation causes significantly fewer CPU load on less powerful machines.
Diffstat (limited to 'src/libmpeg2/decode.c')
-rw-r--r--src/libmpeg2/decode.c99
1 files changed, 72 insertions, 27 deletions
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c
index c3ba6ea4d..2b2426950 100644
--- a/src/libmpeg2/decode.c
+++ b/src/libmpeg2/decode.c
@@ -598,13 +598,63 @@ fprintf(stderr, "AFD changed from %d to %d\n", mpeg2dec->afd_value_reported, mpe
return is_frame_done;
}
+static inline int find_start_code (mpeg2dec_t * mpeg2dec,
+ uint8_t ** current, uint8_t * limit)
+{
+ uint8_t * p;
+
+ if (*current >= limit)
+ return 0;
+ if (mpeg2dec->shift == 0x00000100)
+ return 1;
+
+ mpeg2dec->shift = (mpeg2dec->shift | *(*current)++) << 8;
+
+ if (*current >= limit)
+ return 0;
+ if (mpeg2dec->shift == 0x00000100)
+ return 1;
+
+ mpeg2dec->shift = (mpeg2dec->shift | *(*current)++) << 8;
+
+ if (*current >= limit)
+ return 0;
+ if (mpeg2dec->shift == 0x00000100)
+ return 1;
+
+ limit--;
+
+ if (*current >= limit) {
+ mpeg2dec->shift = (mpeg2dec->shift | *(*current)++) << 8;
+ return 0;
+ }
+
+ p = *current;
+
+ while (p < limit && (p = (uint8_t *)memchr(p, 0x01, limit - p))) {
+ if (p[-2] || p[-1])
+ p += 3;
+ else {
+ *current = ++p;
+ return 1;
+ }
+ }
+
+ *current = ++limit;
+ p = limit - 3;
+ mpeg2dec->shift = (mpeg2dec->shift | *p++) << 8;
+ mpeg2dec->shift = (mpeg2dec->shift | *p++) << 8;
+ mpeg2dec->shift = (mpeg2dec->shift | *p++) << 8;
+
+ return 0;
+}
+
static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
uint8_t * current, uint8_t * end)
{
- uint32_t shift;
- uint8_t * chunk_ptr;
uint8_t * limit;
- uint8_t byte;
+ uint8_t * data = current;
+ int found, bite;
/* sequence end code 0xb7 doesn't have any data and there might be the case
* that no start code will follow this code for quite some time (e. g. in case
@@ -618,37 +668,32 @@ static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
return current;
}
- shift = mpeg2dec->shift;
- chunk_ptr = mpeg2dec->chunk_ptr;
- limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - chunk_ptr);
+ limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - mpeg2dec->chunk_ptr);
if (limit > end)
limit = end;
- while (1) {
-
- byte = *current++;
- if (shift != 0x00000100) {
- shift = (shift | byte) << 8;
- *chunk_ptr++ = byte;
- if (current < limit)
- continue;
- if (current == end) {
- mpeg2dec->chunk_ptr = chunk_ptr;
- mpeg2dec->shift = shift;
- return NULL;
- } else {
- /* we filled the chunk buffer without finding a start code */
- mpeg2dec->code = 0xb4; /* sequence_error_code */
- mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
- return current;
- }
- }
- mpeg2dec->code = byte;
- mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_buffer - 3;
+ found = find_start_code(mpeg2dec, &current, limit);
+ bite = current - data;
+ if (bite) {
+ xine_fast_memcpy(mpeg2dec->chunk_ptr, data, bite);
+ mpeg2dec->chunk_ptr += bite;
+ }
+
+ if (found) {
+ mpeg2dec->code = *current++;
+ mpeg2dec->chunk_size = mpeg2dec->chunk_ptr - mpeg2dec->chunk_buffer - 3;
mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
mpeg2dec->shift = 0xffffff00;
return current;
}
+
+ if (current == end)
+ return NULL;
+
+ /* we filled the chunk buffer without finding a start code */
+ mpeg2dec->code = 0xb4; /* sequence_error_code */
+ mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+ return current;
}
int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end,