add binfolder path relative filters, fix gbrp color model, vwdw timebar tweaks, title...
[goodguy/history.git] / cinelerra-5.1 / guicast / vframe.C
index 25dd05eca6fd90334899ebe46a6024535e8bbe66..3eca676452ca8536fa3f78993e68a24bf35fd9a1 100644 (file)
@@ -131,14 +131,18 @@ VFrame::VFrame(VFrame &frame)
 {
        reset_parameters(1);
        params = new BC_Hash;
+       use_shm = frame.use_shm;
        allocate_data(0, -1, 0, 0, 0, frame.w, frame.h,
                frame.color_model, frame.bytes_per_line);
-       copy_from(&frame);
+       copy_vframe(&frame);
 }
 
+
 VFrame::VFrame(int w, int h, int color_model, long bytes_per_line)
 {
        reset_parameters(1);
+//  use bytes_per_line == 0 to allocate default unshared
+       if( !bytes_per_line ) { bytes_per_line = -1;  use_shm = 0; }
        params = new BC_Hash;
        allocate_data(data, -1, 0, 0, 0, w, h,
                color_model, bytes_per_line);
@@ -275,8 +279,8 @@ int VFrame::reset_parameters(int do_opengl)
        sequence_number = -1;
        timestamp = -1.;
        is_keyframe = 0;
-       draw_point = 0;
-       set_pixel_color(BLACK);
+       pixel_rgb = 0x000000; // BLACK
+       pixel_yuv = 0x008080;
        stipple = 0;
 
        if(do_opengl)
@@ -304,6 +308,11 @@ int VFrame::clear_objects(int do_opengl)
                pbuffer = 0;
        }
 
