Exemple #1
0
/*
 * Apply OSD mask
 * args:
 *    frame - pointer to frame buffer (yuyv format)
 *
 * asserts:
 *    frame is not null
 *
 * returns: void
 */
void render_frame_osd(uint8_t *frame)
{
	float vu_level[2];
	render_get_vu_level(vu_level);

	/*osd vu meter*/
	if(((render_get_osd_mask() & 
		(REND_OSD_VUMETER_MONO | REND_OSD_VUMETER_STEREO))) != 0)
		render_osd_vu_meter(frame, my_width, my_height, vu_level);
	/*osd crosshair*/
	if(((render_get_osd_mask() & REND_OSD_CROSSHAIR)) != 0)
		render_osd_crosshair(frame, my_width, my_height);
}
Exemple #2
0
/*
 * render a frame
 * args:
 *   frame - pointer to frame data (yuyv format)
 *   width - frame width
 *   height - frame height
 *
 * asserts:
 *   poverlay is not nul
 *   frame is not null
 *
 * returns: error code
 */
int render_sdl2_frame(uint8_t *frame, int width, int height)
{
	/*asserts*/
	assert(rending_texture != NULL);
	assert(frame != NULL);

	float vu_level[2];
	render_get_vu_level(vu_level);

#ifdef USE_PLANAR_YUV
	int size = width * height * 3/2; /* for IYUV */
#else
	int size = width * height * 2; /* 2 bytes per pixel for YUYV */
#endif

	void* texture_pixels;
	int pitch;

	SDL_SetRenderDrawColor(main_renderer, 0, 0, 0, 255); /*black*/
	SDL_RenderClear(main_renderer);


	if (SDL_LockTexture(rending_texture, NULL, &texture_pixels, &pitch))
	{
		fprintf(stderr, "RENDER: couldn't lock texture to write\n");
		return -1;
	}

	memcpy(texture_pixels, frame, size);

	/*osd vu meter*/
	if(((render_get_osd_mask() &
		(REND_OSD_VUMETER_MONO | REND_OSD_VUMETER_STEREO))) != 0)
		render_osd_vu_meter(texture_pixels, width, height, vu_level);
	/*osd crosshair*/
	if(((render_get_osd_mask() &
		REND_OSD_CROSSHAIR)) != 0)
		render_osd_crosshair(texture_pixels, width, height);

	SDL_UnlockTexture(rending_texture);

	SDL_RenderCopy(main_renderer, rending_texture, NULL, NULL);

	SDL_RenderPresent(main_renderer);
}
/*
 * render a vu meter
 * args:
 *   frame - pointer to yuyv frame data
 *   width - frame width
 *   height - frame height
 *   vu_level - vu level values (array with 2 channels)
 *
 * asserts:
 *   none
 *
 * returns: none
 */
void render_osd_vu_meter(uint8_t *frame, int width, int height, float vu_level[2])
{
	int bw = 2 * (width  / (VU_BARS * 8)); /*make it at least two pixels*/
	int bh = height / 24;

	int channel;
	for (channel = 0; channel < 2; ++channel)
	{
		if((render_get_osd_mask() & REND_OSD_VUMETER_MONO) != 0 && channel > 0)
			continue; /*if mono mode only render first channel*/

		/*make sure we have a positive value (required by log10)*/
		if(vu_level[channel] < 0)
			vu_level[channel] = -vu_level[channel];

		/* Handle peak calculation and falloff */
		if (vu_peak[channel] < vu_level[channel])
		{
			vu_peak[channel] = vu_level[channel];
			vu_peak_freeze[channel] = 30;
		}
		else if (vu_peak_freeze[channel] > 0)
		{
			vu_peak_freeze[channel]--;
  		}
  		else if (vu_peak[channel] > vu_level[channel])
  		{
			vu_peak[channel] -= (vu_peak[channel] - vu_level[channel]) / 10;
  		}

		/*by default no bar is light */
		float dBuLevel = - 4 * (VU_BARS - 1);
		float dBuPeak = - 4 * (VU_BARS - 1);

		if(vu_level[channel] > 0)
			dBuLevel = 10 * log10(vu_level[channel] / REFERENCE_LEVEL);

		if(vu_peak[channel] > 0)
			dBuPeak  = 10 * log10(vu_peak[channel]  / REFERENCE_LEVEL);

  		/* draw the bars */
  		int peaked = 0;
  		int box = 0;
  		for (box = 0; box <= (VU_BARS - 1); ++box)
  		{
			/*
			 * The dB it takes to light the current box
			 * step of 2 db between boxes
			 */
			float db = 2 * (box - (VU_BARS - 1));

			/* start x coordinate for box */
			int bx = box * (bw + 4) + (16);
			/* Start y coordinate for box (box top)*/
			int by = channel * (bh + 4) + bh;

			yuv_color_t color;
			color.y = 127;
			color.u = 127;
			color.v = 127;

			/*green bar*/
			if (db < -10)
			{
				color.y = 154;
  				color.u = 72;
  				color.v = 57;
			}
			else if (db < -2) /*yellow bar*/
			{
				color.y = 203;
  				color.u = 44;
  				color.v = 142;
			}
			else /*red bar*/
			{
				color.y = 107;
				color.u = 100;
				color.v = 212;
			}

			int light = dBuLevel > db;
			if (dBuPeak < db+1 && !peaked)
			{
  				peaked = 1;
  				light = 1;
			}

			if (light)
				plot_box_yu12(frame, height, width, bx, by, bw, bh, &color);
			else if (bw > 0) /*draw single line*/
				plot_line_yu12(frame, height, width, bx, by + (bh /2), bw, &color);
		}
  	}
}
Exemple #4
0
/*
 * audio processing loop (should run in a separate thread)
 * args:
 *    data - pointer to user data
 *
 * asserts:
 *   none
 *
 * returns: pointer to return code
 */
static void *audio_processing_loop(void *data)
{
	encoder_context_t *encoder_ctx = (encoder_context_t *) data;

	if(debug_level > 1)
		printf("GUVCVIEW: audio thread (tid: %u)\n",
			(unsigned int) syscall (SYS_gettid));
		
	audio_context_t *audio_ctx = get_audio_context();
	if(!audio_ctx)
	{
		fprintf(stderr, "GUVCVIEW: no audio context: skiping audio processing\n");
		return ((void *) -1);
	}
	audio_buff_t *audio_buff = NULL;

	/*start audio capture*/
	int frame_size = encoder_get_audio_frame_size(encoder_ctx);

	audio_ctx->capture_buff_size = frame_size * audio_ctx->channels;
	audio_start(audio_ctx);
	/*
	 * alloc the buffer after audio_start
	 * otherwise capture_buff_size may not
	 * be correct
	 * allocated data is big enough for float samples (32 bit)
	 * although it may contain int16 samples (16 bit)
	 */
	audio_buff = audio_get_buffer(audio_ctx);

	int sample_type = encoder_get_audio_sample_fmt(encoder_ctx);
	
	uint32_t osd_mask = render_get_osd_mask();

	/*enable vu meter OSD display*/
	if(audio_ctx->channels > 1)
		osd_mask |= REND_OSD_VUMETER_STEREO;
	else
		osd_mask |= REND_OSD_VUMETER_MONO;

	render_set_osd_mask(osd_mask);

	while(video_capture_get_save_video())
	{
		int ret = audio_get_next_buffer(audio_ctx, audio_buff,
				sample_type, my_audio_mask);
		
		if(ret > 0)
		{
			/* 
			 * no buffers to process
			 * sleep a couple of milisec
			 */
			 struct timespec req = {
				.tv_sec = 0,
				.tv_nsec = 1000000};/*nanosec*/
			 nanosleep(&req, NULL);
		}
		else if(ret == 0)
		{
			encoder_ctx->enc_audio_ctx->pts = audio_buff->timestamp;

			/*OSD vu meter level*/
			render_set_vu_level(audio_buff->level_meter);

			encoder_process_audio_buffer(encoder_ctx, audio_buff->data);
		}
		
	}

	/*flush any delayed audio frames*/
	encoder_flush_audio_buffer(encoder_ctx);

	/*reset vu meter*/
	audio_buff->level_meter[0] = 0;
	audio_buff->level_meter[1] = 0;
	render_set_vu_level(audio_buff->level_meter);

	/*disable OSD vumeter*/
	osd_mask &= ~REND_OSD_VUMETER_STEREO;
	osd_mask &= ~REND_OSD_VUMETER_MONO;

	render_set_osd_mask(osd_mask);

	audio_stop(audio_ctx);
	audio_delete_buffer(audio_buff);

	return ((void *) 0);
}