#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <windows.h>
#include <process.h>
#include "h264.h"
#define BYTE_LEN 4096
#define MAX_DEC_NUM 1
static save_yuv_file(H264Frm_InfoObj *pfrmInfoObj)
{
U32 encImgWidth, encImgHeight, encImgWidthC, encImgHeightC;
U8* ulImageAddress;
U32 j;
static FILE* yuvFile = NULL;
static int firt_time_entrance = 1;
if (firt_time_entrance)
{
yuvFile = fopen("rec.yuv", "wb");
firt_time_entrance = 0;
}
encImgWidth = pfrmInfoObj->width;
encImgHeight = pfrmInfoObj->height;
encImgWidthC = encImgWidth >> 1;
encImgHeightC = encImgHeight >> 1;
ulImageAddress = pfrmInfoObj->y_addr;
for (j=0; j<encImgHeight; j++)
{
fwrite (ulImageAddress, encImgWidth, 1, yuvFile);
ulImageAddress += pfrmInfoObj->y_stride;
}
ulImageAddress = pfrmInfoObj->u_addr;
for (j=0; j<encImgHeightC; j++)
{
fwrite (ulImageAddress, encImgWidthC, 1, yuvFile);
ulImageAddress += pfrmInfoObj->u_stride;
}
ulImageAddress = pfrmInfoObj->v_addr;
for (j=0; j<encImgHeightC; j++)
{
fwrite (ulImageAddress, encImgWidthC, 1, yuvFile);
ulImageAddress += pfrmInfoObj->v_stride;
}
}
unsigned __stdcall SyncThreadFunc (void* pArguments)
{
H264Cfg_ParaObj* pCfgObj = (H264Cfg_ParaObj*)pArguments;
H264Frm_InfoObj frmInfoObj;
S32 ret, i = 0;
while (1)
{
DWORD k = WaitForMultipleObjects (MAX_DEC_NUM,
pCfgObj[0].hSemaphore, FALSE, 40); // INFINITE);
for (k = 0; k < MAX_DEC_NUM; k++)
{
ret = PgetAPI(&frmInfoObj, &pCfgObj[k]);
if (-2 == ret || -1 == ret)
{
; // printf ("[%d] no frame to display!\n", k);
}
else if (0 == ret)
{
#if 1
printf ("[%d][%d] displaying frame\n", k, i++);
#else
save_yuv_file(&frmInfoObj);
#endif
ret = PsetAPI(frmInfoObj.frame_id, &pCfgObj[k]);
ReleaseSemaphore (*pCfgObj[k].hSemaphore, 1, NULL);
}
}
}
_endthreadex (0);
return 0;
}
unsigned __stdcall DecoderThreadFunc (void* pArguments)
{
H264Cfg_ParaObj* pCfgObj = (H264Cfg_ParaObj*)pArguments;
U8 pStream[4100];
LARGE_INTEGER lpFrequency;
LARGE_INTEGER t1;
LARGE_INTEGER t2;
U32 time;
S64 total_time=0;
QueryPerformanceFrequency(&lpFrequency);
if (NULL == pCfgObj)
{
fprintf (stderr, "DecoderThreadFunc : pCfgObj error!\n");
return -1;
}
// callocate 16M buffer for decoder
pCfgObj->decBufSize = 0x2800000;
pCfgObj->yuv_stride = 2048;
pCfgObj->decBufAddr = (U8*) calloc (pCfgObj->decBufSize, sizeof(U8));
pCfgObj->stream_addr = pStream;
if (NULL == pCfgObj->decBufAddr)
{
fprintf (stderr, "DecoderThreadFunc : decBufAddr[] error!\n");
return -1;
}
/*Initialize process */
if (-1 == OpenAPI(pCfgObj))
{
fprintf (stderr, "DecoderThreadFunc : OpenAPI error!\n");
return -1;
}
#if 0
pCfgObj->stream_len = fread (pCfgObj->stream_addr, 1, BYTE_LEN, pCfgObj->bitsFile);
while (BYTE_LEN == pCfgObj->stream_len)
{
VdecAPI(pCfgObj);
pCfgObj->stream_len = fread (pCfgObj->stream_addr, 1, BYTE_LEN, pCfgObj->bitsFile);
}
pCfgObj->stream_addr[pCfgObj->stream_len++] = 0;
pCfgObj->stream_addr[pCfgObj->stream_len++] = 0;
pCfgObj->stream_addr[pCfgObj->stream_len++] = 0;
pCfgObj->stream_addr[pCfgObj->stream_len++] = 1;
VdecAPI (pCfgObj);
// stope decoding current bitstream
if (NULL != pCfgObj->bitsFile)
{
fclose (pCfgObj->bitsFile);
pCfgObj->bitsFile = NULL;
}
#else
while (1)
{
pCfgObj->stream_len = fread (pCfgObj->stream_addr,
1, BYTE_LEN, pCfgObj->bitsFile);
//printf ("bitstream len in bytes[%d]\n", pCfgObj->stream_len);
/* decoding process */
QueryPerformanceCounter(&t1);
VdecAPI (pCfgObj);
QueryPerformanceCounter (&t2);
total_time += t2.QuadPart - t1.QuadPart;
// ending process : rewind to beginning of stream
if (0 != feof (pCfgObj->bitsFile))
{
fseek (pCfgObj->bitsFile, 0, SEEK_SET);
time = (total_time)*1000 / lpFrequency.QuadPart;
total_time = 0;
printf ("end of bitstream file, ");
printf ("total pure decoding time [%d] ms.\n", time);
CloseAPI (pCfgObj);
if (-1 == OpenAPI(pCfgObj))
{
fprintf (stderr, "DecoderThreadFunc : OpenAPI error!\n");
return -1;
}
}
}
#endif
// stop decoding current bitstream
CloseAPI (pCfgObj);
if (pCfgObj->decBufAddr) free (pCfgObj->decBufAddr);
_endthreadex (0);
return 0;
}
int main (S32 argc, S8** argv)
{
S32 k, i, pre_len = 0;
const S8 infile[100];
const S8 ending[100] = "END_OF_FILE";
S8 infile_1[100], stream_name[100];
H264Cfg_ParaObj CfgObj[MAX_DEC_NUM];
FILE* fd, * bits[MAX_DEC_NUM];
HANDLE hThread[MAX_DEC_NUM], sThread;
HANDLE hSemaphore[MAX_DEC_NUM];
unsigned threadID;
// read the decoder configuration file
if (2 != argc)
{
fprintf (stderr, "main : please check input arguments!\n");
return -1;
}
fd = fopen (argv[1], "r");
if (NULL == fd)
{
fprintf (stderr, "main : configure file open error!\n");
return -1;
}
for (k = 0; k < MAX_DEC_NUM; k++)
{
hSemaphore[k] = CreateSemaphore (NULL, 0, 1, NULL);
if (NULL == hSemaphore[k])
{
fprintf (stderr, "main : createSemaphore[%d] error!\n", k);
}
CfgObj[k].hSemaphore = &hSemaphore[k];
CfgObj[k].p264BufAddr = NULL;
}
// WaitForSingleObject (sThread, INFINITE);
for (k=0; k<MAX_DEC_NUM; k++)
{
// read one bitstream file
fscanf (fd, "%s", infile);
fscanf (fd, "%*[^\n]");
if (0 == strcmp (ending, infile)) break;
sprintf (stream_name, "%s%s", ".\\BitStreams\\", infile);
bits[k] = fopen (stream_name, "rb");
if (NULL == bits[k])
{
fprintf (stderr, "main : bits file open error!\n");
return -1;
}
CfgObj[k].bitsFile = bits[k];
// set yuv file_name same as bitstream file_name
for (i = 0; (infile[i] != '\0'); i++)
{
if ('.' == infile[i])
{
pre_len = i;
break;
}
}
for (i = 0; i < pre_len; i++)
{
infile_1[i] = infile[i];
}
infile_1[i] = '\0';
sprintf (CfgObj[k].fileName, ".\\YUV\\%s%s", infile_1, ".yuv");
printf ("Creating %s Decoding thread ...\n", stream_name);
// create the decoder & player thread.
hThread[k] = (HANDLE) _beginthreadex (NULL, 0, &DecoderThreadFunc, (void*)&CfgObj[k], 0, &threadID);
}
sThread = (HANDLE)_beginthreadex( NULL, 0, &SyncThreadFunc, (void*)CfgObj, 0, &threadID);
for (i=0; i<k; i++)
{
// Wait untill second thread terminates
WaitForSingleObject (hThread[i], INFINITE);
printf ("ending decode thread of %d\n", hThread[i]);
// Destroy the thread object.
CloseHandle (hThread[i]);
if (NULL != bits[i])
{
fclose (bits[i]);
bits[i] = NULL;
}
}
fclose (fd);
WaitForSingleObject (sThread, 1000);
return 0;
}