⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.c

📁 mpeng Lib
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 1992 The Regents of the University of California. * All rights reserved.   * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *//* This file contains C code that implements * the video decoder model. */#include <config.h>#include <stdio.h>#include <stdlib.h>#include <assert.h>#ifndef MIPS# ifdef _MSC_VER#  include <sys/utime.h># else#  ifdef __BORLANDC__#   include <utime.h>#  else#   include <sys/time.h>#  endif# endif#else# include <sys/types.h># include <sys/system.h>#endif#include "globals.h"#include "decoders.h"#include "video.h"#include "util.h"#include "proto.h"#include "my_dmalloc.h"/* Declarations of functions. */static void ReconIMBlock(VidStream *,int);static void ReconPMBlock(VidStream *,int,int,int,int);static void ReconBMBlock(VidStream *,int,int,int,int);static void ReconBiMBlock(VidStream *,int,int,int,int,int,int);static void ReconSkippedBlock(unsigned char *,unsigned char *,int,int,int,int,int,int,int,int);static void DoPictureDisplay(VidStream *);static int ParseSeqHead(VidStream *);static int ParseGOP(VidStream *);static int ParsePicture(VidStream *,TimeStamp);static int ParseSlice(VidStream *);static int ParseMacroBlock(VidStream *);static void ProcessSkippedPFrameMBlocks(VidStream *);static void ProcessSkippedBFrameMBlocks(VidStream *);char *ditherFlags;/* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))/* Declare global pointer to vid stream used for current decoding. */VidStream *curVidStream = NULL;/* Set up array for fast conversion from zig zag order to row/column   coordinates.*/int zigzag[64][2] = {  0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,  2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,  3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,  1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,  2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,7, 5, 7, 6, 6, 7, 7, 7};/* Array mapping zigzag to array pointer offset. */int zigzag_direct[64] = {  0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,  19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,  42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};/* Set up array for fast conversion from row/column coordinates to   zig zag order.*/int scan[8][8] = {  {0, 1, 5, 6, 14, 15, 27, 28},  {2, 4, 7, 13, 16, 26, 29, 42},  {3, 8, 12, 17, 25, 30, 41, 43},  {9, 11, 18, 24, 31, 40, 44, 53},  {10, 19, 23, 32, 39, 45, 52, 54},  {20, 22, 33, 38, 46, 51, 55, 60},  {21, 34, 37, 47, 50, 56, 59, 61},{35, 36, 48, 49, 57, 58, 62, 63}};/* Initialize P and B skip flags. */static int No_P_Flag = 0;static int No_B_Flag = 0;/* Max lum, chrom indices for illegal block checking. */static int lmaxx;static int lmaxy;static int cmaxx;static int cmaxy;/* * We use a lookup table to make sure values stay in the 0..255 range. * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this * table the "crop table". * MAX_NEG_CROP is the maximum neg/pos value we can handle. */#define MAX_NEG_CROP 384#define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP)#define assertCrop(x)	assert(((x) >= -MAX_NEG_CROP) && \			       ((x) <= 256+MAX_NEG_CROP))static unsigned char cropTbl[NUM_CROP_ENTRIES];/* *-------------------------------------------------------------- * * NewVidStream -- * *	Allocates and initializes a VidStream structure. Takes *      as parameter requested size for buffer length. * * Results: *	A pointer to the new VidStream structure. * * Side effects: *      None. * *-------------------------------------------------------------- */VidStream *NewVidStream(bufLength)  int bufLength;{  int i, j;  VidStream *new;  static unsigned char default_intra_matrix[64] = {    8, 16, 19, 22, 26, 27, 29, 34,    16, 16, 22, 24, 27, 29, 34, 37,    19, 22, 26, 27, 29, 34, 34, 38,    22, 22, 26, 27, 29, 34, 37, 40,    22, 26, 27, 29, 32, 35, 40, 48,    26, 27, 29, 32, 35, 40, 48, 58,    26, 27, 29, 34, 38, 46, 56, 69,  27, 29, 35, 38, 46, 56, 69, 83};  /* Check for legal buffer length. */  if (bufLength < 4)    return NULL;  /* Make buffer length multiple of 4. */  bufLength = (bufLength + 3) >> 2;  /* Allocate memory for new structure. */  new = (VidStream *) malloc(sizeof(VidStream));  /* Initialize pointers to extension and user data. */  new->group.ext_data = new->group.user_data =    new->picture.extra_info = new->picture.user_data =    new->picture.ext_data = new->slice.extra_info =    new->ext_data = new->user_data = NULL;  /* Copy default intra matrix. */  for (i = 0; i < 8; i++) {    for (j = 0; j < 8; j++) {      new->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j];    }  }  /* Initialize crop table. */  for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {    if (i <= 0) {      cropTbl[i + MAX_NEG_CROP] = 0;    } else if (i >= 255) {      cropTbl[i + MAX_NEG_CROP] = 255;    } else {      cropTbl[i + MAX_NEG_CROP] = i;    }  }  /* Initialize non intra quantization matrix. */  for (i = 0; i < 8; i++) {    for (j = 0; j < 8; j++) {      new->non_intra_quant_matrix[j][i] = 16;    }  }  /* Initialize pointers to image spaces. */  new->current = new->past = new->future = NULL;  for (i = 0; i < RING_BUF_SIZE; i++) {    new->ring[i] = NULL;  }  /* Create buffer. */  new->buf_start = (unsigned int *) malloc(bufLength * 4);  /*   * Set max_buf_length to one less than actual length to deal with messy   * data without proper seq. end codes.   */  new->max_buf_length = bufLength - 1;  /* Initialize bitstream i/o fields. */  new->bit_offset = 0;  new->buf_length = 0;  new->buffer = new->buf_start;  /* Return structure. */  return new;}/* *-------------------------------------------------------------- * * DestroyVidStream -- * *	Deallocates a VidStream structure. * * Results: *      None. * * Side effects: *	None. * *-------------------------------------------------------------- */voidDestroyVidStream(astream)  VidStream *astream;{  int i;  if (astream->ext_data != NULL)    free(astream->ext_data);  if (astream->user_data != NULL)    free(astream->user_data);  if (astream->group.ext_data != NULL)    free(astream->group.ext_data);  if (astream->group.user_data != NULL)    free(astream->group.user_data);  if (astream->picture.extra_info != NULL)    free(astream->picture.extra_info);  if (astream->picture.ext_data != NULL)    free(astream->picture.ext_data);  if (astream->picture.user_data != NULL)    free(astream->picture.user_data);  if (astream->slice.extra_info != NULL)    free(astream->slice.extra_info);  if (astream->buf_start != NULL)    free(astream->buf_start);  for (i = 0; i < RING_BUF_SIZE; i++) {    if (astream->ring[i] != NULL) {      DestroyPictImage(astream->ring[i]);      astream->ring[i] = NULL;    }  }  free((char *) astream);}/* *-------------------------------------------------------------- * * NewPictImage -- * *	Allocates and initializes a PictImage structure. *      The width and height of the image space are passed in *      as parameters. * * Results: *	A pointer to the new PictImage structure. * * Side effects: *	None. * *-------------------------------------------------------------- */PictImage *NewPictImage(width, height)  unsigned int width, height;{  PictImage *new;  /* Allocate memory space for new structure. */  new = (PictImage *) malloc(sizeof(PictImage));  /* Allocate memory for image spaces. */  if ((ditherType == Twox2_DITHER) || (ditherType == FULL_COLOR_DITHER)) {    new->display = (unsigned char *) malloc(width * height * 4);  } else {    new->display = (unsigned char *) malloc(width * height);  }  new->luminance = (unsigned char *) malloc(width * height);  new->Cr = (unsigned char *) malloc(width * height / 4);  new->Cb = (unsigned char *) malloc(width * height / 4);  /* Reset locked flag. */  new->locked = 0;  /* Return pointer to new structure. */  return new;}/* *-------------------------------------------------------------- * * DestroyPictImage -- * *	Deallocates a PictImage structure. * * Results: *      None. * * Side effects: *	None. * *-------------------------------------------------------------- */voidDestroyPictImage(apictimage)  PictImage *apictimage;{  if (apictimage->luminance != NULL) {    free(apictimage->luminance);  }  if (apictimage->Cr != NULL) {    free(apictimage->Cr);  }  if (apictimage->Cb != NULL) {    free(apictimage->Cb);  }  if (apictimage->display != NULL) {    free(apictimage->display);  }  free(apictimage);}/* *-------------------------------------------------------------- * * mpegVidRsrc -- * *      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. * *      Note that multiple calls to mpegVidRsrc are required  *      decode each frame in the movie.  When mpegVidRsrc has *      determined that it has decoded a single frame, it calls *      DoPictureDisplay(), which converts from YUV space to RGB *      space and then calls ExecuteDisplay().  ExecuteDisplay() *      is passed the currently-being-decoded video stream, which *      has a field called current (a pointer to a PictImage)  *      which in turn points to the raw image data in some  *      X-friendly RGB format. *      *      When the last frame has been decoded, mpegVidRsrc calls *      ExecuteDisplay() one last time (if necessary), destroys *      the video stream, and returns NULL. * * Results: *      A pointer to the video stream structure used, or NULL *      if the last frame has just been finished. * * Side effects: *      Bit stream is irreversibly parsed. If a picture is completed, *      a function is called to display the frame at the correct time. * *-------------------------------------------------------------- */VidStream *mpegVidRsrc(time_stamp, vid_stream)  TimeStamp time_stamp;  VidStream *vid_stream;{  static int num_calls = 0;  unsigned int data;  int i, status;  long int ftell (FILE *stream);  /* If vid_stream is null, create new VidStream structure. */  if (vid_stream == NULL) {    return NULL;  }  /*   * 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 (num_calls == 0) {    next_start_code();    show_bits32(data);    if (data != SEQ_START_CODE) {      fprintf(stderr, "This is not an MPEG stream.");      DestroyVidStream(curVidStream);      exit(1);    }    num_calls++;  }  /* 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.   */  mpeg_debug (("mpegVidRsrc: offset %6ld: found ", ftell (input)));  switch (data) {  case SEQ_END_CODE:    /* Display last frame. */    mpeg_debug (("SEQ_END_CODE\n"));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -