Пример #1
0
/**
 * Put a video frame into the video mixer
 *
 * @param src   Video source
 * @param frame Video frame
 */
void vidmix_source_put(struct vidmix_source *src, const struct vidframe *frame)
{
	if (!src || !frame || frame->fmt != VID_FMT_YUV420P)
		return;

	if (!src->frame_rx || !vidsz_cmp(&src->frame_rx->size, &frame->size)) {

		struct vidframe *frm;
		int err;

		err = vidframe_alloc(&frm, VID_FMT_YUV420P, &frame->size);
		if (err)
			return;

		pthread_rwlock_wrlock(&src->mix->rwlock);

		mem_deref(src->frame_rx);
		src->frame_rx = frm;

		clear_all(src->mix);

		pthread_rwlock_unlock(&src->mix->rwlock);
	}

	vidframe_copy(src->frame_rx, frame);
}
Пример #2
0
static int encode_pip(struct vidfilt_enc_st *st, struct vidframe *frame)
{
	struct selfview_enc *enc = (struct selfview_enc *)st;
	struct selfview *selfview = enc->selfview;
	int err = 0;

	if (!frame)
		return 0;

	lock_write_get(selfview->lock);
	if (!selfview->frame) {
		struct vidsz sz;

		/* Use size if configured, or else 20% of main window */
		if (selfview_size.w && selfview_size.h) {
			sz = selfview_size;
		}
		else {
			sz.w = frame->size.w / 5;
			sz.h = frame->size.h / 5;
		}

		err = vidframe_alloc(&selfview->frame, VID_FMT_YUV420P, &sz);
	}
	if (!err)
		vidconv(selfview->frame, frame, NULL);
	lock_rel(selfview->lock);

	return err;
}
Пример #3
0
static int draw_text(struct panel *panel, struct vidframe *frame)
{
	char buf[256];
	int width = panel->size_text.w;
	int height = panel->size_text.h;
	struct vidframe f;
	struct vidframe *f2 = NULL;
	cairo_t *cr = panel->cr;
	double tx, ty;
	int err;

	tx = 1;
	ty = height - 3;

	/* draw background */
	cairo_rectangle (cr, 0, 0, width, height);
	cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
	cairo_fill (cr);

	/* Draw text */
	if (re_snprintf(buf, sizeof(buf), "%s %2.2f fps",
			panel->label, panel->fps) < 0)
		return ENOMEM;

	cairo_move_to (cr, tx, ty);
	cairo_text_path (cr, buf);
	cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
	cairo_fill_preserve (cr);
	cairo_set_line_width (cr, 0.6);
	cairo_stroke (cr);

	vidframe_init_buf(&f, VID_FMT_ARGB, &panel->size_text,
			  cairo_image_surface_get_data(panel->surface));

	err = vidframe_alloc(&f2, frame->fmt, &panel->size_text);
	if (err)
		goto out;

	vidconv(f2, &f, 0);

	overlay(frame, panel->yoffs, f2);

 out:
	mem_deref(f2);
	return err;
}
Пример #4
0
static int src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs,
		     struct media_ctx **ctx, struct vidsrc_prm *prm,
		     const struct vidsz *size, const char *fmt,
		     const char *dev, vidsrc_frame_h *frameh,
		     vidsrc_error_h *errorh, void *arg)
{
	struct vidsrc_st *st;
	int err;

	(void)ctx;
	(void)fmt;
	(void)dev;
	(void)errorh;

	if (!stp || !prm || !size || !frameh)
		return EINVAL;

	st = mem_zalloc(sizeof(*st), src_destructor);
	if (!st)
		return ENOMEM;

	st->vs     = vs;
	st->fps    = prm->fps;
	st->frameh = frameh;
	st->arg    = arg;

	err = vidframe_alloc(&st->frame, VID_FMT_YUV420P, size);
	if (err)
		goto out;

	st->run = true;
	err = pthread_create(&st->thread, NULL, read_thread, st);
	if (err) {
		st->run = false;
		goto out;
	}

 out:
	if (err)
		mem_deref(st);
	else
		*stp = st;

	return err;
}
Пример #5
0
static int plot_spectrum(const char *filename_png)
{
	struct vidframe *vf = NULL;
	struct vidsz sz = {NUM_FREQ+1, NUM_FREQ/2};
	unsigned long peak_mag = 0;
	size_t peak_bin = 0;
	size_t i;
	unsigned x;
	int err;

	err = vidframe_alloc(&vf, VID_FMT_RGB32, &sz);
	if (err)
		goto out;

	/* find the peak amplitude and its bin */
	for (i=0; i<NUM_FREQ; i++) {

		if (magv[i] > peak_mag) {
			peak_mag = magv[i];
			peak_bin = i;
		}
	}
	re_printf("peak magnitude is %u in bin %u\n", peak_mag, peak_bin);

	vidframe_fill(vf, 255, 255, 255);

	for (x=0; x<NUM_FREQ; x++) {

		unsigned h;

		h = (unsigned)((sz.h-1) * 1.0 * magv[x] / peak_mag);

		vidframe_draw_vline(vf, x, sz.h-1-h, h, 255, 0, 0);
	}

	err = png_save_vidframe(vf, filename_png);
	if (err)
		goto out;

 out:
	mem_deref(vf);

	return err;
}
Пример #6
0
/**
 * Allocate a video mixer source
 *
 * @param srcp    Pointer to allocated video source
 * @param mix     Video mixer
 * @param sz      Size of output video frame (optional)
 * @param fps     Output frame rate (frames per second)
 * @param content True if source is of type content
 * @param fh      Mixer frame handler
 * @param arg     Handler argument
 *
 * @return 0 for success, otherwise error code
 */
