Beispiel #1
0
/* ----------------------------- MNI Header -----------------------------------
@NAME       : GetMPEGFrame
@INPUT      :
@OUTPUT     : Frame - the image data, converted to RGB space, is
              copied to the area pointed to by Frame.  There must be
              enough room for the entire image; the ImageDesc
              structure returned by OpenMPEG() will tell you just how
              much memory this is.  The format of the data depends on
              the dithering type; for full colour dithering, there are
              four bytes per pixel: red, green, blue, and unused.
              (Perfect for passing to lrectwrite() or XPutImage().)
@RETURNS    : TRUE if there are still frames left to decode
              FALSE if we have just decoded the last frame
@DESCRIPTION: Part of the MNI front end to the Berkeley MPEG decoder.
              Essentially reads, decodes, and converts to RGB space the
	      next frame in the MPEG stream opened with OpenMPEG().
@METHOD     :
@GLOBALS    : theStream
              CurrentImage
@CALLS      : mpegVidRsrc ()
@CREATED    : 94/6/16, Greg Ward
@MODIFIED   :
---------------------------------------------------------------------------- */
Boolean GetMPEGFrame (char *Frame) {
    Boolean   MovieDone = FALSE;

    FrameDone = FALSE;
    mpeg_debug (("GetMPEGFrame: starting or continuing movie\n"));

    while (!MovieDone && !FrameDone) { /* FrameDone is set by ExecuteDisplay() */
        MovieDone = (mpegVidRsrc (0, theStream) == NULL);
    }

    mpeg_debug (("\nGetMPEGFrame: just received a finished frame: "
                 "copying from %08X to %08X\n", CurrentImage, Frame));

    if (!MovieDone)
        memcpy (Frame, CurrentImage, ImageInfo.Size);
    return (!MovieDone);

}     /* GetMPEGFrame () */
Beispiel #2
0
/* ----------------------------- MNI Header -----------------------------------
@NAME       : OpenMPEG
@INPUT      : MPEGfile - pointer to a stream opened for reading, positioned
                         at the beginning of an MPEG stream
	      ImgInfo  - pointer to an ImageDesc structure which will have
	                 information such as frame height, width, depth
			 and size (total bytes per frame) put in it.
@OUTPUT     :
@RETURNS    :
@DESCRIPTION: Creates and initializes the variables needed to start
              reading/decoding an MPEG stream.

              This function is part of the MNI front end to the Berkeley
	      MPEG decoder, adapted from the original Berkeley code.
@METHOD     :
@GLOBALS    : theStream
              ditherType
	      input
	      LUM_RANGE, CR_RANGE, CB_RANGE
	      lum_values, cr_values, cb_values
@CALLS      : GetMPEGInfo()
              init_tables()
              InitDither()
@CREATED    : 94/6/16, Greg Ward (adapted from main() in the original
              Berkeley source)
@MODIFIED   :
---------------------------------------------------------------------------- */
Boolean OpenMPEG (FILE *MPEGfile, ImageDesc *ImgInfo) {
    /*
     * First reinitialize these globals in case we're opening a second
     * (or more) file - thanks to Loring Holding <*****@*****.**>
     * for the patch.
     */

    curBits = bitOffset = bufLength = 0;
    EOF_flag = FALSE;


    /*
     * Create the video stream and read the first chunk to get movie
     * stats -- width and height in particular.
     */

    theStream = NewVidStream(BUF_LENGTH);
    if (theStream == NULL) {
        fprintf (stderr, "Error creating video stream\n");
        return (FALSE);
    }

    input = MPEGfile;
    if (mpegVidRsrc(0, theStream) == NULL) {
        fprintf (stderr, "Error reading video stream, or stream empty\n");
        return (FALSE);
    }

    GetMPEGInfo (theStream, ImgInfo);

    /* Allocate/initialize tables used for dithering (?) */

    lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
    cr_values = (int *) malloc(CR_RANGE*sizeof(int));
    cb_values = (int *) malloc(CB_RANGE*sizeof(int));

    init_tables();		/* initialize decoding stuff */

    InitDither (ImgInfo);	/* initializes dithering structures and */
    /* colormap (i.e. this is where we do */
    /* all dither-specific stuff) */
    return (TRUE);
}     /* OpenMPEG () */
/*
======================================================================
mexFunction

This is the Matlab interface function for the MPEG to Matlab decoder.
This routine initializes variables, creates the output matrices and
calls the MPEG encoder functions to decode the MPEG file.

======================================================================
*/
void
mexFunction(int nlhs,
	    mxArray *plhs[],
	    int nrhs,
	    const mxArray *prhs[])
{
  char filename[256];             /* input MPEG file name */
  char err_text[80];              /* string to hold error message */
  static VidStream *theStream;    /* pointer to Video Stream struct. */
  int h,i,j,k;                    /* loop counters */
  double *cm;                     /* pointer to colormap matrix values */
  double *movie;                  /* pointer to movie matrix values */
  double *red;                    /* pointer to R,G,B matrix values */
  double *green;
  double *blue;
  int movie_rows;                 /* number of rows in movie matrix */
  int num_pix_doubles;            /* number of doubles used by each frame */
  int n_colors;                   /* number of colors in colormap */
  unsigned char r,g,b;            /* hold RGB values converted from YUV */
  unsigned char *m_ptr;           /* pointer to bytes in movie matrix */
  double *r_ptr;                  /* pointers to doubles in R,G,B matrices */
  double *g_ptr;
  double *b_ptr;
  unsigned int lum, crom;         /* indices into luminance and crominance */
  int vid_status;                 /* holds return from main decoder call */
  int last_frame;                 /* holds last frame requested by user */
  int n_req_frames;               /* number of requested frames */
  double *req_frames;             /* points to array of frame numbers */
  int frames_stored;              /* counts # of frames stored in matrix */
  int no_colormap;                /* whether or not to return colormap */
  int rgb_format;                 /* RGB if true, otherwise colormapped */
  int NewOutput = 0;              /* 0: Pre-5.3 movie format, 1: 5.3+ movie format */
  int NewTrueColorOutput = 0;     /* 0: Indexed movie, 1: TrueColor movie */
  unsigned int temp_int;          /* used as temp storage for flipping bytes*/
  mxArray *fid[2], *filestr[2];    /* matrices used in searching Matlab path */


  /* check arguments */
  no_colormap = 1;
  rgb_format = 0;
  if (nlhs == 2)
    no_colormap = 0;
  else if (nlhs == 3)
    rgb_format = 1;

  else if (nlhs > 3)
    mexErrMsgTxt("Too many output arguments.");
  else if (nlhs < 1)
    mexErrMsgTxt("Too few output arguments.");

  if (nrhs < 1)
    mexErrMsgTxt("Too few input arguments.");
  if (nrhs > 3)
    mexErrMsgTxt("Too many input arguments.");

  if (!mxIsChar(prhs[0]))
    mexErrMsgTxt("First argument (file name) must be a string.");

  mxGetString(prhs[0], filename, 256);

  /* get list of frame numbers if passed*/
  if ((nrhs >= 2) && (!mxIsEmpty(prhs[1])))
  {
    if (mxGetN(prhs[1]) > 1)
    {
      n_req_frames = mxGetN(prhs[1]);
      if (mxGetM(prhs[1]) > 1)
        mexErrMsgTxt("Second argument must be a vector");
    }
    else
    {
      n_req_frames = mxGetM(prhs[1]);
    }
    req_frames = mxGetPr(prhs[1]);

    /* find the highest number frame requested */
    last_frame = 1;
    for (j = 0; j < n_req_frames; j++)
    {
      if ((int)req_frames[j] > last_frame)
        last_frame = (int)req_frames[j];
    }
  }
  else
  {
    last_frame = 0;
    n_req_frames = 0;
  }

  if (nrhs == 3) {
    char str[100];
    mxGetString(prhs[2], str, 100);
    if (strcmp(str, "truecolor") == 0) {
      NewTrueColorOutput = 1;
    }
    NewOutput = 1;
  }

  /* open the MPEG file */
  /* call Matlab to search the Matlab path */
  filestr[0] = mxCreateString(filename);
  mexCallMATLAB(1,fid,1,filestr,"fopen");
  if (*(mxGetPr(fid[0])) == -1)
  {
    if (strchr(filename, '.') == NULL)
    {
      strcat(filename, ".mpg");
      mxDestroyArray(filestr[0]);
      mxDestroyArray(fid[0]);
      filestr[0] = mxCreateString(filename);
      mexCallMATLAB(1,fid,1,filestr,"fopen");
      if (*mxGetPr(fid[0]) == -1)
        mexErrMsgTxt("Could not open file.");
    }
    else
      mexErrMsgTxt("Could not open file.");
  }
  mxDestroyArray(filestr[0]);
  mexCallMATLAB(1,filestr,1,fid,"fopen");
  mxGetString(filestr[0], filename, 255);
  mxDestroyArray(filestr[0]);
  mexCallMATLAB(1,filestr,1,fid,"fclose");
  mxDestroyArray(fid[0]);
  mxDestroyArray(filestr[0]);
#ifdef WIN32
  input = fopen(filename, "rb");
#else
  input = fopen(filename, "r");
#endif
  if (input == NULL) {
    mexErrMsgTxt("Could not open file.");
  }

  /* initialization */
  ditherType = ORDERED2_DITHER;
  LUM_RANGE = 8;
  CR_RANGE = CB_RANGE = 4;
  noDisplayFlag = 0;

#ifdef SH_MEM
  shmemFlag = 1;
#endif

  init_tables();

  InitColor();
  InitOrdered2Dither();

  
  EOF_flag = 0;
  curBits = 0;
  bitOffset = 0;
  bufLength = 0;
  bitBuffer = NULL;
  totNumFrames = 0;
  
  start_decode = 1;
  curVidStream = NULL;
  theStream = NewVidStream(BUF_LENGTH);
  if (theStream == NULL)
    mexErrMsgTxt("Out of memory.");

  /* parse the MPEG header */
  mpegVidRsrc(0, theStream);

  /* create the movie and colormap Matrices */
  n_colors = LUM_RANGE*CB_RANGE*CR_RANGE;

  /*realTimeStart = ReadSysClock();*/

  if (n_req_frames == 0)
  {
    /* if user did not specify frames to get, one pass is needed to determine
     * the number of frames before actually putting them into the matrix */
    vid_status = 0;
    while (vid_status != 1)
    {
      vid_status = mpegVidRsrc(0, theStream);
    }
    n_req_frames = last_frame = totNumFrames;
    req_frames = (double *)mxCalloc(n_req_frames, sizeof(double));
    for (i = 0; i < n_req_frames; i++)
      req_frames[i] = i+1;
    DestroyVidStream(theStream);
    rewind(input);
    EOF_flag = 0;
    curBits = 0;
    bitOffset = 0;
    bufLength = 0;
    bitBuffer = NULL;
    totNumFrames = 0;
    theStream = NewVidStream(BUF_LENGTH);
    mpegVidRsrc(0, theStream);
  }

  /* create the output matrices */
  if (NewOutput) 
    {
      char *fieldnames[] = {"cdata", "colormap"};
      plhs[0] = mxCreateStructMatrix(1, n_req_frames, 2, (const char **)fieldnames);
      if (NewTrueColorOutput) 
	{
	  int i;
	  int dims[3];
	  dims[0] = theStream->v_size; dims[1] = theStream->h_size; dims[2] = 3;
	  for (i = 0; i < n_req_frames; i++) 
	    {
	      mxArray *cdata = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL);
	      mxSetField(plhs[0], i, "cdata", cdata);
	    }
	}
      else
	{
	  int i;
	  int dims[2];
	  dims[0] = theStream->v_size; dims[1] = theStream->h_size;
	  for (i = 0; i < n_req_frames; i++) 
	    {
	      mxArray *cdata = mxCreateNumericArray(2, dims, mxUINT8_CLASS, mxREAL);
	      mxArray *colormap = mxCreateDoubleMatrix(n_colors, 3, mxREAL);
	      mxSetField(plhs[0], i, "cdata", cdata);
	      mxSetField(plhs[0], i, "colormap", colormap);
	      
	      {
		/* Fill in the colormap */
		double *cm = mxGetPr(colormap);
		int j;
		for (j = 0; j < n_colors; j++)
		  {
		    /* fprintf(stderr, "Color: %d\n", j); */
		    ConvertColor(lum_values[(j/(CR_RANGE*CB_RANGE))%LUM_RANGE],
				 cr_values[(j/CB_RANGE)%CR_RANGE],
				 cb_values[j%CB_RANGE], 
				 &r, &g, &b);
		    cm[j] = (double)r/255;
		    cm[n_colors + j] = (double)g/255;
		    cm[n_colors * 2 + j] = (double)b/255;
		  }
	      }
	    }
	}
    }
  else
    {
      if (rgb_format)
	{
	  plhs[0] = mxCreateDoubleMatrix(theStream->v_size, theStream->h_size*n_req_frames,
					 mxREAL);
	  if (plhs[0] == NULL)
	    mexErrMsgTxt("Out of memory.");

	  plhs[1] = mxCreateDoubleMatrix(theStream->v_size, theStream->h_size*n_req_frames,
					 mxREAL);
	  if (plhs[1] == NULL)
	    mexErrMsgTxt("Out of memory.");

	  plhs[2] = mxCreateDoubleMatrix(theStream->v_size, theStream->h_size*n_req_frames,
					 mxREAL);
	  if (plhs[2] == NULL)
	    mexErrMsgTxt("Out of memory.");

	  red = mxGetPr(plhs[0]);
	  green = mxGetPr(plhs[1]);
	  blue = mxGetPr(plhs[2]);
	  movie_rows = mxGetM(plhs[0]);
	}
      else
	{
	  num_pix_doubles = (int)((theStream->h_size*theStream->v_size + 7)/8);
  
	  if (n_req_frames > 0)
	    plhs[0] = mxCreateDoubleMatrix(388 + num_pix_doubles, n_req_frames, mxREAL);

	  if (plhs[0] == NULL)
	    mexErrMsgTxt("Out of memory.");
	  movie = mxGetPr(plhs[0]);
	  movie_rows = mxGetM(plhs[0]);
	}

      if (!no_colormap)
	{
	  plhs[1] = mxCreateDoubleMatrix(n_colors, 3, mxREAL);
	  if (plhs[1] == NULL)
	    mexErrMsgTxt("Out of memory.");
	  cm = mxGetPr(plhs[1]);
	  /* create a Matlab colormap */
	  /* fprintf(stderr, "About to create colormap\n");*/
	  for (j = 0; j < n_colors; j++)
	    {
	      /* fprintf(stderr, "Color: %d\n", j); */
	      ConvertColor(lum_values[(j/(CR_RANGE*CB_RANGE))%LUM_RANGE],
			   cr_values[(j/CB_RANGE)%CR_RANGE],
			   cb_values[j%CB_RANGE], 
			   &r, &g, &b);
	      cm[j] = (double)r/255;
	      cm[n_colors + j] = (double)g/255;
	      cm[n_colors * 2 + j] = (double)b/255;
	    }
	}
    }
  /*fprintf(stderr, "movie rows: %d\n", movie_rows);*/

  /* get requested frames and store them in output martrix (matrices).*/
  frames_stored = 0;
  for (j = 1; j <= last_frame; j++)
  {
    /*fprintf(stderr, "Generating frame #%d\n", j);*/
    while (totNumFrames < j)
    {
      vid_status = mpegVidRsrc(0, theStream);
      if (vid_status == 1)
      {
        sprintf(err_text, "Frame(s) requested beyond last frame (%d).",
                totNumFrames);
	mexErrMsgTxt(err_text);
      }
    } 

    /* store this frame wherever it has been requested */   
    for (i = 0; i < n_req_frames; i++)
    {
      if ((int)req_frames[i] == j)
      {
        frames_stored++;
        
	if (NewOutput) 
	  {
	    mxArray *cdata = mxGetField(plhs[0], i, "cdata");
	    unsigned char *pr = (unsigned char *)mxGetPr(cdata);
	    if (NewTrueColorOutput) 
	      {
		unsigned char *pg = pr + theStream->v_size * theStream->h_size;
		unsigned char *pb = pg + theStream->v_size * theStream->h_size;

		lum = 0;
		crom = 0;
		for (h = 0; h < theStream->h_size; h++) 
		  {
		    lum = h;
		    crom = h/2;
		    for (k = 0; k < theStream->v_size; k++) 
		      {
			ConvertColor(*(curVidStream->current->luminance + lum),
				     *(curVidStream->current->Cr + crom),
				     *(curVidStream->current->Cb + crom),
				     &r, &g, &b);
			*pr = (unsigned char)r;
			*pg = (unsigned char)g;
			*pb = (unsigned char)b;
			pr++; pg++; pb++;

			lum += theStream->h_size;
			if ((k % 2) == 1)
			  {
			    crom += theStream->h_size / 2;
			  }
		      }
		  }
	      }
	    else
	      {
		int index = 0;
		for (h = 0; h < theStream->h_size; h++) 
		  {
		    for (k = 0; k < theStream->v_size; k++) 
		      {
			index = k * theStream->h_size + h;
			*pr = *(curVidStream->current->display + index);
			pr++;
		      }
		  }
	      }
	  }
	else
	  {
	    if (rgb_format)
	      {
		lum = 0;
		crom = 0;
		for (h = 0; h < theStream->v_size; h++)
		  {
		    r_ptr = red + theStream->v_size*theStream->h_size * i + h;
		    g_ptr = green + theStream->v_size*theStream->h_size * i + h;
		    b_ptr = blue + theStream->v_size*theStream->h_size * i + h;
		    for (k = 0; k < theStream->h_size; k++)
		      {
			ConvertColor(*(curVidStream->current->luminance + lum),
				     *(curVidStream->current->Cr + crom),
				     *(curVidStream->current->Cb + crom),
				     &r, &g, &b);
			*r_ptr = (double)r/255;
			*g_ptr = (double)g/255;
			*b_ptr = (double)b/255;
              
			r_ptr += theStream->v_size;
			g_ptr += theStream->v_size;
			b_ptr += theStream->v_size;

			lum++;
			if (k%2 == 0)
			  crom++;
		      }
		    if (h%2 == 0)
		      crom -= theStream->h_size / 2;
		  }
	      }
	    else
	      {
		/* create Matlab movie frame header */
		m_ptr = (unsigned char *)(movie + (movie_rows * i));
		*((double *)m_ptr) = curVidStream->h_size;
		m_ptr += sizeof(double);
		*((double *)m_ptr) = curVidStream->v_size;
		m_ptr += sizeof(double);
		*((double *)m_ptr) = 0;
		m_ptr += sizeof(double);
		if (MOVIE_GetClientByteOrder() == ELITTLE_ENDIAN)
		  {
		    *((int *)m_ptr) = 0;
		    m_ptr += sizeof(int);
		    *((int *)m_ptr) = LUM_RANGE*CB_RANGE*CR_RANGE;
		    m_ptr += sizeof(int);
		  }
		else
		  {
		    *((int *)m_ptr) = LUM_RANGE*CB_RANGE*CR_RANGE;
		    m_ptr += sizeof(int);
		    *((int *)m_ptr) = 0;
		    m_ptr += sizeof(int);
		  }
		m_ptr += 256*3*sizeof(float);

          /* copy frame data into movie matrix */
		memcpy(m_ptr, curVidStream->current->display, 
		       (theStream->h_size*theStream->v_size));
		if (MOVIE_GetClientByteOrder() == ELITTLE_ENDIAN)
		  {
		    for (k = 0; k < (movie_rows - 388); k++)
		      {
			temp_int = FLIPBYTES(*((unsigned int *)m_ptr));
			*((unsigned int *)m_ptr) = 
			  FLIPBYTES(*((unsigned int *)m_ptr + 1));
			*((unsigned int *)m_ptr + 1) = temp_int;
			m_ptr += sizeof(double);
		      }
		  }
	      }
	  }
      }
    }
  }


  /* destroy the video stream */
  DestroyVidStream(theStream);
  fclose(input);
}