www.pudn.com > H264Player(FFMPEG).zip > H264PlayerDlg.cpp, change:2007-09-16,size:15404b
// H264PlayerDlg.cpp : implementation file
//
#include "stdafx.h"
#include "H264Player.h"
#include "H264PlayerDlg.h"
//进行H264解码的包含文件、定义以及变量
#include "h264.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//AS by tiany for test on 20060403
int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
int info;
int i;
info = 1;
for (i = 0; i zeros_in_startcode; i++)
if(Buf[i] != 0)
info = 0;
if(Buf[i] != 1)
info = 0;
return info;
}
int getNextNal(FILE* inpf, unsigned char* Buf)
{
int pos = 0;
int StartCodeFound = 0;
int info2 = 0;
int info3 = 0;
while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);
while (!StartCodeFound)
{
if (feof (inpf))
{
// return -1;
return pos-1;
}
Buf[pos++] = fgetc (inpf);
info3 = FindStartCode(&Buf[pos-4], 3);
if(info3 != 1)
info2 = FindStartCode(&Buf[pos-3], 2);
StartCodeFound = (info2 == 1 || info3 == 1);
}
fseek (inpf, -4, SEEK_CUR);
return pos - 4;
}
//H.264全局变量
AVCodec *codec; // Codec
AVCodecContext *c; // Codec Context
AVFrame *picture; // Frame
/////////////////////////////////////////////////////////////////////////////
//进行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("安排解码码表内存失败!");
}
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;
}
}
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CH264PlayerDlg dialog
CH264PlayerDlg::CH264PlayerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CH264PlayerDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CH264PlayerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CH264PlayerDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON_PLAY, &CH264PlayerDlg::OnBnClickedButtonPlay)
ON_WM_DESTROY()
ON_MESSAGE(WM_DISPLAY_FRAME,OnDisplayFrameMsg)
ON_MESSAGE(WM_DECODE_COMPLETE,OnDecodeCompleteMsg)
END_MESSAGE_MAP()
// CH264PlayerDlg message handlers
BOOL CH264PlayerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
// 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);
// Initialize DIB for drawing...
// Setup bmpinfo structure yourself
m_bmpinfo=new BITMAPINFO;
m_bmpinfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
m_bmpinfo->bmiHeader.biWidth=IMAGE_WIDTH;
m_bmpinfo->bmiHeader.biHeight=IMAGE_HEIGHT;
m_bmpinfo->bmiHeader.biPlanes=1;
m_bmpinfo->bmiHeader.biBitCount=24;
m_bmpinfo->bmiHeader.biCompression=0;
m_bmpinfo->bmiHeader.biSizeImage=0;
m_bmpinfo->bmiHeader.biXPelsPerMeter=0;
m_bmpinfo->bmiHeader.biYPelsPerMeter=0;
m_bmpinfo->bmiHeader.biClrUsed=0;
m_bmpinfo->bmiHeader.biClrImportant=0;
// Get Dialog DC
m_hdc=this->GetDC()->m_hDC;
hdib=::DrawDibOpen();
if(hdib!=NULL)
{
::DrawDibBegin(hdib,
m_hdc,
-1, // don't stretch
-1, // don't stretch
&m_bmpinfo->bmiHeader,
IMAGE_WIDTH, // width of image
IMAGE_HEIGHT, // height of image
0
);
}
//初始化显示
width=IMAGE_WIDTH;height=IMAGE_HEIGHT;
//bufRGB = (unsigned char *)malloc(sizeof(unsigned char)*(3 * width * height));
init_dither_tab();
m_bDecoding=FALSE;
hDecodeThread=NULL;
FileName="";
return TRUE; // return TRUE unless you set the focus to a control
}
void CH264PlayerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CH264PlayerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CH264PlayerDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//解码线程
DWORD CH264PlayerDlg::DecodeThread(void *pDlg)
{
CH264PlayerDlg* pDialog=(CH264PlayerDlg*)pDlg;
FILE * inpf;
//FILE * outf;
int nWrite;
int i,p;
int nalLen;
unsigned char* Buf;
int got_picture, consumed_bytes;
unsigned char *DisplayBuf;
DisplayBuf=new unsigned char[60000];
int i_frames=0;
int StartTime,EndTime;
CHAR fps[20];
char outfile[] = "test.pgm";
char *file;
file=new char[256];
/*for(i=0;i<pDialog->FileName.GetLength();i++)
{
file[i]=pDialog->FileName.GetAt(i);
}*/
sprintf(file,"E:\\yuv samples\\fore.264");
inpf = fopen("E:\\yuv samples\\test5.264", "rb");
delete file;
//outf = fopen("out.yuv", "wb");
nalLen = 0;
Buf = (unsigned char*)calloc ( 1000000, sizeof(char));
avcodec_init();
avcodec_register_all();
codec = avcodec_find_decoder(CODEC_ID_H264);
if (!codec) {
return 0;
}
//allocate codec context
c = avcodec_alloc_context();
if(!c){
return 0;
}
//open codec
if (avcodec_open(c, codec) 0) {
return 0;
}
//allocate frame buffer
picture = avcodec_alloc_frame();
if(!picture){
return 0;
}
StartTime=GetTickCount();
while(!feof(inpf))
{
nalLen = getNextNal(inpf, Buf);
//try to decode this frame
// consumed_bytes= decode_frame(c, picture, &got_picture, Buf, nalLen);
// if (got_picture > 0)
// c->frame_number++;
consumed_bytes= avcodec_decode_video(c, picture, &got_picture, Buf, nalLen);
if(consumed_bytes > 0)
{
/*
for(i=0; i<c->height; i++)
fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf);
for(i=0; i<c->height/2; i++)
fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf);
for(i=0; i<c->height/2; i++)
fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf);
*/
p=0;
for(i=0; i<c->height; i++)
{
memcpy(DisplayBuf+p,picture->data[0] + i * picture->linesize[0], c->width);
p+=c->width;
}
for(i=0; i<c->height/2; i++)
{
memcpy(DisplayBuf+p,picture->data[1] + i * picture->linesize[1], c->width/2);
p+=c->width/2;
}
for(i=0; i<c->height/2; i++)
{
memcpy(DisplayBuf+p,picture->data[2] + i * picture->linesize[2], c->width/2);
p+=c->width/2;
}
//向窗口发送消息显示画面
pDialog->SendMessage(WM_DISPLAY_FRAME,(WPARAM)DisplayBuf,(LPARAM)p);
i_frames++;
}
}
EndTime=GetTickCount();
if(inpf)
fclose(inpf);
/*
if(outf)
fclose(outf);
*/
if(c) {
avcodec_close(c);
av_free(c);
c = NULL;
}
if(picture) {
av_free(picture);
picture = NULL;
}
if(Buf)
{
free(Buf);
Buf = NULL;
}
delete DisplayBuf;
sprintf(fps,"%f fps",(float)(1000*i_frames)/(float)(EndTime-StartTime));
AfxMessageBox(fps);
pDialog->SendMessage(WM_DECODE_COMPLETE,(WPARAM)NULL,(LPARAM)NULL);
return 0;
}
void CH264PlayerDlg::DisplayVideo(unsigned char* displaybuf)
{
ConvertYUVtoRGB ((unsigned char*)displaybuf,(unsigned char*)(displaybuf+25344),(unsigned char*)(displaybuf+31680),bufRGB,width,height);
unsigned char* rgbdata=bufRGB;
::DrawDibDraw(hdib,
m_hdc,
remote_wnd_x, // dest : left pos
remote_wnd_y, // dest : top pos
-1, // don't zoom x
-1, // don't zoom y
&m_bmpinfo->bmiHeader, // bmp header info
rgbdata, // bmp data
0, // src :left
0, // src :top
IMAGE_WIDTH, // src : width
IMAGE_HEIGHT, // src : height
DDF_SAME_DRAW // use prev params....
);
}
LONG CH264PlayerDlg::OnDisplayFrameMsg(WPARAM wParam,LPARAM lParam)
{
unsigned char* DisplayBuf=(unsigned char*)wParam;
int length=(int)lParam;
int i;
for(i=0;i<length/38016;i++)
{
DisplayVideo(DisplayBuf+i*38016);
}
return 1;
}
LONG CH264PlayerDlg::OnDecodeCompleteMsg(WPARAM wParam,LPARAM lParam)
{
SetDlgItemText(IDC_BUTTON_PLAY,_T("解码"));
//停止编码线程
if(hDecodeThread)
{
TerminateThread(hDecodeThread,0);
CloseHandle(hDecodeThread);
hDecodeThread=NULL;
}
m_bDecoding=FALSE;
return 1;
}
void CH264PlayerDlg::OnBnClickedButtonPlay()
{
if(!m_bDecoding)
{
//获取输入文件和输出文件名称
CFileDialog FileDlg1(TRUE,NULL,NULL,OFN_HIDEREADONLY,TEXT("264 Files(*.264)|*.264||"));
//FileDlg1.m_pOFN->lpstrTitle="请选择需要解码的文件";
if(FileDlg1.DoModal()==IDOK)
{
FileName=FileDlg1.GetPathName();
}
else
{
return;
}
//如果有的话,停止解码线程
if(hDecodeThread)
{
TerminateThread(hDecodeThread,0);
CloseHandle(hDecodeThread);
hDecodeThread=NULL;
}
//开始解码线程
m_bDecoding=TRUE;
SetDlgItemText(IDC_BUTTON_PLAY,_T("停止解码"));
hDecodeThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)DecodeThread,(void *)this,0,&dwThreadID);
}
else
{
SetDlgItemText(IDC_BUTTON_PLAY,_T("解码"));
//停止编码线程
if(hDecodeThread)
{
TerminateThread(hDecodeThread,0);
CloseHandle(hDecodeThread);
hDecodeThread=NULL;
}
m_bDecoding=FALSE;
}
}
void CH264PlayerDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
if(m_bmpinfo)
{
delete m_bmpinfo;
}
// Close graphics....
if(hdib!=NULL)
{
::DrawDibEnd(hdib);
::DrawDibClose(hdib);
}
free(clp1);
}