📄 h264ce.cpp
字号:
// H264CE.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "H264CE.h"
#include <commctrl.h>
#include <aygshell.h>
#include <sipapi.h>
//进行H264解码的包含文件、定义以及变量
#include "h264.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE g_hInst; // The current instance
HWND g_hwndCB; // The command bar handle
static SHACTIVATEINFO s_sai;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass (HINSTANCE, LPTSTR);
BOOL InitInstance (HINSTANCE, int);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
HWND CreateRpCommandBar(HWND);
//H264相关函数和变量
//解码线程函数
DWORD DecodeThread(void *para);
HANDLE hDecodeThread;
DWORD dwThreadID;
//GAPI显示以及硬件按键结构体变量
GXDisplayProperties g_gxdp; // GX struct
GXKeyList g_gxkl; // GX struct
//GAPI显示函数
BOOL m_bGapi;
BOOL OpenGAPI(HWND* Wnd);
void Blt(int x,int y,int width,int height,unsigned char* data);
BOOL CloseGAPI();
typedef struct THDP
{
HWND hWnd;
TCHAR *File;
}THDP;
/////////////////////////////////////////////////////////////////////////////
//进行YUV->RGB转换以及显示视频的函数
int *Cr_r_tab;
int *Cr_g_tab;
int *Cb_g_tab;
int *Cb_b_tab;
Uint32 *r_2_pix_alloc;
Uint32 *g_2_pix_alloc;
Uint32 *b_2_pix_alloc;
int i;
int CR, CB;
Uint32 Rmask, Gmask, Bmask;
int *colortab;
Uint32 *rgb_2_pix;
unsigned short *rgb565;
//用来显示的全局变量
int width,height;
void CreateYUVTable()
{
colortab = (int *)malloc(4*256*sizeof(int));
Cr_r_tab = &colortab[0*256];
Cr_g_tab = &colortab[1*256];
Cb_g_tab = &colortab[2*256];
Cb_b_tab = &colortab[3*256];
rgb_2_pix = (Uint32 *)malloc(3*768*sizeof(Uint32));
r_2_pix_alloc = &rgb_2_pix[0*768];
g_2_pix_alloc = &rgb_2_pix[1*768];
b_2_pix_alloc = &rgb_2_pix[2*768];
/* Generate the tables for the display surface */
for (i=0; i<256; i++) {
/* Gamma correction (luminescence table) and chroma correction
would be done here. See the Berkeley mpeg_play sources.
*/
CB = CR = (i-128);
Cr_r_tab[i] = (int) ( (0.419/0.299) * CR);
Cr_g_tab[i] = (int) (-(0.299/0.419) * CR);
Cb_g_tab[i] = (int) (-(0.114/0.331) * CB);
Cb_b_tab[i] = (int) ( (0.587/0.331) * CB);
}
/*
* Set up entries 0-255 in rgb-to-pixel value tables.
*/
Rmask = 0xF800;//display->format->Rmask;
Gmask = 0x7E0;//display->format->Gmask;
Bmask = 0x1F;//display->format->Bmask;
for ( i=0; i<256; ++i ) {
r_2_pix_alloc[i+256] = i >> (8 - 5);
r_2_pix_alloc[i+256] <<= 0;
g_2_pix_alloc[i+256] = i >> (8 - 6);
g_2_pix_alloc[i+256] <<= 5;
b_2_pix_alloc[i+256] = i >> (8 - 5);
b_2_pix_alloc[i+256] <<= 11;
}
/*
* If we have 16-bit output depth, then we double the value
* in the top word. This means that we can write out both
* pixels in the pixel doubling mode with one op. It is
* harmless in the normal case as storing a 32-bit value
* through a short pointer will lose the top bits anyway.
*/
for ( i=0; i<256; ++i ) {
r_2_pix_alloc[i+256] |= (r_2_pix_alloc[i+256]) << 16;
g_2_pix_alloc[i+256] |= (g_2_pix_alloc[i+256]) << 16;
b_2_pix_alloc[i+256] |= (b_2_pix_alloc[i+256]) << 16;
}
rgb565=(unsigned short *)malloc(320*240*2);
}
void FreeYUVTable()
{
free(colortab);
free(rgb_2_pix);
free(rgb565);
}
static void DisplayYUV( int *colortab, Uint32 *rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned short *out,
int rows, int cols, int mod )
{
unsigned short* row1;
unsigned short* row2;
unsigned char* lum2;
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
row1 = (unsigned short*)rgb565;
row2 = row1 + cols + mod;
lum2 = lum + cols;
mod += cols + mod;
y = rows / 2;
while( y-- )
{
x = cols_2;
while( x-- )
{
register int L;
cr_r = 0*768+256 + colortab[ *cr + 0*256 ];
crb_g = 1*768+256 + colortab[ *cr + 1*256 ]
+ colortab[ *cb + 2*256 ];
cb_b = 2*768+256 + colortab[ *cb + 3*256 ];
++cr; ++cb;
L = *lum++;
*row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] |
rgb_2_pix[ L + crb_g ] |
rgb_2_pix[ L + cb_b ]);
L = *lum++;
*row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] |
rgb_2_pix[ L + crb_g ] |
rgb_2_pix[ L + cb_b ]);
/* Now, do second row. */
L = *lum2++;
*row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] |
rgb_2_pix[ L + crb_g ] |
rgb_2_pix[ L + cb_b ]);
L = *lum2++;
*row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] |
rgb_2_pix[ L + crb_g ] |
rgb_2_pix[ L + cb_b ]);
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
lum += cols;
lum2 += cols;
row1 += mod;
row2 += mod;
}
int offset,y1;
offset=0;
for(x=0;x<320;x++)
{
y1=320;
for(y=0;y<240;y++)
{
out[offset++]=rgb565[y1-x+y];
y1+=320;
}
}
}
//H.264全局变量
AVCodec *codec; // Codec
AVCodecContext *c; // Codec Context
AVFrame *picture; // Frame
AVFrame *displaypicture; // Frame
//读取文件全局变量
#define DATA_MAX 600000
enum
{
PARSE_STATE_INIT=0,
PARSE_STATE_A,
PARSE_STATE_B
};
//解码控制
BOOL m_bDecoding;
BOOL OpenGAPI(HWND *Wnd)
{
//打开GAPI显示
if(GXOpenDisplay(*Wnd,GX_FULLSCREEN)==0)
{
return FALSE; //无法进行GAPI绘图
}
else
{
//取得显示属性
g_gxdp = GXGetDisplayProperties();
}
return TRUE;
}
BOOL CloseGAPI()
{
return GXCloseDisplay();
}
//控制显示的变量
HANDLE hDisplayThread=NULL;
DWORD dwDisplayThreadID=0;
HANDLE hDisplayEvent=NULL;
BOOL bDisplay=FALSE;
unsigned short * VideoBuffer;
unsigned char *DisplayBuf;
//显示线程
DWORD DisplayThread()
{
int i,p;
while(bDisplay)
{
WaitForSingleObject(hDisplayEvent,1000);
p=0;
for(i=0; i<c->height; i++)
{
memcpy(DisplayBuf+p,displaypicture->data[0] + i * displaypicture->linesize[0], c->width);
p+=c->width;
}
for(i=0; i<c->height/2; i++)
{
memcpy(DisplayBuf+p,displaypicture->data[1] + i * displaypicture->linesize[1], c->width/2);
p+=c->width/2;
}
for(i=0; i<c->height/2; i++)
{
memcpy(DisplayBuf+p,displaypicture->data[2] + i * displaypicture->linesize[2], c->width/2);
p+=c->width/2;
}
//显示画面
DisplayYUV(colortab,rgb_2_pix,DisplayBuf,(DisplayBuf+76800),(DisplayBuf+96000),VideoBuffer,240,320,1);
ResetEvent(hDisplayEvent);
}
return 0;
}
//解码线程
DWORD DecodeThread(void *para)
{
THDP* threadpara=(THDP*)para;
FILE * inpf;
int i,p;
int got_picture, consumed_bytes;
int i_data_size, i_cur, i_nal_start; //buffer correlative
int b_eof_h264=0;
int i_read;
int b_need_buffer=0;
int i_parse_state, i_start_code_size; //nal extraction correlative
int b_find_nal;
int b_decode_finish;
DisplayBuf=new unsigned char[115200];
int i_frames=0;
int StartTime,EndTime;
TCHAR fps[20];
//读取文件
char *name;
name=new char [wcslen(threadpara->File)];
//中文转换
int actuallength=0;
actuallength=WideCharToMultiByte(CP_ACP,NULL,(LPCWSTR)threadpara->File,wcslen(threadpara->File),(LPSTR)name,0,NULL,NULL);
delete name;
name=new char [actuallength];
ZeroMemory(name,actuallength);
WideCharToMultiByte(CP_ACP,NULL,(LPCWSTR)threadpara->File,wcslen(threadpara->File),(LPSTR)name,actuallength,NULL,NULL);
inpf = fopen(name, "rb");
LocalFree(threadpara->File);
delete name;
if(!inpf)
{
goto Decodereturn;
}
uint8_t* data=new uint8_t[DATA_MAX];
avcodec_init();
//avcodec_register_all();
codec = &h264_decoder;//avcodec_find_decoder(CODEC_ID_H264);
if (!codec) {
goto Decodereturn;
}
//allocate codec context
c = avcodec_alloc_context();
if(!c){
goto Decodereturn;
}
//open codec
if (avcodec_open(c, codec) < 0) {
goto Decodereturn;
}
//allocate frame buffer
picture = avcodec_alloc_frame();
if(!picture){
goto Decodereturn;
}
displaypicture = avcodec_alloc_frame();
if(!displaypicture){
goto Decodereturn;
}
VideoBuffer=(unsigned short *)GXBeginDraw();
//创建显示线程
hDisplayEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
bDisplay=TRUE;
hDisplayThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)DisplayThread,NULL,0,&dwDisplayThreadID);
StartTime=GetTickCount();
//confirm the first start code
i_read=fread(&data[0],1,DATA_MAX,inpf);
if(i_read < 4)
{
fprintf(stderr,"the h264 stream file is too small, even can't include the first start code\n");
goto Decodereturn;
}
i_data_size=i_read;
if(data[0]!=0x00 || data[1]!=0x00 || data[2]!=0x00 || data[3]!=0x01 )
{
fprintf(stderr,"confirm the first start code failed\n");
goto Decodereturn;
}
i_cur=4;
i_nal_start=4;
b_need_buffer=0;
b_decode_finish=0;
//[2] main loop
while (!b_decode_finish && m_bDecoding)
{
//[2.1] fill buffer
if (b_need_buffer)
{
//transfer the partly read nal data to the top of the buffer
//note: here, i_data_size must equal with i_cur
i_data_size=i_cur-i_nal_start;
memmove(&data[0],&data[i_nal_start],i_data_size); //overlap is possible
i_nal_start=0;
i_cur=i_data_size;
//read more data
i_read=fread(&data[i_data_size],1,DATA_MAX-i_data_size,inpf);
if (i_read<=0)
{
b_eof_h264=1;
}
else
{
i_data_size+=i_read;
}
b_need_buffer=0;//!!
}
else
{
i_parse_state=PARSE_STATE_INIT;
}
//[2.2] extract a nal
b_find_nal=0;
while (i_cur<i_data_size && !b_find_nal)
{
switch(i_parse_state)
{
case PARSE_STATE_INIT:
if (0==data[i_cur])
i_parse_state=PARSE_STATE_A;
else
i_parse_state=PARSE_STATE_INIT;
break;
case PARSE_STATE_A:
if (0==data[i_cur])
{
i_start_code_size=2;
i_parse_state=PARSE_STATE_B;
}
else
i_parse_state=PARSE_STATE_INIT;
break;
case PARSE_STATE_B:
if (0==data[i_cur])
{
i_start_code_size++;
i_parse_state=PARSE_STATE_B;
}
else if (1==data[i_cur])
{
i_start_code_size++;
b_find_nal=1;
}
else
{
i_parse_state=PARSE_STATE_INIT;
}
break;
default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -