home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / guicast / bcbitmap.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  15KB  |  702 lines

  1. #include "bcbitmap.h"
  2. #include "bcipc.h"
  3. #include "bcresources.h"
  4. #include "bcwindow.h"
  5. #include "colormodels.h"
  6. #include "vframe.h"
  7.  
  8. #include <string.h>
  9. #include <X11/extensions/Xvlib.h>
  10.  
  11.  
  12. BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, unsigned char *png_data)
  13. {
  14. // Decompress data into a temporary vframe
  15.     VFrame frame;
  16.  
  17.     frame.read_png(png_data);
  18.  
  19. // Initialize the bitmap
  20.     initialize(parent_window, 
  21.         frame.get_w(), 
  22.         frame.get_h(), 
  23.         parent_window->get_color_model(), 
  24.         0);
  25.  
  26. // Copy the vframe to the bitmap
  27.     read_frame(&frame, 0, 0, w, h, 0);
  28. }
  29.  
  30. BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, VFrame *frame)
  31. {
  32. // Initialize the bitmap
  33.     initialize(parent_window, 
  34.         frame->get_w(), 
  35.         frame->get_h(), 
  36.         parent_window->get_color_model(), 
  37.         0);
  38.  
  39. // Copy the vframe to the bitmap
  40.     read_frame(frame, 0, 0, w, h, 1);
  41. }
  42.  
  43. BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, int w, int h, int color_model, int use_shm)
  44. {
  45.     initialize(parent_window, 
  46.         w, 
  47.         h, 
  48.         color_model, 
  49.         use_shm ? parent_window->get_resources()->use_shm : 0);
  50. }
  51.  
  52. BC_Bitmap::~BC_Bitmap()
  53. {
  54.     delete_data();
  55. }
  56.  
  57. int BC_Bitmap::initialize(BC_WindowBase *parent_window, int w, int h, int color_model, int use_shm)
  58. {
  59.     this->parent_window = parent_window;
  60.     this->top_level = parent_window->top_level;
  61.     this->w = w;
  62.     this->h = h;
  63.     this->color_model = color_model;
  64.     this->use_shm = use_shm;
  65.     this->bg_color = parent_window->bg_color;
  66.     ximage[0] = 0;
  67.     xv_image[0] = 0;
  68.     data[0] = 0;
  69.     last_pixmap_used = 0;
  70.     current_ringbuffer = 0;
  71.     ring_buffers = 1;
  72.  
  73.     allocate_data();
  74.     return 0;
  75. }
  76.  
  77. int BC_Bitmap::match_params(int w, int h, int color_model, int use_shm)
  78. {
  79.     if(this->w != w ||
  80.         this->h != h ||
  81.         this->color_model != color_model ||
  82.         this->use_shm != use_shm)
  83.     {
  84.         delete_data();
  85.         initialize(parent_window, w, h, color_model, use_shm);
  86.     }
  87.  
  88.     return 0;
  89. }
  90.  
  91. int BC_Bitmap::params_match(int w, int h, int color_model, int use_shm)
  92. {
  93.     int result = 0;
  94.     if(this->w == w &&
  95.         this->h == h &&
  96.         this->color_model == color_model)
  97.     {
  98.         if(use_shm == this->use_shm || use_shm == INFINITY)
  99.             result = 1;
  100.     }
  101.  
  102.     return result;
  103. }
  104.  
  105.  
  106. int BC_Bitmap::allocate_data()
  107. {
  108.     int want_row_pointers = 1;
  109.  
  110. // Shared memory available
  111.     if(use_shm)
  112.     {
  113.         switch(color_model)
  114.         {
  115. // Planar YUV.  Must use BC_WindowBase::accel_available before calling this.
  116.             case BC_YUV420P:
  117.             case BC_YUV422P:
  118.                 ring_buffers = BITMAP_RING;
  119.                 xv_portid = top_level->xvideo_port_id;
  120. // Create the X Image
  121.                 xv_image[0] = XvShmCreateImage(top_level->display, 
  122.                             xv_portid, 
  123.                             cmodel_bc_to_x(color_model),
  124.                             0, 
  125.                             w,
  126.                             h,
  127.                             &shm_info);
  128. // Create the shared memory
  129.                 shm_info.shmid = shmget(IPC_PRIVATE, 
  130.                     xv_image[0]->data_size * ring_buffers + 4, 
  131.                     IPC_CREAT | 0777);
  132.                 if(shm_info.shmid < 0) perror("BC_Bitmap::allocate_data shmget");
  133.                 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
  134.                 xv_image[0]->data = shm_info.shmaddr = (char*)data[0];// setting ximage->data stops BadValue
  135.                 shm_info.readOnly = 0;
  136.  
  137. // Get the real parameters
  138.                 w = xv_image[0]->width;
  139.                 h = xv_image[0]->height;
  140.  
  141. // Create remaining X Images
  142.                 for(int i = 1; i < ring_buffers; i++)
  143.                 {
  144.                     data[i] = data[0] + xv_image[0]->data_size * i;
  145.                     xv_image[i] = XvShmCreateImage(top_level->display, 
  146.                                 xv_portid, 
  147.                                 FOURCC_YV12,
  148.                                 (char*)data[i], 
  149.                                 w,
  150.                                 h,
  151.                                 &shm_info);
  152.                     xv_image[i]->data = (char*)data[i];
  153.                 }
  154. //printf("BC_Bitmap %d %d %d\n", color_model, bits_per_pixel, bytes_per_line);
  155.                 bytes_per_line = 0;
  156.                 bits_per_pixel = 0;
  157.                 want_row_pointers = 0;
  158.                 break;
  159.  
  160. // Packed YUV
  161.             case BC_YUV422:
  162.                 ring_buffers = BITMAP_RING;
  163.                 xv_portid = top_level->xvideo_port_id;
  164. // Create the X Image
  165.                 xv_image[0] = XvShmCreateImage(top_level->display, 
  166.                             xv_portid, 
  167.                             cmodel_bc_to_x(color_model),
  168.                             0, 
  169.                             w,
  170.                             h,
  171.                             &shm_info);
  172. // Create the shared memory
  173.                 shm_info.shmid = shmget(IPC_PRIVATE, 
  174.                     xv_image[0]->data_size * ring_buffers + 4, 
  175.                     IPC_CREAT | 0777);
  176.                 if(shm_info.shmid < 0) perror("BC_Bitmap::allocate_data shmget");
  177.                 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
  178.                 xv_image[0]->data = shm_info.shmaddr = (char*)data[0];// setting ximage->data stops BadValue
  179.                 shm_info.readOnly = 0;
  180.  
  181. // Get the real parameters
  182.                 w = xv_image[0]->width;
  183.                 h = xv_image[0]->height;
  184.  
  185. // Create remaining X Images
  186.                 for(int i = 1; i < ring_buffers; i++)
  187.                 {
  188.                     data[i] = data[0] + xv_image[0]->data_size * i;
  189.                     xv_image[i] = XvShmCreateImage(top_level->display, 
  190.                                 xv_portid, 
  191.                                 cmodel_bc_to_x(color_model),
  192.                                 (char*)data[i], 
  193.                                 w,
  194.                                 h,
  195.                                 &shm_info);
  196.                     xv_image[i]->data = (char*)data[i];
  197.                 }
  198.                 bytes_per_line = w * 2;
  199.                 bits_per_pixel = 2;
  200.                 want_row_pointers = 1;
  201. //printf("BC_Bitmap %d %d %d %d\n", color_model, xv_image[0]->data_size, bits_per_pixel, bytes_per_line);
  202.                 break;
  203.  
  204.             default:
  205. // RGB
  206.                 ring_buffers = BITMAP_RING;
  207. // Create first X Image
  208.                 ximage[0] = XShmCreateImage(top_level->display, 
  209.                     top_level->vis, 
  210.                     get_default_depth(), 
  211.                     ZPixmap, 
  212.                     (char*)NULL, 
  213.                     &shm_info, 
  214.                     w, 
  215.                     h);
  216.  
  217. // Create shared memory
  218.                 shm_info.shmid = shmget(IPC_PRIVATE, 
  219.                     h * ximage[0]->bytes_per_line * ring_buffers + 4, 
  220.                     IPC_CREAT | 0777);
  221.                 if(shm_info.shmid < 0) 
  222.                     perror("BC_Bitmap::allocate_data shmget");
  223.                 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
  224.                 ximage[0]->data = shm_info.shmaddr = (char*)data[0];  // setting ximage->data stops BadValue
  225.                 shm_info.readOnly = 0;
  226.  
  227. // Get the real parameters
  228.                 bits_per_pixel = ximage[0]->bits_per_pixel;
  229.                 bytes_per_line = ximage[0]->bytes_per_line;
  230.  
  231. // Create remaining X Images
  232.                 for(int i = 1; i < ring_buffers; i++)
  233.                 {
  234.                     data[i] = data[0] + h * ximage[0]->bytes_per_line * i;
  235.                     ximage[i] = XShmCreateImage(top_level->display, 
  236.                                             top_level->vis, 
  237.                                             get_default_depth(), 
  238.                                             ZPixmap, 
  239.                                             (char*)data[i], 
  240.                                             &shm_info, 
  241.                                             w, 
  242.                                             h);
  243.                     ximage[i]->data = (char*)data[i];
  244.                 }
  245.                 break;
  246.         }
  247.  
  248.         if(!XShmAttach(top_level->display, &shm_info))
  249.         {
  250.             perror("BC_Bitmap::allocate_data XShmAttach");
  251.         }
  252.  
  253.         shmctl(shm_info.shmid, IPC_RMID, 0);
  254.     }
  255.     else
  256. // Use unshared memory.
  257.     {
  258.         ring_buffers = 1;
  259. // need to use bytes_per_line for some X servers
  260.         data[0] = 0;
  261. // Use RGB frame
  262.         ximage[0] = XCreateImage(top_level->display, 
  263.                     top_level->vis, 
  264.                     get_default_depth(), 
  265.                     get_default_depth() == 1 ? XYBitmap : ZPixmap, 
  266.                     0, 
  267.                     (char*)data[0], 
  268.                     w, 
  269.                     h, 
  270.                     8, 
  271.                     0);
  272.  
  273.         data[0] = (unsigned char*)malloc(h * ximage[0]->bytes_per_line + 4);
  274.  
  275.         XDestroyImage(ximage[0]);
  276.  
  277.         ximage[0] = XCreateImage(top_level->display, 
  278.                     top_level->vis, 
  279.                     get_default_depth(), 
  280.                     get_default_depth() == 1 ? XYBitmap : ZPixmap, 
  281.                     0, 
  282.                     (char*)data[0], 
  283.                     w, 
  284.                     h, 
  285.                     8, 
  286.                     0);
  287. // This differs from the depth parameter of the top_level.
  288.         bits_per_pixel = ximage[0]->bits_per_pixel;
  289.         bytes_per_line = ximage[0]->bytes_per_line;
  290.     }
  291.  
  292. // Create row pointers
  293.     if(want_row_pointers)
  294.     {
  295.         for(int j = 0; j < ring_buffers; j++)
  296.         {
  297.             row_data[j] = new unsigned char*[h];
  298.             for(int i = 0; i < h; i++)
  299.             {
  300.                 row_data[j][i] = &data[j][i * bytes_per_line];
  301.             }
  302.         }
  303.     }
  304.     return 0;
  305. }
  306.  
  307. int BC_Bitmap::delete_data()
  308. {
  309.     if(data[0])
  310.     {
  311.         if(use_shm)
  312.         {
  313.             switch(color_model)
  314.             {
  315.                 case BC_YUV420P:
  316.                 case BC_YUV422P:
  317.                 case BC_YUV422:
  318.                     if(last_pixmap_used) XvStopVideo(top_level->display, xv_portid, last_pixmap);
  319.                     XvUngrabPort(top_level->display, xv_portid, CurrentTime);
  320.                     XShmDetach(top_level->display, &shm_info);
  321.                     shmdt(shm_info.shmaddr);
  322.                     shmctl(shm_info.shmid, IPC_RMID, 0);
  323.                     for(int i = 0; i < ring_buffers; i++)
  324.                     {
  325.                         XFree(xv_image[i]);
  326.                     }
  327.                     break;
  328.  
  329.                 default:
  330.                     XShmDetach(top_level->display, &shm_info);
  331.                     shmdt(shm_info.shmaddr);
  332.                     shmctl(shm_info.shmid, IPC_RMID, 0);
  333.                     for(int i = 0; i < ring_buffers; i++)
  334.                     {
  335.                         XDestroyImage(ximage[i]);
  336.                         delete row_data[i];
  337.                     }
  338.             }
  339.         }
  340.         else
  341.         {
  342.             XDestroyImage(ximage[0]);
  343.             delete row_data[0];
  344.         }
  345.  
  346. // data is automatically freed by XDestroyImage
  347.         data[0] = 0;
  348.     }
  349.     return 0;
  350. }
  351.  
  352. int BC_Bitmap::get_default_depth()
  353. {
  354.     if(color_model == BC_TRANSPARENCY)
  355.         return 1;
  356.     else
  357.         return top_level->default_depth;
  358. }
  359.  
  360.  
  361. int BC_Bitmap::set_bg_color(int color)
  362. {
  363.     this->bg_color = color;
  364.     return 0;
  365. }
  366.  
  367. int BC_Bitmap::invert()
  368. {
  369.     for(int j = 0; j < ring_buffers; j++)
  370.         for(int k = 0; k < h; k++)
  371.             for(int i = 0; i < bytes_per_line; i++)
  372.             {
  373.                 row_data[j][k][i] ^= 0xff;
  374.             }
  375.     return 0;
  376. }
  377.  
  378. int BC_Bitmap::write_drawable(Drawable &pixmap, 
  379.                             GC &gc,
  380.                             int dest_x, 
  381.                             int dest_y, 
  382.                             int source_x, 
  383.                             int source_y, 
  384.                             int dest_w, 
  385.                             int dest_h,
  386.                             int dont_wait)
  387. {
  388.     return write_drawable(pixmap, 
  389.         gc,
  390.         source_x, 
  391.         source_y, 
  392.         get_w() - source_x,
  393.         get_h() - source_y,
  394.         dest_x, 
  395.         dest_y, 
  396.         dest_w, 
  397.         dest_h, 
  398.         dont_wait);
  399. }
  400.  
  401.  
  402.  
  403. int BC_Bitmap::write_drawable(Drawable &pixmap, 
  404.         GC &gc,
  405.         int source_x, 
  406.         int source_y, 
  407.         int source_w,
  408.         int source_h,
  409.         int dest_x, 
  410.         int dest_y, 
  411.         int dest_w, 
  412.         int dest_h, 
  413.         int dont_wait)
  414. {
  415.     if(use_shm)
  416.     {
  417. //        if(dont_wait) XSync(top_level->display, False);
  418.  
  419.         switch(color_model)
  420.         {
  421.             case BC_YUV420P:
  422.             case BC_YUV422P:
  423.             case BC_YUV422:
  424.                 XvShmPutImage(top_level->display, 
  425.                     xv_portid, 
  426.                     pixmap, 
  427.                     gc,
  428.                     xv_image[current_ringbuffer], 
  429.                     source_x, 
  430.                     source_y, 
  431.                     source_w, 
  432.                     source_h, 
  433.                     dest_x, 
  434.                     dest_y, 
  435.                     dest_w, 
  436.                     dest_h, 
  437.                     False);
  438. // Need to pass these to the XvStopVideo
  439.                 last_pixmap = pixmap;
  440.                 last_pixmap_used = 1;
  441.                 break;
  442.  
  443.             default:
  444.                 XShmPutImage(top_level->display, 
  445.                     pixmap, 
  446.                     gc, 
  447.                     ximage[current_ringbuffer], 
  448.                     source_x, 
  449.                     source_y, 
  450.                     dest_x, 
  451.                     dest_y, 
  452.                     dest_w, 
  453.                     dest_h, 
  454.                     False);
  455.                 break;
  456.         }
  457. // Force the X server into processing all requests.
  458. // This allows the shared memory to be written to again.
  459.         if(!dont_wait) XSync(top_level->display, 0);
  460.     }
  461.     else
  462.     {
  463.         XPutImage(top_level->display, 
  464.             pixmap, 
  465.             gc, 
  466.             ximage[current_ringbuffer], 
  467.             source_x, 
  468.             source_y, 
  469.             dest_x, 
  470.             dest_y, 
  471.             dest_w, 
  472.             dest_h);
  473.     }
  474.  
  475. //printf("BC_Bitmap %d\n", current_ringbuffer);
  476.     current_ringbuffer++;
  477.     if(current_ringbuffer >= ring_buffers) current_ringbuffer = 0;
  478.     return 0;
  479. }
  480.  
  481.  
  482.  
  483.  
  484. // the bitmap must be wholly contained in the source during a GetImage
  485. int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y)
  486. {
  487.     if(use_shm)
  488.         XShmGetImage(top_level->display, pixmap, ximage[current_ringbuffer], source_x, source_y, 0xffffffff);
  489.     else
  490.         XGetSubImage(top_level->display, pixmap, source_x, source_y, w, h, 0xffffffff, ZPixmap, ximage[current_ringbuffer], 0, 0);
  491.     return 0;
  492. }
  493.  
  494. // ============================ Decoding VFrames
  495.  
  496. int BC_Bitmap::read_frame(VFrame *frame, 
  497.     int x1, 
  498.     int y1, 
  499.     int x2, 
  500.     int y2, 
  501.     int use_alpha)
  502. {
  503.     return read_frame(frame, use_alpha,
  504.         0, 0, frame->get_w(), frame->get_h(),
  505.         x1, y1, x2 - x1, y2 - y1);
  506. }
  507.  
  508.  
  509. int BC_Bitmap::read_frame(VFrame *frame, int use_alpha,
  510.         int in_x, int in_y, int in_w, int in_h,
  511.         int out_x, int out_y, int out_w, int out_h)
  512. {
  513.     switch(color_model)
  514.     {
  515. // Hardware acceleration
  516.         case BC_YUV420P:
  517.             if(frame->get_color_model() == color_model)
  518.             {
  519.                 memcpy(get_y_plane(), frame->get_y(), w * h);
  520.                 memcpy(get_u_plane(), frame->get_u(), w * h / 4);
  521.                 memcpy(get_v_plane(), frame->get_v(), w * h / 4);
  522.                 break;
  523.             }
  524.  
  525.         case BC_YUV422P:
  526.             if(frame->get_color_model() == color_model)
  527.             {
  528.                 memcpy(get_y_plane(), frame->get_y(), w * h);
  529.                 memcpy(get_u_plane(), frame->get_u(), w * h / 2);
  530.                 memcpy(get_v_plane(), frame->get_v(), w * h / 2);
  531.                 break;
  532.             }
  533.  
  534.         case BC_YUV422:
  535.             if(frame->get_color_model() == color_model)
  536.             {
  537.                 memcpy(get_data(), frame->get_data(), w * h + w * h);
  538.                 break;
  539.             }
  540.  
  541. // Software only
  542.         default:
  543.             cmodel_transfer(row_data[current_ringbuffer], 
  544.                 frame->get_rows(),
  545.                 get_y_plane(),
  546.                 get_u_plane(),
  547.                 get_v_plane(),
  548.                 frame->get_y(),
  549.                 frame->get_u(),
  550.                 frame->get_v(),
  551.                 in_x, 
  552.                 in_y, 
  553.                 in_w, 
  554.                 in_h,
  555.                 out_x, 
  556.                 out_y, 
  557.                 out_w, 
  558.                 out_h,
  559.                 frame->get_color_model(), 
  560.                 color_model,
  561.                 bg_color,
  562.                 frame->get_w());
  563.             break;
  564.     }
  565.  
  566.  
  567.     return 0;
  568. }
  569.  
  570. long BC_Bitmap::get_shm_id()
  571. {
  572.     return shm_info.shmid;
  573. }
  574.  
  575. long BC_Bitmap::get_shm_size()
  576. {
  577.     if(xv_image[0])
  578.         return xv_image[0]->data_size * ring_buffers;
  579.     else
  580.         return h * ximage[0]->bytes_per_line;
  581. }
  582.  
  583. long BC_Bitmap::get_shm_offset()
  584. {
  585.     if(xv_image[0])
  586.         return xv_image[0]->data_size * current_ringbuffer;
  587.     else
  588.     if(ximage[0])
  589.         return h * ximage[0]->bytes_per_line * current_ringbuffer;
  590.     else
  591.         return 0;
  592. }
  593.  
  594. long BC_Bitmap::get_y_shm_offset()
  595. {
  596.     if(xv_image[0])
  597.         return get_shm_offset() + xv_image[current_ringbuffer]->offsets[0];
  598.     else
  599.         return 0;
  600. }
  601.  
  602. long BC_Bitmap::get_u_shm_offset()
  603. {
  604.     if(xv_image[0])
  605.         return get_shm_offset() + xv_image[current_ringbuffer]->offsets[2];
  606.     else
  607.         return 0;
  608. }
  609.  
  610. long BC_Bitmap::get_v_shm_offset()
  611. {
  612.     if(xv_image[0])
  613.         return get_shm_offset() + xv_image[current_ringbuffer]->offsets[1];
  614.     else
  615.         return 0;
  616. }
  617.  
  618. long BC_Bitmap::get_y_offset()
  619. {
  620.     if(xv_image[0])
  621.         return xv_image[current_ringbuffer]->offsets[0];
  622.     else
  623.         return 0;
  624. }
  625.  
  626. long BC_Bitmap::get_u_offset()
  627. {
  628.     if(xv_image[0])
  629.         return xv_image[current_ringbuffer]->offsets[2];
  630.     else
  631.         return 0;
  632. }
  633.  
  634. long BC_Bitmap::get_v_offset()
  635. {
  636.     if(xv_image[0])
  637.         return xv_image[current_ringbuffer]->offsets[1];
  638.     else
  639.         return 0;
  640. }
  641.  
  642.  
  643. unsigned char** BC_Bitmap::get_row_pointers()
  644. {
  645.     return row_data[current_ringbuffer];
  646. }
  647.  
  648. unsigned char* BC_Bitmap::get_data()
  649. {
  650. //printf("BC_Bitmap::get_data %d %p\n",current_ringbuffer , data[current_ringbuffer]);
  651.     return data[current_ringbuffer];
  652. }
  653.  
  654. unsigned char* BC_Bitmap::get_y_plane()
  655. {
  656.     if(color_model == BC_YUV420P ||
  657.         color_model == BC_YUV422P)
  658.         return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[0];
  659.     else
  660.         return 0;
  661. }
  662.  
  663. unsigned char* BC_Bitmap::get_v_plane()
  664. {
  665.     if(color_model == BC_YUV420P ||
  666.         color_model == BC_YUV422P)
  667.         return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[1];
  668.     else
  669.         return 0;
  670. }
  671.  
  672. unsigned char* BC_Bitmap::get_u_plane()
  673. {
  674.     if(color_model == BC_YUV420P ||
  675.         color_model == BC_YUV422P)
  676.         return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[2];
  677.     else
  678.         return 0;
  679. }
  680.  
  681. void BC_Bitmap::rewind_ringbuffer()
  682. {
  683.     current_ringbuffer--;
  684.     if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
  685. }
  686.  
  687. int BC_Bitmap::hardware_scaling()
  688. {
  689.     return (get_color_model() == BC_YUV420P || 
  690.         get_color_model() == BC_YUV422P || 
  691.         get_color_model() == BC_YUV422);
  692. }
  693.  
  694. int BC_Bitmap::get_w() { return w; }
  695.  
  696. int BC_Bitmap::get_h() { return h; }
  697.  
  698. int BC_Bitmap::get_color_model() { return color_model; }
  699.  
  700.  
  701.  
  702.