diff options
author | Matt Messier <mmessier@grapetv.org> | 2007-05-08 15:10:27 -0400 |
---|---|---|
committer | Matt Messier <mmessier@grapetv.org> | 2007-05-08 15:10:27 -0400 |
commit | c8f3f69be6bd2a6ce361e2433f174abd57b77911 (patch) | |
tree | a8db2fb70963d1e4e2a4c8291a9a5548540ca7eb /src/libmpeg2 | |
parent | 1956c347edc0af71e479eacbc9e64f67ba7cba05 (diff) | |
parent | 92d72104e3cd37e7470a41a65b230297592f1331 (diff) | |
download | xine-lib-c8f3f69be6bd2a6ce361e2433f174abd57b77911.tar.gz xine-lib-c8f3f69be6bd2a6ce361e2433f174abd57b77911.tar.bz2 |
Merge changes from main 1.2 repository
Diffstat (limited to 'src/libmpeg2')
-rw-r--r-- | src/libmpeg2/decode.c | 155 | ||||
-rw-r--r-- | src/libmpeg2/mpeg2.h | 6 |
2 files changed, 125 insertions, 36 deletions
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index a2bb868df..2b2426950 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -87,6 +87,10 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec, mpeg2dec->code = 0xb4; mpeg2dec->seek_mode = 0; + /* initialize AFD storage */ + mpeg2dec->afd_value_seen = XINE_VIDEO_AFD_NOT_PRESENT; + mpeg2dec->afd_value_reported = (XINE_VIDEO_AFD_NOT_PRESENT - 1); + memset (mpeg2dec->picture, 0, sizeof (picture_t)); /* initialize substructures */ @@ -236,7 +240,7 @@ static void remember_metainfo (mpeg2dec_t *mpeg2dec) { } static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, - uint8_t * buffer) + uint8_t * buffer, int next_code) { picture_t * picture; int is_frame_done; @@ -393,6 +397,14 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, /* abort(); */ break; } + + /* reset AFD value to detect absence */ + mpeg2dec->afd_value_seen = XINE_VIDEO_AFD_NOT_PRESENT; + + /* according to ISO/IEC 13818-2, an extension start code will follow. + * Otherwise the stream follows ISO/IEC 11172-2 which means MPEG1 */ + picture->mpeg1 = (next_code != 0xb5); + if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect; if (mpeg2dec->is_sequence_needed ) { @@ -464,6 +476,18 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if (code >= 0xb0) break; + /* check for AFD change once per picture */ + if (mpeg2dec->afd_value_reported != mpeg2dec->afd_value_seen) { + /* AFD data should better be stored in current_frame to have it */ + /* ready and synchronous with other data like width or height. */ + /* An AFD change should then be detected when a new frame is emitted */ + /* from the decoder to report the AFD change in display order and not */ + /* in decoding order like it happens below for now. */ + _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_VIDEO_AFD, mpeg2dec->afd_value_seen); +fprintf(stderr, "AFD changed from %d to %d\n", mpeg2dec->afd_value_reported, mpeg2dec->afd_value_seen); + mpeg2dec->afd_value_reported = mpeg2dec->afd_value_seen; + } + if (!(mpeg2dec->in_slice)) { mpeg2dec->in_slice = 1; @@ -574,45 +598,102 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, 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 + * of a still image. + * Therefore, return immediately with a chunk_size of 0. Setting code to 0xb4 + * will eat up any trailing garbage next time. + */ + if (mpeg2dec->code == 0xb7) { + mpeg2dec->code = 0xb4; + mpeg2dec->chunk_size = 0; + 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, ¤t, 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, @@ -633,12 +714,12 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end, if (pts) mpeg2dec->pts = pts; - while (current != end) { + while (current != end || mpeg2dec->code == 0xb7) { code = mpeg2dec->code; current = copy_chunk (mpeg2dec, current, end); if (current == NULL) break; - ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer); + ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer, mpeg2dec->code); } libmpeg2_accel_frame_completion(&mpeg2dec->accel, mpeg2dec->frame_format, @@ -805,7 +886,7 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec) void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end){ - uint8_t code; + uint8_t code, next_code; picture_t *picture = mpeg2dec->picture; mpeg2dec->seek_mode = 1; @@ -815,6 +896,7 @@ void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec, current = copy_chunk (mpeg2dec, current, end); if (current == NULL) return ; + next_code = mpeg2dec->code; /* printf ("looking for sequence header... %02x\n", code); */ @@ -825,6 +907,11 @@ void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec, printf ("libmpeg2: bad sequence header\n"); continue; } + + /* according to ISO/IEC 13818-2, an extension start code will follow. + * Otherwise the stream follows ISO/IEC 11172-2 which means MPEG1 */ + picture->mpeg1 = (next_code != 0xb5); + if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect; if (mpeg2dec->is_sequence_needed) { @@ -918,9 +1005,5 @@ static void process_userdata(mpeg2dec_t *mpeg2dec, uint8_t *buffer) } /* check Active Format Description ETSI TS 101 154 V1.5.1 */ else if (buffer[0] == 0x44 && buffer[1] == 0x54 && buffer[2] == 0x47 && buffer[3] == 0x31) - { - int afd = (buffer[4] & 0x40) ? (buffer[5] & 0x0f) : -1; - _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_VIDEO_AFD, afd); - - } + mpeg2dec->afd_value_seen = (buffer[4] & 0x40) ? (buffer[5] & 0x0f) : XINE_VIDEO_AFD_NOT_PRESENT; } diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h index 788fa823c..253f300a2 100644 --- a/src/libmpeg2/mpeg2.h +++ b/src/libmpeg2/mpeg2.h @@ -57,6 +57,12 @@ typedef struct mpeg2dec_s { int force_aspect; int force_pan_scan; + /* AFD data can be found after a sequence, group or picture start code */ + /* and will be stored in afd_value_seen. Later it will be transfered to */ + /* a stream property and stored into afd_value_reported to detect changes */ + int afd_value_seen; + int afd_value_reported; + xine_stream_t *stream; /* a spu decoder for possible closed captions */ |