📄 clienth264dlg.cpp
字号:
char *tmp = snippets.RemoveHead();
free(tmp);
}
char *snippet = (char *) malloc(rVal);
memcpy(snippet, buf, rVal);
snippets.AddTail(snippet);
//==================================================================
LeaveCriticalSection(&lockSnippet);
}
closesocket(client);
WSACleanup();
//AfxMessageBox("finished.");
return SOCKET_OK;
}
//thread that decodes h264 bit stream to frame
UINT H264DecodingThread(LPVOID param)
{
AVCodec *codec;
AVCodecContext *c= NULL;
AVFrame *picture;
uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
int size, got_picture, len;
AVFrame *pFrameYUV;
int numBytes;
uint8_t *buffer;
int y_size = FRAME_WIDTH * FRAME_HEIGHT;
// set end of buffer to 0
memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
// find the h264 video decoder
codec = avcodec_find_decoder(CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c= avcodec_alloc_context();
picture= avcodec_alloc_frame();
// for continuous data retriving
if(codec->capabilities&CODEC_CAP_TRUNCATED)
c->flags|= CODEC_FLAG_TRUNCATED; //uncompleted h264 NAL data
// open h264 codec
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
//buffer to image planes in pFrameRGB
pFrameYUV=avcodec_alloc_frame();
//required buffer size and then allocate buffer
numBytes = avpicture_get_size(PIX_FMT_YUV420P, FRAME_WIDTH, FRAME_HEIGHT);
buffer = (uint8_t*)malloc(numBytes);
avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P, FRAME_WIDTH, FRAME_HEIGHT);
while (nPlaying)
{
if (snippets.GetCount() == 0)
Sleep(10);
else
{
//get some snippets to decode
EnterCriticalSection(&lockSnippet);
//==================================================================
char *snippet = snippets.RemoveHead();
size = _msize(snippet);
memcpy(inbuf, snippet, size);
//free snippet memory
free(snippet);
//==================================================================
LeaveCriticalSection(&lockSnippet);
//now decode h264 frame
if (size == 0)
continue;
inbuf_ptr = inbuf;
while (size > 0) {
int ECode;
__try
{
len = avcodec_decode_video(c, picture, &got_picture, inbuf_ptr, size);
}
__except (ECode=GetExceptionCode())
{
printf("解码发生异常,Code=%d\n",ECode);
break;//inner while
}
if (len < 0) {
break;//inner while
}
if (got_picture) {
//convert raw video stream to YUV420 format
img_convert((AVPicture *)pFrameYUV, PIX_FMT_YUV420P, (AVPicture*)picture,
c->pix_fmt, FRAME_WIDTH, FRAME_HEIGHT);
//convert YUV420P to RGB frame
LPBYTE Y, Cb, Cr, RGBbuf;
RGBbuf = (unsigned char *) malloc(FRAME_WIDTH * FRAME_HEIGHT * 3);
Y = pFrameYUV->data[0];
Cb = pFrameYUV->data[1];
Cr = pFrameYUV->data[2];
conv.YV12_to_RGB24(Y, Cb, Cr, RGBbuf, FRAME_WIDTH, FRAME_HEIGHT);
//put some frames to frame pool
EnterCriticalSection(&lockFrame);
//------------------------------------------------------------------
if (frames.GetCount() > 50) //remove the outdated video frame
{
unsigned char *tmp = frames.RemoveHead();
free(tmp);
}
frames.AddTail(RGBbuf);
//------------------------------------------------------------------
LeaveCriticalSection(&lockFrame);
}
size -= len;
inbuf_ptr += len;
}
}
}
avcodec_close(c);
av_free(c);
av_free(picture);
av_free(pFrameYUV);
free(buffer);
return 0;
}
//thread that plays decoded frame
UINT H264PlayingThread(LPVOID param)
{
CClientH264Dlg *dlg = (CClientH264Dlg *)AfxGetApp()->m_pMainWnd;
CStatic *screen = (CStatic *) dlg->GetDlgItem(IDC_STATIC_SCREEN);
CDC *pDC = screen->GetDC();
BYTE RGBbuf[FRAME_WIDTH * FRAME_HEIGHT * 3];
RECT rect;
screen->GetClientRect(&rect);
int iWidth = FRAME_WIDTH;
int iHeight = FRAME_HEIGHT;
float m_xZoom = (rect.right - rect.left) / (float)iWidth;
float m_yZoom = (rect.bottom - rect.top) / (float)iHeight;
//allocate bmp memory to attach playing window
HANDLE hloc = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 256));
LPBITMAPINFO BmpInfo = (LPBITMAPINFO) GlobalLock(hloc);
BmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BmpInfo->bmiHeader.biPlanes = 1;
BmpInfo->bmiHeader.biBitCount = 24;
BmpInfo->bmiHeader.biCompression = BI_RGB;
BmpInfo->bmiHeader.biWidth = iWidth;
BmpInfo->bmiHeader.biHeight = iHeight;
//============================
CDXSurfaceManager_NBP dxMgr_;
dxMgr_.Initialise(screen->m_hWnd);
pDC->SetStretchBltMode(STRETCH_DELETESCANS);
CBrush brush1; // Must initialize!
brush1.CreateSolidBrush(RGB(0,0,0)); // Black brush.
while (nPlaying)
{
//playing video as fast as possible
if (frames.GetCount() > 0)
{
//get decoded frame
EnterCriticalSection(&lockFrame);
BYTE *frame = frames.RemoveHead();
LeaveCriticalSection(&lockFrame);
//free frame memory
memcpy(RGBbuf, frame, FRAME_WIDTH * FRAME_HEIGHT * 3);
free(frame);
nFrames ++;
//now playing the frame
HDC& hdc = dxMgr_.BeginPaint(GetSysColor(COLOR_3DFACE));
if(NULL !=hdc)
{
CDC* cdc = CDC::FromHandle(hdc);
//------------------------------
if (nZoom)
{
StretchDIBits(hdc, 0, 0, (int)(m_xZoom*iWidth), (int)(m_yZoom*iHeight),
0, 0, iWidth, iHeight,
RGBbuf, BmpInfo, DIB_RGB_COLORS, SRCCOPY);
}
else
{
StretchDIBits(hdc, 0, 0, iWidth, iHeight,
0, 0, iWidth, iHeight,
RGBbuf, BmpInfo, DIB_RGB_COLORS, SRCCOPY);
}
//------------------------------
dxMgr_.EndPaint();
}
}
else
Sleep(1);
}
GlobalUnlock(hloc);
GlobalFree(hloc);
return 0;
}
void CClientH264Dlg::OnButtonConnect()
{
// TODO: Add your control notification handler code here
InitializeCriticalSection(&lockSnippet);
InitializeCriticalSection(&lockFrame);
UpdateData(TRUE);
strcpy(strIP, m_strServerIP);
AfxBeginThread(H264ReceivingThread, (LPVOID)NULL, 0, 0, NULL);
//init h264 codec
avcodec_init();
avcodec_register_all();
AfxBeginThread(H264DecodingThread, (LPVOID)NULL, 0, 0, NULL);
AfxBeginThread(H264PlayingThread, (LPVOID)NULL, 0, 0, NULL);
GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(FALSE);
}
void CClientH264Dlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
KillTimer(SPEED_REFRESH);
WSACleanup();
nPlaying = 0;
Sleep(150);
CDialog::OnClose();
}
void CClientH264Dlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
while (! snippets.IsEmpty())
{
char *buf = snippets.RemoveHead();
free(buf);
}
while (! frames.IsEmpty())
{
unsigned char *buf = frames.RemoveHead();
free(buf);
}
}
void CClientH264Dlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch (nIDEvent)
{
case SPEED_REFRESH:
{
if (nData == 0)//has no data received
return;
nTicks ++;
m_strTimer.Format("计时时间: %d s", nTicks);
m_strTotalReceive.Format("累计接收: %.1f KB", nData/1024.0);
m_strTotalFrames.Format("累计帧数: %d", nFrames);
m_strAveFrames.Format("平均帧率: %.1f fps", nFrames/(1.0*nTicks));
UpdateData(FALSE);
CString s;
s.Format("平均速度:%.1fkbps Snippets:%d-Frames:%d", nData*8/(1024.0 * nTicks), snippets.GetCount(), frames.GetCount());
SetWindowText(s);
break;
}
default:
break;
}
CDialog::OnTimer(nIDEvent);
}
void CClientH264Dlg::OnStaticScreen()
{
// TODO: Add your control notification handler code here
nZoom = (nZoom==0) ? 1 : 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -