📄 mptest.c
字号:
/*
* 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 + -