/** * Reads image data from an Aravis ArvBuffer and saves a png file to filename * TODO: Add error checking and all that stuff (this code is demonstrative) */ void arv_save_png(ArvBuffer * buffer, const char * filename) { // TODO: This only works on image buffers assert(arv_buffer_get_payload_type(buffer) == ARV_BUFFER_PAYLOAD_TYPE_IMAGE); size_t buffer_size; char * buffer_data = (char*)arv_buffer_get_data(buffer, &buffer_size); // raw data int width; int height; arv_buffer_get_image_region(buffer, NULL, NULL, &width, &height); // get width/height int bit_depth = ARV_PIXEL_FORMAT_BIT_PER_PIXEL(arv_buffer_get_image_pixel_format(buffer)); // bit(s) per pixel //TODO: Deal with non-png compliant pixel formats? // EG: ARV_PIXEL_FORMAT_MONO_14 is 14 bits per pixel, so conversion to PNG loses data int arv_row_stride = width * bit_depth/8; // bytes per row, for constructing row pointers int color_type = PNG_COLOR_TYPE_GRAY; //TODO: Check for other types? // boilerplate libpng stuff without error checking (setjmp? Seriously? How many kittens have to die?) png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); FILE * f = fopen(filename, "wb"); png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); // Need to create pointers to each row of pixels for libpng png_bytepp rows = (png_bytepp)(png_malloc(png_ptr, height*sizeof(png_bytep))); int i =0; for (i = 0; i < height; ++i) rows[i] = (png_bytep)(buffer_data + (height - i)*arv_row_stride); // Actually write image png_write_image(png_ptr, rows); png_write_end(png_ptr, NULL); // cleanup fclose(f); }
bool arv_buffer_save_raw(ArvBuffer * buffer, const char * filename) { if (get_free_space() < 50000000) return false; size_t buffer_size; char * buffer_data = (char*)arv_buffer_get_data(buffer, &buffer_size); // raw data int width; int height; arv_buffer_get_image_region(buffer, NULL, NULL, &width, &height); // get width/height int bit_depth = ARV_PIXEL_FORMAT_BIT_PER_PIXEL(arv_buffer_get_image_pixel_format(buffer)); // bit(s) per pixel FILE * f = fopen(filename, "wb"); assert(f != NULL); fwrite(buffer_data, 1, buffer_size, f); fclose(f); return true; }
static GstFlowReturn gst_aravis_create (GstPushSrc * push_src, GstBuffer ** buffer) { GstAravis *gst_aravis; ArvBuffer *arv_buffer; int arv_row_stride; int width, height; char *buffer_data; size_t buffer_size; guint64 timestamp_ns; gst_aravis = GST_ARAVIS (push_src); do { arv_buffer = arv_stream_timeout_pop_buffer (gst_aravis->stream, gst_aravis->buffer_timeout_us); if (arv_buffer != NULL && arv_buffer_get_status (arv_buffer) != ARV_BUFFER_STATUS_SUCCESS) arv_stream_push_buffer (gst_aravis->stream, arv_buffer); } while (arv_buffer != NULL && arv_buffer_get_status (arv_buffer) != ARV_BUFFER_STATUS_SUCCESS); if (arv_buffer == NULL) return GST_FLOW_ERROR; *buffer = gst_buffer_new (); buffer_data = (char *) arv_buffer_get_data (arv_buffer, &buffer_size); arv_buffer_get_image_region (arv_buffer, NULL, NULL, &width, &height); arv_row_stride = width * ARV_PIXEL_FORMAT_BIT_PER_PIXEL (arv_buffer_get_image_pixel_format (arv_buffer)) / 8; timestamp_ns = arv_buffer_get_timestamp (arv_buffer); /* Gstreamer requires row stride to be a multiple of 4 */ if ((arv_row_stride & 0x3) != 0) { int gst_row_stride; size_t size; void *data; int i; gst_row_stride = (arv_row_stride & ~(0x3)) + 4; size = height * gst_row_stride; data = g_malloc (size); for (i = 0; i < height; i++) memcpy (((char *) data) + i * gst_row_stride, buffer_data + i * arv_row_stride, arv_row_stride); GST_BUFFER_DATA (buffer) = data; GST_BUFFER_MALLOCDATA (buffer) = data; GST_BUFFER_SIZE (buffer) = size; } else { GST_BUFFER_DATA (*buffer) = buffer_data; GST_BUFFER_MALLOCDATA (*buffer) = NULL; GST_BUFFER_SIZE (*buffer) = buffer_size; } if (!gst_base_src_get_do_timestamp(GST_BASE_SRC(push_src))) { if (gst_aravis->timestamp_offset == 0) { gst_aravis->timestamp_offset = timestamp_ns; gst_aravis->last_timestamp = timestamp_ns; } GST_BUFFER_TIMESTAMP (*buffer) = timestamp_ns - gst_aravis->timestamp_offset; GST_BUFFER_DURATION (*buffer) = timestamp_ns - gst_aravis->last_timestamp; gst_aravis->last_timestamp = timestamp_ns; } arv_stream_push_buffer (gst_aravis->stream, arv_buffer); gst_buffer_set_caps (*buffer, gst_aravis->fixed_caps); return GST_FLOW_OK; }
static GstFlowReturn gst_aravis_create (GstPushSrc * push_src, GstBuffer ** buffer) { GstAravis *gst_aravis; ArvBuffer *arv_buffer; int arv_row_stride; gst_aravis = GST_ARAVIS (push_src); do { arv_buffer = arv_stream_timeout_pop_buffer (gst_aravis->stream, gst_aravis->buffer_timeout_us); if (arv_buffer != NULL && arv_buffer->status != ARV_BUFFER_STATUS_SUCCESS) arv_stream_push_buffer (gst_aravis->stream, arv_buffer); } while (arv_buffer != NULL && arv_buffer->status != ARV_BUFFER_STATUS_SUCCESS); if (arv_buffer == NULL) return GST_FLOW_ERROR; arv_row_stride = arv_buffer->width * ARV_PIXEL_FORMAT_BIT_PER_PIXEL (arv_buffer->pixel_format) / 8; /* Gstreamer requires row stride to be a multiple of 4 */ if ((arv_row_stride & 0x3) != 0) { int gst_row_stride; size_t size; void *data; int i; gst_row_stride = (arv_row_stride & ~(0x3)) + 4; size = arv_buffer->height * gst_row_stride; data = g_malloc (size); for (i = 0; i < arv_buffer->height; i++) memcpy (((char *) data) + i * gst_row_stride, ((char *) arv_buffer->data) + i * arv_row_stride, arv_row_stride); *buffer = gst_buffer_new_wrapped (data, size); } else { *buffer = gst_buffer_new_wrapped_full (0, arv_buffer->data, arv_buffer->size, 0, arv_buffer->size, NULL, NULL); } if (!gst_base_src_get_do_timestamp(GST_BASE_SRC(push_src))) { if (gst_aravis->timestamp_offset == 0) { gst_aravis->timestamp_offset = arv_buffer->timestamp_ns; gst_aravis->last_timestamp = arv_buffer->timestamp_ns; } GST_BUFFER_PTS (*buffer) = arv_buffer->timestamp_ns - gst_aravis->timestamp_offset; GST_BUFFER_DURATION (*buffer) = arv_buffer->timestamp_ns - gst_aravis->last_timestamp; gst_aravis->last_timestamp = arv_buffer->timestamp_ns; } arv_stream_push_buffer (gst_aravis->stream, arv_buffer); return GST_FLOW_OK; }