bmp9

 

///////////////////////////////////////
// ReadBMP.cpp

#include <afxdlgs.h>
#include <process.h>
#include "resource.h"
#include "ReadBMP.h"

#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")

CMyApp theApp;
char g_buffer[1024 * 1024 * 15];


BOOL CMyApp::InitInstance()
{
 m_pMainWnd = new CMainWindow;
 m_pMainWnd->ShowWindow(m_nCmdShow);
 return TRUE;
}

CMainWindow::CMainWindow()
{
 LPCTSTR lpszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,
  ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW+2), theApp.LoadIcon(IDI_MAIN));

 CreateEx(NULL, lpszClassName, "BMP文件瀏覽器",
  WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL);
}

BEGIN_MESSAGE_MAP(CMainWindow, CWnd)
 ON_WM_CREATE()
 //ON_WM_PAINT()
 ON_WM_DESTROY()
 ON_COMMAND(FILE_OPEN, OnFileOpen)
END_MESSAGE_MAP()

void CMainWindow::PostNcDestroy()
{
 delete this;
}

BOOL CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 ::SetMenu(m_hWnd, ::LoadMenu(theApp.m_hInstance, (LPCTSTR)IDR_MAIN));

 m_hClientDC = ::GetDC(m_hWnd);
 // 初始化內存DC
 m_hMemDC = ::CreateCompatibleDC(m_hClientDC);

 m_nHeight = 0;
 m_nWidth = 0;
 bRun = FALSE;

 return TRUE;
}

void CMainWindow::OnPaint()
{
 // 這裏一不要用m_hClientDC,因爲m_hClientDC在有效之前OnPaint()就被調用了。
 CPaintDC dc(this);
 ::BitBlt(dc, 0, 0, m_nWidth, m_nHeight, m_hMemDC, 0, 0, SRCCOPY);
}

void CMainWindow::OnDestroy()
{
 bRun = FALSE;
 ::WaitForSingleObject(m_hThread, INFINITE);
 ::DeleteDC(m_hMemDC);
}

void CMainWindow::OnFileOpen()
{
 CFileDialog file(TRUE);
 if(file.DoModal() == IDOK)
 {
  strcpy(strFile, file.GetFileName());

  bRun = FALSE;
  ::WaitForSingleObject(m_hThread, INFINITE);
  bRun = TRUE;
  m_hThread = (HANDLE)_beginthreadex(NULL, 0, playThread, (void*)this, 0, NULL);
 }
}


void CMainWindow::av_create_bmp(CWnd *pWnd, uint8_t *pRGBBuffer, int width, int height, int bpp, char *text)  
{  
 CMainWindow* CMainWnd = (CMainWindow*)pWnd;

    BITMAPFILEHEADER bmpheader;  
    BITMAPINFO bmpinfo;   
  
    bmpheader.bfType = ('M'<<8)|'B';  
    bmpheader.bfReserved1 = 0;  
    bmpheader.bfReserved2 = 0;  
    bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);  
    bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8;  
  
    bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);  
    bmpinfo.bmiHeader.biWidth = width;  
    bmpinfo.bmiHeader.biHeight = -height;  
    bmpinfo.bmiHeader.biPlanes = 1;  
    bmpinfo.bmiHeader.biBitCount = bpp;  
    bmpinfo.bmiHeader.biCompression = BI_RGB;  
    bmpinfo.bmiHeader.biSizeImage = 0;  
    bmpinfo.bmiHeader.biXPelsPerMeter = 100;  
    bmpinfo.bmiHeader.biYPelsPerMeter = 100;  
    bmpinfo.bmiHeader.biClrUsed = 0;  
    bmpinfo.bmiHeader.biClrImportant = 0;  
  
 char *tmpinf = g_buffer + sizeof(BITMAPFILEHEADER);
 char *tmpbit = g_buffer + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

 memcpy(g_buffer, &bmpheader, sizeof(BITMAPFILEHEADER));
 memcpy(tmpinf, &bmpinfo, sizeof(BITMAPINFOHEADER));
 memcpy(tmpbit, pRGBBuffer, width*height*bpp/8);

 // 創建一個與指定DC兼容的未初始化的位圖,選入到內存兼容DC中
 HBITMAP hBitmap = ::CreateCompatibleBitmap(CMainWnd->m_hClientDC, width, height);

 // 將位圖選入內存DC中
 ::SelectObject(CMainWnd->m_hMemDC, hBitmap);

 // 把象圖像據放到建立的設備中
 ::SetDIBitsToDevice(CMainWnd->m_hMemDC, 0, 0, width, height, 0, 0, 0, height, tmpbit, (BITMAPINFO *)tmpinf, DIB_RGB_COLORS);

 static unsigned int lasttime = 0;
 static unsigned int cnt = 0;
 static char szCnt[100];
 unsigned int time = 0;
 unsigned int tmp = 0;
 if(cnt == 0)
 {
  lasttime = ::GetTickCount();
  cnt++;
 }
 else
 {
  time = ::GetTickCount() - lasttime;
  cnt++;
  if(time > 1000)
  {
   sprintf(szCnt, "FPS: %d (%d %d)", cnt, width, height);
   cnt = 0;
  }
 }

 ::TextOut(CMainWnd->m_hMemDC, 20, 20, szCnt, strlen(szCnt));
 if (text != NULL)::TextOut(CMainWnd->m_hMemDC, 20, 50, text, strlen(text));

 ::BitBlt(CMainWnd->m_hClientDC, 0, 0, width, height, CMainWnd->m_hMemDC, 0, 0, SRCCOPY);

 ::DeleteObject(hBitmap);
 
}  

