4 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "bcpbuffer.h"
32 #include "bcresources.h"
33 #include "bcsignals.h"
34 #include "bcsynchronous.h"
35 #include "bctexture.h"
36 #include "bcwindowbase.h"
38 #include "bccmodels.h"
44 static void png_read_function(png_structp png_ptr,
45 png_bytep data, png_size_t length)
47 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
48 if(frame->image_size - frame->image_offset < (long)length)
50 printf("PngReadFunction::png_read_function %d: overrun\n", __LINE__);
51 length = frame->image_size - frame->image_offset;
54 memcpy(data, &frame->image[frame->image_offset], length);
55 frame->image_offset += length;
65 VFrameScene::VFrameScene()
69 VFrameScene::~VFrameScene()
79 //static BCCounter counter;
82 VFrame::VFrame(unsigned char *png_data)
89 VFrame::VFrame(unsigned char *png_data, long image_size)
93 read_png(png_data, image_size);
96 VFrame::VFrame(VFrame &frame)
100 allocate_data(0, -1, 0, 0, 0, frame.w, frame.h,
101 frame.color_model, frame.bytes_per_line);
102 memcpy(data, frame.data, bytes_per_line * h);
106 VFrame::VFrame(int w, int h, int color_model, long bytes_per_line)
109 params = new BC_Hash;
110 allocate_data(data, -1, 0, 0, 0, w, h,
111 color_model, bytes_per_line);
114 VFrame::VFrame(unsigned char *data, int shmid, int w, int h,
115 int color_model, long bytes_per_line)
118 params = new BC_Hash;
119 allocate_data(data, shmid, 0, 0, 0, w, h,
120 color_model, bytes_per_line);
123 VFrame::VFrame(unsigned char *data, int shmid,
124 long y_offset, long u_offset, long v_offset,
125 int w, int h, int color_model, long bytes_per_line)
128 params = new BC_Hash;
129 allocate_data(data, shmid, y_offset, u_offset, v_offset, w, h,
130 color_model, bytes_per_line);
133 VFrame::VFrame(BC_Bitmap *bitmap, int w, int h,
134 int color_model, long bytes_per_line)
137 params = new BC_Hash;
139 unsigned char *data = 0;
140 if( bitmap->is_shared() )
141 shmid = bitmap->get_shmid();
143 data = bitmap->get_data();
144 allocate_data(data, shmid,
145 bitmap->get_y_offset(),
146 bitmap->get_u_offset(),
147 bitmap->get_v_offset(),
148 w, h, color_model, bytes_per_line);
154 params = new BC_Hash;
155 this->color_model = BC_COMPRESSED;
163 // Delete effect stack
164 prev_effects.remove_all_objects();
165 next_effects.remove_all_objects();
170 int VFrame::equivalent(VFrame *src, int test_stacks)
172 return (src->get_color_model() == get_color_model() &&
173 src->get_w() == get_w() &&
174 src->get_h() == get_h() &&
175 src->bytes_per_line == bytes_per_line &&
176 (!test_stacks || equal_stacks(src)));
179 int VFrame::data_matches(VFrame *frame)
181 if(data && frame->get_data() &&
182 frame->params_match(get_w(), get_h(), get_color_model()) &&
183 get_data_size() == frame->get_data_size())
185 int data_size = get_data_size();
186 unsigned char *ptr1 = get_data();
187 unsigned char *ptr2 = frame->get_data();
188 for(int i = 0; i < data_size; i++)
190 if(*ptr1++ != *ptr2++) return 0;
197 // long VFrame::set_shm_offset(long offset)
199 // shm_offset = offset;
203 // long VFrame::get_shm_offset()
205 // return shm_offset;
208 int VFrame::get_memory_type()
213 int VFrame::params_match(int w, int h, int color_model)
215 return (this->w == w &&
217 this->color_model == color_model);
221 int VFrame::reset_parameters(int do_opengl)
226 memory_type = VFrame::PRIVATE;
234 compressed_allocated = 0;
235 compressed_size = 0; // Size of current image
242 sequence_number = -1;
248 // By default, anything is going to be done in RAM
249 opengl_state = VFrame::RAM;
254 prev_effects.set_array_delete();
255 next_effects.set_array_delete();
259 int VFrame::clear_objects(int do_opengl)
274 case VFrame::PRIVATE:
276 // if(this->w * this->h > 1500 * 1100)
277 // printf("VFrame::clear_objects 2 this=%p data=%p\n", this, data);
280 //printf("VFrame::clear_objects %d this=%p shmid=%p data=%p\n", __LINE__, this, shmid, data);
300 // Delete row pointers
323 int VFrame::get_field2_offset()
325 return field2_offset;
328 int VFrame::set_field2_offset(int value)
330 this->field2_offset = value;
334 void VFrame::set_keyframe(int value)
336 this->is_keyframe = value;
339 int VFrame::get_keyframe()
345 VFrameScene* VFrame::get_scene()
350 int VFrame::calculate_bytes_per_pixel(int color_model)
352 return BC_CModels::calculate_pixelsize(color_model);
355 long VFrame::get_bytes_per_line()
357 return bytes_per_line;
360 long VFrame::get_data_size()
362 return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
365 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
367 return BC_CModels::calculate_datasize(w, h, bytes_per_line, color_model);
370 void VFrame::create_row_pointers()
373 switch(color_model) {
375 if( this->v_offset ) break;
378 this->v_offset = sz + w / 4 * h / 4;
383 if( this->v_offset ) break;
386 this->v_offset = sz + sz / 4;
390 if( this->v_offset ) break;
393 this->v_offset = sz + sz / 2;
396 if( this->v_offset ) break;
399 this->v_offset = sz + sz;
402 if( this->v_offset || a ) break;
403 a = this->data + 3 * sz * sizeof(float);
405 if( this->v_offset ) break;
407 this->u_offset = sz * sizeof(float);
408 this->v_offset = 2 * sz * sizeof(float);
412 rows = new unsigned char*[h];
413 for(int i = 0; i < h; i++)
414 rows[i] = &this->data[i * this->bytes_per_line];
417 y = this->data + this->y_offset;
418 u = this->data + this->u_offset;
419 v = this->data + this->v_offset;
422 int VFrame::allocate_data(unsigned char *data, int shmid,
423 long y_offset, long u_offset, long v_offset, int w, int h,
424 int color_model, long bytes_per_line)
428 this->color_model = color_model;
429 this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
430 this->y_offset = this->u_offset = this->v_offset = 0;
432 // printf("VFrame::allocate_data %d shmid == 0\n", __LINE__, shmid);
435 this->bytes_per_line = bytes_per_line >= 0 ?
436 bytes_per_line : this->bytes_per_pixel * w;
438 // Allocate data + padding for MMX
440 //printf("VFrame::allocate_data %d %p\n", __LINE__, this->data);
441 memory_type = VFrame::SHARED;
444 this->y_offset = y_offset;
445 this->u_offset = u_offset;
446 this->v_offset = v_offset;
448 else if(shmid >= 0) {
449 memory_type = VFrame::SHMGET;
450 this->data = (unsigned char*)shmat(shmid, NULL, 0);
451 //printf("VFrame::allocate_data %d shmid=%d data=%p\n", __LINE__, shmid, this->data);
453 this->y_offset = y_offset;
454 this->u_offset = u_offset;
455 this->v_offset = v_offset;
458 memory_type = VFrame::PRIVATE;
459 int size = calculate_data_size(this->w, this->h,
460 this->bytes_per_line, this->color_model);
461 if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm) {
462 this->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
463 if(this->shmid < 0) {
464 printf("VFrame::allocate_data %d could not allocate shared memory\n", __LINE__);
467 this->data = (unsigned char*)shmat(this->shmid, NULL, 0);
468 //printf("VFrame::allocate_data %d %d %d\n", __LINE__, size, this->shmid);
470 //printf("VFrame::allocate_data %d %p\n", __LINE__, this->data);
471 // This causes it to automatically delete when the program exits.
472 shmctl(this->shmid, IPC_RMID, 0);
475 // Have to use malloc for libpng
476 this->data = (unsigned char *)malloc(size);
480 // if(this->w * this->h > 1500 * 1100)
481 // printf("VFrame::allocate_data 2 this=%p w=%d h=%d this->data=%p\n",
482 // this, this->w, this->h, this->data);
485 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
487 //printf("VFrame::allocate_data %d %p data=%p %d %d\n", __LINE__, this, this->data, this->w, this->h);
488 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
491 // Create row pointers
492 create_row_pointers();
496 void VFrame::set_memory(unsigned char *data,
506 memory_type = VFrame::SHARED;
509 this->y_offset = y_offset;
510 this->u_offset = u_offset;
511 this->v_offset = v_offset;
516 memory_type = VFrame::SHMGET;
517 this->data = (unsigned char*)shmat(shmid, NULL, 0);
521 y = this->data + this->y_offset;
522 u = this->data + this->u_offset;
523 v = this->data + this->v_offset;
525 create_row_pointers();
528 void VFrame::set_memory(BC_Bitmap *bitmap)
531 unsigned char *data = 0;
532 if( bitmap->is_shared() )
533 shmid = bitmap->get_shmid();
535 data = bitmap->get_data();
536 set_memory(data, shmid,
537 bitmap->get_y_offset(),
538 bitmap->get_u_offset(),
539 bitmap->get_v_offset());
542 void VFrame::set_compressed_memory(unsigned char *data,
551 memory_type = VFrame::SHARED;
558 memory_type = VFrame::SHMGET;
559 this->data = (unsigned char*)shmat(shmid, NULL, 0);
563 this->compressed_allocated = data_allocated;
564 this->compressed_size = data_size;
568 // Reallocate uncompressed buffer with or without alpha
569 int VFrame::reallocate(
580 // if(shmid == 0) printf("VFrame::reallocate %d shmid=%d\n", __LINE__, shmid);
582 // reset_parameters(0);
595 int VFrame::allocate_compressed_data(long bytes)
597 if(bytes < 1) return 1;
599 // Want to preserve original contents
600 if(data && compressed_allocated < bytes)
603 unsigned char *new_data = 0;
604 if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm)
606 new_shmid = shmget(IPC_PRIVATE,
609 new_data = (unsigned char*)shmat(new_shmid, NULL, 0);
610 shmctl(new_shmid, IPC_RMID, 0);
614 // Have to use malloc for libpng
615 new_data = (unsigned char *)malloc(bytes);
618 bcopy(data, new_data, compressed_allocated);
621 if(memory_type == VFrame::PRIVATE)
631 if(memory_type == VFrame::SHMGET)
639 compressed_allocated = bytes;
644 if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm)
646 shmid = shmget(IPC_PRIVATE,
649 data = (unsigned char*)shmat(shmid, NULL, 0);
650 shmctl(shmid, IPC_RMID, 0);
654 // Have to use malloc for libpng
655 data = (unsigned char *)malloc(bytes);
658 compressed_allocated = bytes;
665 int VFrame::read_png(const unsigned char *data, long img_sz)
667 // Test for RAW format
668 if(data[0] == 'R' && data[1] == 'A' && data[2] == 'W' && data[3] == ' ') {
669 int new_color_model = BC_RGBA8888;
670 w = data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24);
671 h = data[8] | (data[9] << 8) | (data[10] << 16) | (data[11] << 24);
672 int components = data[12];
673 new_color_model = components == 3 ? BC_RGB888 : BC_RGBA8888;
674 // This shares the data directly
675 // reallocate(data + 20, 0, 0, 0, w, h, new_color_model, -1);
677 // Can't use shared data for theme since button constructions overlay the
679 reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);
680 memcpy(get_data(), data + 16, w * h * components);
683 else if(data[0] == 0x89 && data[1] == 'P' && data[2] == 'N' && data[3] == 'G') {
685 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
686 png_infop info_ptr = png_create_info_struct(png_ptr);
690 image = data; image_size = img_sz;
691 png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
692 png_read_info(png_ptr, info_ptr);
694 w = png_get_image_width(png_ptr, info_ptr);
695 h = png_get_image_height(png_ptr, info_ptr);
697 int src_color_model = png_get_color_type(png_ptr, info_ptr);
699 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
700 png_set_strip_16(png_ptr);
702 /* extract multiple pixels with bit depths of 1, 2, and 4 from a single
703 * byte into separate bytes (useful for paletted and grayscale images).
705 png_set_packing(png_ptr);
707 /* expand paletted colors into true RGB triplets */
708 if (src_color_model == PNG_COLOR_TYPE_PALETTE)
709 png_set_expand(png_ptr);
711 /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
712 if (src_color_model == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8)
713 png_set_expand(png_ptr);
715 if (src_color_model == PNG_COLOR_TYPE_GRAY ||
716 src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
717 png_set_gray_to_rgb(png_ptr);
719 /* expand paletted or RGB images with transparency to full alpha channels
720 * so the data will be available as RGBA quartets */
721 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)){
723 png_set_expand(png_ptr);
726 switch(src_color_model)
728 case PNG_COLOR_TYPE_GRAY:
729 case PNG_COLOR_TYPE_RGB:
730 new_color_model = BC_RGB888;
733 case PNG_COLOR_TYPE_GRAY_ALPHA:
734 case PNG_COLOR_TYPE_RGB_ALPHA:
736 new_color_model = BC_RGBA8888;
739 case PNG_COLOR_TYPE_PALETTE:
741 new_color_model = BC_RGBA8888;
743 new_color_model = BC_RGB888;
746 reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);
748 //printf("VFrame::read_png %d %d %d %p\n", __LINE__, w, h, get_rows());
749 png_read_image(png_ptr, get_rows());
750 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
753 printf("VFrame::read_png %d: unknown file format"
754 " 0x%02x 0x%02x 0x%02x 0x%02x\n",
755 __LINE__, data[4], data[5], data[6], data[7]);
760 int VFrame::read_png(const unsigned char *data)
763 ((long)data[0] << 24) | ((long)data[1] << 16) |
764 ((long)data[2] << 8) | (long)data[3];
765 return read_png(data+4, img_sz);
768 int VFrame::write_png(const char *path)
770 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
771 png_infop info_ptr = png_create_info_struct(png_ptr);
772 FILE *out_fd = fopen(path, "w");
775 printf("VFrame::write_png %d %s %s\n", __LINE__, path, strerror(errno));
779 int png_cmodel = PNG_COLOR_TYPE_RGB;
780 switch(get_color_model())
784 png_cmodel = PNG_COLOR_TYPE_RGB;
788 png_cmodel = PNG_COLOR_TYPE_GRAY;
792 png_init_io(png_ptr, out_fd);
793 png_set_compression_level(png_ptr, 9);
794 png_set_IHDR(png_ptr,
801 PNG_COMPRESSION_TYPE_DEFAULT,
802 PNG_FILTER_TYPE_DEFAULT);
803 png_write_info(png_ptr, info_ptr);
804 png_write_image(png_ptr, get_rows());
805 png_write_end(png_ptr, info_ptr);
806 png_destroy_write_struct(&png_ptr, &info_ptr);
812 #define ZERO_YUV(components, type, max) \
814 for(int i = 0; i < h; i++) \
816 type *row = (type*)get_rows()[i]; \
817 for(int j = 0; j < w; j++) \
819 row[j * components] = 0; \
820 row[j * components + 1] = (max + 1) / 2; \
821 row[j * components + 2] = (max + 1) / 2; \
822 if(components == 4) row[j * components + 3] = 0; \
827 int VFrame::clear_frame()
830 //printf("VFrame::clear_frame %d\n", __LINE__);
831 switch(color_model) {
837 bzero(get_u(), w / 4 * h / 4);
838 bzero(get_v(), w / 4 * h / 4);
844 bzero(get_u(), sz / 4);
845 bzero(get_v(), sz / 4);
850 bzero(get_u(), sz / 2);
851 bzero(get_v(), sz / 2);
854 case BC_RGBA_FLOATP: if( a ) {
855 float *ap = (float *)a;
856 for( int i=sz; --i>=0; ++ap ) *ap = 1.f; }
857 case BC_RGB_FLOATP: {
858 float *rp = (float *)y;
859 for( int i=sz; --i>=0; ++rp ) *rp = 0.f;
860 float *gp = (float *)u;
861 for( int i=sz; --i>=0; ++gp ) *gp = 0.f;
862 float *bp = (float *)v;
863 for( int i=sz; --i>=0; ++bp ) *bp = 0.f;
872 ZERO_YUV(3, unsigned char, 0xff);
876 ZERO_YUV(4, unsigned char, 0xff);
880 ZERO_YUV(3, uint16_t, 0xffff);
883 case BC_YUVA16161616:
884 ZERO_YUV(4, uint16_t, 0xffff);
888 bzero(data, calculate_data_size(w, h, bytes_per_line, color_model));
894 void VFrame::rotate90()
896 // Allocate new frame
897 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
898 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
899 unsigned char **new_rows = new unsigned char*[new_h];
900 for(int i = 0; i < new_h; i++)
901 new_rows[i] = &new_data[new_bytes_per_line * i];
904 for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
906 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
908 for(int k = 0; k < bytes_per_pixel; k++)
910 new_rows[out_y][out_x * bytes_per_pixel + k] =
911 rows[in_y][in_x * bytes_per_pixel + k];
920 bytes_per_line = new_bytes_per_line;
925 void VFrame::rotate270()
927 // Allocate new frame
928 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
929 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
930 unsigned char **new_rows = new unsigned char*[new_h];
931 for(int i = 0; i < new_h; i++)
932 new_rows[i] = &new_data[new_bytes_per_line * i];
935 for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
937 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
939 for(int k = 0; k < bytes_per_pixel; k++)
941 new_rows[out_y][out_x * bytes_per_pixel + k] =
942 rows[in_y][in_x * bytes_per_pixel + k];
951 bytes_per_line = new_bytes_per_line;
956 void VFrame::flip_vert()
958 unsigned char *temp = new unsigned char[bytes_per_line];
959 for(int i = 0, j = h - 1; i < j; i++, j--)
961 memcpy(temp, rows[j], bytes_per_line);
962 memcpy(rows[j], rows[i], bytes_per_line);
963 memcpy(rows[i], temp, bytes_per_line);
968 void VFrame::flip_horiz()
970 unsigned char temp[32];
971 for(int i = 0; i < h; i++)
973 unsigned char *row = rows[i];
974 for(int j = 0; j < bytes_per_line / 2; j += bytes_per_pixel)
976 memcpy(temp, row + j, bytes_per_pixel);
977 memcpy(row + j, row + bytes_per_line - j - bytes_per_pixel, bytes_per_pixel);
978 memcpy(row + bytes_per_line - j - bytes_per_pixel, temp, bytes_per_pixel);
985 int VFrame::copy_from(VFrame *frame)
987 int w = MIN(this->w, frame->get_w());
988 int h = MIN(this->h, frame->get_h());
989 timestamp = frame->timestamp;
991 switch(frame->color_model)
994 allocate_compressed_data(frame->compressed_size);
995 memcpy(data, frame->data, frame->compressed_size);
996 this->compressed_size = frame->compressed_size;
1000 memcpy(get_y(), frame->get_y(), w * h);
1001 memcpy(get_u(), frame->get_u(), w / 4 * h / 4);
1002 memcpy(get_v(), frame->get_v(), w / 4 * h / 4);
1007 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
1008 memcpy(get_y(), frame->get_y(), w * h);
1009 memcpy(get_u(), frame->get_u(), w * h / 4);
1010 memcpy(get_v(), frame->get_v(), w * h / 4);
1014 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
1015 memcpy(get_y(), frame->get_y(), w * h);
1016 memcpy(get_u(), frame->get_u(), w * h / 2);
1017 memcpy(get_v(), frame->get_v(), w * h / 2);
1021 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
1022 memcpy(get_y(), frame->get_y(), w * h);
1023 memcpy(get_u(), frame->get_u(), w * h);
1024 memcpy(get_v(), frame->get_v(), w * h);
1027 // printf("VFrame::copy_from %d\n", calculate_data_size(w,
1030 // frame->color_model));
1031 // Copy without extra 4 bytes in case the source is a hardware device
1032 memmove(data, frame->data, get_data_size());
1039 int VFrame::transfer_from(VFrame *that, int bg_color)
1041 if( this->get_color_model() == that->get_color_model() &&
1042 this->get_w() == that->get_w() && this->get_h() == that->get_h() )
1043 return this->copy_from(that);
1045 timestamp = that->timestamp;
1047 BC_CModels::transfer(
1048 this->get_rows(), that->get_rows(), // Packed data out/in
1049 this->get_y(), this->get_u(), this->get_v(), // Planar data out/in
1050 that->get_y(), that->get_u(), that->get_v(),
1051 0, 0, that->get_w(), that->get_h(), // Dimensions in/out
1052 0, 0, this->get_w(), this->get_h(),
1053 that->get_color_model(), this->get_color_model(), // Color models in/out
1054 bg_color, // alpha blend bg_color
1055 that->get_w(), this->get_w()); // rowspans (of luma for YUV)
1057 unsigned char *in_ptrs[4], *out_ptrs[4];
1058 unsigned char **inp, **outp;
1059 if( BC_CModels::is_planar(that->get_color_model()) ) {
1060 in_ptrs[0] = that->get_y();
1061 in_ptrs[1] = that->get_u();
1062 in_ptrs[2] = that->get_v();
1063 in_ptrs[3] = that->get_a();
1067 inp = that->get_rows();
1068 if( BC_CModels::is_planar(this->get_color_model()) ) {
1069 out_ptrs[0] = this->get_y();
1070 out_ptrs[1] = this->get_u();
1071 out_ptrs[2] = this->get_v();
1072 out_ptrs[3] = this->get_a();
1076 outp = this->get_rows();
1077 BC_CModels::transfer(outp, this->get_color_model(),
1078 0, 0, this->get_w(), this->get_h(), this->get_w(),
1079 inp, that->get_color_model(),
1080 0, 0, that->get_w(), that->get_h(), that->get_w(),
1091 #define OVERLAY(type, max, components) \
1093 type **in_rows = (type**)src->get_rows(); \
1094 type **out_rows = (type**)get_rows(); \
1095 int in_w = src->get_w(); \
1096 int in_h = src->get_h(); \
1098 for(int i = 0; i < in_h; i++) \
1100 if(i + out_y1 >= 0 && i + out_y1 < h) \
1102 type *src_row = in_rows[i]; \
1103 type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
1105 for(int j = 0; j < in_w; j++) \
1107 if(j + out_x1 >= 0 && j + out_x1 < w) \
1109 int opacity = src_row[3]; \
1110 int transparency = dst_row[3] * (max - src_row[3]) / max; \
1111 dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
1112 dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
1113 dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
1114 dst_row[3] = MAX(dst_row[3], src_row[3]); \
1117 dst_row += components; \
1118 src_row += components; \
1125 void VFrame::overlay(VFrame *src,
1129 switch(get_color_model())
1132 OVERLAY(unsigned char, 0xff, 4);
1139 int VFrame::get_scale_tables(int *column_table, int *row_table,
1140 int in_x1, int in_y1, int in_x2, int in_y2,
1141 int out_x1, int out_y1, int out_x2, int out_y2)
1144 float w_in = in_x2 - in_x1;
1145 float h_in = in_y2 - in_y1;
1146 int w_out = out_x2 - out_x1;
1147 int h_out = out_y2 - out_y1;
1149 float hscale = w_in / w_out;
1150 float vscale = h_in / h_out;
1152 for(i = 0; i < w_out; i++)
1154 column_table[i] = (int)(hscale * i);
1157 for(i = 0; i < h_out; i++)
1159 row_table[i] = (int)(vscale * i) + in_y1;
1164 void VFrame::push_prev_effect(const char *name)
1167 prev_effects.append(ptr = new char[strlen(name) + 1]);
1169 if(prev_effects.total > MAX_STACK_ELEMENTS) prev_effects.remove_object(0);
1172 void VFrame::pop_prev_effect()
1174 if(prev_effects.total)
1175 prev_effects.remove_object(prev_effects.last());
1178 void VFrame::push_next_effect(const char *name)
1181 next_effects.append(ptr = new char[strlen(name) + 1]);
1183 if(next_effects.total > MAX_STACK_ELEMENTS) next_effects.remove_object(0);
1186 void VFrame::pop_next_effect()
1188 if(next_effects.total)
1189 next_effects.remove_object(next_effects.last());
1192 const char* VFrame::get_next_effect(int number)
1194 if(!next_effects.total) return "";
1196 if(number > next_effects.total - 1) number = next_effects.total - 1;
1198 return next_effects.values[next_effects.total - number - 1];
1201 const char* VFrame::get_prev_effect(int number)
1203 if(!prev_effects.total) return "";
1205 if(number > prev_effects.total - 1) number = prev_effects.total - 1;
1207 return prev_effects.values[prev_effects.total - number - 1];
1210 BC_Hash* VFrame::get_params()
1215 void VFrame::clear_stacks()
1217 next_effects.remove_all_objects();
1218 prev_effects.remove_all_objects();
1223 void VFrame::copy_params(VFrame *src)
1225 status = src->status;
1226 params->copy_from(src->params);
1229 void VFrame::copy_stacks(VFrame *src)
1233 for(int i = 0; i < src->next_effects.total; i++)
1236 next_effects.append(ptr = new char[strlen(src->next_effects.values[i]) + 1]);
1237 strcpy(ptr, src->next_effects.values[i]);
1239 for(int i = 0; i < src->prev_effects.total; i++)
1242 prev_effects.append(ptr = new char[strlen(src->prev_effects.values[i]) + 1]);
1243 strcpy(ptr, src->prev_effects.values[i]);
1249 int VFrame::equal_stacks(VFrame *src)
1251 for(int i = 0; i < src->next_effects.total && i < next_effects.total; i++)
1253 if(strcmp(src->next_effects.values[i], next_effects.values[i])) return 0;
1256 for(int i = 0; i < src->prev_effects.total && i < prev_effects.total; i++)
1258 if(strcmp(src->prev_effects.values[i], prev_effects.values[i])) return 0;
1261 if(!params->equivalent(src->params)) return 0;
1265 void VFrame::dump_stacks()
1267 printf("VFrame::dump_stacks\n");
1268 printf(" next_effects:\n");
1269 for(int i = next_effects.total - 1; i >= 0; i--)
1270 printf(" %s\n", next_effects.values[i]);
1271 printf(" prev_effects:\n");
1272 for(int i = prev_effects.total - 1; i >= 0; i--)
1273 printf(" %s\n", prev_effects.values[i]);
1276 void VFrame::dump_params()
1283 printf("VFrame::dump %d this=%p\n", __LINE__, this);
1284 printf(" w=%d h=%d colormodel=%d rows=%p use_shm=%d shmid=%d\n",
1285 w, h, color_model, rows, use_shm, shmid);
1288 int VFrame::filefork_size()
1290 return sizeof(int) * 13 + sizeof(long);
1294 void VFrame::to_filefork(unsigned char *buffer)
1296 *(int*)(buffer + 0) = shmid;
1297 *(int*)(buffer + 4) = y_offset;
1298 *(int*)(buffer + 8) = u_offset;
1299 *(int*)(buffer + 12) = v_offset;
1300 *(int*)(buffer + 16) = w;
1301 *(int*)(buffer + 20) = h;
1302 *(int*)(buffer + 24) = color_model;
1303 *(int*)(buffer + 28) = bytes_per_line;
1304 *(int*)(buffer + 32) = compressed_allocated;
1305 *(int*)(buffer + 36) = compressed_size;
1306 *(int*)(buffer + 40) = is_keyframe;
1307 *(int*)(buffer + 44) = status;
1308 *(long*)(buffer + 48) = sequence_number;
1311 //printf("VFrame::to_filefork %d %lld\n", __LINE__, sequence_number);
1312 // printf("VFrame::to_filefork %d", __LINE__);
1313 // for(int i = 0; i < 40; i++)
1315 // printf(" %02x", buffer[i]);
1322 void VFrame::from_filefork(unsigned char *buffer)
1324 // This frame will always be preallocated shared memory
1325 //printf("VFrame::from_filefork %d %d\n", __LINE__, *(int*)(buffer + 24));
1326 if(*(int*)(buffer + 24) == BC_COMPRESSED)
1328 set_compressed_memory(0,
1329 *(int*)(buffer + 0), // shmid
1330 *(int*)(buffer + 36), // compressed_size
1331 *(int*)(buffer + 32)); // compressed_allocated
1332 color_model = BC_COMPRESSED;
1333 //printf("VFrame::from_filefork %d %d\n", __LINE__, get_compressed_size());
1338 // printf("VFrame::from_filefork %d", __LINE__);
1339 // for(int i = 0; i < 40; i++)
1341 // printf(" %02x", buffer[i]);
1345 *(int*)(buffer + 0), // shmid
1346 *(int*)(buffer + 4), // y_offset
1347 *(int*)(buffer + 8), // u_offset
1348 *(int*)(buffer + 12), // v_offset
1349 *(int*)(buffer + 16), // w
1350 *(int*)(buffer + 20), // h
1351 *(int*)(buffer + 24), // colormodel
1352 *(int*)(buffer + 28)); // bytes per line
1356 is_keyframe = *(int*)(buffer + 40);
1357 status = *(int*)(buffer + 44);
1358 sequence_number = *(long*)(buffer + 48);
1359 //printf("VFrame::from_filefork %d %lld\n", __LINE__, sequence_number);
1362 int VFrame::get_memory_usage()
1364 if(get_compressed_allocated()) return get_compressed_allocated();
1365 return get_h() * get_bytes_per_line();