From 8f2a2877b52894349f2f5f9315c5bf7498de4b02 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 17 Apr 2013 20:26:09 +0200 Subject: [PATCH] ArdourCanvas::Image allow to set custom data instead of class pre-allocated memory. --- gtk2_ardour/video_image_frame.cc | 22 ++++++++++++++-------- libs/canvas/canvas/image.h | 22 +++++++++++++++++++--- libs/canvas/image.cc | 14 +++++++++----- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/gtk2_ardour/video_image_frame.cc b/gtk2_ardour/video_image_frame.cc index b10b546857..c892bacfa6 100644 --- a/gtk2_ardour/video_image_frame.cc +++ b/gtk2_ardour/video_image_frame.cc @@ -35,6 +35,13 @@ using namespace std; using namespace ARDOUR; +static void freedata_cb (uint8_t *d, void *arg) { + /* later this can be used with libharvid + * the buffer/videocacheline instead of freeing it + */ + free (d); +} + VideoImageFrame::VideoImageFrame (PublicEditor& ed, ArdourCanvas::Group& parent, int w, int h, std::string vsurl, std::string vfn) : editor (ed) , _parent(&parent) @@ -117,7 +124,7 @@ VideoImageFrame::draw_line () const int rowstride = img->stride; const int clip_height = img->height; uint8_t *pixels, *p; - pixels = img->data.get(); + pixels = img->data; int y; for (y = 0;y < clip_height; y++) { @@ -133,7 +140,7 @@ VideoImageFrame::fill_frame (const uint8_t r, const uint8_t g, const uint8_t b) const int clip_height = img->height; const int clip_width = img->width; uint8_t *pixels, *p; - pixels = img->data.get(); + pixels = img->data; int x,y; for (y = 0; y < clip_height; ++y) { @@ -152,7 +159,7 @@ VideoImageFrame::draw_x () const int clip_width = img->width; const int clip_height = img->height; uint8_t *pixels, *p; - pixels = img->data.get(); + pixels = img->data; for (x = 0;x < clip_width; x++) { y = clip_height * x / clip_width; @@ -173,7 +180,7 @@ VideoImageFrame::cut_rightend () const int clip_height = img->height; const int clip_width = img->width; uint8_t *pixels, *p; - pixels = img->data.get(); + pixels = img->data; if (rightend > clip_width) { return; } int x,y; @@ -233,10 +240,9 @@ VideoImageFrame::http_download_done (char *data){ cut_rightend(); image->put_image(img); } else { - img = image->get_image(); - /* TODO - have curl write directly to the shared memory region */ - memcpy((void*) img->data.get(), data, img->stride * img->height); - free(data); + img = image->get_image(false); + img->data = (uint8_t*) data; + img->destroy_callback = &freedata_cb; draw_line(); cut_rightend(); image->put_image(img); diff --git a/libs/canvas/canvas/image.h b/libs/canvas/canvas/image.h index a3b1a269ba..0dcf8e51b3 100644 --- a/libs/canvas/canvas/image.h +++ b/libs/canvas/canvas/image.h @@ -25,27 +25,42 @@ #include "canvas/item.h" +typedef void (*ImageReleaseCallback)(uint8_t *d, void *arg); + namespace ArdourCanvas { + class Image : public Item { public: Image (Group *, Cairo::Format, int width, int height); struct Data { - Data (boost::shared_array d, int w, int h, int s, Cairo::Format fmt) + Data (uint8_t *d, int w, int h, int s, Cairo::Format fmt) : data (d) , width (w) , height (h) , stride (s) , format (fmt) + , destroy_callback(NULL) + , destroy_arg(NULL) {} - boost::shared_array data; + virtual ~Data () { + if (destroy_callback) { + destroy_callback(data, destroy_arg); + } else { + free(data); + } + } + + uint8_t* data; int width; int height; int stride; Cairo::Format format; + ImageReleaseCallback destroy_callback; + void* destroy_arg; }; /** @@ -59,7 +74,8 @@ public: * ... to avoid collisions with Image deletion, some synchronization method * may be required or the use of shared_ptr or similar. */ - boost::shared_ptr get_image (); + boost::shared_ptr get_image (bool allocate_data = true); + /** * Queues a Data object to be used to redraw this Image item diff --git a/libs/canvas/image.cc b/libs/canvas/image.cc index 71a5df64dd..b13859aeda 100644 --- a/libs/canvas/image.cc +++ b/libs/canvas/image.cc @@ -36,7 +36,7 @@ void Image::render (Rect const& area, Cairo::RefPtr context) const { if (_need_render && _pending) { - _surface = Cairo::ImageSurface::create (_pending->data.get(), + _surface = Cairo::ImageSurface::create (_pending->data, _pending->format, _pending->width, _pending->height, @@ -59,14 +59,18 @@ Image::compute_bounding_box () const } boost::shared_ptr -Image::get_image () +Image::get_image (bool allocate_data) { /* can be called by any thread */ int stride = Cairo::ImageSurface::format_stride_for_width (_format, _width); - boost::shared_ptr d (new Data (boost::shared_array (new uint8_t[stride*_height]), _width, _height, stride, _format)); - - return d; + if (allocate_data) { + boost::shared_ptr d (new Data (new uint8_t[stride*_height], _width, _height, stride, _format)); + return d; + } else { + boost::shared_ptr d (new Data (NULL, _width, _height, stride, _format)); + return d; + } } void