📄 pjmplayerdlg.cpp
字号:
************************************************************************
* \brief
* Read input from configuration file
*
* \par Input:
* Name of configuration filename
*
* \par Output
* none
************************************************************************
*/
void init_conf(struct inp_par *inp, char *config_filename)
{
FILE *fd;
int NAL_mode;
// picture error concealment
int temp;
char tempval[100];
// read the decoder configuration file
if((fd=fopen(config_filename,"r")) == NULL)
{
snprintf(errortext, ET_SIZE, "Error: Control file %s not found\n",config_filename);
error(errortext, 300);
}
fscanf(fd,"%s",inp->infile); // H.264 compressed input bitstream
fscanf(fd,"%*[^\n]");
fscanf(fd,"%s",inp->outfile); // RAW (YUV/RGB) output file
fscanf(fd,"%*[^\n]");
fscanf(fd,"%s",inp->reffile); // reference file
fscanf(fd,"%*[^\n]");
fscanf(fd,"%d",&(inp->write_uv)); // write UV in YUV 4:0:0 mode
fscanf(fd,"%*[^\n]");
fscanf(fd,"%d",&(NAL_mode)); // NAL mode
fscanf(fd,"%*[^\n]");
switch(NAL_mode)
{
case 0:
inp->FileFormat = PAR_OF_ANNEXB;
break;
case 1:
inp->FileFormat = PAR_OF_RTP;
break;
default:
snprintf(errortext, ET_SIZE, "NAL mode %i is not supported", NAL_mode);
error(errortext,400);
}
fscanf(fd,"%d,",&inp->ref_offset); // offset used for SNR computation
fscanf(fd,"%*[^\n]");
fscanf(fd,"%d,",&inp->poc_scale); // offset used for SNR computation
fscanf(fd,"%*[^\n]");
if (inp->poc_scale < 1 || inp->poc_scale > 10)
{
snprintf(errortext, ET_SIZE, "Poc Scale is %d. It has to be within range 1 to 10",inp->poc_scale);
error(errortext,1);
}
inp->write_uv=1;
// picture error concealment
img->conceal_mode = inp->conceal_mode = 0;
img->ref_poc_gap = inp->ref_poc_gap = 2;
img->poc_gap = inp->poc_gap = 2;
#ifdef _LEAKYBUCKET_
fscanf(fd,"%ld,",&inp->R_decoder); // Decoder rate
fscanf(fd, "%*[^\n]");
fscanf(fd,"%ld,",&inp->B_decoder); // Decoder buffer size
fscanf(fd, "%*[^\n]");
fscanf(fd,"%ld,",&inp->F_decoder); // Decoder initial delay
fscanf(fd, "%*[^\n]");
fscanf(fd,"%s",inp->LeakyBucketParamFile); // file where Leaky Bucket params (computed by encoder) are stored
fscanf(fd,"%*[^\n]");
#endif
/* since error concealment parameters are added at the end of
decoder conf file we need to read the leakybucket params to get to
those parameters */
#ifndef _LEAKYBUCKET_
fscanf(fd,"%ld,",&temp);
fscanf(fd, "%*[^\n]");
fscanf(fd,"%ld,",&temp);
fscanf(fd, "%*[^\n]");
fscanf(fd,"%ld,",&temp);
fscanf(fd, "%*[^\n]");
fscanf(fd,"%s",tempval);
fscanf(fd,"%*[^\n]");
#endif
fscanf(fd,"%d",&inp->conceal_mode); // Mode of Error Concealment
fscanf(fd,"%*[^\n]");
img->conceal_mode = inp->conceal_mode;
fscanf(fd,"%d",&inp->ref_poc_gap); // POC gap depending on pattern
fscanf(fd,"%*[^\n]");
img->ref_poc_gap = inp->ref_poc_gap;
fscanf(fd,"%d",&inp->poc_gap); // POC gap between consecutive frames in display order
fscanf(fd,"%*[^\n]");
img->poc_gap = inp->poc_gap;
fclose (fd);
}
//进行YUV->RGB转换以及显示视频的函数
//用来显示的全局变量
unsigned char *src[3];
BOOL PlayingVideo=FALSE;
unsigned char *clp = NULL;
unsigned char *clp1;
int width,height;
unsigned char bufRGB[80000];
//进行YUV->RGB转换的函数
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)))
{
AfxMessageBox(L"安排解码码表内存失败!");
}
clp1 = clp;
clp += 384;
for (i = -384; i < 640; i++)
clp[i] = (i < 0) ? 0 : ((i > 255) ? 255 : i);
}
void ConvertYUVtoRGB (unsigned char *src0, unsigned char *src1, unsigned char *src2,
unsigned char *dst_ori,int width,int height)
{
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;
}
}
/////////////////////////////////////////////////////////////////////////////
// CPJMPlayerDlg dialog
CPJMPlayerDlg::CPJMPlayerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPJMPlayerDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPJMPlayerDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPJMPlayerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPJMPlayerDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPJMPlayerDlg, CDialog)
//{{AFX_MSG_MAP(CPJMPlayerDlg)
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPJMPlayerDlg message handlers
BOOL CPJMPlayerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
CenterWindow(GetDesktopWindow()); // center to the hpc screen
// TODO: Add extra initialization here
//初始化视频窗口
// Adjust display windows
// For remote video display window
wnd=this->GetDlgItem(IDC_REMOTEVIDEO); // Video display window
bwnd=this->GetDlgItem(IDC_REMOTEBORDER); // Border window...
bwnd->GetWindowRect(brect);
ScreenToClient(brect);
remote_wnd_x=brect.TopLeft().x+(brect.Width()-IMAGE_WIDTH)/2;
remote_wnd_y=brect.TopLeft().y+(brect.Height()-IMAGE_HEIGHT)/2;
// Centre the remote video window
wnd->SetWindowPos(&wndTop,remote_wnd_x-4,remote_wnd_y-4,IMAGE_WIDTH+9,IMAGE_HEIGHT+9,SWP_SHOWWINDOW | SWP_DRAWFRAME);
//初始化JM
int argc;char **argv;
// allocate memory for the structures
if ((input = (struct inp_par *)calloc(1, sizeof(struct inp_par)))==NULL) no_mem_exit("main: input");
if ((snr = (struct snr_par *)calloc(1, sizeof(struct snr_par)))==NULL) no_mem_exit("main: snr");
if ((img = (struct img_par *)calloc(1, sizeof(struct img_par)))==NULL) no_mem_exit("main: img");
Configure (argc, argv);
//初始化显示
width=IMAGE_WIDTH;height=IMAGE_HEIGHT;
//bufRGB = (unsigned char *)malloc(sizeof(unsigned char)*(3 * width * height));
init_dither_tab();
m_bDecoding=FALSE;
hDecodeThread=NULL;
return TRUE; // return TRUE unless you set the focus to a control
}
void CPJMPlayerDlg::OnButton1()
{
if(!m_bDecoding)
{
//如果有的话,停止解码线程
if(hDecodeThread)
{
TerminateThread(hDecodeThread,0);
CloseHandle(hDecodeThread);
hDecodeThread=NULL;
}
//开始解码线程
Ready=0;
SetTimer(123,20,NULL);
m_bDecoding=TRUE;
SetDlgItemText(IDC_BUTTON1,_T("停止解码"));
hDecodeThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)DecodeThread,(void *)this,0,&dwThreadID);
}
else
{
SetDlgItemText(IDC_BUTTON1,_T("解码"));
//停止编码线程
if(hDecodeThread)
{
TerminateThread(hDecodeThread,0);
CloseHandle(hDecodeThread);
hDecodeThread=NULL;
}
m_bDecoding=FALSE;
}
}
void CPJMPlayerDlg::DisplayVideo()
{
ConvertYUVtoRGB ((unsigned char*)displaybuf,(unsigned char*)(displaybuf+25344),(unsigned char*)(displaybuf+31680),bufRGB,width,height);
unsigned char* rgbdata=bufRGB;
int x,y;
unsigned char temp;
{
for(y=0;y<144;y++)
{
for(x=0;x<88;x++)
{
temp=rgbdata[(176*y+x)*3];
rgbdata[(176*y+x)*3]=rgbdata[(176*y+176-x)*3];
rgbdata[(176*y+176-x)*3]=temp;
temp=rgbdata[(176*y+x)*3+1];
rgbdata[(176*y+x)*3+1]=rgbdata[(176*y+176-x)*3+1];
rgbdata[(176*y+176-x)*3+1]=temp;
temp=rgbdata[(176*y+x)*3+2];
rgbdata[(176*y+x)*3+2]=rgbdata[(176*y+176-x)*3+2];
rgbdata[(176*y+176-x)*3+2]=temp;
}
}
for(x=0;x<38016;x++)
{
temp=rgbdata[x];
rgbdata[x]=rgbdata[76032-x];
rgbdata[76032-x]=temp;
}
}
CBitmap bitmap;
bitmap.CreateBitmap(176,144,1,24,rgbdata);
CWnd* pWnd=GetDlgItem(IDC_REMOTEVIDEO);
pWnd->UpdateWindow();
CDC* pDC=pWnd->GetDC();
CDC bitmapDC;
bitmapDC.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = bitmapDC.SelectObject(&bitmap);
//pDC->StretchBlt(0,0,176,144,&bitmapDC,0,0,176,144,SRCCOPY);
pDC->BitBlt(0,0,176,144,&bitmapDC,0,0,SRCCOPY);
bitmapDC.SelectObject(pOldBitmap);
bitmap.DeleteObject();
}
//解码线程
DWORD CPJMPlayerDlg::DecodeThread(void *pDlg)
{
init_old_slice();
switch (input->FileFormat)
{
case 0:
OpenBitstreamFile (input->infile);
break;
case 1:
OpenRTPFile (input->infile);
break;
default:
printf ("Unsupported file format %d, exit\n", input->FileFormat);
}
// Allocate Slice data struct
malloc_slice(input,img);
init(img);
dec_picture = NULL;
dpb.init_done = 0;
g_nFrame = 0;
init_out_buffer();
img->idr_psnr_number=input->ref_offset;
img->psnr_number=0;
img->number=0;
img->type = I_SLICE;
img->dec_ref_pic_marking_buffer = NULL;
// B pictures
Bframe_ctr=snr->frame_ctr=0;
// time for total decoding session
tot_time = 0;
while (decode_one_frame(img, input, snr) != EOS)
;
//report(input, img, snr);
free_slice(input,img);
FmoFinit();
free_global_buffers();
flush_dpb();
#ifdef PAIR_FIELDS_IN_OUTPUT
flush_pending_output(p_out);
#endif
CloseBitstreamFile();
close(p_out);
// fclose(p_out2);
if (p_ref)
close(p_ref);
#if TRACE
fclose(p_trace);
#endif
ercClose(erc_errorVar);
free_dpb();
uninit_out_buffer();
free_colocated(Co_located);
free (input);
free (snr);
free (img);
return 0;
}
void CPJMPlayerDlg::OnTimer(UINT nIDEvent)
{
if(Ready==1)
{
DisplayVideo();
Ready=0;
}
CDialog::OnTimer(nIDEvent);
}
void CPJMPlayerDlg::OnDestroy()
{
CDialog::OnDestroy();
free(clp1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -