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

📄 mptest.c

📁 用于TM1300/PNX1300系列DSP(主要用于视频处理)的外部设备的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
 /*
 * Copyright (c) 1997,1998,1999,2000 by TriMedia Technologies. 
 *
 * +------------------------------------------------------------------+
 * | This software is furnished under a license and may only be used  |
 * | and copied in accordance with the terms and conditions of  such  |
 * | a license and with the inclusion of this copyright notice. This  |
 * | software or any other copies of this software may not be provided|
 * | or otherwise made available to any other person.  The ownership  |
 * | and title of this software is not transferred.                   |
 * |                                                                  |
 * | The information in this software is subject  to change without   |
 * | any  prior notice and should not be construed as a commitment by |
 * | TriMedia Technologies.                                           |
 * |                                                                  |
 * | this code and information is provided "as is" without any        |
 * | warranty of any kind, either expressed or implied, including but |
 * | not limited to the implied warranties of merchantability and/or  |
 * | fitness for any particular purpose.                              |
 * +------------------------------------------------------------------+
 *
 *  Module name              : mptest.c    1.19
 *
 *  Last update              : 14:45:03 - 99/01/11
 *
 *  Description              :
 *
 *    MPEG Video Decoder Controller for slice level mpeg pipe.
 *    Example application using mp device library.
 *              
 *    Provides basic verfication of mpeg pipe operation.
 *    In SELF_CHECK mode compilation DSPCPU compares decoded images 
 *    with array stored in SDRAM.
 *    
 *    With FILEIO and WRITE_TO_FILE flags compiled decoded images are stored in
 *     files for off-line comparison or viewing.
 *     usage:
 *    -file(single bitstream input) and -filelist(list of streams) are available.
 *            -z half res mode
 *            -j No vertical interpolation for Y
 *            -k No vertical interpolation for UV
 *            -m No backward prediction for B pics                
 * 
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <tm1/tmMP.h>
#include <ops/custom_defs.h>
#include <tmlib/tmlibc.h>
#include "tmalTm2VdecMpeg.h"
#include <tmlib/dprintf.h>

#ifndef QUIET
#define PRINT(x) printf x
#define MY_DP(x) DP(x)
#else
#define MY_DP(x) DP(x)
#define PRINT(x) (DP(x)) 
#endif

#ifdef SELFCHECK_REGRESSION 
#define LAST_FRAME 300
#else
#define LAST_FRAME 9
#endif

#define BITBUFSIZE  (2048)	/* bit stream DMA buffer size (bytes) */

extern unsigned long bitstream[];

#ifdef FILEIO
char FrameName[80];
static char fn[80];
static unsigned char *bits;
static int bitsfile = 0;
static int filelist = 0;
static int input_done=0;
#endif
int sequence_done=0;
int mp_error_detected=0;
int start_display=0;

unsigned long find_start_code    (ptm2MpegDecInstVars_t livp);
void  find_seq_start_code    (ptm2MpegDecInstVars_t livp);
static void program_mmio         (ptm2MpegDecInstVars_t livp);
static int  show_bits            (ptm2MpegDecInstVars_t livp, unsigned n);
static tmMpCallbackStat_t parse_slice    (UInt32 parentID);
static tmMpCallbackStat_t refill_bitbuf  (UInt32 parentID);
static tmMpCallbackStat_t handle_error   (UInt32 parentID);
static tmMpCallbackStat_t handle_success (UInt32 parentID);

int get_bits(ptm2MpegDecInstVars_t livp, unsigned n);

static void check_output(ptm2MpegDecInstVars_t livp, int framenum, unsigned long *field0[2], unsigned long *field1[2]);

/**********************************************************/
/* Device library Callback function - Set done flag*/
/**********************************************************/
static tmMpCallbackStat_t
set_done_flag(UInt32 instance)
{
  tm2MpegDecInstVars_t *livp = (ptm2MpegDecInstVars_t) instance;

  livp->mpDone = 1;
  return TMMPCALLBACK_OK;
}
/**********************************************************/
/* Callback function - Set empty flag*/
/**********************************************************/
static tmMpCallbackStat_t
empty_stub(UInt32 instance)
{
  tm2MpegDecInstVars_t *livp = (ptm2MpegDecInstVars_t) instance;
#ifdef FILEIO
  if (!input_done)
#endif
    livp->mpEmpty = 1;
  return TMMPCALLBACK_OK;
}
/**********************************************************/
/* Callback function - MP pipe error detected*/
/**********************************************************/
static tmMpCallbackStat_t
handle_error(UInt32 instance)
{
  tm2MpegDecInstVars_t *livp = (ptm2MpegDecInstVars_t) instance;
  mp_error_detected=1;
	      
  livp->callbackError = VDEC_MPEG_ERROR_FAIL;
  return TMMPCALLBACK_FAIL;
}
/**********************************************************/
/* Callback function -  Command success*/
/**********************************************************/
static tmMpCallbackStat_t
handle_success(UInt32 instance)
{

  tm2MpegDecInstVars_t *livp = (ptm2MpegDecInstVars_t) instance;
  livp->callbackError = VDEC_MPEG_CALLBACK_OK;
  return TMMPCALLBACK_OK;
}

