📄 vldtest.c
字号:
/*
* Copyright (c) 1995-1999 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 : vldtest.c 1.22
*
* Last update : 17:37:20 - 00/11/09
*
* VLD library test program.
*
* This program parses MPEG-1 and MPEG-2 macroblocks along with other
* headers necessary to parse the macroblocks, then compare
* the result with the reference result.
* It uses interrupt to get more data in, but polls to detect
* the completion of parsing each macro block.
*/
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <tmlib/dprintf.h>
#include <tmlib/tmlibc.h>
#include <ops/custom_defs.h>
#include <tm1/tmVLD.h>
#include <tm1/tmInterrupts.h>
#include <tmlib/AppModel.h>
#include <tm1/tmHelp.h>
#define PROGRAM_VERSION "2.0"
/*
* Do up to this many frames or SEQ_END_CODE
*/
#define MAX_NUM_FRAMES 10
#define VLD_MAX_MHB 511 /* (2^9)-1 */
#define VLD_MAX_RL 4095 /* (2^12)-1 */
#define MAX_MBS 20
#define MAX_TOKENS_PER_MB (64*6)
/* MPEG video start codes */
#define PICTURE_START_CODE 0x00000100
#define SLICE_MIN_START_CODE 0x00000101
#define SLICE_MAX_START_CODE 0x000001af
#define USER_START_CODE 0x000001b2
#define SEQ_START_CODE 0x000001b3
#define SEQ_ERROR_CODE 0x000001b4
#define EXT_START_CODE 0x000001b5 /* MPEG2 confirmation code */
#define SEQ_END_CODE 0x000001b7
#define GOP_START_CODE 0x000001b8
/* MPEG extension start code id */
#define SEQ_EXT_ID 0x1
#define SEQ_DISPLAY_EXT_ID 0x2
#define SEQ_SCALABLE_EXT_ID 0x5
#define PICT_CODING_EXT_ID 0x8
#define QUANT_MATRIX_EXT_ID 0x3
#define PICT_DISPLAY_EXT_ID 0x7
#define PICT_TEMP_SCAL_EXT_ID 0xa
#define PICT_SPAT_SCAL_EXT_ID 0x9
#define COPYRIGHT_EXT_ID 0x4
#define ISO_END_CODE 0x1B9
#define PACK_START_CODE 0x1BA
#define SYSTEM_START_CODE 0x1BB
#define VIDEO_ELEMENTARY_STREAM 0x1e0
/* scalable_mode */
#define SC_NONE 0
#define SC_DP 1
#define SC_SPAT 2
#define SC_SNR 3
#define SC_TEMP 4
/* picture coding type */
#define I_TYPE 1
#define P_TYPE 2
#define B_TYPE 3
#define D_TYPE 4
/* picture structure */
#define TOP_FIELD 1
#define BOTTOM_FIELD 2
#define FRAME_PICTURE 3
/*
* macroblock types encoded in mbType field of MB header
*/
#define MB_INTRA 1
#define MB_PATTERN 2
#define MB_BACKWARD 4
#define MB_FORWARD 8
#define MB_QUANT 16
/*
* Number of bytes given to VLD each time
*/
#define READSIZE 64
#define ERROR_IF_NOT_OK(x) \
{ \
tmLibdevErr_t status; \
\
status = x; \
if (status != TMLIBDEV_OK) \
{ \
error(#x "failed. status = 0x%x", status); \
} \
}
#ifdef __BIG_ENDIAN__
#define SWAP_INT(a) \
((FUNSHIFT3(a, a) & 0xff00ff00) | (FUNSHIFT1(a, a) & 0x00ff00ff))
#else /* big endian */
#define SWAP_INT(a) (a)
#endif
/*
* Never check EMPTY status since it will be serviced by ISR.
* If EMPTY status is checked, we may actually read it, but ISR will
* service it and all we can do is to ignore it. Why bother.
* Instead, we are checking VldEmpty flag in case ISR was not able
* to service it.
*/
#define GET_RETURN_VALUE_FROM_HVLD \
(vldGetSTATUS() & \
(VLD_STATUS_SUCCESS | VLD_STATUS_STARTCODE | VLD_STATUS_ERROR | \
VLD_STATUS_MBH_OUT_DONE | VLD_STATUS_RL_OUT_DONE))
/*
* Input and reference data
*/
#define BUF_SIZE (128*1024)
extern UInt32 in_data[];
/* Video Sequence Header structure */
typedef struct vid_header {
UInt16 h_size;
UInt16 v_size;
UInt8 aspect_ratio;
UInt8 frame_rate;
UInt32 bit_rate;
UInt16 vbv_buf_size;
UInt8 const_param_flag;
UInt8 intra_quant_matrix[8][8];
UInt8 non_intra_quant_matrix[8][8];
} SeqHeader;
/* Sequence extension structure */
typedef struct seq_ext {
UInt8 ext_id;
UInt8 profile_level;
UInt8 progressive_seq_flag;
UInt8 chroma_format;
UInt8 h_size_ext;
UInt8 v_size_ext;
UInt16 bit_rate_ext;
UInt8 vbv_buf_size_ext;
UInt8 low_delay;
UInt8 frame_rate_ext_n;
UInt8 frame_rate_ext_d;
} SeqExt;
typedef struct GoP {
Bool drop_flag; /* Flag indicating dropped frame. */
UInt32 tc_hours; /* Hour component of time code. */
UInt32 tc_minutes; /* Minute component of time code. */
UInt32 tc_seconds; /* Second component of time code. */
UInt32 tc_pictures; /* Picture counter of time code. */
Bool closed_gop; /* Indicates no pred. vectors to
previous group of pictures. */
Bool broken_link; /* B frame unable to be decoded. */
UInt8 *ext_data; /* Extension data. */
UInt8 *user_data; /* User data. */
} GoP;
static SeqHeader seqhead;
static SeqExt seqext;
static Int stream = 0;
static UInt8 InData[BUF_SIZE];
static UInt8 MbhRef[BUF_SIZE];
static UInt8 TokenRef[BUF_SIZE];
static UInt8 PictTypeChar[] = "UIPBD";
static Int instance;
static Pointer ReadAddr;
static vldMBHMpeg2_t *Mbh;
static UInt32 *Token;
static Int ParsedMbs;
static Int ErrorMbs;
static Int ParsedFrames;
static Pointer pvidStream;
static void error(char *fmt,...);
static void inputEmptyCallback(Pointer vidStream, Int32 flag);
static void vldIrqHandler(void);
static Int allocVldOutput(void);
static Int parseOffUptoPicture(void);
static Int parseSeqHeader(void);
static Int parseGOP(GoP *groupict);
static Int parsePict(vldPictureInfo_t * pictinfo);
static Int decodeframe(vldPictureInfo_t * pictinfo);
static void *cache_calloc_share(unsigned num, unsigned size, int i);
static void *cache_calloc(unsigned num, unsigned size, int i);
static void reportPictureInfo(vldPictureInfo_t * pictinfo);
static Int parseSlice(void);
static UInt reportMbh(vldMBHMpeg2_t * mbh);
static Int compareMbh(Pointer mbh, Pointer * pMbhRef, Int mpeg2Mode);
static Int compareToken(Pointer token, Pointer * pTokenRef, Int cbp);
#ifdef DEBUG_VLD_PARSE
static void printMBInfo(vldMBHMpeg2_t * mbh, UInt32 * token);
#endif
/* Set up array for fast conversion from zig zag order to row/column
coordinates.
*/
unsigned char zigzag_direct[64] = {
0, 8, 2, 4, 10, 16, 24, 18,
12, 6, 1, 14, 20, 26, 32, 40,
34, 28, 22, 9, 3, 5, 11, 17,
30, 36, 42, 48, 56, 50, 44, 38,
25, 19, 13, 7, 15, 21, 27, 33,
46, 52, 58, 60, 54, 41, 35, 29,
23, 31, 37, 43, 49, 62, 57, 51,
45, 39, 47, 53, 59, 61, 55, 63
};
/****************************************************************************
main()
VLD library test program.
****************************************************************************/
main()
{
UInt32 data, *p, i, j, going;
vldInstanceSetup_t vldCtrl;
GoP group;
vldPictureInfo_t pictinfo;
pvldCapabilities_t pcap;
Int inFile;
Int refMbhFile;
Int refTokenFile;
Int res;
UInt8 *pointers, *pointerd;
UInt32 tempdata;
/*
* =========================================================== Start
* of initialization
*/
DPsize(4 * 1024 * 1024);
ERROR_IF_NOT_OK(vldGetCapabilities(&pcap));
DP(("\nTrimedia VLD Test Program, V%s\n\n", PROGRAM_VERSION));
DP(("This program uses VLD library version %d.%d.%d\n",
pcap->version.majorVersion,
pcap->version.minorVersion,
pcap->version.buildVersion));
DP(("to parse a simple MPEG-1 or MPEG-2 stream.\n"));
DP(("Running on ")); tmHelpReportSystem(Null);
printf("Running on "); tmHelpReportSystem(stdout);
/*
* Sanity checking for program correctness
*/
if (TMLIBDEV_OK != 0) {
error("This program assumes TMLIBDEV_OK == 0");
}
/*
* Get VLD ready by: Open, setup, prime, shift by 0
*/
ERROR_IF_NOT_OK(vldOpen(&instance));
vldCtrl.interrupts = VLD_IMASK_DMA_IN_DONE;
vldCtrl.vldEmptyFunc = (pFnVldEmpty_t) inputEmptyCallback;
vldCtrl.priority = intPRIO_4; /* interrupt priority */
vldCtrl.vldISR = (pFnVldISR_t) vldIrqHandler;
ERROR_IF_NOT_OK(vldInstanceSetup(instance, &vldCtrl));
DP(("Setup done \n"));
#ifdef __LITTLE_ENDIAN__
/* endian swap if little endian */
for(i=0; i<(160*4); i++)
{
pointerd = (UInt8 *)&in_data[i];
tempdata = in_data[i];
pointers = (UInt8 *) &tempdata;
for(j=0; j<4; j++)
*(pointerd+3-j) = *(pointers+j);
}
pointers = (UInt8 *) &in_data[0];
_cache_copyback(in_data, 160*4);
#endif
/*
* Get the data ready by reading in from files
*/
inFile = open("bike.m1v", O_RDONLY | O_BINARY);
refMbhFile = open("refmbh_bike.bits", O_RDONLY | O_BINARY);
refTokenFile = open("reftoken_bike.bits", O_RDONLY | O_BINARY);
if (inFile < 0 || refMbhFile < 0 || refTokenFile < 0) {
error("opening file failed");
}
res = read(inFile, InData, BUF_SIZE);
printf("input data: %d bytes read\n", res);
DP(("input data: %d bytes read\n", res));
res = read(refMbhFile, MbhRef, BUF_SIZE);
printf("mbh reference data: %d bytes read\n", res);
DP(("mbh reference data: %d bytes read\n", res));
res = read(refTokenFile, TokenRef, BUF_SIZE);
printf("token reference data: %d bytes read\n", res);
DP(("token reference data: %d bytes read\n", res));
p = (UInt32 *) MbhRef;
for (i = 0; i < (BUF_SIZE >> 2); i++) {
p[i] = SWAP_INT(p[i]);
}
p = (UInt32 *) TokenRef;
for (i = 0; i < (BUF_SIZE >> 2); i++) {
p[i] = SWAP_INT(p[i]);
}
/*
* Copyback so that the data is in memory. We are rather loose about
* the number of copybacks here knowing that we will not use the
* whole buffer.
*/
_cache_copyback(InData, BUF_SIZE);
/* vldInput: setup input address and count */
while (stream != 1 && stream != 2) {
printf("MPEG-1 or MPEG-2 bitstream (key in 1 or 2, respectively): ");
scanf("%d", &stream);
printf("\n");
}
if (stream == 2)
ReadAddr = (Pointer) &in_data[0];
else
ReadAddr = (Pointer) InData;
vldInput(instance, ReadAddr, READSIZE);
printf("vldInput done and data address: 0x%x \n", ReadAddr);
DP(("Starting address: 0x%x \n", ReadAddr));
/*
* Shifting 0 assures alignment
*/
vldCommand(instance, VLD_COMMAND_SHIFT | 0);
/*
* Allocate spaces for VLD output. Mbh: macro block header Token:
* run-length tokens
*/
ERROR_IF_NOT_OK(allocVldOutput());
DP(("spaces allocated for VLD outut\n"));
/*
* default picture info Set it for MPEG-1 since all are written by
* MPEG-2
*/
pictinfo.pictureType = 1;
pictinfo.pictureStruct = 3;
pictinfo.framePFrameD = 1;
pictinfo.intraVLC = 0;
pictinfo.concealMV = 0;
pictinfo.mpeg2Mode = 0;
pictinfo.hForwRSize = 15;
pictinfo.vForwRSize = 15;
pictinfo.hBackRSize = 0xf;
pictinfo.vBackRSize = 0xf;
ERROR_IF_NOT_OK(vldSetPictureInfo(instance, &pictinfo));
DP(("vldSetPictureInfo done \n"));
/*
* End of initialization
* ===================================================================
* = Start parsing.
*/
/*ERROR_IF_NOT_OK(parseOffUptoPicture());
*/
ERROR_IF_NOT_OK(vldNextStartCode(instance, &data));
going = 1;
ParsedFrames = 0;
while (going && ParsedFrames < MAX_NUM_FRAMES) {
vldShowBits(instance, 8, &data);
data |= 0x100;
DP(("data for switch: 0x%x \n", data));
switch (data) {
case SEQ_END_CODE:
DP(("Sequence End \n"));
going = 0;
break;
case SEQ_START_CODE:
DP(("Sequence start code \n"));
ERROR_IF_NOT_OK(parseSeqHeader());
break;
case GOP_START_CODE:
DP(("Group of picture start code\n"));
ERROR_IF_NOT_OK(parseGOP(&group));
break;
case PICTURE_START_CODE:
ERROR_IF_NOT_OK(parsePict(&pictinfo));
printf("Mpeg-%d frame %d: (%c)", pictinfo.mpeg2Mode + 1,
ParsedFrames, PictTypeChar[pictinfo.pictureType]);
DP(("Mpeg-%d frame %d: (%c)", pictinfo.mpeg2Mode + 1,
ParsedFrames, PictTypeChar[pictinfo.pictureType]));
decodeframe(&pictinfo);
printf(" %d MBs parsed, %d MBs error\n",
ParsedMbs, ErrorMbs);
DP((" %d MBs parsed, %d MBs error\n",
ParsedMbs, ErrorMbs));
ParsedFrames++;
break;
case EXT_START_CODE:
vldNextStartCode(instance, &data);
break;
default:
error("invalid start code");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -