From f3d9b1791bef682bb78b502299daa1ba9bc76695 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Tue, 1 Jul 2008 10:27:48 +0000 Subject: Bring libmpeg2 portions that we use up to date with the latest libmpeg2 CVS. Fix up some file headers and add a revision history to the libmpeg2 files detailing to which CVS file revisions things were synced. This makes it easier to start in the right place by hand in the future. Hopefully no mistakes and everything works. :-) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17904 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/mpegplayer/header.c | 261 ++++++++++++++++++++++++++++----------- 1 file changed, 188 insertions(+), 73 deletions(-) (limited to 'apps/plugins/mpegplayer/header.c') diff --git a/apps/plugins/mpegplayer/header.c b/apps/plugins/mpegplayer/header.c index d8d005b692..f5571835c1 100644 --- a/apps/plugins/mpegplayer/header.c +++ b/apps/plugins/mpegplayer/header.c @@ -20,6 +20,10 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.101 */ #include "plugin.h" @@ -325,14 +329,14 @@ static int sequence_display_ext (mpeg2dec_t * mpeg2dec) { uint8_t * buffer = mpeg2dec->chunk_start; mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; - uint32_t flags; + int x; - flags = (sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) | + sequence->flags = (sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) | ((buffer[0] << 4) & SEQ_MASK_VIDEO_FORMAT); if (buffer[0] & 1) { - flags |= SEQ_FLAG_COLOUR_DESCRIPTION; + sequence->flags |= SEQ_FLAG_COLOUR_DESCRIPTION; sequence->colour_primaries = buffer[1]; sequence->transfer_characteristics = buffer[2]; sequence->matrix_coefficients = buffer[3]; @@ -342,15 +346,36 @@ static int sequence_display_ext (mpeg2dec_t * mpeg2dec) if (!(buffer[2] & 2)) /* missing marker_bit */ return 1; - sequence->display_width = - (buffer[1] << 6) | (buffer[2] >> 2); + x = (buffer[1] << 6) | (buffer[2] >> 2); + if (x) + sequence->display_width = x; - sequence->display_height = - ((buffer[2] & 1) << 13) | (buffer[3] << 5) | (buffer[4] >> 3); + x = ((buffer[2] & 1) << 13) | (buffer[3] << 5) | (buffer[4] >> 3); + if (x) + sequence->display_height = x; return 0; } +static inline void simplify (unsigned int * u, unsigned int * v) +{ + unsigned int a, b, tmp; + + a = *u; + b = *v; + + /* find greatest common divisor */ + while (a) + { + tmp = a; + a = b % tmp; + b = tmp; + } + + *u /= b; + *v /= b; +} + static inline void finalize_sequence (mpeg2_sequence_t * sequence) { int width; @@ -411,9 +436,13 @@ static inline void finalize_sequence (mpeg2_sequence_t * sequence) sequence->pixel_width = 32; sequence->pixel_height = 27; return; - case 12: /* 720*480 4:3 */ - sequence->pixel_width = 8; - sequence->pixel_height = 9; + case 8: /* BT.601 625 lines 4:3 */ + sequence->pixel_width = 59; + sequence->pixel_height = 54; + return; + case 12: /* BT.601 525 lines 4:3 */ + sequence->pixel_width = 10; + sequence->pixel_height = 11; return; default: height = 88 * sequence->pixel_width + 1171; @@ -424,17 +453,113 @@ static inline void finalize_sequence (mpeg2_sequence_t * sequence) sequence->pixel_width = width; sequence->pixel_height = height; - /* find greatest common divisor */ - while (width) + simplify(&sequence->pixel_width, &sequence->pixel_height); +} + +int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence, + unsigned int * pixel_width, + unsigned int * pixel_height) +{ + static const struct + { + unsigned int width, height; + } video_modes[] = + { + {720, 576}, /* 625 lines, 13.5 MHz (D1, DV, DVB, DVD) */ + {704, 576}, /* 625 lines, 13.5 MHz (1/1 D1, DVB, DVD, 4CIF) */ + {544, 576}, /* 625 lines, 10.125 MHz (DVB, laserdisc) */ + {528, 576}, /* 625 lines, 10.125 MHz (3/4 D1, DVB, laserdisc) */ + {480, 576}, /* 625 lines, 9 MHz (2/3 D1, DVB, SVCD) */ + {352, 576}, /* 625 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVB, DVD) */ + {352, 288}, /* 625 lines, 6.75 MHz, 1 field (D4, VCD, DVB, DVD, CIF) */ + {176, 144}, /* 625 lines, 3.375 MHz, half field (QCIF) */ + {720, 486}, /* 525 lines, 13.5 MHz (D1) */ + {704, 486}, /* 525 lines, 13.5 MHz */ + {720, 480}, /* 525 lines, 13.5 MHz (DV, DSS, DVD) */ + {704, 480}, /* 525 lines, 13.5 MHz (1/1 D1, ATSC, DVD) */ + {544, 480}, /* 525 lines. 10.125 MHz (DSS, laserdisc) */ + {528, 480}, /* 525 lines. 10.125 MHz (3/4 D1, laserdisc) */ + {480, 480}, /* 525 lines, 9 MHz (2/3 D1, SVCD) */ + {352, 480}, /* 525 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVD) */ + {352, 240} /* 525 lines. 6.75 MHz, 1 field (D4, VCD, DSS, DVD) */ + }; + unsigned int width, height, pix_width, pix_height, i, DAR_16_9; + + *pixel_width = sequence->pixel_width; + *pixel_height = sequence->pixel_height; + width = sequence->picture_width; + height = sequence->picture_height; + + for (i = 0; i < sizeof (video_modes) / sizeof (video_modes[0]); i++) + { + if (width == video_modes[i].width && height == video_modes[i].height) + break; + } + + if (i == ARRAYLEN(video_modes) || + (sequence->pixel_width == 1 && sequence->pixel_height == 1) || + width != sequence->display_width || height != sequence->display_height) + { + return 0; + } + + for (pix_height = 1; height * pix_height < 480; pix_height <<= 1); + height *= pix_height; + + for (pix_width = 1; width * pix_width <= 352; pix_width <<= 1); + width *= pix_width; + + if (!(sequence->flags & SEQ_FLAG_MPEG2)) { - int tmp = width; - width = height % tmp; - height = tmp; + static unsigned int mpeg1_check[2][2] = {{11, 54}, {27, 45}}; + DAR_16_9 = (sequence->pixel_height == 27 || + sequence->pixel_height == 45); + if (width < 704 || + sequence->pixel_height != mpeg1_check[DAR_16_9][height == 576]) + return 0; + } + else + { + DAR_16_9 = (3 * sequence->picture_width * sequence->pixel_width > + 4 * sequence->picture_height * sequence->pixel_height); + switch (width) + { + case 528: + case 544: + pix_width *= 4; + pix_height *= 3; + break; + case 480: + pix_width *= 3; + pix_height *= 2; + break; + } } - sequence->pixel_width /= height; - sequence->pixel_height /= height; -} + if (DAR_16_9) + { + pix_width *= 4; + pix_height *= 3; + } + + if (height == 576) + { + pix_width *= 59; + pix_height *= 54; + } + else + { + pix_width *= 10; + pix_height *= 11; + } + + *pixel_width = pix_width; + *pixel_height = pix_height; + + simplify (pixel_width, pixel_height); + + return (height == 576) ? 1 : 2; +} static void copy_matrix (mpeg2dec_t * mpeg2dec, int index) { @@ -506,36 +631,33 @@ void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec) if (mpeg2dec->sequence.width != (unsigned)-1) { - unsigned int new_byte_rate; - /* * According to 6.1.1.6, repeat sequence headers should be - * identical to the original. However some DVDs dont respect - * that and have different bitrates in the repeat sequence - * headers. So we'll ignore that in the comparison and still - * consider these as repeat sequence headers. - * - * However, be careful not to alter the current sequence when - * returning STATE_INVALID_END. + * identical to the original. However some encoders don't + * respect that and change various fields (including bitrate + * and aspect ratio) in the repeat sequence headers. So we + * choose to be as conservative as possible and only restart + * the decoder if the width, height, chroma_width, + * chroma_height or low_delay flag are modified. */ - new_byte_rate = sequence->byte_rate; - sequence->byte_rate = mpeg2dec->sequence.byte_rate; - - if (rb->memcmp(&mpeg2dec->sequence, sequence, - sizeof (mpeg2_sequence_t))) + if (sequence->width != mpeg2dec->sequence.width || + sequence->height != mpeg2dec->sequence.height || + sequence->chroma_width != mpeg2dec->sequence.chroma_width || + sequence->chroma_height != mpeg2dec->sequence.chroma_height || + ((sequence->flags ^ mpeg2dec->sequence.flags) & + SEQ_FLAG_LOW_DELAY)) { decoder->stride_frame = sequence->width; - sequence->byte_rate = new_byte_rate; - mpeg2_header_end (mpeg2dec); - mpeg2dec->action = invalid_end_action; mpeg2dec->state = STATE_INVALID_END; return; } - sequence->byte_rate = new_byte_rate; - mpeg2dec->state = STATE_SEQUENCE_REPEATED; + mpeg2dec->state = rb->memcmp(&mpeg2dec->sequence, sequence, + sizeof (mpeg2_sequence_t)) ? + STATE_SEQUENCE_MODIFIED : + STATE_SEQUENCE_REPEATED; } else { @@ -601,70 +723,61 @@ void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type) } } -mpeg2_state_t mpeg2_header_picture_start (mpeg2dec_t * mpeg2dec) +int mpeg2_header_picture (mpeg2dec_t * mpeg2dec) { + uint8_t * buffer = mpeg2dec->chunk_start; mpeg2_picture_t * picture = &mpeg2dec->new_picture; + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + int type; mpeg2dec->state = (mpeg2dec->state != STATE_SLICE_1ST) ? STATE_PICTURE : STATE_PICTURE_2ND; - picture->flags = 0; + mpeg2dec->ext_state = PIC_CODING_EXT; + + picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6); + + type = (buffer [1] >> 3) & 7; + + if (type == PIC_FLAG_CODING_TYPE_P || type == PIC_FLAG_CODING_TYPE_B) + { + /* forward_f_code and backward_f_code - used in mpeg1 only */ + decoder->f_motion.f_code[1] = (buffer[3] >> 2) & 1; + decoder->f_motion.f_code[0] = + (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1; + decoder->b_motion.f_code[1] = (buffer[4] >> 6) & 1; + decoder->b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1; + } + + picture->flags = PIC_FLAG_PROGRESSIVE_FRAME | type; picture->tag = picture->tag2 = 0; if (mpeg2dec->num_tags) { - if (mpeg2dec->bytes_since_tag >= 4) + if (mpeg2dec->bytes_since_tag >= mpeg2dec->chunk_ptr - buffer + 4) { mpeg2dec->num_tags = 0; picture->tag = mpeg2dec->tag_current; picture->tag2 = mpeg2dec->tag2_current; - picture->flags = PIC_FLAG_TAGS; + picture->flags |= PIC_FLAG_TAGS; } else if (mpeg2dec->num_tags > 1) { mpeg2dec->num_tags = 1; picture->tag = mpeg2dec->tag_previous; picture->tag2 = mpeg2dec->tag2_previous; - picture->flags = PIC_FLAG_TAGS; + picture->flags |= PIC_FLAG_TAGS; } } + picture->nb_fields = 2; picture->display_offset[0].x = picture->display_offset[1].x = picture->display_offset[2].x = mpeg2dec->display_offset_x; picture->display_offset[0].y = picture->display_offset[1].y = picture->display_offset[2].y = mpeg2dec->display_offset_y; - return mpeg2_parse_header (mpeg2dec); -} - -int mpeg2_header_picture (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_picture_t * picture = &mpeg2dec->new_picture; - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - int type; - - type = (buffer [1] >> 3) & 7; - mpeg2dec->ext_state = PIC_CODING_EXT; - - picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6); - - picture->flags |= type; - - if (type == PIC_FLAG_CODING_TYPE_P || type == PIC_FLAG_CODING_TYPE_B) - { - /* forward_f_code and backward_f_code - used in mpeg1 only */ - decoder->f_motion.f_code[1] = (buffer[3] >> 2) & 1; - decoder->f_motion.f_code[0] = - (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1; - decoder->b_motion.f_code[1] = (buffer[4] >> 6) & 1; - decoder->b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1; - } - /* XXXXXX decode extra_information_picture as well */ - picture->nb_fields = 2; - mpeg2dec->q_scale_type = 0; decoder->intra_dc_precision = 7; decoder->frame_pred_frame_dct = 1; @@ -722,7 +835,9 @@ static int picture_coding_ext (mpeg2dec_t * mpeg2dec) mpeg2dec->q_scale_type = buffer[3] & 16; decoder->intra_vlc_format = (buffer[3] >> 3) & 1; decoder->scan = (buffer[3] & 4) ? mpeg2_scan_alt : mpeg2_scan_norm; - flags |= (buffer[4] & 0x80) ? PIC_FLAG_PROGRESSIVE_FRAME : 0; + + if (!(buffer[4] & 0x80)) + flags &= ~PIC_FLAG_PROGRESSIVE_FRAME; if (buffer[4] & 0x40) { @@ -1120,7 +1235,7 @@ mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec) mpeg2dec->action = NULL; - return (mpeg2_state_t)-1; + return STATE_INTERNAL_NORETURN; } static mpeg2_state_t seek_sequence (mpeg2dec_t * mpeg2dec) -- cgit v1.2.3