+#ifdef LEAKER
+if( memory_type != VFrame::SHARED )
+  printf("==del %p from %p\n", data, __builtin_return_address(0));
+#endif
+
 // Delete data
        switch(memory_type)
        {
@@ -345,6 +354,7 @@ int VFrame::clear_objects(int do_opengl)
                case BC_YUV444P:
                case BC_RGB_FLOATP:
                case BC_RGBA_FLOATP:
+               case BC_GBRP:
                        break;
 
                default:
@@ -436,6 +446,12 @@ void VFrame::create_row_pointers()
                this->u_offset = sz;
                this->v_offset = sz + sz;
                break;
+       case BC_GBRP:
+               if( this->v_offset ) break;
+               this->y_offset = 0;
+               this->u_offset = sz * sizeof(uint8_t);
+               this->v_offset = 2 * sz * sizeof(uint8_t);
+               break;
        case BC_RGBA_FLOATP:
                if( this->v_offset || a ) break;
                a = this->data + 3 * sz * sizeof(float);
@@ -494,27 +510,30 @@ int VFrame::allocate_data(unsigned char *data, int shmid,
        }
        else {
                memory_type = VFrame::PRIVATE;
+               this->data = 0;
                int size = calculate_data_size(this->w, this->h,
                        this->bytes_per_line, this->color_model);
-               if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm) {
+               if( use_shm && size >= SHM_MIN_SIZE &&
+                   BC_WindowBase::get_resources()->use_vframe_shm() ) {
                        this->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
-                       if(this->shmid < 0) {
-                               printf("VFrame::allocate_data %d could not allocate shared memory\n", __LINE__);
-                       }
-
-                       this->data = (unsigned char*)shmat(this->shmid, NULL, 0);
-//printf("VFrame::allocate_data %d %d %d\n", __LINE__, size, this->shmid);
-
-//printf("VFrame::allocate_data %d %p\n", __LINE__, this->data);
+                       if( this->shmid >= 0 ) {
+                               this->data = (unsigned char*)shmat(this->shmid, NULL, 0);
+//printf("VFrame::allocate_data %d %d %d %p\n", __LINE__, size, this->shmid, this->data);
 // This causes it to automatically delete when the program exits.
-                       shmctl(this->shmid, IPC_RMID, 0);
+                               shmctl(this->shmid, IPC_RMID, 0);
+                       }
+                       else {
+                               printf("VFrame::allocate_data %d could not allocate"
+                                       " shared memory, %dx%d (model %d) size=0x%08x\n",
+                                       __LINE__, w, h, color_model, size);
+                               BC_Trace::dump_shm_stats(stdout);
+                       }
                }
-               else {
 // Have to use malloc for libpng
-//printf("==vframe %d from %p\n", size, __builtin_return_address(0));
+               if( !this->data ) {
                        this->data = (unsigned char *)malloc(size);
+                       this->shmid = -1;
                }
-
 // Memory check
 // if(this->w * this->h > 1500 * 1100)
 // printf("VFrame::allocate_data 2 this=%p w=%d h=%d this->data=%p\n",
@@ -522,6 +541,9 @@ int VFrame::allocate_data(unsigned char *data, int shmid,
 
                if(!this->data)
                        printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
+#ifdef LEAKER
+printf("==new %p from %p sz %d\n", this->data, __builtin_return_address(0), size);
+#endif
 
 //printf("VFrame::allocate_data %d %p data=%p %d %d\n", __LINE__, this, this->data, this->w, this->h);
 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
@@ -826,7 +848,7 @@ int VFrame::write_png(const char *path)
                        bc_cmodel = BC_RGBA8888;
                        png_cmodel = PNG_COLOR_TYPE_RGB_ALPHA;
                }
-               vframe = new VFrame(get_w(), get_h(), bc_cmodel, -1);
+               vframe = new VFrame(get_w(), get_h(), bc_cmodel, 0);
                vframe->transfer_from(this);
                break;
        }
@@ -869,27 +891,33 @@ int VFrame::clear_frame()
 
        case BC_YUV410P:
                bzero(get_y(), sz);
-               bzero(get_u(), w / 4 * h / 4);
-               bzero(get_v(), w / 4 * h / 4);
+               memset(get_u(), 0x80, w / 4 * h / 4);
+               memset(get_v(), 0x80, w / 4 * h / 4);
                break;
 
        case BC_YUV411P:
        case BC_YUV420P:
        case BC_YUV420PI:
                bzero(get_y(), sz);
-               bzero(get_u(), sz / 4);
-               bzero(get_v(), sz / 4);
+               memset(get_u(), 0x80, sz / 4);
+               memset(get_v(), 0x80, sz / 4);
                break;
 
        case BC_YUV422P:
                bzero(get_y(), sz);
-               bzero(get_u(), sz / 2);
-               bzero(get_v(), sz / 2);
+               memset(get_u(), 0x80, sz / 2);
+               memset(get_v(), 0x80, sz / 2);
+               break;
+
+       case BC_GBRP:
+               bzero(get_y(), sz);
+               bzero(get_u(), sz);
+               bzero(get_b(), sz);
                break;
 
        case BC_RGBA_FLOATP: if( a ) {
                float *ap = (float *)a;
-               for( int i=sz; --i>=0; ++ap ) *ap = 1.f; }
+               for( int i=sz; --i>=0; ++ap ) *ap = 0.f; }
        case BC_RGB_FLOATP: {
                float *rp = (float *)y;
                for( int i=sz; --i>=0; ++rp ) *rp = 0.f;
@@ -900,8 +928,8 @@ int VFrame::clear_frame()
                break; }
        case BC_YUV444P:
                bzero(get_y(), sz);
-               bzero(get_u(), sz);
-               bzero(get_v(), sz);
+               memset(get_u(), 0x80, sz);
+               memset(get_v(), 0x80, sz);
                break;
 
        case BC_YUV888:
@@ -930,12 +958,9 @@ int VFrame::clear_frame()
 void VFrame::rotate90()
 {
 // Allocate new frame
-       int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
-       unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
-       unsigned char **new_rows = new unsigned char*[new_h];
-       for(int i = 0; i < new_h; i++)
-               new_rows[i] = &new_data[new_bytes_per_line * i];
-
+       int new_w = h, new_h = w;
+       VFrame new_frame(new_w, new_h, color_model);
+       unsigned char **new_rows = new_frame.get_rows();
 // Copy data
        for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
        {
@@ -950,23 +975,34 @@ void VFrame::rotate90()
        }
 
 // Swap frames
-       clear_objects(0);
+// swap memory
+       unsigned char *new_data = new_frame.data;
+       new_frame.data = data;
        data = new_data;
+// swap rows
+       new_rows = new_frame.rows;
+       new_frame.rows = rows;
        rows = new_rows;
-       bytes_per_line = new_bytes_per_line;
-       w = new_w;
-       h = new_h;
+// swap shmid
+       int new_shmid = new_frame.shmid;
+       new_frame.shmid = shmid;
+       shmid = new_shmid;
+// swap bytes_per_line
+       int new_bpl = new_frame.bytes_per_line;
+       new_frame.bytes_per_line = bytes_per_line;
+       bytes_per_line = new_bpl;
+       new_frame.clear_objects(0);
+
+       w = new_frame.w;
+       h = new_frame.h;
 }
 
 void VFrame::rotate270()
 {
 // Allocate new frame
-       int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
-       unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
-       unsigned char **new_rows = new unsigned char*[new_h];
-       for(int i = 0; i < new_h; i++)
-               new_rows[i] = &new_data[new_bytes_per_line * i];
-
+       int new_w = h, new_h = w;
+       VFrame new_frame(new_w, new_h, color_model);
+       unsigned char **new_rows = new_frame.get_rows();
 // Copy data
        for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
        {
@@ -981,24 +1017,36 @@ void VFrame::rotate270()
        }
 
 // Swap frames
-       clear_objects(0);
+// swap memory
+       unsigned char *new_data = new_frame.data;
+       new_frame.data = data;
        data = new_data;
+// swap rows
+       new_rows = new_frame.rows;
+       new_frame.rows = rows;
        rows = new_rows;
-       bytes_per_line = new_bytes_per_line;
-       w = new_w;
-       h = new_h;
+// swap shmid
+       int new_shmid = new_frame.shmid;
+       new_frame.shmid = shmid;
+       shmid = new_shmid;
+// swap bytes_per_line
+       int new_bpl = new_frame.bytes_per_line;
+       new_frame.bytes_per_line = bytes_per_line;
+       bytes_per_line = new_bpl;
+       new_frame.clear_objects(0);
+
+       w = new_frame.w;
+       h = new_frame.h;
 }
 
 void VFrame::flip_vert()
 {
-       unsigned char *temp = new unsigned char[bytes_per_line];
-       for(int i = 0, j = h - 1; i < j; i++, j--)
-       {
+       unsigned char temp[bytes_per_line];
+       for( int i=0, j=h; --j>i; ++i ) {
                memcpy(temp, rows[j], bytes_per_line);
                memcpy(rows[j], rows[i], bytes_per_line);
                memcpy(rows[i], temp, bytes_per_line);
        }
-       delete [] temp;
 }
 
 void VFrame::flip_horiz()
@@ -1020,6 +1068,18 @@ void VFrame::flip_horiz()
 
 int VFrame::copy_from(VFrame *frame)
 {
+       if(this->w != frame->get_w() ||
+               this->h != frame->get_h())
+       {
+               printf("VFrame::copy_from %d sizes differ src %dx%d != dst %dx%d\n",
+                       __LINE__,
+                       frame->get_w(),
+                       frame->get_h(),
+                       get_w(),
+                       get_h());
+               return 1;
+       }
+
        int w = MIN(this->w, frame->get_w());
        int h = MIN(this->h, frame->get_h());
        timestamp = frame->timestamp;
@@ -1070,18 +1130,19 @@ int VFrame::copy_from(VFrame *frame)
                        break;
        }
 
-       params->copy_from(frame->params);
        return 0;
 }
 
 int VFrame::transfer_from(VFrame *that, int bg_color, int in_x, int in_y, int in_w, int in_h)
 {
+       timestamp = that->timestamp;
+       copy_params(that);
+
        if( this->get_color_model() == that->get_color_model() &&
            this->get_w() == that->get_w() && this->get_h() == that->get_h() &&
            this->get_bytes_per_line() == that->get_bytes_per_line() )
                return this->copy_from(that);
 
-       timestamp = that->timestamp;
 #if 0
        BC_CModels::transfer(
                this->get_rows(), that->get_rows(),          // Packed data out/in
@@ -1122,7 +1183,6 @@ int VFrame::transfer_from(VFrame *that, int bg_color, int in_x, int in_y, int in
                        that->get_bytes_per_line(),
                bg_color);
 #endif
-       params->copy_from(that->params);
        return 0;
 }
 
@@ -1221,22 +1281,20 @@ void VFrame::copy_stacks(VFrame *src)
 {
        clear_stacks();
 
-       for(int i = 0; i < src->next_effects.total; i++)
-       {
-               char *ptr;
-               next_effects.append(ptr = new char[strlen(src->next_effects.values[i]) + 1]);
-               strcpy(ptr, src->next_effects.values[i]);
-       }
-       for(int i = 0; i < src->prev_effects.total; i++)
-       {
-               char *ptr;
-               prev_effects.append(ptr = new char[strlen(src->prev_effects.values[i]) + 1]);
-               strcpy(ptr, src->prev_effects.values[i]);
-       }
+       for( int i=0; i < src->next_effects.total; ++i )
+               next_effects.append(cstrdup(src->next_effects[i]));
+       for( int i=0; i < src->prev_effects.total; ++i )
+               prev_effects.append(cstrdup(src->prev_effects[i]));
 
        copy_params(src);
 }
 
+int VFrame::copy_vframe(VFrame *frame)
+{
+       copy_stacks(frame);
+       return copy_from(frame);
+}
+
 int VFrame::equal_stacks(VFrame *src)
 {
        for(int i = 0; i < src->next_effects.total && i < next_effects.total; i++)
@@ -1289,7 +1347,7 @@ void VFrame::set_pixel_color(int rgb)
        int ir = 0xff & (pixel_rgb >> 16);
        int ig = 0xff & (pixel_rgb >> 8);
        int ib = 0xff & (pixel_rgb >> 0);
-       bc_rgb2yuv(ir,ig,ib, ir,ig,ib);
+       YUV::yuv.rgb_to_yuv_8(ir, ig, ib);
        pixel_yuv =  (ir<<16) | (ig<<8) | (ib<<0);
 }
 
@@ -1301,7 +1359,6 @@ void VFrame::set_stiple(int mask)
 int VFrame::draw_pixel(int x, int y)
 {
        if( x < 0 || y < 0 || x >= get_w() || y >= get_h() ) return 1;
-       if( draw_point ) return (this->*draw_point)(x, y);
 
 #define DRAW_PIXEL(type, r, g, b) { \
        type **rows = (type**)get_rows(); \
@@ -1630,6 +1687,7 @@ void VFrame::smooth_draw(int x1, int y1, int x2, int y2, int x3, int y3)
        }
 }
 
+
 void VFrame::draw_rect(int x1, int y1, int x2, int y2)
 {
        draw_line(x1, y1, x2, y1);
@@ -1638,6 +1696,52 @@ void VFrame::draw_rect(int x1, int y1, int x2, int y2)
        draw_line(x1, y2 - 1, x1, y1 + 1);
 }
 
+
+void VFrame::draw_oval(int x1, int y1, int x2, int y2)
+{
+       int w = x2 - x1;
+       int h = y2 - y1;
+       int center_x = (x2 + x1) / 2;
+       int center_y = (y2 + y1) / 2;
+       int x_table[h / 2];
+
+//printf("VFrame::draw_oval %d %d %d %d %d\n", __LINE__, x1, y1, x2, y2);
+
+       for(int i = 0; i < h / 2; i++) {
+// A^2 = -(B^2) + C^2
+               x_table[i] = (int)(sqrt(-SQR(h / 2 - i) + SQR(h / 2)) * w / h);
+//printf("VFrame::draw_oval %d i=%d x=%d\n", __LINE__, i, x_table[i]);
+       }
+
+       for(int i = 0; i < h / 2 - 1; i++) {
+               int x3 = x_table[i];
+               int x4 = x_table[i + 1];
+
+               if(x4 > x3 + 1) {
+                       for(int j = x3; j < x4; j++) {
+                               draw_pixel(center_x + j, y1 + i);
+                               draw_pixel(center_x - j, y1 + i);
+                               draw_pixel(center_x + j, y2 - i - 1);
+                               draw_pixel(center_x - j, y2 - i - 1);
+                       }
+               }
+               else {
+                       draw_pixel(center_x + x3, y1 + i);
+                       draw_pixel(center_x - x3, y1 + i);
+                       draw_pixel(center_x + x3, y2 - i - 1);
+                       draw_pixel(center_x - x3, y2 - i - 1);
+               }
+       }
+       
+       draw_pixel(center_x, y1);
+       draw_pixel(center_x, y2 - 1);
+       draw_pixel(x1, center_y);
+       draw_pixel(x2 - 1, center_y);
+       draw_pixel(x1, center_y - 1);
+       draw_pixel(x2 - 1, center_y - 1);
+}
+
+
 void VFrame::draw_arrow(int x1, int y1, int x2, int y2, int sz)
 {
        double angle = atan((float)(y2 - y1) / (float)(x2 - x1));