/* ----------------------------- 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); }