/**********************************************************/
/* Re-fill DMA input buffer for VLD */
/**********************************************************/
static tmMpCallbackStat_t
refill_bitbuf(UInt32 instance)
{
  tm2MpegDecInstVars_t *livp = (ptm2MpegDecInstVars_t) instance;

#ifdef FILEIO
  {
  int rs;
  static int lastFramenum=0;

  if (filelist == 1) {

    static FILE * bitstreamFile = NULL;
    
    /* open filelist */
    if(bitstreamFile == NULL){
      if ((bitstreamFile = fopen (fn, "r")) == NULL){
	printf("Error opening file '%s'. Exiting.\n",fn);
	exit(-1);
      }
    }

    while (bitsfile == 0){

      int i;
      /* Get next stream from filelist */
      if (fscanf(bitstreamFile, "%s", fn) == EOF) {
	printf(" MPEG exiting no more streams\n");
	fclose(bitstreamFile);
	exit(0);
      }
      for (i=0; (fn[i] != '.') && (fn[i] != 0) ; i++) {
	FrameName[i] = fn[i];
      }
      FrameName[i]=0;
      
      printf("Doing %s\n",FrameName);
      MY_DP(("Doing %s\n",FrameName));
      input_done = 0;
      /* open the bitstream file */
      if (( bitsfile = open(fn, O_RDONLY | O_BINARY )) == -1 ) {
	printf("\n ***Error opening bitstream '%s'. *** \n",fn);	
	bitsfile = 0;
      }
      
    }
    
  } /* Filelist */

  /* read block of bits */
  rs = read(bitsfile, bits, BITBUFSIZE);
  _cache_copyback(bits, BITBUFSIZE);
  /* setup vld */
  mpInput(livp->pipeInstance, bits, BITBUFSIZE );

  /* could be equal on last packet but unlikely 1 in 2k chance*/
  /* indicates end of stream and flags for closure */
  if (rs < BITBUFSIZE) {
    input_done = 1;
  }
  }
#else

  livp->prevDMAAddr += livp->prevDMACount >> 2;
  mpInput(livp->pipeInstance, livp->prevDMAAddr, BITBUFSIZE); 
  livp->prevDMACount = BITBUFSIZE;

#endif
  return TMMPCALLBACK_OK;
  }	           

/**********************************************************/
/* Setup pipe */
/**********************************************************/
static void program_mmio(ptm2MpegDecInstVars_t livp)
{
  unsigned i;
  mpPictureInfo_t m2info;
  mpRefPtrs_t mc_info;

  livp->pictureHeight = livp->MBHeight >> (livp->ph.picture_structure != FRAME_PICTURE);

  m2info.MBWidth      = livp->MBWidth;
  m2info.MBHeight     = livp->MBHeight;
  m2info.MBRowOffset  = 0;

  m2info.pictureType  = livp->ph.picture_coding_type;
  m2info.halfResMode  = livp->halfResMode;
  m2info.noYVertHalf  = livp->noYVertHalfPel;
  m2info.noUVVertHalf = livp->noUVVertHalfPel;
  m2info.noBackwardMC = livp->noBackwardMC;

  if(livp->ph.MPEG2_Flag) { /* MPEG2 specific field settings */
    m2info.mpeg2Mode       = 1; /* set mpeg2mode flag */
    m2info.pictureStruct   = livp->ph.picture_structure;
    m2info.framePFrameD    = livp->ph.frame_pred_frame_dct;
    m2info.intraVLC        = livp->ph.intra_vlc_format;
    m2info.concealMV       = livp->ph.concealment_motion_vectors;
    m2info.topFieldFirst   = livp->ph.top_field_first;
    m2info.fullPelForward  = 0;  /* full_pel_forward = 0 */
    m2info.fullPelBackward = 0;  /* full_pel_backward = 0 */
    m2info.hForwRSize      = (livp->ph.f_code[0][0]-1);
    m2info.vForwRSize      = (livp->ph.f_code[0][1]-1);
    m2info.hBackRSize      = (livp->ph.f_code[1][0]-1);
    m2info.vBackRSize      = (livp->ph.f_code[1][1]-1);

    m2info.quantScaleType = livp->ph.q_scale_type;
    m2info.altScan        = livp->ph.alternate_scan; 
    m2info.intraDCPrecision = livp->ph.intra_dc_precision; 
  }
  else { /* MPEG1 specific field settings */
    m2info.mpeg2Mode       = 0;/* reset mpeg2mode bit */ 
    m2info.pictureStruct   = 3; /* picture structure == FRAME_PICTURE */
    m2info.framePFrameD    = 1; /* frame_pred_frame_dct==1 */
    m2info.intraVLC        = 0;
    m2info.concealMV       = 0; /* concealment_mv = 0 */
    m2info.topFieldFirst   = 0;/* top_field_first= don't care */
    m2info.fullPelForward  = livp->ph.full_pel_forward_vector;
    m2info.fullPelBackward = livp->ph.full_pel_backward_vector;
    m2info.hForwRSize      = (livp->ph.forward_f_code-1);
    m2info.vForwRSize      = (livp->ph.forward_f_code-1);
    m2info.hBackRSize      = (livp->ph.backward_f_code-1);
    m2info.vBackRSize      = (livp->ph.backward_f_code-1);

    m2info.quantScaleType = 0;
    m2info.altScan        = 0;
    m2info.intraDCPrecision = 0;
  } 


  m2info.IQSel0 = livp->IQSel0;
  m2info.IQSel1 = livp->IQSel1;
  m2info.lineSize          = livp->lineSize;

  m2info.loadIntraQuant    = (livp->ph.load_intra_quantizer_matrix != 0);
  m2info.loadNonIntraQuant = (livp->ph.load_non_intra_quantizer_matrix != 0);
  if(livp->ph.load_intra_quantizer_matrix) {
    int * m= livp->ph.intra_quantizer_matrix;
    for(i=0; i < 64; i++) {
      m2info.intraQuantMatrix[i]  = (unsigned char) *m++;
    }
  }    
  if(livp->ph.load_non_intra_quantizer_matrix) {
    int * m= livp->ph.non_intra_quantizer_matrix;
    for(i=0; i < 64; i++) {
      m2info.nonIntraQuantMatrix[i]  = (unsigned char) *m++;
    }
  }  
  mpSetPictureInfo(livp->pipeInstance, &m2info);


  mc_info.lumaDestF0      = (unsigned char *)livp->currentFrame[0][0];
  mc_info.chromaDestF0    = (unsigned char *)livp->currentFrame[0][1];
  mc_info.lumaDestF1      = (unsigned char *)livp->currentFrame[1][0];
  mc_info.chromaDestF1    = (unsigned char *)livp->currentFrame[1][1];

  mc_info.lumaForwRefF0   = (unsigned char *)livp->forwardReferenceFrame[0][0];
  mc_info.chromaForwRefF0 = (unsigned char *)livp->forwardReferenceFrame[0][1];
  mc_info.lumaForwRefF1   = (unsigned char *)livp->forwardReferenceFrame[1][0];
  mc_info.chromaForwRefF1 = (unsigned char *)livp->forwardReferenceFrame[1][1];
  mc_info.lumaBackRefF0   = (unsigned char *)livp->backwardReferenceFrame[0][0];
  mc_info.chromaBackRefF0 = (unsigned char *)livp->backwardReferenceFrame[0][1];
  mc_info.lumaBackRefF1   = (unsigned char *)livp->backwardReferenceFrame[1][0];
  mc_info.chromaBackRefF1 = (unsigned char *)livp->backwardReferenceFrame[1][1];


  if(!livp->secondField) {
    mpSetRefPtrs(livp->pipeInstance, &mc_info);
  }
  else if(livp->ph.picture_coding_type==P_TYPE) {
    if(livp->ph.picture_structure==BOTTOM_FIELD) {
      mc_info.lumaForwRefF0   = (unsigned char *)livp->backwardReferenceFrame[0][0];
      mc_info.chromaForwRefF0 = (unsigned char *)livp->backwardReferenceFrame[0][1];
    }
    else if(livp->ph.picture_structure==TOP_FIELD) {
      mc_info.lumaForwRefF1   = (unsigned char *)livp->backwardReferenceFrame[1][0];
      mc_info.chromaForwRefF1 = (unsigned char *)livp->backwardReferenceFrame[1][1];
    }	
    mpSetRefPtrs(livp->pipeInstance, &mc_info);
  }    

}
/**********************************************************/
/* Compare and verify decoded pictures against reference */
/**********************************************************/
static void check_output(ptm2MpegDecInstVars_t livp, int framenum, unsigned long *field0[2], unsigned long *field1[2])
{
  int offset;
  int frame_size;
  int cc,x,y;
  unsigned long * exp_data[2];
  extern unsigned long luma_pics[];
  extern unsigned long chroma_pics[];
  unsigned long got,got1;
  unsigned long exp,exp1;
  int fail = 0;

  exp_data[0] = luma_pics;
  exp_data[1] = chroma_pics;

  framenum--;

  frame_size = livp->codedPictureWidth * livp->codedPictureHeight >> 2;
  offset = framenum * frame_size;
  for(cc = 0; cc < 2; cc++){
    for(y = 0; y < livp->codedPictureHeight >> cc; y+=2){
      _cache_invalidate(field0[cc] + 
			((y>>1) * (livp->lineSize >> 2)),livp->codedPictureWidth);
      _cache_invalidate(field1[cc] + 
			((y>>1) * (livp->lineSize >> 2)),livp->codedPictureWidth);
      for(x = 0; x < livp->codedPictureWidth>> 2; x++){
	got = *(field0[cc] + ((y>>1) * (livp->lineSize >> 2)) + x);
	exp = *(exp_data[cc] + offset + (y * livp->codedPictureWidth >> 2) + x);

	got1 = *(field1[cc] + ((y>>1) * (livp->lineSize >> 2)) + x);
	exp1 = *(exp_data[cc] + offset + ((y+1) * livp->codedPictureWidth >> 2) + x);
	if((exp - got) || (exp1 - got1)){
	  fail = 1;
	  PRINT(("\nFrame %d mismatch at cc = %d x = %d y = %d ---\n ",framenum,cc,x,y));
	  PRINT(("F0 exp 0x%x @ 0x%x, F0 got 0x%x @ 0x%x\n F1 exp 0x%x @ 0x%x, F1 got 0x%x @ 0x%x\n",
		 exp,
		 exp_data[cc] + offset + (y * livp->codedPictureWidth >> 2) + x,
		 got,
		 field0[cc] + ((y>>1) * (livp->lineSize >> 2)) + x,
		 exp1,
		 exp_data[cc] + offset + ((y+1) * livp->codedPictureWidth >> 2) + x,
		 got1,
		 field1[cc] + ((y>>1) * (livp->lineSize >> 2)) + x));
	  exit(1); /* remove for continued mismatch dump */
	}
      }
    }
    offset >>= 1;
  }

  if (fail) {
    exit(1);
  }

  PRINT(("Verified pic %d\n",framenum));
  if(framenum + 1 >= LAST_FRAME){
    PRINT(("\n\n******Test Passed*****\n"));
    exit(0);
  }
}

/**********************************************************/
void program_vout_mmio(ptm2MpegDecInstVars_t livp) {
  if(livp->ph.picture_coding_type==B_TYPE) {
    check_output(livp,livp->bitstreamFramenum,livp->currentFrame[0],livp->currentFrame[1]);
  }  
  else {
    check_output(livp, livp->bitstreamFramenum,livp->forwardReferenceFrame[0],livp->forwardReferenceFrame[1]);
  }
}
/**********************************************************/
void Output_Last_Frame_of_Sequence(ptm2MpegDecInstVars_t livp)
{
PRINT(("Check Output last frame\n"));
  if(!livp->secondField) {
    check_output(livp, livp->bitstreamFramenum,livp->backwardReferenceFrame[0],livp->backwardReferenceFrame[1]);
  }  
} /* Output_Last_Frame_of_Sequence() */

/**********************************************************/
/* parse slice header */
/**********************************************************/	           
static tmMpCallbackStat_t
parse_slice(UInt32 instance)
{
  extern int slice_header(tm2MpegDecInstVars_t *livp, tmMPEGHdr_t *lph);
  unsigned long code;
  tm2MpegDecInstVars_t *livp = (ptm2MpegDecInstVars_t) instance;

  code = 0x100 | get_bits(livp,8);

  livp->slice_start_code = code;

  slice_header(livp,&(livp->ph));

  mpSetSliceInfo(livp->pipeInstance, (code & 0xff), livp->ph.quantizer_scale_code);
  return TMMPCALLBACK_OK;
}
/**********************************************************/
/* flush n bits from VLD buffer; 0<=n<=255 */
/**********************************************************/
void flush_buffer(ptm2MpegDecInstVars_t livp, unsigned n)
{
  unsigned long error;

#ifdef FILEIO
  if(livp->mpEmpty){
    livp->mpEmpty = 0;
    refill_bitbuf((UInt32) livp);
  }
#endif
  if(TMLIBDEV_OK != (error = mpFlushBits(livp->pipeInstance, n))){
    PRINT(("mpFlushBits failed %x\n",error));
    exit(1);
  }
} /* flush_buffer() */

/**********************************************************/
/* read n VLD SR bits with shifing; 0 <= n <= 32) */
/**********************************************************/
int get_bits(ptm2MpegDecInstVars_t livp, unsigned n)
{
  unsigned long temp,error;
  
#ifdef FILEIO

⌨️ 快捷键说明

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