Beispiel #1
1
int main()
{
	int i;
	struct picture_t pic;
	struct encoded_pic_t encoded_pic;
	errno = 0;
	if(!camera_init(&pic))
		goto error_cam;
	if(!encoder_init(&pic)){
		fprintf(stderr,"failed to initialize encoder\n");
		goto error_encoder;
	}
	if(!preview_init(&pic))
		goto error_preview;
	if(!output_init(&pic))
		goto error_output;
	if(!encoder_encode_headers(&encoded_pic))
		goto error_output;
	if(!output_write_headers(&encoded_pic))
		goto error_output;
	if(!camera_on())
		goto error_cam_on;
	if(signal(SIGINT, stop_recording) == SIG_ERR){
		fprintf(stderr,"signal() failed\n");
		goto error_signal;
	}
	printf("Press ctrl-c to stop recording...\n");
	recording = 1;
	for(i=0; recording; i++){
		if(!camera_get_frame(&pic))
			break;
		gen_osd_info();
		osd_print(&pic, osd_string);
		if((i&7)==0) // i%8==0
			preview_display(&pic);
		if(!encoder_encode_frame(&pic, &encoded_pic))
			break;
		applog_flush();
		if(!output_write_frame(&encoded_pic))
			break;
	}
	printf("\nrecorded %d frames\n", i);

error_signal:
	camera_off();
error_cam_on:
	output_close();
error_output:
	preview_close();
error_preview:
	encoder_close();
error_encoder:
	camera_close();
error_cam:
	return 0;
}
void reinit(){
	int i=0;
	hold_on=1;
	while(hold_on_ready==0&&i<1000){i++;}
	if(hold_on_ready==1&&hold_on==1){
		encoder_close();
		encoder_init(&pic,fps,brightness,bitrate);
		encoder_encode_headers(&header_pic);
		printf("reinit\n");
		hold_on=0;
	}
}
static void
recorder_output_close(void *data)
{
	struct recorder_output *recorder = data;

	/* flush the encoder and write the rest to the file */

	if (encoder_flush(recorder->encoder, NULL))
		recorder_output_encoder_to_file(recorder, NULL);

	/* now really close everything */

	encoder_close(recorder->encoder);

	close(recorder->fd);
}
void *schedule_do(void *arg){
    int i=0;
	//unsigned int ringbuffer;
	//int buflen=0,ringbuflen=0,ringbuftype;
	//struct ringbuf ringinfo;
	int WriteSize=0;
	int flag=0;
	CHAR *cBuf = (CHAR *) malloc(10);
	int nRet;
	int beginFrame=1;//0;
	
	sendcoded.buffer=malloc(1024*100);
	sendcoded.length=0;
	copycoded.buffer=malloc(1024*100);
	copycoded.length=0;
	
	
	while(!schedule_do_Quit){
		if(hold_on==0){
			hold_on_ready=0;
			memset(sendcoded.buffer,0,sendcoded.length);
			sendcoded.length=0;
			encoder_encode_frame(&sendcoded);
		
			if(g_s32DoPlay>0)
			{
				if(headflag>0)
				{
					headflag--;
					STARX_Write(SessionHandle,VideoChannel,header_pic.buffer,header_pic.length);
					printf("write head\r\n");
				}
				if(sendcoded.length>0)
				STARX_Write(SessionHandle,VideoChannel,sendcoded.buffer,sendcoded.length);
			}
			memcpy(copycoded.buffer,sendcoded.buffer,sendcoded.length);
			copycoded.length=sendcoded.length;
		}else{
			hold_on_ready=1;
			headflag=1;
		}
	}
	encoder_close();
	//free(sendcoded.buffer);
	printf("schedule_do exit");
	pthread_exit(0);	
}
Beispiel #5
0
static void httpd_output_close(void *data)
{
	struct httpd_output *httpd = data;

	g_mutex_lock(httpd->mutex);

	timer_free(httpd->timer);

	g_list_foreach(httpd->clients, httpd_client_delete, NULL);
	g_list_free(httpd->clients);

	if (httpd->header != NULL)
		page_unref(httpd->header);

	encoder_close(httpd->encoder);

	g_source_remove(httpd->source_id);
	close(httpd->fd);

	g_mutex_unlock(httpd->mutex);
}
Beispiel #6
0
static void
httpd_output_close(struct audio_output *ao)
{
	struct httpd_output *httpd = (struct httpd_output *)ao;

	g_mutex_lock(httpd->mutex);

	httpd->open = false;

	timer_free(httpd->timer);

	g_list_foreach(httpd->clients, httpd_client_delete, NULL);
	g_list_free(httpd->clients);

	if (httpd->header != NULL)
		page_unref(httpd->header);

	encoder_close(httpd->encoder);

	g_mutex_unlock(httpd->mutex);
}
Beispiel #7
0
int main()
{
	int s32MainFd,temp;
	struct timespec ts = { 2, 0 };


//=================================================
	ringmalloc(640*480);
	errno = 0;
	if(!camera_init(&pic))
		goto error_cam;
	if(!encoder_init(&pic))
		goto error_encoder;
	if(!preview_init(&pic))
		goto error_preview;
	get_filename();
	printf("file:%s\n",mkv_filename);
	if(!output_init(&pic,mkv_filename))
		goto error_output;
	if(!encoder_encode_headers(&encoded_pic))
		goto error_output;
	memcpy(&header_pic,&encoded_pic,sizeof(encoded_pic));
	header_pic.buffer=malloc(encoded_pic.length);
	memcpy(header_pic.buffer,encoded_pic.buffer,encoded_pic.length);
	if(!output_write_headers(&encoded_pic,&psp))
		goto error_output;
	encoder_release(&encoded_pic);
	if(!camera_on())
		goto error_cam_on;
	
//================================================

	printf("RTSP server START\n");

	PrefsInit();
	printf("listen for client connecting...\n");

	signal(SIGINT, IntHandl);

	s32MainFd = tcp_listen(SERVER_RTSP_PORT_DEFAULT);

	/* 初始化schedule_list 队列,创建调度线程,参考 schedule.c */
	if (ScheduleInit(&pic,&encoded_pic) == ERR_FATAL)
	{
		fprintf(stderr,"Fatal: Can't start scheduler %s, %i \nServer is aborting.\n", __FILE__, __LINE__);
		return 0;
	}

	/* 将所有可用的RTP端口号放入到port_pool[MAX_SESSION] 中 */
	RTP_port_pool_init(RTP_DEFAULT_PORT);

	//循环等待
	if((temp = pthread_create(&thread[0], NULL, cam_thread, NULL)) != 0)         
                printf("cam_thread error!\n");  
        else  
                printf("cam_thread ok\n"); 
	pthread_mutex_init(&mut,NULL);
	while (!g_s32Quit)
	{
		nanosleep(&ts, NULL);

		/*查找收到的rtsp连接,
	    * 对每一个连接产生所有的信息放入到结构体rtsp_list中
	    */
//		trace_point();
		EventLoop(s32MainFd);
	}
	ringfree();
	printf("The Server quit!\n");


	camera_off();
error_cam_on:
	output_close();
error_output:
	preview_close();
error_preview:
	encoder_close();
error_encoder:
	camera_close();
error_cam:

	return NULL;
}
Beispiel #8
0
/*
 * encoder loop (should run in a separate thread)
 * args:
 *    data - pointer to user data
 *
 * asserts:
 *   none
 *
 * returns: pointer to return code
 */
static void *encoder_loop(void *data)
{
	v4l2_dev_t *device = (v4l2_dev_t *) data;

	my_encoder_status = 1;
	
	if(debug_level > 1)
		printf("GUVCVIEW: encoder thread (tid: %u)\n",
			(unsigned int) syscall (SYS_gettid));

	/*get the audio context*/
	audio_context_t *audio_ctx = get_audio_context();

	__THREAD_TYPE encoder_audio_thread;

	int channels = 0;
	int samprate = 0;

	if(audio_ctx)
	{
		channels = audio_ctx->channels;
		samprate = audio_ctx->samprate;
	}

	if(debug_level > 0)
		printf("GUVCVIEW: audio [channels= %i; samprate= %i] \n",
			channels, samprate);

	/*create the encoder context*/
	encoder_context_t *encoder_ctx = encoder_get_context(
		device->requested_fmt,
		get_video_codec_ind(),
		get_audio_codec_ind(),
		get_video_muxer(),
		device->format.fmt.pix.width,
		device->format.fmt.pix.height,
		device->fps_num,
		device->fps_denom,
		channels,
		samprate);

	/*store external SPS and PPS data if needed*/
	if(encoder_ctx->video_codec_ind == 0 && /*raw - direct input*/
		device->requested_fmt == V4L2_PIX_FMT_H264)
	{
		/*request a IDR (key) frame*/
		v4l2core_h264_request_idr(device);

		if(debug_level > 0)
			printf("GUVCVIEW: storing external pps and sps data in encoder context\n");
		encoder_ctx->h264_pps_size = device->h264_PPS_size;
		if(encoder_ctx->h264_pps_size > 0)
		{
			encoder_ctx->h264_pps = calloc(device->h264_PPS_size, sizeof(uint8_t));
			if(encoder_ctx->h264_pps == NULL)
			{
				fprintf(stderr,"GUVCVIEW: FATAL memory allocation failure (encoder_loop): %s\n", strerror(errno));
				exit(-1);
			}
			memcpy(encoder_ctx->h264_pps, device->h264_PPS, device->h264_PPS_size);
		}

		encoder_ctx->h264_sps_size = device->h264_SPS_size;
		if(encoder_ctx->h264_sps_size > 0)
		{
			encoder_ctx->h264_sps = calloc(device->h264_SPS_size, sizeof(uint8_t));
			if(encoder_ctx->h264_sps == NULL)
			{
				fprintf(stderr,"GUVCVIEW: FATAL memory allocation failure (encoder_loop): %s\n", strerror(errno));
				exit(-1);
			}
			memcpy(encoder_ctx->h264_sps, device->h264_SPS, device->h264_SPS_size);
		}
	}

	uint32_t current_framerate = 0;
	if(device->requested_fmt == V4L2_PIX_FMT_H264)
	{
		/* store framerate since it may change due to scheduler*/
		current_framerate = v4l2core_get_h264_frame_rate_config(device);
	}

	char *video_filename = NULL;
	/*get_video_[name|path] always return a non NULL value*/
	char *name = strdup(get_video_name());
	char *path = strdup(get_video_path());

	if(get_video_sufix_flag())
	{
		char *new_name = add_file_suffix(path, name);
		free(name); /*free old name*/
		name = new_name; /*replace with suffixed name*/
	}
	int pathsize = strlen(path);
	if(path[pathsize] != '/')
		video_filename = smart_cat(path, '/', name);
	else
		video_filename = smart_cat(path, 0, name);

	snprintf(status_message, 79, _("saving video to %s"), video_filename);
	gui_status_message(status_message);

	/*muxer initialization*/
	encoder_muxer_init(encoder_ctx, video_filename);

	/*start video capture*/
	video_capture_save_video(1);

	int treshold = 102400; /*100 Mbytes*/
	int64_t last_check_pts = 0; /*last pts when disk supervisor called*/

	/*start audio processing thread*/
	if(encoder_ctx->enc_audio_ctx != NULL && audio_ctx->channels > 0)
	{
		if(debug_level > 1)
			printf("GUVCVIEW: starting encoder audio thread\n");
		
		int ret = __THREAD_CREATE(&encoder_audio_thread, audio_processing_loop, (void *) encoder_ctx);
		
		if(ret)
			fprintf(stderr, "GUVCVIEW: encoder audio thread creation failed (%i)\n", ret);
		else if(debug_level > 2)
			printf("GUVCVIEW: created audio encoder thread with tid: %u\n", 
				(unsigned int) encoder_audio_thread);
	}

	while(video_capture_get_save_video())
	{
		/*process the video buffer*/
		encoder_process_next_video_buffer(encoder_ctx);

		/*disk supervisor*/
		if(encoder_ctx->enc_video_ctx->pts - last_check_pts > 2 * NSEC_PER_SEC)
		{
			last_check_pts = encoder_ctx->enc_video_ctx->pts;

			if(!encoder_disk_supervisor(treshold, path))
			{
				/*stop capture*/
				gui_set_video_capture_button_status(0);
			}
		}
	}
	
	/*flush the video buffer*/
	encoder_flush_video_buffer(encoder_ctx);

	/*make sure the audio processing thread has stopped*/
	if(encoder_ctx->enc_audio_ctx != NULL && audio_ctx->channels > 0)
	{
		if(debug_level > 1)
			printf("GUVCVIEW: join encoder audio thread\n");
		__THREAD_JOIN(encoder_audio_thread);
	}

	/*close the muxer*/
	encoder_muxer_close(encoder_ctx);

	/*close the encoder context (clean up)*/
	encoder_close(encoder_ctx);

	if(device->requested_fmt == V4L2_PIX_FMT_H264)
	{
		/* restore framerate */
		v4l2core_set_h264_frame_rate_config(device, current_framerate);
	}

	/*clean string*/
	free(video_filename);
	free(path);
	free(name);

	my_encoder_status = 0;

	return ((void *) 0);
}
Beispiel #9
0
int32_t encoder_setup(void *arg)
{
    struct codec_control *codecctrl = NULL;
    vpu_mem_desc mem_desc = { 0 };
    vpu_mem_desc scratch_mem_desc = { 0 };
    struct encode *enc;
    int32_t ret = 0;

    /*set the parameters of encoder input here!! */
    codecctrl = (struct codec_control *)arg;

    /* allocate memory for must remember stuff */
    enc = (struct encode *)calloc(1, sizeof(struct encode));
    if (enc == NULL) {
        err_msg("Failed to allocate encode structure\n");
        return -1;
    }

    /* get the contigous bit stream buffer */
    mem_desc.size = STREAM_BUF_SIZE;
    ret = vpu_malloc(&mem_desc);
    if (ret) {
        err_msg("Unable to obtain physical memory\n");
        free(enc);
        return -1;
    }

    /* mmap that physical buffer, in OS the virt and phy addr could be different */
    enc->virt_bsbuf_addr = mem_desc.virt_addr;
    enc->phy_bsbuf_addr = mem_desc.phy_addr;
    enc->codecctrl = codecctrl;

    /* get the contigous bit stream buffer */
    mem_desc.size = ENCODER_OUTPUT_SIZE;
    ret = vpu_malloc(&mem_desc);
    if (ret) {
        err_msg("Unable to obtain physical memory\n");
        free(enc);
        return -1;
    }
    enc->codecctrl->output_mem_addr = mem_desc.phy_addr;
    g_bs_memory.bs_start = enc->codecctrl->output_mem_addr;
    g_bs_memory.bs_end = enc->codecctrl->output_mem_addr;

    if (enc->codecctrl->mapType) {
        enc->linear2TiledEnable = 1;
        enc->codecctrl->chromaInterleave = 1;   /* Must be CbCrInterleave for tiled */
    } else
        enc->linear2TiledEnable = 0;

    /* open the encoder */
    ret = encoder_open(enc);
    if (ret)
        goto err;

    /* configure the encoder */
    ret = encoder_configure(enc);
    if (ret)
        goto err1;

    if ((codecctrl->format == STD_MPEG4) && enc->mp4_dataPartitionEnable) {
        scratch_mem_desc.size = MPEG4_SCRATCH_SIZE;
        ret = vpu_malloc(&scratch_mem_desc);
        if (ret) {
            err_msg("Unable to obtain physical slice save mem\n");
            goto err1;
        }
        enc->scratchBuf.bufferBase = scratch_mem_desc.phy_addr;
        enc->scratchBuf.bufferSize = scratch_mem_desc.size;
    }
    /* allocate memory for the frame buffers */
    ret = encoder_allocate_framebuffer(enc);
    if (ret)
        goto err1;

    /* start encoding */
    ret = encoder_start(enc);

    if (enc->codecctrl->dst_scheme == PATH_MEM)
        printf("Encoded output is stored from 0x%08x to 0x%08x\n", g_bs_memory.bs_start,
               g_bs_memory.bs_end);

    /* free the allocated framebuffers */
    encoder_free_framebuffer(enc);
  err1:
    /* close the encoder */
    encoder_close(enc);
  err:
    free(enc);
    return ret;
}
Beispiel #10
0
/*
 * encoder loop (should run in a separate thread)
 * args:
 *    data - pointer to user data
 *
 * asserts:
 *   none
 *
 * returns: pointer to return code
 */
