📄 video.c
字号:
* Parses bit stream until MB_QUANTUM number of * macroblocks have been decoded or current slice or * picture ends, whichever comes first. If the start * of a frame is encountered, the frame is time stamped * with the value passed in time_stamp. If the value * passed in buffer is not null, the video stream buffer * is set to buffer and the length of the buffer is * expected in value passed in through length. The current * video stream is set to vid_stream. If vid_stream * is passed as NULL, a new VidStream structure is created * and initialized and used as the current video stream. * * Results: * A pointer to the video stream structure used. * * Side effects: * Bit stream is irreversibly parsed. If a picture is completed, * a function is called to display the frame at the correct time. * *-------------------------------------------------------------- */int mpegVidRsrc(TimeStamp time_stamp, VidStream *vid_stream){ unsigned int data; int i, status; /* If vid_stream is null, create new VidStream structure. */ if (vid_stream == NULL) { return 0; } /* * Set global curVidStream to vid_stream. Necessary because bit i/o use * curVidStream and are not passed vid_stream. Also set global bitstream * parameters. */ curVidStream = vid_stream; bitOffset = curVidStream->bit_offset;#ifdef UTIL2 curBits = *curVidStream->buffer << bitOffset;#else curBits = *curVidStream->buffer;#endif bufLength = curVidStream->buf_length; bitBuffer = curVidStream->buffer; /* * If called for the first time, find start code, make sure it is a * sequence start code. */ if (start_decode) { /*fprintf(stderr, "Starting new stream.\n");*/ next_start_code(); show_bits32(data); if (data != SEQ_START_CODE) { DestroyVidStream(curVidStream); mexErrMsgTxt("This is not an MPEG stream."); } start_decode = 0; } /* Get next 32 bits (size of start codes). */ show_bits32(data); /* * Process according to start code (or parse macroblock if not a start code * at all. */ switch (data) { case SEQ_END_CODE: /* Display last frame. */ if (vid_stream->future != NULL) { vid_stream->current = vid_stream->future; /*ExecuteDisplay(vid_stream);*/ } /* Sequence done. */ /* if (!quietFlag) { fprintf(stderr, "\nDone!\n"); } */#ifdef ANALYSIS PrintAllStats();#endif /* PrintTimeInfo(); */ return(1); break; case SEQ_START_CODE: /* Sequence start code. Parse sequence header. */ if (ParseSeqHead(vid_stream) != PARSE_OK) goto error; /* * Return after sequence start code so that application above can use * info in header. */ goto done; case GOP_START_CODE: /* Group of Pictures start code. Parse gop header. */ if (ParseGOP(vid_stream) != PARSE_OK) goto error; case PICTURE_START_CODE: /* Picture start code. Parse picture header and first slice header. */ status = ParsePicture(vid_stream, time_stamp); if (status == SKIP_PICTURE) { next_start_code(); fprintf(stderr, "Skipping picture..."); while (!next_bits(32, PICTURE_START_CODE)) { if (next_bits(32, GOP_START_CODE)) break; else if (next_bits(32, SEQ_END_CODE)) break; flush_bits(24); next_start_code(); } fprintf(stderr, "Done.\n"); goto done; } else if (status != PARSE_OK) goto error; if (ParseSlice(vid_stream) != PARSE_OK) goto error; break; default: /* Check for slice start code. */ if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) { /* Slice start code. Parse slice header. */ if (ParseSlice(vid_stream) != PARSE_OK) goto error; } break; } /* Parse next MB_QUANTUM macroblocks. */ for (i = 0; i < MB_QUANTUM; i++) { /* Check to see if actually a startcode and not a macroblock. */ if (!next_bits(23, 0x00000000)) { /* Not start code. Parse Macroblock. */ if (ParseMacroBlock(vid_stream) != PARSE_OK) goto error;#ifdef ANALYSIS if (showmb_flag) { DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr, vid_stream->current->Cb, vid_stream->current->display, vid_stream->mb_height * 16, vid_stream->mb_width * 16); /* ExecuteDisplay(vid_stream);*/ }#endif } else { /* Not macroblock, actually start code. Get start code. */ next_start_code(); show_bits32(data); /* * If start code is outside range of slice start codes, frame is * complete, display frame. */ if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {#ifdef ANALYSIS EndTime(); stat_a[0].totsize += bitCountRead() - pictureSizeCount; if (showEachFlag) { PrintOneStat(); }; CollectStats();#endif DoPictureDisplay(vid_stream); } break; } } goto done;error: fprintf(stderr, "Error!!!!\n"); next_start_code(); goto done;done: /* Copy global bit i/o variables back into vid_stream. */ vid_stream->buffer = bitBuffer; vid_stream->buf_length = bufLength; vid_stream->bit_offset = bitOffset; return(0);}/* *-------------------------------------------------------------- * * ParseSeqHead -- * * Assumes bit stream is at the begining of the sequence * header start code. Parses off the sequence header. * * Results: * Fills the vid_stream structure with values derived and * decoded from the sequence header. Allocates the pict image * structures based on the dimensions of the image space * found in the sequence header. * * Side effects: * Bit stream irreversibly parsed off. * *-------------------------------------------------------------- */static intParseSeqHead(VidStream *vid_stream){ unsigned int data; int i; /* Flush off sequence start code. */ flush_bits32; /* Get horizontal size of image space. */ get_bits12(data); vid_stream->h_size = data; /* Get vertical size of image space. */ get_bits12(data); vid_stream->v_size = data; /* Calculate macroblock width and height of image space. */ vid_stream->mb_width = (vid_stream->h_size + 15) / 16; vid_stream->mb_height = (vid_stream->v_size + 15) / 16; /* If dither type is MBORDERED allocate ditherFlags. */ if (ditherType == MBORDERED_DITHER) { ditherFlags = (char *) mxCalloc(vid_stream->mb_width*vid_stream->mb_height, sizeof(char)); } /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */ lmaxx = vid_stream->mb_width*16-1; lmaxy = vid_stream->mb_height*16-1; cmaxx = vid_stream->mb_width*8-1; cmaxy = vid_stream->mb_height*8-1; /* * Initialize ring buffer of pict images now that dimensions of image space * are known. *//*#ifdef SH_MEM if (display != NULL) { InstallXErrorHandler(); }#endif*/ if (vid_stream->ring[0] == NULL) { for (i = 0; i < RING_BUF_SIZE; i++) { vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16, vid_stream->mb_height * 16); } }/*#ifdef SH_MEM if (display != NULL) { DeInstallXErrorHandler(); }#endif*/ /* Parse of aspect ratio code. */ get_bits4(data); vid_stream->aspect_ratio = (unsigned char) data; /* Parse off picture rate code. */ get_bits4(data); vid_stream->picture_rate = (unsigned char) data; /* Parse off bit rate. */ get_bits18(data); vid_stream->bit_rate = data; /* Flush marker bit. */ flush_bits(1); /* Parse off vbv buffer size. */ get_bits10(data); vid_stream->vbv_buffer_size = data; /* Parse off contrained parameter flag. */ get_bits1(data); if (data) { vid_stream->const_param_flag = TRUE; } else vid_stream->const_param_flag = FALSE; /* * If intra_quant_matrix_flag set, parse off intra quant matrix values. */ get_bits1(data); if (data) { for (i = 0; i < 64; i++) { get_bits8(data); vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] = (unsigned char) data; } } /* * If non intra quant matrix flag set, parse off non intra quant matrix * values. */ get_bits1(data); if (data) { for (i = 0; i < 64; i++) { get_bits8(data); vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] = (unsigned char) data; } } /* Go to next start code. */ next_start_code(); /* * If next start code is extension start code, parse off extension data. */ if (next_bits(32, EXT_START_CODE)) { flush_bits32; if (vid_stream->ext_data != NULL) { /*mxFree(vid_stream->ext_data);*/ vid_stream->ext_data = NULL; } vid_stream->ext_data = get_ext_data(); } /* If next start code is user start code, parse off user data. */ if (next_bits(32, USER_START_CODE)) { flush_bits32; if (vid_stream->user_data != NULL) { /*mxFree(vid_stream->user_data);*/ vid_stream->user_data = NULL; } vid_stream->user_data = get_ext_data(); } return PARSE_OK;}/* *-------------------------------------------------------------- * * ParseGOP -- * * Parses of group of pictures header from bit stream * associated with vid_stream. * * Results: * Values in gop header placed into video stream structure. * * Side effects: * Bit stream irreversibly parsed. * *-------------------------------------------------------------- */static intParseGOP(VidStream *vid_stream){ unsigned int data; /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */ flush_bits32; /* Parse off drop frame flag. */ get_bits1(data); if (data) { vid_stream->group.drop_flag = TRUE; } else vid_stream->group.drop_flag = FALSE; /* Parse off hour component of time code. */ get_bits5(data); vid_stream->group.tc_hours = data; /* Parse off minute component of time code. */ get_bits6(data); vid_stream->group.tc_minutes = data; /* Flush marker bit. */ flush_bits(1); /* Parse off second component of time code. */ get_bits6(data); vid_stream->group.tc_seconds = data; /* Parse off picture count component of time code. */ get_bits6(data); vid_stream->group.tc_pictures = data; /* Parse off closed gop and broken link flags. */ get_bits2(data); if (data > 1) { vid_stream->group.closed_gop = TRUE; if (data > 2) { vid_stream->group.broken_link = TRUE; } else vid_stream->group.broken_link = FALSE; } else { vid_stream->group.closed_gop = FALSE; if (data) { vid_stream->group.broken_link = TRUE; } else vid_stream->group.broken_link = FALSE; } /* Goto next start code. */ next_start_code(); /* If next start code is extension data, parse off extension data. */ if (next_bits(32, EXT_START_CODE)) { flush_bits32; if (vid_stream->group.ext_data != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -