diff options
Diffstat (limited to 'src/dump_state.c')
-rw-r--r-- | src/dump_state.c | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/src/dump_state.c b/src/dump_state.c new file mode 100644 index 0000000..dbba70a --- /dev/null +++ b/src/dump_state.c @@ -0,0 +1,445 @@ +/* + * dump_state.c + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 + */ + +#include "config.h" + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#include "mpeg2.h" + +void dump_state (FILE * f, mpeg2_state_t state, const mpeg2_info_t * info, + int offset, int verbose); + +static struct { + const mpeg2_sequence_t * ptr; + mpeg2_sequence_t value; +} last_sequence; +static struct { + const mpeg2_gop_t * ptr; + mpeg2_gop_t value; +} last_gop; +static struct save_buf { + const mpeg2_fbuf_t * ptr; + mpeg2_fbuf_t value; +} last_curbuf, last_dispbuf, last_discbuf, buf_code_list[26]; +static int buf_code_index = 0; +static int buf_code_new = -1; +static struct save_pic { + const mpeg2_picture_t * ptr; + mpeg2_picture_t value; +} last_curpic, last_curpic2, last_disppic, last_disppic2, pic_code_list[26]; +static int pic_code_index = 0; +static int pic_code_new = -1; + +static int sequence_match (const mpeg2_sequence_t * seq) +{ + return (last_sequence.ptr == seq && + (seq == NULL || + !memcmp (seq, &last_sequence.value, sizeof (mpeg2_sequence_t)))); +} + +static void sequence_save (const mpeg2_sequence_t * seq) +{ + last_sequence.ptr = seq; + if (seq != NULL) + last_sequence.value = *seq; +} + +static char seq_code (const mpeg2_sequence_t * seq) +{ + if (seq == NULL) + return '-'; + else if (sequence_match (seq)) + return 'S'; + else + return '?'; +} + +static int gop_match (const mpeg2_gop_t * gop) +{ + return (last_gop.ptr == gop && + (gop == NULL || + !memcmp (gop, &last_gop.value, sizeof (mpeg2_gop_t)))); +} + +static void gop_save (const mpeg2_gop_t * gop) +{ + last_gop.ptr = gop; + if (gop != NULL) + last_gop.value = *gop; +} + +static char gop_code (const mpeg2_gop_t * gop) +{ + if (gop == NULL) + return '-'; + else if (gop_match (gop)) + return 'G'; + else + return '?'; +} + +static int fbuf_match (const mpeg2_fbuf_t * fbuf, struct save_buf * saved) +{ + return (saved->ptr == fbuf && + (fbuf == NULL || + !memcmp (fbuf, &saved->value, sizeof (mpeg2_fbuf_t)))); +} + +static void fbuf_save (const mpeg2_fbuf_t * fbuf, struct save_buf * saved) +{ + saved->ptr = fbuf; + if (fbuf != NULL) + saved->value = *fbuf; +} + +static char buf_code (const mpeg2_fbuf_t * fbuf) +{ + int i; + + if (fbuf == NULL) + return '-'; + for (i = 0; i < 26; i++) + if (fbuf_match (fbuf, buf_code_list + i)) + return ((i == buf_code_new) ? 'A' : 'a') + i; + return '?'; +} + +static void buf_code_add (const mpeg2_fbuf_t * fbuf, FILE * f) +{ + int i; + + if (fbuf == NULL) + fprintf (f, "buf_code_add error\n"); + for (i = 0; i < 26; i++) + if (buf_code_list[i].ptr == fbuf) + fprintf (f, "buf_code_add error\n"); + buf_code_new = buf_code_index; + fbuf_save (fbuf, buf_code_list + buf_code_index); + if (++buf_code_index == 26) + buf_code_index = 0; +} + +static void buf_code_del (const mpeg2_fbuf_t * fbuf) +{ + int i; + + if (fbuf == NULL) + return; + for (i = 0; i < 26; i++) + if (fbuf_match (fbuf, buf_code_list + i)) { + buf_code_list[i].ptr = NULL; + return; + } +} + +static int picture_match (const mpeg2_picture_t * pic, struct save_pic * saved) +{ + return (saved->ptr == pic && + (pic == NULL || + !memcmp (pic, &saved->value, sizeof (mpeg2_picture_t)))); +} + +static void picture_save (const mpeg2_picture_t * pic, struct save_pic * saved) +{ + saved->ptr = pic; + if (pic != NULL) + saved->value = *pic; +} + +static char pic_code (const mpeg2_picture_t * pic) +{ + int i; + + if (pic == NULL) + return '-'; + for (i = 0; i < 26; i++) + if (picture_match (pic, pic_code_list + i)) + return ((i == pic_code_new) ? 'A' : 'a') + i; + return '?'; +} + +static void pic_code_add (const mpeg2_picture_t * pic, FILE * f) +{ + int i; + + if (pic == NULL) + fprintf (f, "pic_code_add error\n"); + for (i = 0; i < 26; i++) + if (pic_code_list[i].ptr == pic) + fprintf (f, "pic_code_add error\n"); + pic_code_new = pic_code_index; + picture_save (pic, pic_code_list + pic_code_index); + if (++pic_code_index == 26) + pic_code_index = 0; +} + +static void pic_code_del (const mpeg2_picture_t * pic) +{ + int i; + + if (pic == NULL) + return; + for (i = 0; i < 26; i++) + if (picture_match (pic, pic_code_list + i)) { + pic_code_list[i].ptr = NULL; + return; + } +} + +void dump_state (FILE * f, mpeg2_state_t state, const mpeg2_info_t * info, + int offset, int verbose) +{ + static const char * state_name[] = { + "BUFFER", "SEQUENCE", "SEQUENCE_REPEATED","GOP", + "PICTURE", "SLICE_1ST", "PICTURE_2ND", "SLICE", "END", + "INVALID", "INVALID_END", "SEQUENCE_MODIFIED" + }; + static const char * profile[] = { "HP", "Spatial", "SNR", "MP", "SP" }; + static const char * level[] = { "HL", "H-14", "ML", "LL" }; + static const char * profile2[] = { "422@HL", NULL, NULL, "422@ML", + NULL, NULL, NULL, NULL, "MV@HL", + "MV@H-14", NULL, "MV@ML", "MV@LL" }; + static const char * video_fmt[] = { "COMPONENT", "PAL", "NTSC", "SECAM", "MAC"}; + static const char coding_type[] = { '0', 'I', 'P', 'B', 'D', '5', '6', '7'}; + static const char * colour[] = { NULL, "BT.709", "UNSPECIFIED", NULL, + "BT.470-2/M", "BT.470-2/B,G", + "SMPTE170M", "SMPTE240M", "LINEAR" }; + static const char * colour3[] = { NULL, "BT.709", "UNSPEC_COLORS", NULL, NULL, + "BT.470-2/B,G", "SMPTE170M", "SMPTE240M" }; + const mpeg2_sequence_t * seq = info->sequence; + const mpeg2_gop_t * gop = info->gop; + const mpeg2_picture_t * pic; + unsigned int i, nb_pos, pixel_width, pixel_height; + + if (state == STATE_BUFFER && + sequence_match (seq) && gop_match (gop) && + info->user_data == NULL && info->user_data_len == 0 && + fbuf_match (info->current_fbuf, &last_curbuf) && + fbuf_match (info->display_fbuf, &last_dispbuf) && + fbuf_match (info->discard_fbuf, &last_discbuf) && + picture_match (info->current_picture, &last_curpic) && + picture_match (info->current_picture_2nd, &last_curpic2) && + picture_match (info->display_picture, &last_disppic) && + picture_match (info->display_picture_2nd, &last_disppic2)) + return; + fprintf (f, "%8x", offset); + if (verbose > 1) { + switch (state) { + case STATE_PICTURE: + buf_code_add (info->current_fbuf, f); + pic_code_add (info->current_picture, f); + break; + case STATE_PICTURE_2ND: + pic_code_add (info->current_picture_2nd, f); + break; + case STATE_SEQUENCE_MODIFIED: + if (last_sequence.value.width != seq->width || + last_sequence.value.height != seq->height || + last_sequence.value.chroma_width != seq->chroma_width || + last_sequence.value.chroma_height != seq->chroma_height || + ((last_sequence.value.flags & SEQ_FLAG_LOW_DELAY) != + (seq->flags & SEQ_FLAG_LOW_DELAY))) + fprintf (f, " (INVALID)"); + case STATE_SEQUENCE: + sequence_save (seq); + break; + break; + case STATE_GOP: + gop_save (gop); + break; + default: + break; + } + fprintf (f, " %c%c %c%c%c %c%c%c %c", seq_code (seq), gop_code (gop), + buf_code (info->current_fbuf), + pic_code (info->current_picture), + pic_code (info->current_picture_2nd), + buf_code (info->display_fbuf), + pic_code (info->display_picture), + pic_code (info->display_picture_2nd), + buf_code (info->discard_fbuf)); + if (state == STATE_SLICE || state == STATE_END || + state == STATE_INVALID_END) { + if (state != STATE_SLICE) + buf_code_del (info->display_fbuf); + buf_code_del (info->discard_fbuf); + pic_code_del (info->display_picture); + pic_code_del (info->display_picture_2nd); + } + buf_code_new = pic_code_new = -1; + } + fprintf (f, " %s", state_name[state]); + switch (state) { + case STATE_SEQUENCE: + case STATE_SEQUENCE_REPEATED: + case STATE_SEQUENCE_MODIFIED: + if (seq->flags & SEQ_FLAG_MPEG2) + fprintf (f, " MPEG2"); + if (0x10 <= seq->profile_level_id && seq->profile_level_id < 0x60 && + !(seq->profile_level_id & 1) && + 4 <= (seq->profile_level_id & 15) && + (seq->profile_level_id & 15) <= 10) + fprintf (f, " %s@%s", + profile[(seq->profile_level_id >> 4) - 1], + level[((seq->profile_level_id & 15) - 4) >> 1]); + else if (0x82 <= seq->profile_level_id && + seq->profile_level_id<= 0x8e && + profile2[seq->profile_level_id - 0x82]) + fprintf (f, " %s", profile2[seq->profile_level_id - 0x82]); + else if (seq->flags & SEQ_FLAG_MPEG2) + fprintf (f, " profile %02x", seq->profile_level_id); + if (seq->flags & SEQ_FLAG_CONSTRAINED_PARAMETERS) + fprintf (f, " CONST"); + if (seq->flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE) + fprintf (f, " PROG"); + if (seq->flags & SEQ_FLAG_LOW_DELAY) + fprintf (f, " LOWDELAY"); + if ((seq->flags & SEQ_MASK_VIDEO_FORMAT) < + SEQ_VIDEO_FORMAT_UNSPECIFIED) + fprintf (f, " %s", video_fmt[(seq->flags & SEQ_MASK_VIDEO_FORMAT) / + SEQ_VIDEO_FORMAT_PAL]); + if (seq->flags & SEQ_FLAG_COLOUR_DESCRIPTION) { + if (seq->colour_primaries == seq->transfer_characteristics && + seq->colour_primaries == seq->matrix_coefficients && + seq->colour_primaries <= 7 && colour3[seq->colour_primaries]) + fprintf (f, " %s", colour3[seq->colour_primaries]); + else { + char prim[16], trans[16], matrix[16]; + sprintf (prim, "%d", seq->colour_primaries); + sprintf (trans, "%d", seq->transfer_characteristics); + sprintf (matrix, "%d", seq->matrix_coefficients); + if (seq->colour_primaries <= 7 && + colour[seq->colour_primaries]) + strncpy (prim, colour[seq->colour_primaries], 15); + if (seq->transfer_characteristics <= 8 && + colour[seq->transfer_characteristics]) + strncpy (trans, colour[seq->transfer_characteristics], 15); + if (seq->matrix_coefficients == 4) + strncpy (matrix, "FCC", 15); + else if (seq->matrix_coefficients <= 7 && + colour[seq->matrix_coefficients]) + strncpy (matrix, colour[seq->matrix_coefficients], 15); + fprintf (f, " COLORS (prim %s trans %s matrix %s)", + prim, trans, matrix); + } + } + fprintf (f, " %dx%d chroma %dx%d fps %.*f maxBps %d vbv %d " + "picture %dx%d display %dx%d pixel %dx%d", + seq->width, seq->height, + seq->chroma_width, seq->chroma_height, + 27000000%seq->frame_period?2:0, 27000000.0/seq->frame_period, + seq->byte_rate, seq->vbv_buffer_size, + seq->picture_width, seq->picture_height, + seq->display_width, seq->display_height, + seq->pixel_width, seq->pixel_height); + if (mpeg2_guess_aspect (seq, &pixel_width, &pixel_height)) + fprintf (f, " guessed %dx%d", pixel_width, pixel_height); + fprintf (f, "\n"); + break; + case STATE_GOP: + if (gop->flags & GOP_FLAG_DROP_FRAME) + fprintf (f, " DROP"); + if (gop->flags & GOP_FLAG_CLOSED_GOP) + fprintf (f, " CLOSED"); + if (gop->flags & GOP_FLAG_BROKEN_LINK) + fprintf (f, " BROKEN"); + fprintf (f, " %2d:%2d:%2d:%2d\n", + gop->hours, gop->minutes, gop->seconds, gop->pictures); + break; + case STATE_PICTURE: + case STATE_PICTURE_2ND: + pic = ((state == STATE_PICTURE) ? + info->current_picture : info->current_picture_2nd); + fprintf (f, " %c", + coding_type[pic->flags & PIC_MASK_CODING_TYPE]); + if (pic->flags & PIC_FLAG_PROGRESSIVE_FRAME) + fprintf (f, " PROG"); + if (pic->flags & PIC_FLAG_SKIP) + fprintf (f, " SKIP"); + fprintf (f, " fields %d", pic->nb_fields); + if (pic->flags & PIC_FLAG_TOP_FIELD_FIRST) + fprintf (f, " TFF"); + if (pic->flags & PIC_FLAG_TAGS) + fprintf (f, " pts %08x dts %08x", pic->tag, pic->tag2); + fprintf (f, " time_ref %d", pic->temporal_reference); + if (pic->flags & PIC_FLAG_COMPOSITE_DISPLAY) + fprintf (f, " composite %05x", pic->flags >> 12); + fprintf (f, " offset"); + nb_pos = pic->nb_fields; + if (seq->flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE) + nb_pos >>= 1; + for (i = 0; i < nb_pos; i++) + fprintf (f, " %d/%d", + pic->display_offset[i].x, pic->display_offset[i].y); + fprintf (f, "\n"); + break; + default: + fprintf (f, "\n"); + } + if (verbose > 2 && info->user_data_len) { + fprintf (f, " USER_DATA %d bytes\n", info->user_data_len); + if (verbose > 3) + for (i = 0; i < info->user_data_len; i += 16) { + unsigned int j; + + fprintf (f, " "); + for (j = i; j < i + 16; j++) + if (j < info->user_data_len) + fprintf (f, "%02x ", info->user_data[j]); + else + fprintf (f, " "); + fprintf (f, " "); + for (j = i; j < i + 16; j++) + if (j < info->user_data_len && + 32 <= info->user_data[j] && info->user_data[j] <= 126) + fprintf (f, "%c", info->user_data[j]); + else + fprintf (f, " "); + fprintf (f, "\n"); + } + } + if (state == STATE_END || state == STATE_INVALID_END) { + sequence_save (NULL); + gop_save (NULL); + fbuf_save (NULL, &last_curbuf); + fbuf_save (NULL, &last_dispbuf); + fbuf_save (NULL, &last_discbuf); + picture_save (NULL, &last_curpic); + picture_save (NULL, &last_curpic2); + picture_save (NULL, &last_disppic); + picture_save (NULL, &last_disppic2); + } else { + sequence_save (seq); + gop_save (gop); + fbuf_save (info->current_fbuf, &last_curbuf); + fbuf_save (info->display_fbuf, &last_dispbuf); + fbuf_save (info->discard_fbuf, &last_discbuf); + picture_save (info->current_picture, &last_curpic); + picture_save (info->current_picture_2nd, &last_curpic2); + picture_save (info->display_picture, &last_disppic); + picture_save (info->display_picture_2nd, &last_disppic2); + } +} |