static void *encoder_loop(void *data)
{
	my_encoder_status = 1;
	
	if(debug_level > 1)
		printf("GUVCVIEW: encoder thread (tid: %u)\n",
			(unsigned int) syscall (SYS_gettid));

	/*get the audio context*/
	audio_context_t *audio_ctx = get_audio_context();

	__THREAD_TYPE encoder_audio_thread;

	int channels = 0;
	int samprate = 0;

	if(audio_ctx)
	{
		channels = audio_ctx->channels;
		samprate = audio_ctx->samprate;
	}

	if(debug_level > 0)
		printf("GUVCVIEW: audio [channels= %i; samprate= %i] \n",
			channels, samprate);

	/*create the encoder context*/
	encoder_context_t *encoder_ctx = encoder_get_context(
		v4l2core_get_requested_frame_format(),
		get_video_codec_ind(),
		get_audio_codec_ind(),
		get_video_muxer(),
		v4l2core_get_frame_width(),
		v4l2core_get_frame_height(),
		v4l2core_get_fps_num(),
		v4l2core_get_fps_denom(),
		channels,
		samprate);

	/*store external SPS and PPS data if needed*/
	if(encoder_ctx->video_codec_ind == 0 && /*raw - direct input*/
		v4l2core_get_requested_frame_format() == V4L2_PIX_FMT_H264)
	{
		/*request a IDR (key) frame*/
		v4l2core_h264_request_idr();

		if(debug_level > 0)
			printf("GUVCVIEW: storing external pps and sps data in encoder context\n");
		encoder_ctx->h264_pps_size = v4l2core_get_h264_pps_size();
		if(encoder_ctx->h264_pps_size > 0)
		{
			encoder_ctx->h264_pps = calloc(encoder_ctx->h264_pps_size, sizeof(uint8_t));
			if(encoder_ctx->h264_pps == NULL)
			{
				fprintf(stderr,"GUVCVIEW: FATAL memory allocation failure (encoder_loop): %s\n", strerror(errno));
				exit(-1);
			}
			memcpy(encoder_ctx->h264_pps, v4l2core_get_h264_pps(), encoder_ctx->h264_pps_size);
		}

		encoder_ctx->h264_sps_size = v4l2core_get_h264_sps_size();
		if(encoder_ctx->h264_sps_size > 0)
		{
			encoder_ctx->h264_sps = calloc(encoder_ctx->h264_sps_size, sizeof(uint8_t));
			if(encoder_ctx->h264_sps == NULL)
			{
				fprintf(stderr,"GUVCVIEW: FATAL memory allocation failure (encoder_loop): %s\n", strerror(errno));
				exit(-1);
			}
			memcpy(encoder_ctx->h264_sps, v4l2core_get_h264_sps(), encoder_ctx->h264_sps_size);
		}
	}

	uint32_t current_framerate = 0;
	if(v4l2core_get_requested_frame_format() == V4L2_PIX_FMT_H264)
	{
		/* store framerate since it may change due to scheduler*/
		current_framerate = v4l2core_get_h264_frame_rate_config();
	}

	char *video_filename = NULL;
	/*get_video_[name|path] always return a non NULL value*/
	char *name = strdup(get_video_name());
	char *path = strdup(get_video_path());

	if(get_video_sufix_flag())
	{
		char *new_name = add_file_suffix(path, name);
		free(name); /*free old name*/
		name = new_name; /*replace with suffixed name*/
	}
	int pathsize = strlen(path);
	if(path[pathsize] != '/')
		video_filename = smart_cat(path, '/', name);
	else
		video_filename = smart_cat(path, 0, name);

	snprintf(status_message, 79, _("saving video to %s"), video_filename);
	gui_status_message(status_message);

	/*muxer initialization*/
	encoder_muxer_init(encoder_ctx, video_filename);

	/*start video capture*/
	video_capture_save_video(1);

	int treshold = 102400; /*100 Mbytes*/
	int64_t last_check_pts = 0; /*last pts when disk supervisor called*/

	/*start audio processing thread*/
	if(encoder_ctx->enc_audio_ctx != NULL && audio_ctx->channels > 0)
	{
		if(debug_level > 1)
			printf("GUVCVIEW: starting encoder audio thread\n");
		
		int ret = __THREAD_CREATE(&encoder_audio_thread, audio_processing_loop, (void *) encoder_ctx);
		
		if(ret)
			fprintf(stderr, "GUVCVIEW: encoder audio thread creation failed (%i)\n", ret);
		else if(debug_level > 2)
			printf("GUVCVIEW: created audio encoder thread with tid: %u\n", 
				(unsigned int) encoder_audio_thread);
	}

	while(video_capture_get_save_video())
	{
		/*process the video buffer*/
		if(encoder_process_next_video_buffer(encoder_ctx) > 0)
		{
			/* 
			 * no buffers to process
			 * sleep a couple of milisec
			 */
			 struct timespec req = {
				.tv_sec = 0,
				.tv_nsec = 1000000};/*nanosec*/
			 nanosleep(&req, NULL);
			 
		}	

		/*disk supervisor*/
		if(encoder_ctx->enc_video_ctx->pts - last_check_pts > 2 * NSEC_PER_SEC)
		{
			last_check_pts = encoder_ctx->enc_video_ctx->pts;

			if(!encoder_disk_supervisor(treshold, path))
			{
				/*stop capture*/
				gui_set_video_capture_button_status(0);
			}
		}
	}
	
	/*flush the video buffer*/
	encoder_flush_video_buffer(encoder_ctx);

	/*make sure the audio processing thread has stopped*/
	if(encoder_ctx->enc_audio_ctx != NULL && audio_ctx->channels > 0)
	{
		if(debug_level > 1)
			printf("GUVCVIEW: join encoder audio thread\n");
		__THREAD_JOIN(encoder_audio_thread);
	}

	/*close the muxer*/
	encoder_muxer_close(encoder_ctx);

	/*close the encoder context (clean up)*/
	encoder_close(encoder_ctx);

	if(v4l2core_get_requested_frame_format() == V4L2_PIX_FMT_H264)
	{
		/* restore framerate */
		v4l2core_set_h264_frame_rate_config(current_framerate);
	}

	/*clean string*/
	free(video_filename);
	free(path);
	free(name);

	my_encoder_status = 0;

	return ((void *) 0);
}

/*
 * capture loop (should run in a separate thread)
 * args:
 *    data - pointer to user data (options data)
 *
 * asserts:
 *    none
 *
 * returns: pointer to return code
 */
void *capture_loop(void *data)
{
	capture_loop_data_t *cl_data = (capture_loop_data_t *) data;
	options_t *my_options = (options_t *) cl_data->options;
	//config_t *my_config = (config_t *) cl_data->config;

	uint64_t my_last_photo_time = 0; /*timer count*/
	int my_photo_npics = 0;/*no npics*/

	/*reset quit flag*/
	quit = 0;
	
	if(debug_level > 1)
		printf("GUVCVIEW: capture thread (tid: %u)\n", 
			(unsigned int) syscall (SYS_gettid));

	int ret = 0;
	
	int render_flags = 0;
	
	if (strcasecmp(my_options->render_flag, "full") == 0)
		render_flags = 1;
	else if (strcasecmp(my_options->render_flag, "max") == 0)
		render_flags = 2;
	
	render_set_verbosity(debug_level);
	
	if(render_init(render, v4l2core_get_frame_width(), v4l2core_get_frame_height(), render_flags) < 0)
		render = RENDER_NONE;
	else
	{
		render_set_event_callback(EV_QUIT, &quit_callback, NULL);
		render_set_event_callback(EV_KEY_V, &key_V_callback, NULL);
		render_set_event_callback(EV_KEY_I, &key_I_callback, NULL);
		render_set_event_callback(EV_KEY_UP, &key_UP_callback, NULL);
		render_set_event_callback(EV_KEY_DOWN, &key_DOWN_callback, NULL);
		render_set_event_callback(EV_KEY_LEFT, &key_LEFT_callback, NULL);
		render_set_event_callback(EV_KEY_RIGHT, &key_RIGHT_callback, NULL);
	}

	/*add a video capture timer*/
	if(my_options->video_timer > 0)
	{
		my_video_timer = NSEC_PER_SEC * my_options->video_timer;
		my_video_begin_time = v4l2core_time_get_timestamp(); /*timer count*/
		/*if are not saving video start it*/
		if(!get_encoder_status())
			start_encoder_thread();
	}

	/*add a photo capture timer*/
	if(my_options->photo_timer > 0)
	{
		my_photo_timer = NSEC_PER_SEC * my_options->photo_timer;
		my_last_photo_time = v4l2core_time_get_timestamp(); /*timer count*/
	}

	if(my_options->photo_npics > 0)
		my_photo_npics = my_options->photo_npics;

	v4l2core_start_stream();
	
	v4l2_frame_buff_t *frame = NULL; //pointer to frame buffer

	while(!quit)
	{
		if(restart)
		{
			restart = 0; /*reset*/
			v4l2core_stop_stream();

			/*close render*/
			render_close();

			v4l2core_clean_buffers();

			/*try new format (values prepared by the request callback)*/
			ret = v4l2core_update_current_format();
			/*try to set the video stream format on the device*/
			if(ret != E_OK)
			{
				fprintf(stderr, "GUCVIEW: could not set the defined stream format\n");
				fprintf(stderr, "GUCVIEW: trying first listed stream format\n");

				v4l2core_prepare_valid_format();
				v4l2core_prepare_valid_resolution();
				ret = v4l2core_update_current_format();

				if(ret != E_OK)
				{
					fprintf(stderr, "GUCVIEW: also could not set the first listed stream format\n");

					gui_error("Guvcview error", "could not start a video stream in the device", 1);

					return ((void *) -1);
				}
			}

			/*restart the render with new format*/
			if(render_init(render, v4l2core_get_frame_width(), v4l2core_get_frame_height(), render_flags) < 0)
				render = RENDER_NONE;
			else
			{
				render_set_event_callback(EV_QUIT, &quit_callback, NULL);
				render_set_event_callback(EV_KEY_V, &key_V_callback, NULL);
				render_set_event_callback(EV_KEY_I, &key_I_callback, NULL);
				render_set_event_callback(EV_KEY_UP, &key_UP_callback, NULL);
				render_set_event_callback(EV_KEY_DOWN, &key_DOWN_callback, NULL);
				render_set_event_callback(EV_KEY_LEFT, &key_LEFT_callback, NULL);
				render_set_event_callback(EV_KEY_RIGHT, &key_RIGHT_callback, NULL);
			}


			if(debug_level > 0)
				printf("GUVCVIEW: reset to pixelformat=%x width=%i and height=%i\n", v4l2core_get_requested_frame_format(), v4l2core_get_frame_width(), v4l2core_get_frame_height());

			v4l2core_start_stream();

		}

		frame = v4l2core_get_decoded_frame();
		if( frame != NULL)
		{
			/*run software autofocus (must be called after frame was grabbed and decoded)*/
			if(do_soft_autofocus || do_soft_focus)
				do_soft_focus = v4l2core_soft_autofocus_run(frame);

			/*render the decoded frame*/
			snprintf(render_caption, 29, "Guvcview  (%2.2f fps)", v4l2core_get_realfps());
			render_set_caption(render_caption);
			render_frame(frame->yuv_frame, my_render_mask);

			if(check_photo_timer())
			{
				if((frame->timestamp - my_last_photo_time) > my_photo_timer)
				{
					save_image = 1;
					my_last_photo_time = frame->timestamp;

					if(my_options->photo_npics > 0)
					{
						if(my_photo_npics > 0)
							my_photo_npics--;
						else
							stop_photo_timer(); /*close timer*/
					}
				}
			}

			if(check_video_timer())
			{
				if((frame->timestamp - my_video_begin_time) > my_video_timer)
					stop_video_timer();
			}

			if(save_image)
			{
				char *img_filename = NULL;

				/*get_photo_[name|path] always return a non NULL value*/
				char *name = strdup(get_photo_name());
				char *path = strdup(get_photo_path());

				if(get_photo_sufix_flag())
				{
					char *new_name = add_file_suffix(path, name);
					free(name); /*free old name*/
					name = new_name; /*replace with suffixed name*/
				}
				int pathsize = strlen(path);
				if(path[pathsize] != '/')
					img_filename = smart_cat(path, '/', name);
				else
					img_filename = smart_cat(path, 0, name);

				//if(debug_level > 1)
				//	printf("GUVCVIEW: saving image to %s\n", img_filename);

				snprintf(status_message, 79, _("saving image to %s"), img_filename);
				gui_status_message(status_message);

				v4l2core_save_image(frame, img_filename, get_photo_format());

				free(path);
				free(name);
				free(img_filename);

				save_image = 0; /*reset*/
			}

			if(video_capture_get_save_video())
			{
#ifdef USE_PLANAR_YUV
				int size = (v4l2core_get_frame_width() * v4l2core_get_frame_height() * 3) / 2;
#else
				int size = v4l2core_get_frame_width() * v4l2core_get_frame_height() * 2;
#endif
				uint8_t *input_frame = frame->yuv_frame;
				/*
				 * TODO: check codec_id, format and frame flags
				 * (we may want to store a compressed format
				 */
				if(get_video_codec_ind() == 0) //raw frame
				{
					switch(v4l2core_get_requested_frame_format())
					{
						case  V4L2_PIX_FMT_H264:
							input_frame = frame->h264_frame;
							size = (int) frame->h264_frame_size;
							break;
						default:
							input_frame = frame->raw_frame;
							size = (int) frame->raw_frame_size;
							break;
					}

				}
				encoder_add_video_frame(input_frame, size, frame->timestamp, frame->isKeyframe);

				/*
				 * exponencial scheduler
				 *  with 50% threshold (nanosec)
				 *  and max value of 250 ms (4 fps)
				 */
				int time_sched = encoder_buff_scheduler(ENCODER_SCHED_EXP, 0.5, 250);
				if(time_sched > 0)
				{
					switch(v4l2core_get_requested_frame_format())
					{
						case  V4L2_PIX_FMT_H264:
						{
							uint32_t framerate = time_sched; /*nanosec*/
							v4l2core_set_h264_frame_rate_config(framerate);
							break;
						}
						default:
						{
							struct timespec req = {
								.tv_sec = 0,
								.tv_nsec = time_sched};/*nanosec*/
							nanosleep(&req, NULL);
							break;
						}
					}
				}
			}
			/*we are done with the frame buffer release it*/
			v4l2core_release_frame(frame);
		}
	}

	v4l2core_stop_stream();
	
	/*if we are still saving video then stop it*/
	if(video_capture_get_save_video())
		stop_encoder_thread();

	render_close();

	return ((void *) 0);
}

/*
 * start the encoder thread
 * args:
 *   data - pointer to user data
 *
 * asserts:
 *   none
 *
 * returns: error code
 */
int start_encoder_thread(void *data)
{
	int ret = __THREAD_CREATE(&encoder_thread, encoder_loop, data);
	
	if(ret)
		fprintf(stderr, "GUVCVIEW: encoder thread creation failed (%i)\n", ret);
	else if(debug_level > 2)
		printf("GUVCVIEW: created encoder thread with tid: %u\n", 
			(unsigned int) encoder_thread);

	return ret;
}