⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 h264ce.cpp

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -