コード例 #1
0
ファイル: utility.c プロジェクト: Tayyib/uludag
void
pack_replace(struct pack *p, const char *arg, const char *value, size_t size)
{
	unsigned char *ptr;
	char *t;
	size_t ts;
	size_t old_size;
	size_t diff;

	p->pos = 0;
	while (pack_get(p, &t, &ts)) {
		if (strcmp(t, arg) == 0) {
			// found it, replace the old value
			ptr = p->buffer + p->pos;
			old_size =  ptr[0] + (ptr[1] << 8);
			diff = size - old_size;
			if (old_size < size && p->max - p->used < diff) {
				pack_ensure_size(p, p->max + diff);
				ptr = p->buffer + p->pos;
			}
			if (diff) {
				size_t len = p->used - (p->pos + old_size + 3);
				memmove(ptr + old_size + 3 + diff, ptr + old_size + 3, len);
			}
			*ptr++ = (size & 0xff);
			*ptr++ = (size & 0xff00) >> 8;
			memcpy(ptr, value, size);
			ptr += size;
			*ptr = '\0';
			p->used += diff;
			return;
		}
		// skip the argument's value
		pack_get(p, &t, &ts);
	}
コード例 #2
0
ファイル: data.c プロジェクト: Tayyib/uludag
void
db_del_profile(int node_no, const char *app, struct pack *args)
{
	struct databases db;
	char *key = NULL;
	char *inst_key = NULL;
	char *inst_value = NULL;
	char *t;
	size_t ts;

	if (open_env(&db, PROFILE_DB)) goto out;

	while (pack_get(args, &t, &ts)) {
		if (model_is_instance(node_no, t)) {
			inst_key = t;
			pack_get(args, &t, &ts);
			inst_value = t;
		} else {
			pack_get(args, &t, &ts);
		}
	}

	key = make_profile_key(node_no, app, inst_key, inst_value);
	if (!key) goto out;

	del_data(db.profile, key);

out:
	if (key) free(key);
	close_env(&db);
}
コード例 #3
0
ファイル: data.c プロジェクト: Tayyib/uludag
int
db_put_profile(int node_no, const char *app, struct pack *args)
{
	struct databases db;
	struct pack *old_args = NULL;
	int e, ret = -1;
	char *key = NULL;
	char *inst_key = NULL;
	char *inst_value = NULL;
	char *t, *t2, *data;
	size_t ts, size;

	if (open_env(&db, PROFILE_DB)) goto out;

	while (pack_get(args, &t, &ts)) {
		if (model_is_instance(node_no, t)) {
			inst_key = t;
			pack_get(args, &t, &ts);
			inst_value = t;
		} else {
			pack_get(args, &t, &ts);
		}
	}

	key = make_profile_key(node_no, app, inst_key, inst_value);
	if (!key) goto out;

	data = get_data(db.profile, key, &size, &e);
	// FIXME: handle notfound separately, see also csl.c/c_get_profile()
	if (e && e != DB_NOTFOUND) goto out;

	if (!e) {
		old_args = pack_wrap(data, size);
		args->pos = 0;
		while (pack_get(args, &t, &ts)) {
			pack_get(args,&t2, &ts);
			pack_replace(old_args, t, t2, ts);
		}
		e = put_data(db.profile, key, old_args->buffer, old_args->used);
	} else {
		e = put_data(db.profile, key, args->buffer, args->used);
	}

	if (e) goto out;

	ret = 0;
out:
	close_env(&db);
	if (old_args) pack_delete(old_args);
	if (key) free(key);
	return ret;
}
コード例 #4
0
ファイル: data.c プロジェクト: Tayyib/uludag
char *
db_dump_profile(void)
{
	struct databases db;
	struct pack *p;
	DBC *cursor = NULL;
	DBT pair[2];
	int e;
	iks *xml = NULL, *item, *x;
	char *ret = NULL;

	memset(&pair[0], 0, sizeof(DBT) * 2);
	pair[1].flags = DB_DBT_MALLOC;

	if (open_env(&db, PROFILE_DB)) goto out;

	db.profile->cursor(db.profile, NULL, &cursor, 0);

	xml = iks_new("comarProfile");
	iks_insert_cdata(xml, "\n", 1);
	while ((e = cursor->c_get(cursor, &pair[0], &pair[1], DB_NEXT)) == 0) {
		char *t;
		size_t ts;
		item = iks_insert(xml, "item");
		iks_insert_cdata(iks_insert(item, "key"), pair[0].data, pair[0].size);
		p = pack_wrap(pair[1].data, pair[1].size);
		while (pack_get(p, &t, &ts)) {
			iks_insert_cdata(item, "\n", 1);
			x = iks_insert(item, "data");
			iks_insert_attrib(x, "key", t);
			pack_get(p, &t, &ts);
			iks_insert_cdata(iks_insert(x, "value"), t, ts);
		}
		pack_delete(p);
		iks_insert_cdata(xml, "\n", 1);
	}
	if (e != DB_NOTFOUND) {
		goto out;
	}

	ret = iks_string(NULL, xml);
out:
	if (cursor) cursor->c_close(cursor);
	close_env(&db);
	if (xml) iks_delete(xml);
	return ret;
}
コード例 #5
0
ファイル: csl.c プロジェクト: Tayyib/uludag
static PyObject *
c_get_profile(PyObject *self, PyObject *args)
{
	struct pack *p;
	const char *node = NULL;
	char *app;
	int node_no;
	char *t;
	size_t ts;
	PyObject *dict;

	proc_check_shutdown();

	dict = PyDict_New();

	if (!PyArg_ParseTuple(args, "|s", &node))
		return NULL;

	if (node)
		node_no = model_lookup_method(node);
	else
		node_no = bk_node;

	if (model_flags(node_no) & P_PACKAGE)
		app = bk_app;
	else
		app = NULL;

	p = db_get_profile(node_no, app, NULL, NULL);
	if (!p) {
		Py_INCREF(Py_None);
		return Py_None;
	}

	while (pack_get(p, &t, &ts)) {
		PyObject *val;
		char *t2;
		pack_get(p, &t2, &ts);
		val = PyString_FromStringAndSize(t2, ts);
		PyDict_SetItemString(dict, t, val);
	}

	return dict;
}
コード例 #6
0
ファイル: csl.c プロジェクト: Tayyib/uludag
static PyObject *
c_get_instance(PyObject *self, PyObject *args)
{
	struct pack *p;
	const char *inst_key = NULL, *inst_value = NULL;
	char *app;
	char *t;
	size_t ts;
	PyObject *dict;

	proc_check_shutdown();

	dict = PyDict_New();

	if (!PyArg_ParseTuple(args, "|ss", &inst_key, &inst_value))
		return NULL;

	if (inst_key && !inst_value)
		return NULL;

	// FIXME: no global instances for now, handle nicely in model.xml
	//if (model_package_profile(bk_node))
		app = bk_app;
	//else
	//	app = NULL;

	p = db_get_profile(bk_node, app, inst_key, inst_value);
	if (!p) {
		Py_INCREF(Py_None);
		return Py_None;
	}

	while (pack_get(p, &t, &ts)) {
		PyObject *val;
		char *t2;
		pack_get(p, &t2, &ts);
		val = PyString_FromStringAndSize(t2, ts);
		PyDict_SetItemString(dict, t, val);
	}

	return dict;
}
コード例 #7
0
ファイル: job.c プロジェクト: Tayyib/uludag
static void
job_proc(void)
{
	struct ipc_struct ipc;
	struct pack *p;
	struct ProcChild *sender;
	char *t, *s;
	int cmd;
	size_t size;

	p = pack_new(256);
	while (1) {
		if (1 == proc_listen(&sender, &cmd, &size, 1)) break;
	}
	proc_get(sender, &ipc, p, size);

	bk_channel = ipc.source;

	switch (cmd) {
		case CMD_REGISTER:
			pack_get(p, &t, NULL);
			pack_get(p, &s, NULL);
			do_register(ipc.node, t, s);
			break;
		case CMD_REMOVE:
			pack_get(p, &t, NULL);
			do_remove(t);
			break;
		case CMD_CALL:
			do_call(ipc.node, p);
			break;
		case CMD_CALL_PACKAGE:
			pack_get(p, &t, NULL);
			do_call_package(ipc.node, t, p);
			break;
		case CMD_GETLIST:
			do_getlist(ipc.node);
			break;
		case CMD_DUMP_PROFILE:
			do_dump_profile();
			break;
		case CMD_EVENT:
			pack_get(p, &t, NULL);
			pack_get(p, &s, NULL);
			do_event(t, ipc.node, s, p);
			break;
	}
}
コード例 #8
0
ファイル: simple_demo.c プロジェクト: lixiantai/Camkit
int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        printf("Usage: #simple_demo ip port\n");
        return  -1;
    }

	struct cap_handle *caphandle = NULL;
	struct cvt_handle *cvthandle = NULL;
	struct enc_handle *enchandle = NULL;
	struct pac_handle *pachandle = NULL;
    struct net_handle *nethandle = NULL;
	struct cap_param capp;
	struct cvt_param cvtp;
	struct enc_param encp;
	struct pac_param pacp;
    struct net_param netp;

	// set paraments
	U32 vfmt = V4L2_PIX_FMT_YUYV;
	U32 ofmt = V4L2_PIX_FMT_YUV420;

	capp.dev_name = "/dev/video0";
	capp.width = WIDTH;
	capp.height = HEIGHT;
	capp.pixfmt = vfmt;
	capp.rate = FRAMERATE;

	cvtp.inwidth = WIDTH;
	cvtp.inheight = HEIGHT;
	cvtp.inpixfmt = vfmt;
	cvtp.outwidth = WIDTH;
	cvtp.outheight = HEIGHT;
	cvtp.outpixfmt = ofmt;

	encp.src_picwidth = WIDTH;
	encp.src_picheight = HEIGHT;
	encp.enc_picwidth = WIDTH;
	encp.enc_picheight = HEIGHT;
	encp.chroma_interleave = 0;
	encp.fps = FRAMERATE;
	encp.gop = 30;
	encp.bitrate = 800;

	pacp.max_pkt_len = 1400;
	pacp.ssrc = 10;

    netp.type = UDP;
    netp.serip = argv[1];
    netp.serport = atoi(argv[2]);

	caphandle = capture_open(capp);
	if (!caphandle)
	{
		printf("--- Open capture failed\n");
		return -1;
	}

	cvthandle = convert_open(cvtp);
	if (!cvthandle)
	{
		printf("--- Open convert failed\n");
		return -1;
	}

	enchandle = encode_open(encp);
	if (!enchandle)
	{
		printf("--- Open encode failed\n");
		return -1;
	}

	pachandle = pack_open(pacp);
	if (!pachandle)
	{
		printf("--- Open pack failed\n");
		return -1;
	}

    nethandle = net_open(netp);
    if (!nethandle)
    {
        printf("--- Open network failed\n");
        return -1;
    }

	// start stream loop
	int ret;
	void *cap_buf, *cvt_buf, *hd_buf, *enc_buf, *pac_buf;
	int cap_len, cvt_len, hd_len, enc_len, pac_len;
	enum pic_t ptype;
	unsigned long framecount = 0;

	capture_start(caphandle);		// !!! need to start capture stream!

	while (1)
	{
		ret = capture_get_data(caphandle, &cap_buf, &cap_len);
		if (ret != 0)
		{
			if (ret < 0)		// error
			{
				printf("--- capture_get_data failed\n");
				break;
			}
			else	// again
			{
				usleep(10000);
				continue;
			}
		}
		if (cap_len <= 0)
		{
			printf("!!! No capture data\n");
			continue;
		}
		// else

		ret = convert_do(cvthandle, cap_buf, cap_len, &cvt_buf, &cvt_len);
		if (ret < 0)
		{
			printf("--- convert_do failed\n");
			break;
		}
		if (cvt_len <= 0)
		{
			printf("!!! No convert data\n");
			continue;
		}
		// else

		// fetch h264 headers first!
		while ((ret = encode_get_headers(enchandle, &hd_buf, &hd_len, &ptype))
				== 1)
		{
            //fwrite(hd_buf, 1, hd_len, dumpfile);
			pack_put(pachandle, hd_buf, hd_len);
			while (pack_get(pachandle, &pac_buf, &pac_len) == 1)
			{
                ret = net_send(nethandle, pac_buf, pac_len);
				if (ret != pac_len)
				{
					printf("send pack data failed, size: %d, err: %s\n", pac_len,
							strerror(errno));
				}
			}
		}

		ret = encode_do(enchandle, cvt_buf, cvt_len, &enc_buf, &enc_len,
				&ptype);
		if (ret < 0)
		{
			printf("--- encode_do failed\n");
			break;
		}
		if (enc_len <= 0)
		{
			printf("!!! No encode data\n");
			continue;
		}
		// else

        //fwrite(enc_buf, 1, enc_len, dumpfile);
		// RTP pack and send
		pack_put(pachandle, enc_buf, enc_len);
		while (pack_get(pachandle, &pac_buf, &pac_len) == 1)
		{
            ret = net_send(nethandle, pac_buf, pac_len);
			if (ret != pac_len)
			{
				printf("send pack failed, size: %d, err: %s\n", pac_len,
						strerror(errno));
			}
		}

		framecount++;
	}
	capture_stop(caphandle);

    net_close(nethandle);
	pack_close(pachandle);
	encode_close(enchandle);
	convert_close(cvthandle);
	capture_close(caphandle);

	return 0;
}
コード例 #9
0
ファイル: csl.c プロジェクト: Tayyib/uludag
int
csl_execute(char *code, size_t size, const char *func_name, struct pack *pak, char **resptr, int *reslen)
{
	PyObject *pCode, *pModule, *pDict, *pFunc, *pValue, *pStr;
	PyObject *pArgs, *pkArgs;
	PyMethodDef *meth;
	node *n;

	pModule = PyImport_AddModule("__builtin__");
	pDict = PyModule_GetDict(pModule);
	for (meth = methods; meth->ml_name; meth++) {
		pCode = PyCFunction_New(meth, NULL);
		PyDict_SetItemString(pDict, meth->ml_name, pCode);
	}

	if (size == 0) {
		n = PyParser_SimpleParseString(code, Py_file_input);
		if (!n) {
			log_exception();
			return CSL_BADCODE;
		}
		pCode = (PyObject *) PyNode_Compile(n, "lala");
		PyNode_Free(n);
		if (!pCode) {
			log_exception();
			return CSL_BADCODE;
		}
	} else {
		pCode = PyMarshal_ReadObjectFromString(code, size);
		if (!pCode) {
			log_exception();
			return CSL_BADCODE;
		}
	}
	pModule = PyImport_ExecCodeModule("csl", pCode);
	Py_DECREF(pCode);

	if (!pModule || !PyModule_Check(pModule)) {
		return CSL_BADCODE;
	}

	pDict = PyModule_GetDict(pModule);
	if (!pDict) {
		Py_DECREF(pModule);
		return CSL_BADCODE;
	}

	pFunc = PyDict_GetItemString(pDict, func_name);
	if (!pFunc || !PyCallable_Check(pFunc)) {
		Py_DECREF(pModule);
		return CSL_NOFUNC;
	}

	pArgs = NULL;
	pkArgs = PyDict_New();
	while (pak) {
		PyObject *p;
		char *t, *t2;
		size_t sz;
		if (pack_get(pak, &t, &sz) == 0) break;
		if (pack_get(pak, &t2, &sz) == 0) {
			pArgs = PyTuple_New(1);
			PyTuple_SetItem(pArgs, 0, PyString_FromString(t));
			Py_DECREF(pkArgs);
			break;
		}
		p = PyString_FromStringAndSize(t2, sz);
		PyDict_SetItemString(pkArgs, t, p);
	}
	if (!pArgs) pArgs = PyTuple_New(0);

	pValue = PyObject_Call(pFunc, pArgs, pkArgs);
	if (!pValue) {
		log_exception();
		Py_DECREF(pModule);
		return CSL_FUNCERR;
	}

	pStr = PyObject_Str(pValue);

	Py_DECREF(pValue);
	Py_DECREF(pModule);

	// is return value asked?
	if (resptr == NULL) return 0;

	*reslen = PyString_Size(pStr);
	*resptr = malloc((*reslen) + 1);
	if (!*resptr) {
		Py_DECREF(pStr);
		return CSL_NOMEM;
	}
	memcpy(*resptr, PyString_AsString(pStr), *reslen);
	(*resptr)[*reslen] = '\0';

	return 0;
}
コード例 #10
0
ファイル: cktool.c プロジェクト: Yanwei-Tim/Camkit
int main(int argc, char *argv[])
{
	struct cap_handle *caphandle = NULL;
	struct cvt_handle *cvthandle = NULL;
	struct enc_handle *enchandle = NULL;
	struct pac_handle *pachandle = NULL;
	struct net_handle *nethandle = NULL;
	struct cap_param capp;
	struct cvt_param cvtp;
	struct enc_param encp;
	struct pac_param pacp;
	struct net_param netp;
	int stage = 0b00000011;

	U32 vfmt = V4L2_PIX_FMT_YUYV;
	U32 ofmt = V4L2_PIX_FMT_YUV420;

	// set default values
	capp.dev_name = "/dev/video0";
	capp.width = 640;
	capp.height = 480;
	capp.pixfmt = vfmt;
	capp.rate = 15;

	cvtp.inwidth = 640;
	cvtp.inheight = 480;
	cvtp.inpixfmt = vfmt;
	cvtp.outwidth = 640;
	cvtp.outheight = 480;
	cvtp.outpixfmt = ofmt;

	encp.src_picwidth = 640;
	encp.src_picheight = 480;
	encp.enc_picwidth = 640;
	encp.enc_picheight = 480;
	encp.chroma_interleave = 0;
	encp.fps = 15;
	encp.gop = 12;
	encp.bitrate = 1000;

	pacp.max_pkt_len = 1400;
	pacp.ssrc = 1234;

	netp.serip = NULL;
	netp.serport = -1;
	netp.type = UDP;

	char *outfile = NULL;
	// options
	int opt = 0;
	static const char *optString = "?di:o:a:p:w:h:r:f:t:g:s:c:";

	opt = getopt(argc, argv, optString);
	while (opt != -1)
	{
		int fmt;
		switch (opt)
		{
			case '?':
				display_usage();
				return 0;
			case 'd':
				debug = 1;
				break;
			case 's':
				stage = atoi(optarg);
				break;
			case 'i':
				capp.dev_name = optarg;
				break;
			case 'o':
				outfile = optarg;
				break;
			case 'a':
				netp.serip = optarg;
				break;
			case 'p':
				netp.serport = atoi(optarg);
				break;
			case 'c':
				fmt = atoi(optarg);
				if (fmt == 1)
					capp.pixfmt = V4L2_PIX_FMT_YUV420;
				else
					capp.pixfmt = V4L2_PIX_FMT_YUYV;
				break;
			case 'w':
				capp.width = cvtp.inwidth = cvtp.outwidth = encp.src_picwidth =
						encp.enc_picwidth = atoi(optarg);
				break;
			case 'h':
				capp.height = cvtp.inheight = cvtp.outheight =
						encp.src_picheight = encp.enc_picheight = atoi(optarg);
				break;
			case 'r':
				encp.bitrate = atoi(optarg);
				break;
			case 'f':
				capp.rate = encp.fps = atoi(optarg);
				break;
			case 't':
				encp.chroma_interleave = atoi(optarg);
				break;
			case 'g':
				encp.gop = atoi(optarg);
				break;
			default:
				printf("Unknown option: %s\n", optarg);
				display_usage();
				return -1;
		}

		opt = getopt(argc, argv, optString);
	}

	if (outfile)
		outfd = fopen(outfile, "wb");

	signal(SIGINT, quit_func);

	caphandle = capture_open(capp);
	if (!caphandle)
	{
		printf("--- Open capture failed\n");
		return -1;
	}

	if ((stage & 0b00000001) != 0)
	{
		cvthandle = convert_open(cvtp);
		if (!cvthandle)
		{
			printf("--- Open convert failed\n");
			return -1;
		}
	}

	if ((stage & 0b00000010) != 0)
	{
		enchandle = encode_open(encp);
		if (!enchandle)
		{
			printf("--- Open encode failed\n");
			return -1;
		}
	}

	if ((stage & 0b00000100) != 0)
	{
		pachandle = pack_open(pacp);
		if (!pachandle)
		{
			printf("--- Open pack failed\n");
			return -1;
		}
	}

	if ((stage & 0b00001000) != 0)
	{
		if (netp.serip == NULL || netp.serport == -1)
		{
			printf(
					"--- Server ip and port must be specified when using network\n");
			return -1;
		}

		nethandle = net_open(netp);
		if (!nethandle)
		{
			printf("--- Open network failed\n");
			return -1;
		}
	}

	// start capture encode loop
	int ret;
	void *cap_buf, *cvt_buf, *hd_buf, *enc_buf;
	char *pac_buf = (char *) malloc(MAX_RTP_SIZE);
	int cap_len, cvt_len, hd_len, enc_len, pac_len;
	enum pic_t ptype;
	struct timeval ctime, ltime;
	unsigned long fps_counter = 0;
	int sec, usec;
	double stat_time = 0;

	capture_start(caphandle);		// !!! need to start capture stream!
	quit = 0;
	gettimeofday(&ltime, NULL);
	while (!quit)
	{
		if (debug)		// print fps
		{
			gettimeofday(&ctime, NULL);
			sec = ctime.tv_sec - ltime.tv_sec;
			usec = ctime.tv_usec - ltime.tv_usec;
			if (usec < 0)
			{
				sec--;
				usec = usec + 1000000;
			}
			stat_time = (sec * 1000000) + usec;		// diff in microsecond

			if (stat_time >= 1000000)    // >= 1s
			{
				printf("\n*** FPS: %ld\n", fps_counter);

				fps_counter = 0;
				ltime = ctime;
			}
			fps_counter++;
		}

		ret = capture_get_data(caphandle, &cap_buf, &cap_len);
		if (ret != 0)
		{
			if (ret < 0)		// error
			{
				printf("--- capture_get_data failed\n");
				break;
			}
			else	// again
			{
				usleep(10000);
				continue;
			}
		}
		if (cap_len <= 0)
		{
			printf("!!! No capture data\n");
			continue;
		}
		if (debug)
			fputc('.', stdout);

		if ((stage & 0b00000001) == 0)    // no convert, capture only
		{
			if (outfd)
				fwrite(cap_buf, 1, cap_len, outfd);

			continue;
		}

		// convert
		if (capp.pixfmt == V4L2_PIX_FMT_YUV420)    // no need to convert
		{
			cvt_buf = cap_buf;
			cvt_len = cap_len;
		}
		else	// do convert: YUYV => YUV420
		{
			ret = convert_do(cvthandle, cap_buf, cap_len, &cvt_buf, &cvt_len);
			if (ret < 0)
			{
				printf("--- convert_do failed\n");
				break;
			}
			if (cvt_len <= 0)
			{
				printf("!!! No convert data\n");
				continue;
			}
		}
		if (debug)
			fputc('-', stdout);

		if ((stage & 0b00000010) == 0)		// no encode
		{
			if (outfd)
				fwrite(cvt_buf, 1, cvt_len, outfd);

			continue;
		}

		// encode
		// fetch h264 headers first!
		while ((ret = encode_get_headers(enchandle, &hd_buf, &hd_len, &ptype))
				!= 0)
		{
			if (debug)
				fputc('S', stdout);

			if ((stage & 0b00000100) == 0)		// no pack
			{
				if (outfd)
					fwrite(hd_buf, 1, hd_len, outfd);

				continue;
			}

			// pack headers
			pack_put(pachandle, hd_buf, hd_len);
			while (pack_get(pachandle, pac_buf, MAX_RTP_SIZE, &pac_len) == 1)
			{
				if (debug)
					fputc('#', stdout);

				if ((stage & 0b00001000) == 0)    // no network
				{
					if (outfd)
						fwrite(pac_buf, 1, pac_len, outfd);

					continue;
				}

				// network
				ret = net_send(nethandle, pac_buf, pac_len);
				if (ret != pac_len)
				{
					printf("send pack failed, size: %d, err: %s\n", pac_len,
							strerror(errno));
				}
				if (debug)
					fputc('>', stdout);
			}
		}

		ret = encode_do(enchandle, cvt_buf, cvt_len, &enc_buf, &enc_len,
				&ptype);
		if (ret < 0)
		{
			printf("--- encode_do failed\n");
			break;
		}
		if (enc_len <= 0)
		{
			printf("!!! No encode data\n");
			continue;
		}

		if (debug)
		{
			char c;
			switch (ptype)
			{
				case PPS:
					c = 'S';
					break;
				case SPS:
					c = 'S';
					break;
				case I:
					c = 'I';
					break;
				case P:
					c = 'P';
					break;
				case B:
					c = 'B';
					break;
				default:
					c = 'N';
					break;
			}

			fputc(c, stdout);
		}

		if ((stage & 0b00000100) == 0)		// no pack
		{
			if (outfd)
				fwrite(enc_buf, 1, enc_len, outfd);

			continue;
		}

		// pack
		pack_put(pachandle, enc_buf, enc_len);
		while (pack_get(pachandle, pac_buf, MAX_RTP_SIZE, &pac_len) == 1)
		{
			if (debug)
				fputc('#', stdout);

			if ((stage & 0b00001000) == 0)    // no network
			{
				if (outfd)
					fwrite(pac_buf, 1, pac_len, outfd);

				continue;
			}

			// network
			ret = net_send(nethandle, pac_buf, pac_len);
			if (ret != pac_len)
			{
				printf("send pack failed, size: %d, err: %s\n", pac_len,
						strerror(errno));
			}
			if (debug)
				fputc('>', stdout);
		}
	}
	capture_stop(caphandle);

	free(pac_buf);
	if ((stage & 0b00001000) != 0)
		net_close(nethandle);
	if ((stage & 0b00000100) != 0)
		pack_close(pachandle);
	if ((stage & 0b00000010) != 0)
		encode_close(enchandle);
	if ((stage & 0b00000001) != 0)
		convert_close(cvthandle);
	capture_close(caphandle);

	if (outfd)
		fclose(outfd);
	return 0;
}