UINT CMainWindow::playThread(LPVOID pWnd)
{
 CMainWindow* pMainWnd = (CMainWindow*)pWnd;

 AVFormatContext* pFormatCtx = NULL;
 AVCodecContext*  pCodecCtx = NULL;
 AVCodec*         pCodec = NULL;   
 AVFrame*         pFrame = NULL;  
 AVFrame*         pFrameRGB = NULL;
 SwsContext*      pSWSCtx = NULL;
 AVPacket         packet; //E:\\Media\\44.mp4

 const char *filename = pMainWnd->strFile;  
 int i, videoStream;  
 int numBytes, frameFinished;  
 uint8_t *buffer = NULL;    

 av_register_all();  

 if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0)
 {
  pMainWnd->MessageBox("av_open_input_file error!");
  return 0;
 }

 if(av_find_stream_info(pFormatCtx)<0)
 {
  pMainWnd->MessageBox("av_find_stream_info error!");
  return 0;
 } 

 dump_format(pFormatCtx, 0, filename, false);  

 videoStream = -1;  
 for(i = 0; i < pFormatCtx->nb_streams; i++)  
 {
  if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
  {  
   videoStream=i;  
   break;  
  }
 }

 if(videoStream==-1)
 {
  pMainWnd->MessageBox("Didn't find a video stream!");
  return 0;
 }

 // 得到視頻流編碼上下文的指針  
 pCodecCtx = pFormatCtx->streams[videoStream]->codec;
   
 // 尋找視頻流的解碼器 
 pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
 if(pCodec==NULL)
 {
  pMainWnd->MessageBox("Didn't find the video decoder!");
  return 0;
 }

 // 通知解碼器我們能夠處理截斷的bit流--ie,  
 // bit流幀邊界可以在包中  

 // 打開解碼器  
 if(avcodec_open(pCodecCtx, pCodec) < 0)
 {
  pMainWnd->MessageBox("Can't open the video decoder!");
  return 0;
 }

 pFrame    = avcodec_alloc_frame();  
  
 unsigned int time = 0x88888888;
 while(av_read_frame(pFormatCtx,&packet)>=0 && pMainWnd->bRun == TRUE)  
 {
  //time = ::GetTickCount();
  if(packet.stream_index==videoStream)
  {  
   avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);  
   if(frameFinished)  
   {  
    // if(pFrame->key_frame==1) pMainWnd->m_nWidth, pMainWnd->m_nHeight 
    {    
     // 圖像大小發生變化
     if (pMainWnd->m_nWidth != pCodecCtx->width || pMainWnd->m_nHeight != pCodecCtx->height)
     {
      if(pFrameRGB){ av_free(pFrameRGB);pFrameRGB = NULL;}

      if(buffer != NULL){ av_free(buffer);buffer = NULL; }

      if(pSWSCtx){ sws_freeContext(pSWSCtx);pSWSCtx = NULL; }
      
      pFrameRGB = avcodec_alloc_frame();  
      numBytes  = avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,pCodecCtx->height);  
      buffer    = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
      avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,pCodecCtx->width, pCodecCtx->height);
      pSWSCtx   = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);  

      pMainWnd->Invalidate();
     }
     sws_scale(pSWSCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

     pMainWnd->m_nWidth = pCodecCtx->width;
     pMainWnd->m_nHeight = pCodecCtx->height;

     int a = 30 - (::GetTickCount() - time);
     char szCnt[100];
     sprintf(szCnt, "a = %d  pts = %d", a, packet.pts);

     if(a > 0)Sleep(a); 
  
     av_create_bmp(pMainWnd, pFrameRGB->data[0], pCodecCtx->width, pCodecCtx->height, 24, szCnt);  

     time = ::GetTickCount();
    }  
   }  
  }
  av_free_packet(&packet);
 }  

 av_free(buffer);

 // 釋放 RGB 圖象  
 av_free(pFrameRGB);

 // 釋放YUV 幀  
 av_free(pFrame);  

 sws_freeContext(pSWSCtx);  

 // 關閉解碼器(codec)  
 avcodec_close(pCodecCtx);  

 // 關閉視頻文件  
 av_close_input_file(pFormatCtx);
 
 pMainWnd->m_nWidth  = 0;
 pMainWnd->m_nHeight = 0;

 pMainWnd->bRun = FALSE;

 return 0;

}

 

 

 

/////////////////////////////////////////////////
// ReadBMP.h文件

#include <afxwin.h>
#include "avcodec.h"  
#include "avformat.h" 
#include "swscale.h"


class CMyApp : public CWinApp
{
public:
 virtual BOOL InitInstance();
};

class CMainWindow : public CWnd
{
public:
 CMainWindow();

private:
 static void av_create_bmp(CWnd *pWnd, uint8_t *pRGBBuffer, int width, int height, int bpp, char *text);
 static UINT __stdcall  playThread(LPVOID pWnd);

protected:
 HDC m_hClientDC;
 HDC m_hMemDC; // 與客戶區兼容的內存DC句柄
 int m_nWidth; // BMP圖像的寬度static
 int m_nHeight; // BMP圖像的高度static
 HANDLE m_hThread;
 BOOL bRun;
 char strFile[500];


protected:
 virtual void PostNcDestroy();
 afx_msg BOOL OnCreate(LPCREATESTRUCT);
 afx_msg void OnPaint();
 afx_msg void OnDestroy();
 afx_msg void OnFileOpen();
 DECLARE_MESSAGE_MAP()
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章