00001 #include <png.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <stdint.h>
00005
00006 #include "bchash.h"
00007 #include "bcpbuffer.h"
00008 #include "bcsignals.h"
00009 #include "bcsynchronous.h"
00010 #include "bctexture.h"
00011 #include "bcwindowbase.h"
00012 #include "clip.h"
00013 #include "colormodels.h"
00014 #include "vframe.h"
00015
00016 class PngReadFunction
00017 {
00018 public:
00019 static void png_read_function(png_structp png_ptr,
00020 png_bytep data,
00021 png_size_t length)
00022 {
00023 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
00024 if(frame->image_size - frame->image_offset < length)
00025 length = frame->image_size - frame->image_offset;
00026
00027 memcpy(data, &frame->image[frame->image_offset], length);
00028 frame->image_offset += length;
00029 };
00030 };
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 VFrame::VFrame(unsigned char *png_data)
00042 {
00043 reset_parameters(1);
00044 params = new BC_Hash;
00045 read_png(png_data);
00046 }
00047
00048 VFrame::VFrame(VFrame &frame)
00049 {
00050 reset_parameters(1);
00051 params = new BC_Hash;
00052 allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
00053 memcpy(data, frame.data, bytes_per_line * h);
00054 copy_stacks(&frame);
00055 }
00056
00057 VFrame::VFrame(unsigned char *data,
00058 int w,
00059 int h,
00060 int color_model,
00061 long bytes_per_line)
00062 {
00063 reset_parameters(1);
00064 params = new BC_Hash;
00065 allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
00066 }
00067
00068 VFrame::VFrame(unsigned char *data,
00069 long y_offset,
00070 long u_offset,
00071 long v_offset,
00072 int w,
00073 int h,
00074 int color_model,
00075 long bytes_per_line)
00076 {
00077 reset_parameters(1);
00078 params = new BC_Hash;
00079 allocate_data(data,
00080 y_offset,
00081 u_offset,
00082 v_offset,
00083 w,
00084 h,
00085 color_model,
00086 bytes_per_line);
00087 }
00088
00089 VFrame::VFrame()
00090 {
00091 reset_parameters(1);
00092 params = new BC_Hash;
00093 this->color_model = BC_COMPRESSED;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 VFrame::~VFrame()
00107 {
00108 clear_objects(1);
00109
00110 prev_effects.remove_all_objects();
00111 next_effects.remove_all_objects();
00112 delete params;
00113 }
00114
00115 int VFrame::equivalent(VFrame *src, int test_stacks)
00116 {
00117 return (src->get_color_model() == get_color_model() &&
00118 src->get_w() == get_w() &&
00119 src->get_h() == get_h() &&
00120 src->bytes_per_line == bytes_per_line &&
00121 (!test_stacks || equal_stacks(src)));
00122 }
00123
00124 long VFrame::set_shm_offset(long offset)
00125 {
00126 shm_offset = offset;
00127 return 0;
00128 }
00129
00130 long VFrame::get_shm_offset()
00131 {
00132 return shm_offset;
00133 }
00134
00135 int VFrame::get_shared()
00136 {
00137 return shared;
00138 }
00139
00140 int VFrame::params_match(int w, int h, int color_model)
00141 {
00142 return (this->w == w &&
00143 this->h == h &&
00144 this->color_model == color_model);
00145 }
00146
00147
00148 int VFrame::reset_parameters(int do_opengl)
00149 {
00150 field2_offset = -1;
00151 shared = 0;
00152 shm_offset = 0;
00153 bytes_per_line = 0;
00154 data = 0;
00155 rows = 0;
00156 color_model = 0;
00157 compressed_allocated = 0;
00158 compressed_size = 0;
00159 w = 0;
00160 h = 0;
00161 y = u = v = 0;
00162 y_offset = 0;
00163 u_offset = 0;
00164 v_offset = 0;
00165 sequence_number = -1;
00166 is_keyframe = 0;
00167
00168 if(do_opengl)
00169 {
00170
00171 opengl_state = VFrame::RAM;
00172 pbuffer = 0;
00173 texture = 0;
00174 }
00175
00176 prev_effects.set_array_delete();
00177 next_effects.set_array_delete();
00178 return 0;
00179 }
00180
00181 int VFrame::clear_objects(int do_opengl)
00182 {
00183
00184 if(do_opengl)
00185 {
00186 delete texture;
00187 texture = 0;
00188
00189 delete pbuffer;
00190 pbuffer = 0;
00191 }
00192
00193
00194 if(!shared)
00195 {
00196
00197
00198
00199
00200 UNBUFFER(data);
00201 if(data) delete [] data;
00202 data = 0;
00203 }
00204
00205
00206 switch(color_model)
00207 {
00208 case BC_COMPRESSED:
00209 case BC_YUV420P:
00210 break;
00211
00212 default:
00213 delete [] rows;
00214 break;
00215 }
00216
00217
00218 return 0;
00219 }
00220
00221 int VFrame::get_field2_offset()
00222 {
00223 return field2_offset;
00224 }
00225
00226 int VFrame::set_field2_offset(int value)
00227 {
00228 this->field2_offset = value;
00229 return 0;
00230 }
00231
00232 void VFrame::set_keyframe(int value)
00233 {
00234 this->is_keyframe = value;
00235 }
00236
00237 int VFrame::get_keyframe()
00238 {
00239 return is_keyframe;
00240 }
00241
00242
00243 int VFrame::calculate_bytes_per_pixel(int color_model)
00244 {
00245 return cmodel_calculate_pixelsize(color_model);
00246 }
00247
00248 long VFrame::get_bytes_per_line()
00249 {
00250 return bytes_per_line;
00251 }
00252
00253 long VFrame::get_data_size()
00254 {
00255 return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
00256
00257 }
00258
00259 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
00260 {
00261 return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
00262 return 0;
00263 }
00264
00265 void VFrame::create_row_pointers()
00266 {
00267 switch(color_model)
00268 {
00269 case BC_YUV420P:
00270 case BC_YUV411P:
00271 if(!this->v_offset)
00272 {
00273 this->y_offset = 0;
00274 this->u_offset = w * h;
00275 this->v_offset = w * h + w * h / 4;
00276 }
00277 y = this->data + this->y_offset;
00278 u = this->data + this->u_offset;
00279 v = this->data + this->v_offset;
00280 break;
00281
00282 case BC_YUV422P:
00283 if(!this->v_offset)
00284 {
00285 this->y_offset = 0;
00286 this->u_offset = w * h;
00287 this->v_offset = w * h + w * h / 2;
00288 }
00289 y = this->data + this->y_offset;
00290 u = this->data + this->u_offset;
00291 v = this->data + this->v_offset;
00292 break;
00293
00294 default:
00295 rows = new unsigned char*[h];
00296 for(int i = 0; i < h; i++)
00297 {
00298 rows[i] = &this->data[i * this->bytes_per_line];
00299 }
00300 break;
00301 }
00302 }
00303
00304 int VFrame::allocate_data(unsigned char *data,
00305 long y_offset,
00306 long u_offset,
00307 long v_offset,
00308 int w,
00309 int h,
00310 int color_model,
00311 long bytes_per_line)
00312 {
00313 this->w = w;
00314 this->h = h;
00315 this->color_model = color_model;
00316 this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
00317 this->y_offset = this->u_offset = this->v_offset = 0;
00318
00319 if(bytes_per_line >= 0)
00320 {
00321 this->bytes_per_line = bytes_per_line;
00322 }
00323 else
00324 this->bytes_per_line = this->bytes_per_pixel * w;
00325
00326
00327 if(data)
00328 {
00329 shared = 1;
00330 this->data = data;
00331 this->y_offset = y_offset;
00332 this->u_offset = u_offset;
00333 this->v_offset = v_offset;
00334 }
00335 else
00336 {
00337 shared = 0;
00338 int size = calculate_data_size(this->w,
00339 this->h,
00340 this->bytes_per_line,
00341 this->color_model);
00342 this->data = new unsigned char[size];
00343
00344
00345
00346
00347
00348 if(!this->data)
00349 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
00350
00351
00352
00353 }
00354
00355
00356 create_row_pointers();
00357 return 0;
00358 }
00359
00360 void VFrame::set_memory(unsigned char *data,
00361 long y_offset,
00362 long u_offset,
00363 long v_offset)
00364 {
00365 shared = 1;
00366 this->data = data;
00367 this->y_offset = y_offset;
00368 this->u_offset = u_offset;
00369 this->v_offset = v_offset;
00370 y = this->data + this->y_offset;
00371 u = this->data + this->u_offset;
00372 v = this->data + this->v_offset;
00373 create_row_pointers();
00374 }
00375
00376 void VFrame::set_compressed_memory(unsigned char *data,
00377 int data_size,
00378 int data_allocated)
00379 {
00380 clear_objects(0);
00381 shared = 1;
00382 this->data = data;
00383 this->compressed_allocated = data_allocated;
00384 this->compressed_size = data_size;
00385 }
00386
00387
00388
00389 int VFrame::reallocate(unsigned char *data,
00390 long y_offset,
00391 long u_offset,
00392 long v_offset,
00393 int w,
00394 int h,
00395 int color_model,
00396 long bytes_per_line)
00397 {
00398 clear_objects(0);
00399 reset_parameters(0);
00400 allocate_data(data,
00401 y_offset,
00402 u_offset,
00403 v_offset,
00404 w,
00405 h,
00406 color_model,
00407 bytes_per_line);
00408 return 0;
00409 }
00410
00411 int VFrame::allocate_compressed_data(long bytes)
00412 {
00413 if(bytes < 1) return 1;
00414
00415
00416 if(data && compressed_allocated < bytes)
00417 {
00418 unsigned char *new_data = new unsigned char[bytes];
00419 bcopy(data, new_data, compressed_allocated);
00420 UNBUFFER(data);
00421 delete [] data;
00422 data = new_data;
00423 compressed_allocated = bytes;
00424 }
00425 else
00426 if(!data)
00427 {
00428 data = new unsigned char[bytes];
00429 compressed_allocated = bytes;
00430 compressed_size = 0;
00431 }
00432
00433 return 0;
00434 }
00435
00436 int VFrame::read_png(unsigned char *data)
00437 {
00438 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00439 png_infop info_ptr = png_create_info_struct(png_ptr);
00440 int new_color_model;
00441
00442 image_offset = 0;
00443 image = data + 4;
00444 image_size = (((unsigned long)data[0]) << 24) |
00445 (((unsigned long)data[1]) << 16) |
00446 (((unsigned long)data[2]) << 8) |
00447 (unsigned char)data[3];
00448 png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
00449 png_read_info(png_ptr, info_ptr);
00450
00451 w = png_get_image_width(png_ptr, info_ptr);
00452 h = png_get_image_height(png_ptr, info_ptr);
00453
00454 int src_color_model = png_get_color_type(png_ptr, info_ptr);
00455 switch(src_color_model)
00456 {
00457 case PNG_COLOR_TYPE_RGB:
00458 new_color_model = BC_RGB888;
00459 break;
00460
00461
00462 case PNG_COLOR_TYPE_GRAY_ALPHA:
00463 case PNG_COLOR_TYPE_RGB_ALPHA:
00464 default:
00465 new_color_model = BC_RGBA8888;
00466 break;
00467 }
00468
00469 reallocate(NULL,
00470 0,
00471 0,
00472 0,
00473 w,
00474 h,
00475 new_color_model,
00476 -1);
00477
00478 png_read_image(png_ptr, get_rows());
00479
00480
00481
00482 if(src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
00483 {
00484 for(int i = 0; i < get_h(); i++)
00485 {
00486 unsigned char *row = get_rows()[i];
00487 unsigned char *out_ptr = row + get_w() * 4 - 4;
00488 unsigned char *in_ptr = row + get_w() * 2 - 2;
00489
00490 for(int j = get_w() - 1; j >= 0; j--)
00491 {
00492 out_ptr[0] = in_ptr[0];
00493 out_ptr[1] = in_ptr[0];
00494 out_ptr[2] = in_ptr[0];
00495 out_ptr[3] = in_ptr[1];
00496 out_ptr -= 4;
00497 in_ptr -= 2;
00498 }
00499 }
00500 }
00501
00502 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
00503 return 0;
00504 }
00505
00506 unsigned char* VFrame::get_data()
00507 {
00508 return data;
00509 }
00510
00511 long VFrame::get_compressed_allocated()
00512 {
00513 return compressed_allocated;
00514 }
00515
00516 long VFrame::get_compressed_size()
00517 {
00518 return compressed_size;
00519 }
00520
00521 long VFrame::set_compressed_size(long size)
00522 {
00523 compressed_size = size;
00524 return 0;
00525 }
00526
00527 int VFrame::get_color_model()
00528 {
00529 return color_model;
00530 }
00531
00532
00533 int VFrame::equals(VFrame *frame)
00534 {
00535 if(frame->data == data)
00536 return 1;
00537 else
00538 return 0;
00539 }
00540
00541 #define ZERO_YUV(components, type, max) \
00542 { \
00543 for(int i = 0; i < h; i++) \
00544 { \
00545 type *row = (type*)get_rows()[i]; \
00546 for(int j = 0; j < w; j++) \
00547 { \
00548 row[j * components] = 0; \
00549 row[j * components + 1] = (max + 1) / 2; \
00550 row[j * components + 2] = (max + 1) / 2; \
00551 if(components == 4) row[j * components + 3] = 0; \
00552 } \
00553 } \
00554 }
00555
00556 int VFrame::clear_frame()
00557 {
00558 switch(color_model)
00559 {
00560 case BC_COMPRESSED:
00561 break;
00562
00563 case BC_YUV420P:
00564 bzero(data, h * w * 2);
00565 break;
00566
00567 case BC_YUV888:
00568 ZERO_YUV(3, unsigned char, 0xff);
00569 break;
00570
00571 case BC_YUVA8888:
00572 ZERO_YUV(4, unsigned char, 0xff);
00573 break;
00574
00575 case BC_YUV161616:
00576 ZERO_YUV(3, uint16_t, 0xffff);
00577 break;
00578
00579 case BC_YUVA16161616:
00580 ZERO_YUV(4, uint16_t, 0xffff);
00581 break;
00582
00583 default:
00584 bzero(data, h * bytes_per_line);
00585 break;
00586 }
00587 return 0;
00588 }
00589
00590 void VFrame::rotate90()
00591 {
00592
00593 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
00594 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
00595 unsigned char **new_rows = new unsigned char*[new_h];
00596 for(int i = 0; i < new_h; i++)
00597 new_rows[i] = &new_data[new_bytes_per_line * i];
00598
00599
00600 for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
00601 {
00602 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
00603 {
00604 for(int k = 0; k < bytes_per_pixel; k++)
00605 {
00606 new_rows[out_y][out_x * bytes_per_pixel + k] =
00607 rows[in_y][in_x * bytes_per_pixel + k];
00608 }
00609 }
00610 }
00611
00612
00613 clear_objects(0);
00614 data = new_data;
00615 rows = new_rows;
00616 bytes_per_line = new_bytes_per_line;
00617 w = new_w;
00618 h = new_h;
00619 }
00620
00621 void VFrame::rotate270()
00622 {
00623
00624 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
00625 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
00626 unsigned char **new_rows = new unsigned char*[new_h];
00627 for(int i = 0; i < new_h; i++)
00628 new_rows[i] = &new_data[new_bytes_per_line * i];
00629
00630
00631 for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
00632 {
00633 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
00634 {
00635 for(int k = 0; k < bytes_per_pixel; k++)
00636 {
00637 new_rows[out_y][out_x * bytes_per_pixel + k] =
00638 rows[in_y][in_x * bytes_per_pixel + k];
00639 }
00640 }
00641 }
00642
00643
00644 clear_objects(0);
00645 data = new_data;
00646 rows = new_rows;
00647 bytes_per_line = new_bytes_per_line;
00648 w = new_w;
00649 h = new_h;
00650 }
00651
00652 void VFrame::flip_vert()
00653 {
00654 unsigned char *temp = new unsigned char[bytes_per_line];
00655 for(int i = 0, j = h - 1; i < j; i++, j--)
00656 {
00657 memcpy(temp, rows[j], bytes_per_line);
00658 memcpy(rows[j], rows[i], bytes_per_line);
00659 memcpy(rows[i], temp, bytes_per_line);
00660 }
00661 delete [] temp;
00662 }
00663
00664
00665
00666 int VFrame::copy_from(VFrame *frame)
00667 {
00668 int w = MIN(this->w, frame->get_w());
00669 int h = MIN(this->h, frame->get_h());
00670
00671
00672 switch(frame->color_model)
00673 {
00674 case BC_COMPRESSED:
00675 allocate_compressed_data(frame->compressed_size);
00676 memcpy(data, frame->data, frame->compressed_size);
00677 this->compressed_size = frame->compressed_size;
00678 break;
00679
00680 case BC_YUV420P:
00681
00682 memcpy(get_y(), frame->get_y(), w * h);
00683 memcpy(get_u(), frame->get_u(), w * h / 4);
00684 memcpy(get_v(), frame->get_v(), w * h / 4);
00685 break;
00686
00687 case BC_YUV422P:
00688
00689 memcpy(get_y(), frame->get_y(), w * h);
00690 memcpy(get_u(), frame->get_u(), w * h / 2);
00691 memcpy(get_v(), frame->get_v(), w * h / 2);
00692 break;
00693
00694 default:
00695
00696
00697
00698
00699 memcpy(data, frame->data, calculate_data_size(w,
00700 h,
00701 -1,
00702 frame->color_model));
00703 break;
00704 }
00705
00706 return 0;
00707 }
00708
00709
00710 #define OVERLAY(type, max, components) \
00711 { \
00712 type **in_rows = (type**)src->get_rows(); \
00713 type **out_rows = (type**)get_rows(); \
00714 int in_w = src->get_w(); \
00715 int in_h = src->get_h(); \
00716 \
00717 for(int i = 0; i < in_h; i++) \
00718 { \
00719 if(i + out_y1 >= 0 && i + out_y1 < h) \
00720 { \
00721 type *src_row = in_rows[i]; \
00722 type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
00723 \
00724 for(int j = 0; j < in_w; j++) \
00725 { \
00726 if(j + out_x1 >= 0 && j + out_x1 < w) \
00727 { \
00728 int opacity = src_row[3]; \
00729 int transparency = max - src_row[3]; \
00730 dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
00731 dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
00732 dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
00733 dst_row[3] = MAX(dst_row[3], src_row[3]); \
00734 } \
00735 \
00736 dst_row += components; \
00737 src_row += components; \
00738 } \
00739 } \
00740 } \
00741 }
00742
00743
00744 void VFrame::overlay(VFrame *src,
00745 int out_x1,
00746 int out_y1)
00747 {
00748 switch(get_color_model())
00749 {
00750 case BC_RGBA8888:
00751 OVERLAY(unsigned char, 0xff, 4);
00752 break;
00753 }
00754 }
00755
00756
00757
00758 int VFrame::get_scale_tables(int *column_table, int *row_table,
00759 int in_x1, int in_y1, int in_x2, int in_y2,
00760 int out_x1, int out_y1, int out_x2, int out_y2)
00761 {
00762 int y_out, i;
00763 float w_in = in_x2 - in_x1;
00764 float h_in = in_y2 - in_y1;
00765 int w_out = out_x2 - out_x1;
00766 int h_out = out_y2 - out_y1;
00767
00768 float hscale = w_in / w_out;
00769 float vscale = h_in / h_out;
00770
00771 for(i = 0; i < w_out; i++)
00772 {
00773 column_table[i] = (int)(hscale * i);
00774 }
00775
00776 for(i = 0; i < h_out; i++)
00777 {
00778 row_table[i] = (int)(vscale * i) + in_y1;
00779 }
00780 return 0;
00781 }
00782
00783 int VFrame::get_bytes_per_pixel()
00784 {
00785 return bytes_per_pixel;
00786 }
00787
00788 unsigned char** VFrame::get_rows()
00789 {
00790 if(rows)
00791 {
00792 return rows;
00793 }
00794 return 0;
00795 }
00796
00797 int VFrame::get_w()
00798 {
00799 return w;
00800 }
00801
00802 int VFrame::get_h()
00803 {
00804 return h;
00805 }
00806
00807 int VFrame::get_w_fixed()
00808 {
00809 return w - 1;
00810 }
00811
00812 int VFrame::get_h_fixed()
00813 {
00814 return h - 1;
00815 }
00816
00817 unsigned char* VFrame::get_y()
00818 {
00819 return y;
00820 }
00821
00822 unsigned char* VFrame::get_u()
00823 {
00824 return u;
00825 }
00826
00827 unsigned char* VFrame::get_v()
00828 {
00829 return v;
00830 }
00831
00832 void VFrame::set_number(long number)
00833 {
00834 sequence_number = number;
00835 }
00836
00837 long VFrame::get_number()
00838 {
00839 return sequence_number;
00840 }
00841
00842 void VFrame::push_prev_effect(char *name)
00843 {
00844 char *ptr;
00845 prev_effects.append(ptr = new char[strlen(name) + 1]);
00846 strcpy(ptr, name);
00847 if(prev_effects.total > MAX_STACK_ELEMENTS) prev_effects.remove_object(0);
00848 }
00849
00850 void VFrame::pop_prev_effect()
00851 {
00852 if(prev_effects.total)
00853 prev_effects.remove_object(prev_effects.last());
00854 }
00855
00856 void VFrame::push_next_effect(char *name)
00857 {
00858 char *ptr;
00859 next_effects.append(ptr = new char[strlen(name) + 1]);
00860 strcpy(ptr, name);
00861 if(next_effects.total > MAX_STACK_ELEMENTS) next_effects.remove_object(0);
00862 }
00863
00864 void VFrame::pop_next_effect()
00865 {
00866 if(next_effects.total)
00867 next_effects.remove_object(next_effects.last());
00868 }
00869
00870 char* VFrame::get_next_effect(int number)
00871 {
00872 if(!next_effects.total) return "";
00873 else
00874 if(number > next_effects.total - 1) number = next_effects.total - 1;
00875
00876 return next_effects.values[next_effects.total - number - 1];
00877 }
00878
00879 char* VFrame::get_prev_effect(int number)
00880 {
00881 if(!prev_effects.total) return "";
00882 else
00883 if(number > prev_effects.total - 1) number = prev_effects.total - 1;
00884
00885 return prev_effects.values[prev_effects.total - number - 1];
00886 }
00887
00888 BC_Hash* VFrame::get_params()
00889 {
00890 return params;
00891 }
00892
00893 void VFrame::clear_stacks()
00894 {
00895 next_effects.remove_all_objects();
00896 prev_effects.remove_all_objects();
00897 delete params;
00898 params = new BC_Hash;
00899 }
00900
00901 void VFrame::copy_params(VFrame *src)
00902 {
00903 params->copy_from(src->params);
00904 }
00905
00906 void VFrame::copy_stacks(VFrame *src)
00907 {
00908 clear_stacks();
00909
00910 for(int i = 0; i < src->next_effects.total; i++)
00911 {
00912 char *ptr;
00913 next_effects.append(ptr = new char[strlen(src->next_effects.values[i]) + 1]);
00914 strcpy(ptr, src->next_effects.values[i]);
00915 }
00916 for(int i = 0; i < src->prev_effects.total; i++)
00917 {
00918 char *ptr;
00919 prev_effects.append(ptr = new char[strlen(src->prev_effects.values[i]) + 1]);
00920 strcpy(ptr, src->prev_effects.values[i]);
00921 }
00922
00923 params->copy_from(src->params);
00924 }
00925
00926 int VFrame::equal_stacks(VFrame *src)
00927 {
00928 for(int i = 0; i < src->next_effects.total && i < next_effects.total; i++)
00929 {
00930 if(strcmp(src->next_effects.values[i], next_effects.values[i])) return 0;
00931 }
00932 for(int i = 0; i < src->prev_effects.total && i < prev_effects.total; i++)
00933 {
00934 if(strcmp(src->prev_effects.values[i], prev_effects.values[i])) return 0;
00935 }
00936 if(!params->equivalent(src->params)) return 0;
00937 return 1;
00938 }
00939
00940 void VFrame::dump_stacks()
00941 {
00942 printf("VFrame::dump_stacks\n");
00943 printf(" next_effects:\n");
00944 for(int i = next_effects.total - 1; i >= 0; i--)
00945 printf(" %s\n", next_effects.values[i]);
00946 printf(" prev_effects:\n");
00947 for(int i = prev_effects.total - 1; i >= 0; i--)
00948 printf(" %s\n", prev_effects.values[i]);
00949 }
00950
00951 void VFrame::dump_params()
00952 {
00953 params->dump();
00954 }
00955
00956
00957