/************************************************************************
*
* win.c, display routines for Win32 for tmndecode
*
************************************************************************/
#include "win.h"
/* vdinit.c */
unsigned char *clp = NULL;
unsigned char *clp1 = NULL;
#ifdef __cplusplus
extern "C"
{
#endif
T_VDWINDOW vdWindow;
int initDisplay (int pels, int lines)
{
int errFlag = 0;
DWORD dwRetVal;
init_dither_tab ();
errFlag |= InitDisplayWindowThread (pels, lines);
dwRetVal = WaitForSingleObject (vdWindow.hReadyEvt, INFINITE);
return errFlag;
}
int InitDisplayWindowThread (int width, int height)
{
int errFlag = 0;
/* now modify the couple that need it */
vdWindow.width = width;
vdWindow.height = height;
vdWindow.biHeader.biWidth = vdWindow.width;
vdWindow.biHeader.biHeight = vdWindow.height;
vdWindow.biHeader.biSize = sizeof (BITMAPINFOHEADER);
vdWindow.biHeader.biCompression = BI_RGB;
vdWindow.biHeader.biPlanes = 1;
vdWindow.biHeader.biBitCount = 24;
vdWindow.biHeader.biSizeImage = 3 * vdWindow.width * vdWindow.height;
vdWindow.imageIsReady = FALSE;
/* allocate the memory needed to hold the RGB and visualization
* information */
vdWindow.bufRGB = NULL;
vdWindow.bufRGB = (unsigned char *)malloc(sizeof(unsigned char)
*(3 * vdWindow.width * vdWindow.height));
/* Create synchronization event */
vdWindow.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
vdWindow.hReadyEvt = CreateEvent (NULL, FALSE, FALSE, NULL);
vdWindow.hReadyQuitEvt = CreateEvent (NULL, FALSE, FALSE, NULL);
vdWindow.hThread =
CreateThread (
NULL,
0,
(LPTHREAD_START_ROUTINE) DisplayWinMain,
(LPVOID) NULL,
0,
&(vdWindow.dwThreadID)
);
if (vdWindow.hThread == NULL)
{
errFlag = 1;
return errFlag;
}
return errFlag;
}
/* vddraw.c */
int displayImage (unsigned char *lum, unsigned char *Cr, unsigned char *Cb)
{
int errFlag = 0;
DWORD dwRetVal;
vdWindow.src[0] = lum;
vdWindow.src[1] = Cb;
vdWindow.src[2] = Cr;
/* wait until we have finished drawing the last frame */
if (vdWindow.windowDismissed == FALSE)
{
vdWindow.imageIsReady = TRUE;
/* Post message to drawing thread's window to draw frame */
PostMessage (vdWindow.hWnd, VIDEO_DRAW_FRAME, (WPARAM) NULL, (LPARAM) NULL);
/* wait until the frame has been drawn */
dwRetVal = WaitForSingleObject (vdWindow.hEvent, INFINITE);
free(vdWindow.src[0]);
free(vdWindow.src[1]);
free(vdWindow.src[2]);
}
else
{
free(vdWindow.src[0]);
free(vdWindow.src[1]);
free(vdWindow.src[2]);
}
return errFlag;
}
int DrawDIB ()
{
int errFlag = 0;
errFlag |=
DrawDibDraw (
vdWindow.hDrawDib,
vdWindow.hDC,
0,
0,
vdWindow.zoom * vdWindow.width,
vdWindow.zoom * vdWindow.height,
&vdWindow.biHeader,
vdWindow.bufRGB,
0,
0,
vdWindow.width,
vdWindow.height,
DDF_SAME_DRAW
);
return errFlag;
}
/* vdwinman.c */
void DisplayWinMain (void *dummy)
{
int errFlag = 0;
DWORD dwStyle;
vdWindow.wc.style = CS_BYTEALIGNWINDOW;
vdWindow.wc.lpfnWndProc = MainWndProc;
vdWindow.wc.cbClsExtra = 0;
vdWindow.wc.cbWndExtra = 0;
vdWindow.wc.hInstance = 0;
vdWindow.wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
vdWindow.wc.hCursor = LoadCursor (NULL, IDC_ARROW);
vdWindow.wc.hbrBackground = (HBRUSH)(GetStockObject (WHITE_BRUSH));
vdWindow.wc.lpszMenuName = NULL;
vdWindow.zoom = 1;
strcpy (vdWindow.lpszAppName, "H.264 Display");
vdWindow.wc.lpszClassName = vdWindow.lpszAppName;
RegisterClass (&vdWindow.wc);
dwStyle = WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
vdWindow.hWnd =
CreateWindow (vdWindow.lpszAppName,
vdWindow.lpszAppName,
dwStyle,
CW_USEDEFAULT,
CW_USEDEFAULT,
vdWindow.width + 6,
vdWindow.height + 25,
NULL,
NULL,
0,
NULL
);
if (vdWindow.hWnd == NULL)
ExitThread (errFlag = 1);
ShowWindow (vdWindow.hWnd, SW_SHOWNOACTIVATE);
UpdateWindow (vdWindow.hWnd);
/* Message loop for display window's thread */
while (GetMessage (&(vdWindow.msg), NULL, 0, 0))
{
TranslateMessage (&(vdWindow.msg));
DispatchMessage (&(vdWindow.msg));
}
ExitThread (0);
}
LRESULT APIENTRY MainWndProc (HWND hWnd, UINT msg, UINT wParam, LONG lParam)
{
LPMINMAXINFO lpmmi;
switch (msg)
{
case VIDEO_BEGIN:
vdWindow.hDC = GetDC (vdWindow.hWnd);
vdWindow.hDrawDib = DrawDibOpen ();
vdWindow.zoom = 1;
vdWindow.oldzoom = 0;
DrawDibBegin (
vdWindow.hDrawDib,
vdWindow.hDC,
2 * vdWindow.width,
2 * vdWindow.height,
&vdWindow.biHeader,
vdWindow.width,
vdWindow.height,
0
);
SetEvent (vdWindow.hReadyEvt);
vdWindow.windowDismissed = FALSE;
ReleaseDC (vdWindow.hWnd, vdWindow.hDC);
break;
case VIDEO_DRAW_FRAME:
vdWindow.hDC = GetDC (vdWindow.hWnd);
ConvertYUVtoRGB (
vdWindow.src[0],
vdWindow.src[1],
vdWindow.src[2],
vdWindow.bufRGB,
vdWindow.width,
vdWindow.height
);
/* draw the picture onto the screen */
DrawDIB ();
SetEvent (vdWindow.hEvent);
ReleaseDC (vdWindow.hWnd, vdWindow.hDC);
break;
case VIDEO_END:
/* Window has been closed. The following lines handle the cleanup. */
vdWindow.hDC = GetDC (vdWindow.hWnd);
DrawDibEnd (vdWindow.hDrawDib);
DrawDibClose (vdWindow.hDrawDib);
ReleaseDC (vdWindow.hWnd, vdWindow.hDC);
SetEvent (vdWindow.hReadyQuitEvt);
vdWindow.windowDismissed = TRUE;
PostQuitMessage (0);
break;
case WM_CREATE:
PostMessage (hWnd, VIDEO_BEGIN, 0, 0);
break;
case WM_SIZE:
switch (wParam)
{
case SIZE_MAXIMIZED:
vdWindow.zoom = 2;
break;
case SIZE_MINIMIZED:
vdWindow.oldzoom = vdWindow.zoom;
break;
case SIZE_RESTORED:
if (vdWindow.oldzoom)
{
vdWindow.zoom = vdWindow.oldzoom;
vdWindow.oldzoom = 0;
} else
vdWindow.zoom = 1;
break;
case SIZE_MAXHIDE:
break;
case SIZE_MAXSHOW:
break;
}
PostMessage (hWnd, WM_PAINT, 0, 0);
break;
case WM_GETMINMAXINFO:
lpmmi = (LPMINMAXINFO) lParam;
GetWindowRect (hWnd, &vdWindow.rect);
lpmmi->ptMaxPosition.x = vdWindow.rect.left;
lpmmi->ptMaxPosition.y = vdWindow.rect.top;
lpmmi->ptMaxSize.x = 2 * (vdWindow.width) + 6;
lpmmi->ptMaxSize.y = 2 * (vdWindow.height) + 25;
break;
case WM_DESTROY:
/* Window has been closed. The following lines handle the cleanup. */
DrawDibEnd (vdWindow.hDrawDib);
ReleaseDC (vdWindow.hWnd, vdWindow.hDC);
DrawDibClose (vdWindow.hDrawDib);
vdWindow.windowDismissed = TRUE;
PostQuitMessage (0);
break;
case WM_PAINT:
if (vdWindow.imageIsReady)
{
vdWindow.hDC = GetDC (vdWindow.hWnd);
DrawDIB ();
ReleaseDC (vdWindow.hWnd, vdWindow.hDC);
}
break;
}
return DefWindowProc (hWnd, msg, wParam, lParam);
}
/* vdclose.c */
int closeDisplay ()
{
int errFlag = 0;
DWORD dwRetVal;
if (vdWindow.hWnd)
{
PostMessage (vdWindow.hWnd, VIDEO_END, (WPARAM) NULL, (LPARAM) NULL);
dwRetVal = WaitForSingleObject (vdWindow.hReadyQuitEvt, INFINITE);
}
if (vdWindow.hEvent)
CloseHandle (vdWindow.hEvent);
if (vdWindow.hReadyEvt)
CloseHandle(vdWindow.hReadyEvt);
if (vdWindow.hReadyEvt)
CloseHandle(vdWindow.hReadyQuitEvt);
if (vdWindow.hThread)
CloseHandle (vdWindow.hThread);
if(vdWindow.bufRGB != NULL)
free(vdWindow.bufRGB);
if(clp1 != NULL)
free(clp1);
return errFlag;
}
#ifdef __cplusplus
}
#endif
/************************************************************************
*
* yuvrgb24.c, colour space conversion for tmndecode (H.264 decoder)
*
************************************************************************/
#ifdef __GCC__
#include "display.h"
#endif
#include <stdio.h>
#include <malloc.h>
/* Data for ConvertYUVtoRGB */
extern unsigned char *clp;
extern unsigned char *clp1;
#ifdef __cplusplus
extern "C"
{
#endif
long int crv_tab[256];
long int cbu_tab[256];
long int cgu_tab[256];
long int cgv_tab[256];
long int tab_76309[256];
void init_dither_tab ()
{
long int crv, cbu, cgu, cgv;
int i;
crv = 104597;
cbu = 132201; /* fra matrise i global.h */
cgu = 25675;
cgv = 53279;
for (i = 0; i < 256; i++)
{
crv_tab[i] = (i - 128) * crv;
cbu_tab[i] = (i - 128) * cbu;
cgu_tab[i] = (i - 128) * cgu;
cgv_tab[i] = (i - 128) * cgv;
tab_76309[i] = 76309 * (i - 16);
}
if (!(clp = (unsigned char *)malloc(sizeof(unsigned char)*1024)))
printf("malloc failed\n");
clp1 = clp;
clp += 384;
for (i = -384; i < 640; i++)
clp[i] = (i < 0) ? 0 : ((i > 255) ? 255 : i);
}
/**********************************************************************
*
* Name: ConvertYUVtoRGB
* Description: Converts YUV image to RGB (packed mode)
*
* Input: pointer to source luma, Cr, Cb, destination,
* image width and height
* Returns:
* Side effects:
*
* Date: 951208 Author: Karl.Lillevold@nta.no
*
***********************************************************************/
void ConvertYUVtoRGB (unsigned char *src0, unsigned char *src1, unsigned char *src2,
unsigned char *dst_ori,int width,int height)
{
extern long int crv_tab[];
extern long int cbu_tab[];
extern long int cgu_tab[];
extern long int cgv_tab[];
extern long int tab_76309[];
int y11, y21;
int y12, y22;
int y13, y23;
int y14, y24;
int u, v;
int i, j;
int c11, c21, c31, c41;
int c12, c22, c32, c42;
unsigned int DW;
unsigned int *id1, *id2;
unsigned char *py1, *py2, *pu, *pv;
unsigned char *d1, *d2;
d1 = dst_ori;
d1 += width * height * 3 - width * 3;
d2 = d1 - width * 3;
py1 = src0;
pu = src1;
pv = src2;
py2 = py1 + width;
id1 = (unsigned int *) d1;
id2 = (unsigned int *) d2;
for (j = 0; j < height; j += 2)
{
/* line j + 0 */
for (i = 0; i < width; i += 4)
{
u = *pu++;
v = *pv++;
c11 = crv_tab[v];
c21 = cgu_tab[u];
c31 = cgv_tab[v];
c41 = cbu_tab[u];
u = *pu++;
v = *pv++;
c12 = crv_tab[v];
c22 = cgu_tab[u];
c32 = cgv_tab[v];
c42 = cbu_tab[u];
y11 = tab_76309[*py1++]; /* (255/219)*65536 */
y12 = tab_76309[*py1++];
y13 = tab_76309[*py1++]; /* (255/219)*65536 */
y14 = tab_76309[*py1++];
y21 = tab_76309[*py2++];
y22 = tab_76309[*py2++];
y23 = tab_76309[*py2++];
y24 = tab_76309[*py2++];
/* RGBR */
DW = ((clp[(y11 + c41) >> 16])) |
((clp[(y11 - c21 - c31) >> 16]) << 8) |
((clp[(y11 + c11) >> 16]) << 16) |
((clp[(y12 + c41) >> 16]) << 24);
*id1++ = DW;
/* GBRG */
DW = ((clp[(y12 - c21 - c31) >> 16])) |
((clp[(y12 + c11) >> 16]) << 8) |
((clp[(y13 + c42) >> 16]) << 16) |
((clp[(y13 - c22 - c32) >> 16]) << 24);
*id1++ = DW;
/* BRGB */
DW = ((clp[(y13 + c12) >> 16])) |
((clp[(y14 + c42) >> 16]) << 8) |
((clp[(y14 - c22 - c32) >> 16]) << 16) |
((clp[(y14 + c12) >> 16]) << 24);
*id1++ = DW;
/* RGBR */
DW = ((clp[(y21 + c41) >> 16])) |
((clp[(y21 - c21 - c31) >> 16]) << 8) |
((clp[(y21 + c11) >> 16]) << 16) |
((clp[(y22 + c41) >> 16]) << 24);
*id2++ = DW;
/* GBRG */
DW = ((clp[(y22 - c21 - c31) >> 16])) |
((clp[(y22 + c11) >> 16]) << 8) |
((clp[(y23 + c42) >> 16]) << 16) |
((clp[(y23 - c22 - c32) >> 16]) << 24);
*id2++ = DW;
/* BRGB */
DW = ((clp[(y23 + c12) >> 16])) |
((clp[(y24 + c42) >> 16]) << 8) |
((clp[(y24 - c22 - c32) >> 16]) << 16) |
((clp[(y24 + c12) >> 16]) << 24);
*id2++ = DW;
}
id1 -= (9 * width) >> 2;
id2 -= (9 * width) >> 2;
py1 += width;
py2 += width;
}
}
#ifdef __cplusplus
}
#endif
win.h
#include <windows.h>
#include <process.h>
#include <vfw.h>
#include <memory.h>
typedef struct
{
HANDLE hThread;
HANDLE hReadyEvt; //Add for initDisplay()
HANDLE hReadyQuitEvt; //Add for closeDisplay()
HANDLE hEvent;
HWND hWnd;
MSG msg;
WNDCLASS wc;
HDRAWDIB hDrawDib;
HDC hDC;
BITMAPINFOHEADER biHeader;
char lpszAppName[15];
DWORD dwThreadID;
BOOL imageIsReady;
unsigned char *bufRGB;
RECT rect;
unsigned char *src[3];
int width, height;
int zoom, oldzoom;
int windowDismissed;
} T_VDWINDOW;
#define VIDEO_BEGIN (WM_USER + 0)
#define VIDEO_DRAW_FRAME (WM_USER + 1)
#define VIDEO_REDRAW_FRAME (WM_USER + 2)
#define VIDEO_END (WM_USER + 3)
#ifdef __cplusplus
extern "C"
{
#endif
int initDisplay (int pels, int lines);
int displayImage (unsigned char *lum, unsigned char *Cr, unsigned char *Cb);
int closeDisplay ();
void DisplayWinMain (void *);
LONG APIENTRY MainWndProc (HWND, UINT, UINT, LONG);
int DrawDIB ();
void init_dither_tab();
void ConvertYUVtoRGB(
unsigned char *src0,
unsigned char *src1,
unsigned char *src2,
unsigned char *dst_ori,
int width,
int height
);
int InitDisplayWindowThread (int,int);
#pragma comment(lib, "vfw32.lib")
#ifdef __cplusplus
}
#endif
/*****************************************************************************
*
* VM_H264 AVC CODEC
*
****************************************************************************/
// h264.c : Defines the entry point for the console application.
//
//#define USE_DISPLAY
#include "config.h"
#ifdef USE_DISPLAY
#ifndef __GCC__
#include "win.h"
#else
#include "display.h"
#endif
#endif
#include "stdio.h"
#include "sys/timeb.h"
#include "time.h"
#include "stdlib.h"
#include "memory.h"
#include "math.h"
#include "vm_h264.h"
#include "utility.h"
#include "string.h"
// parameters begin
int32_t total_no = 300;
char src_path[256];
char out_path[256];
char rec_path[256];
// for decoder PSNR
char ref_path[256];
static int ref_skip;
// parameters end
#ifdef USE_DISPLAY
//将一帧数据写到YUV中并显示
void winDisplay(H264_t* t, H264_frame_t* f)
{
uint8_t* p;
unsigned char* buffer1, *buffer2, *buffer3, *Y, *U, *V;
unsigned char *src[3];
int32_t i;
src[0] = Y = buffer1 = malloc(t->width*t->height*sizeof(char));
p = f->Y[0];
for (i = 0 ; i < t->height ; i++)
{
memcpy(buffer1, p, t->width);
buffer1 += t->width;
p += t->edged_stride;
}
src[2] = V = buffer2 = malloc((t->width*t->height*sizeof(char))>>2);
p = f->V;
for (i = 0 ; i < (t->height >> 1); i++)
{
memcpy(buffer2, p, t->width >> 1);
buffer2 += (t->width >> 1);
p += t->edged_stride_uv;
}
src[1] = U = buffer3 = malloc((t->width*t->height*sizeof(char))>>2);
p = f->U;
for (i = 0 ; i < (t->height >> 1); i++)
{
memcpy(buffer3, p, t->width >> 1);
buffer3 += (t->width >> 1);
p += t->edged_stride_uv;
}
#ifndef __GCC__
displayImage(Y,V,U);
#else
dither(src);
free(src[1]);
free(src[2]);
free(src[0]);
#endif
}
void
uninit_display()
{
#ifndef __GCC__
closeDisplay ();
#else
exit_display();
#endif
}
#endif
void
init_param(H264_param_t* param, const char* file)
{
FILE* fd;
char line[255];
int32_t b;
if (!(fd = fopen(file,"r")))
{
printf("Couldn't open parameter file %s.\n", file);
exit(-1);
}
memset(param, 0, sizeof(*param));
fgets(line, 254, fd); sscanf(line,"%d", &b);
if (b != 4)
{
printf("wrong param file version, expect v4.0\n");
exit(-1);
}
fgets(line, 254, fd); sscanf(line,"%d", ¶m->width);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->height);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->search_x);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->search_y);
fgets(line, 254, fd); sscanf(line,"%d", &total_no);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->iframe);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->idrframe);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->b_num);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->ref_num);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->enable_rc);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->bitrate);
fgets(line, 254, fd); sscanf(line,"%f", ¶m->framerate);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->qp);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->min_qp);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->max_qp);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->enable_stat);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->disable_filter);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->aspect_ratio);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->video_format);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->luma_coeff_cost);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_INTRA16x16) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_INTRA4x4) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_INTRAININTER) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_HALFPEL) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_QUARTPEL) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_SUBBLOCK) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_FULLSEARCH) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_DIAMONDSEACH) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_FORCEBLOCKSIZE) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_FASTINTERPOLATE) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_SAD) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_EXTRASUBPELSEARCH) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_SCENEDETECT) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x16P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x8P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x16P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x8P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x4P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_4x8P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_4x4P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x16B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x8B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x16B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x8B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", ¶m->cpu);
fgets(line, 254, fd); sscanf(line, "%d", ¶m->cabac);
fgets(line, 254, fd); sscanf(line,"%s", src_path);
fgets(line, 254, fd); sscanf(line,"%s", out_path);
fgets(line, 254, fd); sscanf(line,"%s", rec_path);
param->rec_name = rec_path;
fclose(fd);
}
//将frame中的数据写到文件f_rec中
void write_frame(H264_t* t,H264_frame_t *frame,FILE *f_rec)
{
int i;
uint8_t* p;
if (f_rec)
{
p = frame->Y[0];
for(i = 0 ; i < t->height ; i ++)
{
fwrite(p, t->width, 1, f_rec);
p += t->edged_stride;
}
p = frame->U;
for(i = 0 ; i < t->height >> 1 ; i ++)
{
fwrite(p, t->width >> 1, 1, f_rec);
p += t->edged_stride_uv;
}
p = frame->V;
for(i = 0 ; i < t->height >> 1 ; i ++)
{
fwrite(p, t->width >> 1, 1, f_rec);
p += t->edged_stride_uv;
}
}
}
static float __inline
dec_psnr(uint8_t* p1, uint8_t* p2, int32_t width1, int32_t width2, int32_t height, int print)
{
float sad = 0, psnr;
int32_t i, j, size, ii, jj, diff, iii, jjj;
uint8_t* p11, *p22;
for(j=0; j<height; j+=16)
{
for (i = 0 ; i < width2 ; i +=16)
{
p11 = p1+i;
p22 = p2+i;
diff = 0;
for(jj=0; jj<16; jj++)
{
for(ii=0; ii<16; ii++)
{
int32_t tmp;
tmp = (p11[ii] - p22[ii]);
sad += tmp * tmp;
if(tmp != 0 && diff != 1)
{
if(print)
printf("%2d != %2d ", p11[ii], p22[ii]);
iii = ii;
jjj = jj;
diff = 1;
}
}
p11 += width1;
p22 += width2;
}
if(diff && print)
{
printf("%4d, %2d, %2d\n", (j)*(width2>>4) + (i), iii, jjj);
print = 0;
}
}
p1 += width1*16;
p2 += width2*16;
}
size = width2 * height;
if(sad < 1e-6)
psnr = 0.0f;
else
psnr = (float)(10 * log10(65025.0f * size / sad));
return psnr;
}
int32_t
decode(const char* filename)
{
/* just for show how to drive the decoder */
#define BUFFER_SIZE 4096
H264_t* t = H264dec_open();
uint8_t buffer[BUFFER_SIZE + 4];
int32_t run = 1,screen = 0;
FILE* src_file = fopen(filename, "rb");
size_t size;
FILE* f_rec = 0;
//for decoder PSNR
int frame_num = 0;
FILE* f_ref = 0;
uint8_t *ref_buf = NULL;
int32_t frame_nums = 0;
float total_time;
#ifdef _WIN32
struct _timeb beg, end;
#endif
// xxx
printf("Current fully support h264 encoder's bitstream.\n");
if (!src_file)
{
printf("cannot open file %s.\n", filename);
return -1;
}
if (rec_path[0])
{
f_rec = fopen(rec_path, "wb");
if (!f_rec)
{
printf("cannot open rec file %s.\n", rec_path);
}
}
//for decoder PSNR
if(ref_path[0])
{
f_ref = fopen(ref_path, "rb");
if(!f_ref)
{
printf("cannot open ref file %s.\n", ref_path);
}
}
#ifdef _WIN32
_ftime(&beg);
#endif
while (run)
{
decoder_state_t state = H264dec_parse(t);
switch(state)
{
case DEC_STATE_BUFFER:
/* read more data */
size = fread(buffer, 1, BUFFER_SIZE, src_file);
if (size > 0)
{
if (size != BUFFER_SIZE)
{
buffer[size] = 0;
buffer[size + 1] = 0;
buffer[size + 2] = 0;
buffer[size + 3] = 1;
size += 4;
}
H264dec_buffer(t, buffer, size);
}
else
{
/* if all data has readed, here we will return */
run = 0;
/* NOTE: here we should get the last frame */
write_frame(t, H264dec_flush_frame(t), f_rec);
#ifdef USE_DISPLAY
winDisplay(t, H264dec_flush_frame(t));
#endif
frame_nums ++;
}
break;
case DEC_STATE_PIC:
/* write one pic */
break;
case DEC_STATE_SEQ:
#ifdef USE_DISPLAY
if (screen == 0)
{
#ifndef __GCC__
initDisplay(t->width, t->height);
#else
init_display("",t->width, t->height);
#endif
screen++;
}
#endif
if (t->frame_id > 0)
{
/* NOTE: here we should get the last frame */
write_frame(t, H264dec_flush_frame(t), f_rec);
#ifdef USE_DISPLAY
winDisplay(t, H264dec_flush_frame(t));
#endif
frame_nums ++;
}
printf("ref frames num: %d.\n", t->ss.num_ref_frames);
printf("width: %d.\n", (t->ss.pic_width_in_mbs_minus1 + 1) << 4);
printf("height: %d.\n", (t->ss.pic_height_in_mbs_minus1 + 1) << 4);
break;
case DEC_STATE_SLICE:
{
if (t->output.poc >= 0)
{
write_frame(t, &t->output, f_rec);
//for decoder PSNR
if(f_ref)
{
float psnr_y, psnr_u, psnr_v;
int size;
size = t->width*t->height;
if(ref_buf == NULL)
{
ref_buf = (uint8_t *)malloc(size);
}
if(ref_buf != NULL)
{
uint8_t *p;
p = t->output.Y[0];
fread(ref_buf, 1, size, f_ref);
psnr_y = dec_psnr(p, ref_buf, t->edged_stride, t->width, t->height, 0);
size >>= 2;
p = t->output.U;
fread(ref_buf, 1, size, f_ref);
psnr_u = dec_psnr(p, ref_buf, t->edged_stride_uv, t->width>>1, t->height>>1, 0);
p = t->output.V;
fread(ref_buf, 1, size, f_ref);
psnr_v = dec_psnr(p, ref_buf, t->edged_stride_uv, t->width>>1, t->height>>1, 0);
printf("%4d, %.2f, %.2f, %.2f\n", frame_num++, psnr_y, psnr_u, psnr_v);
if(ref_skip > 0)
{
fseek(f_ref, ref_skip*size*6, SEEK_CUR);
}
}
}
#ifdef USE_DISPLAY
winDisplay(t, &t->output);
#endif
frame_nums ++;
}
};
break;
case DEC_STATE_CUSTOM_SET:
{
printf("used fast interpolate: %s.\n", t->flags & USE_FASTINTERPOLATE ? "yes" : "no");
}
break;
default:
/* do not care */
break;
}
};
#ifndef CHIP_DM642
#ifdef _WIN32
_ftime(&end);
total_time = (float)(end.time - beg.time) + (float)(end.millitm - beg.millitm) / 1000;
#endif
printf("fps: %.2ffps(total decode: %d frames).\n", (float)frame_nums / total_time, frame_nums);
#endif
#ifdef CHIP_DM642
printf("fps: %.2ffps(total decode: %d frames).\n", (float)frame_nums / total_time, frame_nums);
#endif
H264dec_close(t);
fclose(src_file);
if (f_rec)
fclose(f_rec);
if (f_ref)
fclose(f_ref);
if(ref_buf != NULL)
free(ref_buf);
#ifdef USE_DISPLAY
uninit_display();
#endif
return 0;
}
void
help()
{
//printf("Usage:\n"
// "\th264_decoder -d vmdata.264 [rec_path] [reference_path] [skip_num](to decode a 264 file.)\n");
printf("Usage:\n"
"\th264_decoder -d vmdata.264 [decoded_file] [reference_file] [skip_num]\n"
"or\n"
"\th264_decoder -d vmdata.264 [decoded_file]");
}
int
main(int argc, char* argv[])
{
int32_t i;
int32_t is_encode = 0;
int32_t is_decode = 0;
char* file_name;
printf("VM_H264 ver: %d.%02d\n", H264_MAJOR, H264_MINOR);
if (argc < 3)
{
help();
return 0;
}
for (i = 1 ; i < 3 ; i ++)
{
if (strcmp(argv[i], "-d") == 0)
{
is_decode = 1;
}
else
{
file_name = argv[i];
}
}
if (is_decode)
{
if (argc <= 3)
rec_path[0] = 0;
else
{
strcpy(rec_path, argv[3]);
}
if(argc <= 4)
{
ref_path[0] = 0;
}
else
{
strcpy(ref_path, argv[4]);
}
if(argc > 5)
{
ref_skip = atoi(argv[5]);
}
return decode(file_name);
}
help();
return -1;
}