H263编解码在VS2005中结合opencv2.2的测试

            今天开始学习VideoNet(一个很出名的在codeproject上的印度人写的关于点对点的视频聊天的程序,可以在codeproject上下载到源码,而且在vckbase上有中文的翻译)中H.263的编解码器部分,网上搜罗了几个例子,但是都是采用的VFW,有的能编译通过,但是运行时我的免驱USB摄像头根本打不开,没有图像,而且都是基于VideoNet那个程序的,所以干脆自己看看结合着opencv来弄算了(我在VC2005下使用opencv2.2前两天还能打开USB camera,今天不行了~~哎!)。

           在codeproject上的文章中以及源码的头文件中有关于如何使用编码器,解码器的步骤,不多说。需要注意的是编码时使用了一个回调函数,不要忘记。

           开始直接弄视频来测试,结果总是出问题,出现错位,开始以为是RGB与YUV转换的问题,于是加上转换部分的测试发现正常(但是发现了源码中的一个问题,见后面的附:),那可能是编解码器部分问题,找出decoder文件夹下的作者的一个测试解码的例子main来看了看,在程序中加了测试,发现也正常,就是出现上下翻转(这个是opencv与BMP文件的坐标系定义不一样的问题)。后来以为是动态图像问题,测试静态图像没问题了,那就只有是自己动态图像部分程序写错了,再检查。。。。。!!!!原来从视频中读取的图像大小忘了转换,不是标准的CIF或者QCIF格式,导致出现错位,而测试静态图像时进行了大小转换所以没出问题~~~~~~

         修改问题,在测试。。。。。OK!恩~~~编码果然比解码花时间啊!!!!CPU使用率对比明显。

下面是测试的代码:使用VS2005+opencv2.2+VideoNet中的encoder+decoder---------程序有点乱,呵呵

#include <core.hpp>
#include <highgui.hpp>
#include <imgproc.hpp>
#include <iostream>
#include "encoder/libr263.h"
#include "decoder/Tmndec.h"

using namespace std;
using namespace cv;

#pragma comment(lib, "opencv_core220d.lib")
#pragma comment(lib, "opencv_highgui220d.lib")
#pragma comment(lib, "opencv_imgproc220d.lib")

#define WIDTH_QCIF 176
#define HEIGHT_QCIF 144

#define WIDTH_CIF  352
#define HEIGHT_CIF 288

#ifdef WRITE
#undef WRITE
#endif

#ifdef TESTAVI
#undef TESTAVI
#endif

#ifdef H263
#undef H263
#endif

#ifdef CIF
#undef CIF
#endif

//定义H263时---使用类似decoder文件夹下main程序的例子测试解码器--succeed!--不过图像是反的
//不定义H263时,使用下面的测试自己的AVI或者静态图像的编解码
//#define H263	

//定义TESTAVI---测试动态AVI的编码与#define WRITE配合使用-定义WRITE时写入文件,
//--------------不定义WRITE时从文件中读出并播放
//不定义TESTAVI---测试静态图像的RGB与YUV420的转换
#define TESTAVI		
#define WRITE		

//定义了CIF则使用CIF大小,否则使用QCIF大小
#define CIF			

#ifdef CIF
#define WIDTH		WIDTH_CIF
#define HEIGHT		HEIGHT_CIF
#define PARAM_FORM	CPARAM_CIF
#else
#define WIDTH	WIDTH_QCIF
#define HEIGHT	HEIGHT_QCIF
#define PARAM_FORM	CPARAM_QCIF
#endif

//这些值设的比较大,可能有浪费,但是如果小了就会出问题!
int count=0;
unsigned char cdata[20000];
int cbuffer_size=20000;
unsigned char rgbdata[800000];
int buffersize=800000;

//编码回调
void OwnWriteFunction(int byte)
{
	if(::count<cbuffer_size)
	{
		cdata[::count]=(unsigned char)byte;
	::count++;
	}
}

int main(int argc, char **argv)
{
	//var
	Mat rgb;
	Mat temp[3];
	VideoCapture capture;
	CParam EncodeParam;
	FILE *file;
	unsigned char *readdata = NULL;
	unsigned int yuv[WIDTH*HEIGHT*3/2];
	Bits bits;
//初始化
	InitLookupTable();
	EncodeParam.format = PARAM_FORM;
	InitH263Encoder(&EncodeParam);
	WriteByteFunction = OwnWriteFunction;
	InitH263Decoder();

//
#ifdef H263

	FILE *fin, *fout;
	uchar data[5000];
	fin = fopen("h263","rb");
	fout = fopen("my.263","wb");

	int h263size = 2130;	//----decoder中给出的h263文件的大小---根据自己的可以设置
	int n = fread(data, sizeof(char), h263size, fin);
	if(n<h263size)
	{
		cout<<"read total size less than 2130, is: "<<n<<endl;
		goto over;
	}
	
	int ret=DecompressFrame(data, h263size, rgbdata, 800000);
	if(!ret)
	{
		cout<<"decompose failed...."<<endl;
		goto over;
	}
	{
		Mat h263(HEIGHT_QCIF, WIDTH_QCIF, CV_8UC3, rgbdata);
		imwrite("h263.bmp", h263);
		Mat tt = imread("d:\\picture\\123.bmp");
		resize(tt, temp[0], cv::Size(WIDTH_QCIF, HEIGHT_QCIF));

		ConvertRGB2YUV(WIDTH_QCIF, HEIGHT_QCIF, temp[0].data, yuv);	
		::count = 0;
		EncodeParam.format = CPARAM_QCIF;
		EncodeParam.inter = CPARAM_INTRA;
		EncodeParam.Q_intra = 8;
		EncodeParam.data = yuv;

		CompressFrame(&EncodeParam, &bits);
		cout<<"the size is: "<<(::count)<<endl;
		fwrite(cdata, ::count, 1, fout);
	}

	fclose(fin);
	fclose(fout);
#else
//

#ifdef WRITE
	file = fopen("video.263", "wb");
#else
	file = fopen("video.263", "rb");
#endif	
	
	capture.open("d:\\video\\petsc1.avi");
	if (!capture.isOpened())
	{
		cout<<"open camera failed"<<endl;
		return -1;
	}

	temp[1] = imread("d:\\picture\\123.bmp");
	if(temp[1].empty())
	{
		cout<<"read img failed!"<<endl;
		goto over;
	}
	namedWindow("show", CV_WINDOW_AUTOSIZE);
	namedWindow("decom", CV_WINDOW_AUTOSIZE);
	while( waitKey(30) != 27 )
	{
		capture>>rgb;
		if (rgb.empty())
		{
			cout<<"grab no frames, exit"<<endl;
			break;
		}

#ifdef TESTAVI
		resize(rgb, temp[0], cv::Size(WIDTH, HEIGHT));
#else
		resize(temp[1], temp[0], cv::Size(WIDTH, HEIGHT));
#endif
		imshow("show", temp[0]);

#ifdef TESTAVI		//----write or read avi frames 
				
#ifdef WRITE	//---write compressed frames to file
		ConvertRGB2YUV(WIDTH, HEIGHT, temp[0].data, yuv);	
		::count = 0;
		EncodeParam.format = PARAM_FORM;
		EncodeParam.inter = CPARAM_INTRA;
		EncodeParam.Q_intra = 8;
		EncodeParam.data = yuv;

		CompressFrame(&EncodeParam, &bits);
		cout<<"count num: "<<::count<<endl;
		size_t n = fwrite(&(::count), 4, 1, file);
		if(n==0)
		{
			cout<<"count write 0 byte, failed"<<endl;
			goto over;
		}
		n = fwrite(cdata, ::count, 1, file);
		if(n==0)
		{
			cout<<"data write 0 byte, failed"<<endl;
			goto over;
		}
#else	//read stored data and decompress then show
		int bytecount = 0;
		size_t n = fread(&bytecount, 4, 1, file);
		if(n==0)
		{
			cout<<"count read 0 byte, failed"<<endl;
			goto over;
		}
		cout<<"read byte size: "<<bytecount<<endl;
		readdata = new unsigned char[bytecount+1];

		n = fread(readdata, bytecount, 1, file);
		if(n==0)
		{
			cout<<"data read 0 byte, failed"<<endl;
			goto over;
		}

		DecompressFrame(readdata, bytecount, rgbdata, buffersize);
		Mat decodeimg(HEIGHT, WIDTH, CV_8UC3, rgbdata);
		imshow("decom", decodeimg);

		delete []readdata;
		readdata = NULL;
#endif	//---for #ifdef WRITE end

#else	// not define TESTAVI------for the test of static convert functions
		ConvertRGB2YUV(WIDTH, HEIGHT, temp[0].data, yuv);
		readdata = new unsigned char[WIDTH*HEIGHT*3/2];
		memset(readdata, 0, WIDTH*HEIGHT*3/2);

		for(int i=0; i<WIDTH*HEIGHT*3/2; ++i)
			readdata[i] = (unsigned char)yuv[i];
		uchar *y = readdata;
		uchar *u = y+WIDTH*HEIGHT;
		uchar *v = u+WIDTH*HEIGHT/4;

		ConvertYUV2RGB(y, u, v, rgbdata, WIDTH, HEIGHT);

		Mat decodeimg(HEIGHT, WIDTH, CV_8UC3, rgbdata);
		imshow("decom", decodeimg);

		delete [] readdata;
		readdata = NULL;
#endif	//----for #ifdef TESTAVI end
	}
	fclose(file);
	cvDestroyAllWindows();
#endif //--for #ifdef H263 end

over:
	cout<<"exit......"<<endl;
//release resource
	ExitH263Decoder();
	ExitH263Encoder(&EncodeParam);

	system("pause");

	return 0;
}


附:在VideoNet的源码convert.cpp中,ConvertRGB2YUV函数,开始时动态new的是数组:

	uu=new unsigned int[w*h];
	vv=new unsigned int[w*h];

 

但是最后:

delete uu;
delete vv;

 

却没有使用使用正确的释放方法,虽然貌似也没多大问题,但是总归是不对的。改为如下就OK了:

delete [] uu;
delete [] vv;


 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值