int vidmix_source_alloc(struct vidmix_source **srcp, struct vidmix *mix,
			const struct vidsz *sz, unsigned fps, bool content,
			vidmix_frame_h *fh, void *arg)
{
	struct vidmix_source *src;
	int err;

	if (!srcp || !mix || !fps || !fh)
		return EINVAL;

	src = mem_zalloc(sizeof(*src), source_destructor);
	if (!src)
		return ENOMEM;

	src->mix     = mem_ref(mix);
	src->fint    = 1000/fps;
	src->content = content;
	src->fh      = fh;
	src->arg     = arg;

	err = pthread_mutex_init(&src->mutex, NULL);
	if (err)
		goto out;

	if (sz) {
		err = vidframe_alloc(&src->frame_tx, VID_FMT_YUV420P, sz);
		if (err)
			goto out;

		clear_frame(src->frame_tx);
	}

 out:
	if (err)
		mem_deref(src);
	else
		*srcp = src;

	return err;
}
Пример #7
0
static int encode_pip(struct vidfilt_st *st, struct vidframe *frame)
{
	struct selfview *sv = (struct selfview *)st;
	int err = 0;

	if (!frame)
		return 0;

	lock_write_get(sv->lock);
	if (!sv->frame) {
		struct vidsz sz;

		sz.w = frame->size.w / 5;
		sz.h = frame->size.h / 5;

		err = vidframe_alloc(&sv->frame, VID_FMT_YUV420P, &sz);
	}
	if (!err)
		vidconv(sv->frame, frame, NULL);
	lock_rel(sv->lock);

	return err;
}
Пример #8
0
/**
 * Set video mixer output frame size
 *
 * @param src  Video mixer source
 * @param sz   Size of output video frame
 *
 * @return 0 for success, otherwise error code
 */
int vidmix_source_set_size(struct vidmix_source *src, const struct vidsz *sz)
{
	struct vidframe *frame;
	int err;

	if (!src || !sz)
		return EINVAL;

	if (src->frame_tx && vidsz_cmp(&src->frame_tx->size, sz))
		return 0;

	err = vidframe_alloc(&frame, VID_FMT_YUV420P, sz);
	if (err)
		return err;

	clear_frame(frame);

	pthread_mutex_lock(&src->mutex);
	mem_deref(src->frame_tx);
	src->frame_tx = frame;
	pthread_mutex_unlock(&src->mutex);

	return 0;
}
Пример #9
0
static int encode_process(struct vidfilt_enc_st *st, struct vidframe *frame)
{
	struct swscale_enc *enc = (struct swscale_enc *)st;
	enum AVPixelFormat avpixfmt, avpixfmt_dst;
	const uint8_t *srcSlice[4];
	uint8_t *dst[4];
	int srcStride[4], dstStride[4];
	int width, height, i, h;
	int err = 0;

	if (!st)
		return EINVAL;

	if (!frame)
		return 0;

	width = frame->size.w;
	height = frame->size.h;

	avpixfmt = vidfmt_to_avpixfmt(frame->fmt);
	if (avpixfmt == AV_PIX_FMT_NONE) {
		warning("swscale: unknown pixel-format (%s)\n",
			vidfmt_name(frame->fmt));
		return EINVAL;
	}

	avpixfmt_dst = vidfmt_to_avpixfmt(swscale_format);
	if (avpixfmt_dst == AV_PIX_FMT_NONE) {
		warning("swscale: unknown pixel-format (%s)\n",
			vidfmt_name(swscale_format));
		return EINVAL;
	}

	if (!enc->sws) {

		struct SwsContext *sws;
		int flags = 0;

		sws = sws_getContext(width, height, avpixfmt,
				     enc->dst_size.w, enc->dst_size.h,
				     avpixfmt_dst,
				     flags, NULL, NULL, NULL);
		if (!sws) {
			warning("swscale: sws_getContext error\n");
			return ENOMEM;
		}

		enc->sws = sws;

		info("swscale: created SwsContext:"
		     " `%s' %d x %d --> `%s' %u x %u\n",
		     vidfmt_name(frame->fmt), width, height,
		     vidfmt_name(swscale_format),
		     enc->dst_size.w, enc->dst_size.h);
	}

	if (!enc->frame) {

		err = vidframe_alloc(&enc->frame, swscale_format,
				     &enc->dst_size);
		if (err) {
			warning("swscale: vidframe_alloc error (%m)\n", err);
			return err;
		}
	}

	for (i=0; i<4; i++) {
		srcSlice[i]  = frame->data[i];
		srcStride[i] = frame->linesize[i];
		dst[i]       = enc->frame->data[i];
		dstStride[i] = enc->frame->linesize[i];
	}

	h = sws_scale(enc->sws, srcSlice, srcStride,
		      0, height, dst, dstStride);
	if (h <= 0) {
		warning("swscale: sws_scale error (%d)\n", h);
		return EPROTO;
	}

	/* Copy the converted frame back to the input frame */
	for (i=0; i<4; i++) {
		frame->data[i]     = enc->frame->data[i];
		frame->linesize[i] = enc->frame->linesize[i];
	}
	frame->size = enc->frame->size;
	frame->fmt = enc->frame->fmt;

	return 0;
}
Пример #10
0
int png_save_vidframe(const struct vidframe *vf, const char *filename)
{
	png_byte **png_row_pointers = NULL;
	png_byte *row;
	const png_byte *p;
	png_byte red, green, blue;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	FILE *fp = NULL;
	size_t x, y;
	unsigned int width = vf->size.w & ~1;
	unsigned int height = vf->size.h & ~1;
	unsigned int bytes_per_pixel = 3; /* RGB format */
	struct vidframe *f2 = NULL;
	int err = 0;

	if (vf->fmt != VID_FMT_RGB32) {

		err = vidframe_alloc(&f2, VID_FMT_RGB32, &vf->size);
		if (err)
			goto out;

		vidconv(f2, vf, NULL);
		vf = f2;
	}

	/* Initialize the write struct. */
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
					  NULL, NULL, NULL);
	if (png_ptr == NULL) {
		err = ENOMEM;
		goto out;
	}

	/* Initialize the info struct. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		err = ENOMEM;
		goto out;
	}

	/* Set up error handling. */
	if (setjmp(png_jmpbuf(png_ptr))) {
		err = ENOMEM;
		goto out;
	}

	/* Set image attributes. */
	png_set_IHDR(png_ptr,
		     info_ptr,
		     width,
		     height,
		     8,
		     PNG_COLOR_TYPE_RGB,
		     PNG_INTERLACE_NONE,
		     PNG_COMPRESSION_TYPE_DEFAULT,
		     PNG_FILTER_TYPE_DEFAULT);

	/* Initialize rows of PNG
	 *    bytes_per_row = width * bytes_per_pixel;
	 */
	png_row_pointers = png_malloc(png_ptr,
				      height * sizeof(png_byte *));

	for (y = 0; y < height; ++y) {
		png_row_pointers[y] =
			(png_byte *) png_malloc(png_ptr,
						width * sizeof(uint8_t) *
						bytes_per_pixel);
	}

	p = vf->data[0];
	for (y = 0; y < height; ++y) {

		row = png_row_pointers[y];

		for (x = 0; x < width; ++x) {

			red   = *p++;
			green = *p++;
			blue  = *p++;

			*row++ = blue;
			*row++ = green;
			*row++ = red;

			++p;		/* skip alpha */
		}
	}

	/* Write the image data. */
	fp = fopen(filename, "wb");
	if (fp == NULL) {
		err = errno;
		goto out;
	}

	png_init_io(png_ptr, fp);
	png_set_rows(png_ptr, info_ptr, png_row_pointers);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	re_printf("wrote %u x %u pixels to %s\n",
		  vf->size.w, vf->size.h, filename);

 out:
	/* Finish writing. */
	mem_deref(f2);
	png_save_free(png_ptr, png_row_pointers, height);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	if (fp)
		fclose(fp);

	return 0;
}
Пример #11
0
int jpg_save_vidframe(const struct vidframe *vf, const char *path)
{

	struct		jpeg_compress_struct cinfo;
	struct		jpeg_error_mgr jerr;
  	JSAMPROW	row_pointer[1];
	
	unsigned char *imgdata,*src,*dst;
	int row_stride,pixs;
	
	FILE * fp;
	char filename_buf[64];

	struct vidframe *f2 = NULL;
	int err = 0;

	unsigned int width = vf->size.w & ~1;
	unsigned int height = vf->size.h & ~1;
	
	time_t tnow;
	struct tm *tmx;
	
	// 0
	tnow = time(NULL);
	tmx = localtime(&tnow);
	imgdata = vf->data[0];

	if (vf->fmt != VID_FMT_RGB32)
	{
		err = vidframe_alloc(&f2, VID_FMT_RGB32, &vf->size);
		if (err) goto out;
		vidconv(f2, vf, NULL);
		imgdata = f2->data[0];
	}

	fp = fopen(jpg_filename(tmx, path, filename_buf, sizeof(filename_buf)), "wb");
	if (fp == NULL) 
	{
		err = errno;
		goto out;
	}

	// 32bpp -> 24bpp
	pixs = width*height;
	src = imgdata; 
	dst = imgdata; 
	while (pixs--)
	{
		*dst++=*src++; //R
		*dst++=*src++; //G
		*dst++=*src++; //B
		src++; //A
	}

	// create jpg structures
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, fp);
	
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3; // 24 bpp
	// I wonder if this will make double conversion.
	cinfo.in_color_space = JCS_EXT_BGR;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, 85 , TRUE); // quality 85%

	// compress
	jpeg_start_compress(&cinfo, TRUE);

	row_stride = width * cinfo.input_components;		
	//buffer = (JSAMPARRAY) imgdata;

	while (cinfo.next_scanline < cinfo.image_height) 
	{
		row_pointer[0] = & imgdata[cinfo.next_scanline * row_stride];
		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);

	
	/* Finish writing. */
out:
	jpeg_destroy_compress(&cinfo);
	mem_deref(f2);
	if (fp) fclose(fp);
	return 0;
}