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 / quicktime / yuv2.c < prev    next >
C/C++ Source or Header  |  2000-11-29  |  9KB  |  334 lines

  1. #include "colormodels.h"
  2. #include "yuv2.h"
  3.  
  4. /* U V values are signed but Y R G B values are unsigned! */
  5. /*
  6.  *      R = Y               + 1.40200 * V
  7.  *      G = Y - 0.34414 * U - 0.71414 * V
  8.  *      B = Y + 1.77200 * U
  9.  */
  10.  
  11. /*
  12.  *        Y =  0.2990 * R + 0.5870 * G + 0.1140 * B
  13.  *        U = -0.1687 * R - 0.3310 * G + 0.5000 * B
  14.  *        V =  0.5000 * R - 0.4187 * G - 0.0813 * B  
  15.  */
  16.  
  17.  
  18. static int quicktime_delete_codec_yuv2(quicktime_video_map_t *vtrack)
  19. {
  20.     quicktime_yuv2_codec_t *codec;
  21.  
  22.     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  23.     free(codec->work_buffer);
  24.     free(codec);
  25.     return 0;
  26. }
  27.  
  28. static int quicktime_reads_colormodel_yuv2(quicktime_t *file, 
  29.         int colormodel, 
  30.         int track)
  31. {
  32.     return (colormodel == BC_RGB888 ||
  33.         colormodel == BC_YUV888 ||
  34.         colormodel == BC_YUV422P);
  35. }
  36.  
  37.  
  38. static int quicktime_decode_yuv2(quicktime_t *file, unsigned char **row_pointers, int track)
  39. {
  40.     long bytes, x, y;
  41.     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  42.     quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  43.     int width = vtrack->track->tkhd.track_width;
  44.     int height = vtrack->track->tkhd.track_height;
  45.     unsigned char *buffer;
  46.     char *input_row;
  47.     unsigned char *output_row, *y_plane, *u_plane, *v_plane;
  48.     int result = 0;
  49.     int y1, u, v, y2, r, g, b;
  50.     int bytes_per_row = width * cmodel_calculate_pixelsize(file->color_model);
  51.  
  52.     vtrack->track->tkhd.track_width;
  53.     quicktime_set_video_position(file, vtrack->current_position, track);
  54.     bytes = quicktime_frame_size(file, vtrack->current_position, track);
  55.  
  56.     switch(file->color_model)
  57.     {
  58.         case BC_RGB888:
  59.             buffer = codec->work_buffer;
  60.             result = !quicktime_read_data(file, buffer, bytes);
  61.  
  62.             for(y = 0; y < height; y++)
  63.             {
  64.                 input_row = &buffer[y * codec->bytes_per_line];
  65.                 for(x = 0; x < bytes_per_row; )
  66.                 {
  67.                     y1 = (unsigned char)*input_row++;
  68.                     u = *input_row++;
  69.                     y2 = (unsigned char)*input_row++;
  70.                     v = *input_row++;
  71.                     y1 <<= 16;
  72.                     y2 <<= 16;
  73.  
  74.                     r = ((y1 + codec->vtor[v]) >> 16);
  75.                     g = ((y1 + codec->utog[u] + codec->vtog[v]) >> 16);
  76.                     b = ((y1 + codec->utob[u]) >> 16);
  77.                     if(r < 0) r = 0;
  78.                     if(g < 0) g = 0;
  79.                     if(b < 0) b = 0;
  80.                     if(r > 255) r = 255;
  81.                     if(g > 255) g = 255;
  82.                     if(b > 255) b = 255;
  83.  
  84.                     row_pointers[y][x++] = r;
  85.                     row_pointers[y][x++] = g;
  86.                     row_pointers[y][x++] = b;
  87.  
  88. /* Odd numbers of columns quit here */
  89.                     if(x < bytes_per_row)
  90.                     {
  91.                         r = ((y2 + codec->vtor[v]) >> 16);
  92.                         g = ((y2 + codec->utog[u] + codec->vtog[v]) >> 16);
  93.                         b = ((y2 + codec->utob[u]) >> 16);
  94.                         if(r < 0) r = 0;
  95.                         if(g < 0) g = 0;
  96.                         if(b < 0) b = 0;
  97.                         if(r > 255) r = 255;
  98.                         if(g > 255) g = 255;
  99.                         if(b > 255) b = 255;
  100.  
  101.                         row_pointers[y][x++] = r;
  102.                         row_pointers[y][x++] = g;
  103.                         row_pointers[y][x++] = b;
  104.                     }
  105.                 }
  106.             }
  107.             break;
  108.  
  109.         case BC_YUV888:
  110.             buffer = codec->work_buffer;
  111.             result = !quicktime_read_data(file, buffer, bytes);
  112.  
  113.             for(y = 0; y < height; y++)
  114.             {
  115.                 input_row = &buffer[y * codec->bytes_per_line];
  116.                 output_row = row_pointers[y];
  117.  
  118.                 for(x = 0; x < bytes_per_row; )
  119.                 {
  120.                     output_row[x++] = *input_row++;
  121.                     output_row[x++] = u = *input_row++ + 128;
  122.                     y2 = *input_row++;
  123.                     output_row[x++] = v = *input_row++ + 128;
  124.  
  125.                     if(x < bytes_per_row)
  126.                     {
  127.                         output_row[x++] = y2;
  128.                         output_row[x++] = u;
  129.                         output_row[x++] = v;
  130.                     }
  131.                 }
  132.             }
  133.             break;
  134.  
  135.         case BC_YUV422P:
  136.             for(y = 0; y < height; y++)
  137.             {
  138.                 input_row = &buffer[y * codec->bytes_per_line];
  139.                 y_plane = row_pointers[0] + y * bytes_per_row;
  140.                 u_plane = row_pointers[1] + y * bytes_per_row;
  141.                 v_plane = row_pointers[2] + y * bytes_per_row;
  142.                 for(x = 0; x < width; )
  143.                 {
  144.                     y_plane[x++] = *input_row++;
  145.                     *u_plane++ = *input_row++ + 128;
  146.                     if(x < bytes_per_row) y_plane[x++] = *input_row++;
  147.                     *v_plane++ = *input_row++ + 128;
  148.                 }
  149.             }
  150.             break;
  151.     }
  152.  
  153.     return result;
  154. }
  155.  
  156. static int quicktime_encode_yuv2(quicktime_t *file, unsigned char **row_pointers, int track)
  157. {
  158.     long offset = quicktime_position(file);
  159.     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  160.     quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  161.     int result = 0;
  162.     int width = vtrack->track->tkhd.track_width;
  163.     int height = vtrack->track->tkhd.track_height;
  164.     long bytes = height * codec->bytes_per_line;
  165.     unsigned char *buffer = codec->work_buffer;
  166.     int x, y;
  167.     int y1, u, y2, v;
  168.     int r, g, b;
  169.     int bytes_per_row = width * 3;
  170.  
  171.     switch(file->color_model)
  172.     {
  173.         case BC_RGB888:
  174.             for(y = 0; y < height; y++)
  175.             {
  176.                 unsigned char *row_pointer = buffer + y * codec->bytes_per_line;
  177.                 for(x = 0; x < bytes_per_row; )
  178.                 {
  179.                     r = row_pointers[y][x++];
  180.                     g = row_pointers[y][x++];
  181.                     b = row_pointers[y][x++];
  182.  
  183.                     y1 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
  184.                     u  = (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
  185.                     v  = (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
  186.  
  187.                     if(x < bytes_per_row)
  188.                     {
  189.                         r = row_pointers[y][x++];
  190.                         g = row_pointers[y][x++];
  191.                         b = row_pointers[y][x++];
  192.                     }
  193.  
  194.                     y2 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
  195.                     u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
  196.                     v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
  197.  
  198.                     y1 /= 0x10000;
  199.                     y2 /= 0x10000;
  200.                     u /= 0x20000;
  201.                     v /= 0x20000;
  202.                     if(y1 > 255) y1 = 255;
  203.                     if(y2 > 255) y2 = 255;
  204.                     if(u > 127) u = 127;
  205.                     if(v > 127) v = 127;
  206.                     if(y1 < 0) y1 = 0;
  207.                     if(y2 < 0) y2 = 0;
  208.                     if(u < -128) u = -128;
  209.                     if(v < -128) v = -128;
  210.  
  211.                     *row_pointer++ = y1;
  212.                     *row_pointer++ = u;
  213.                     *row_pointer++ = y2;
  214.                     *row_pointer++ = v;
  215.                 }
  216.             }
  217.             result = quicktime_write_data(file, buffer, bytes);
  218.             break;
  219.         case BC_YUV422:
  220. // Change signs
  221.             for(y = 0; y < height; y++)
  222.             {
  223.                 unsigned char *out_row = buffer + y * codec->bytes_per_line;
  224.                 unsigned char *in_row = row_pointers[y];
  225.                 for(x = 0; x < bytes_per_row; )
  226.                 {
  227.                     *out_row++ = *in_row++;
  228.                     *out_row++ = (int)(*in_row++) - 128;
  229.                     *out_row++ = *in_row++;
  230.                     *out_row++ = (int)(*in_row++) - 128;
  231.                     x += 4;
  232.                 }
  233.             }
  234.             result = quicktime_write_data(file, buffer, bytes);
  235.             break;
  236.     }
  237.  
  238.     if(result) result = 0; else result = 1;
  239.  
  240.     quicktime_update_tables(file,
  241.                         file->vtracks[track].track,
  242.                         offset,
  243.                         file->vtracks[track].current_chunk,
  244.                         file->vtracks[track].current_position,
  245.                         1,
  246.                         bytes);
  247.  
  248.     file->vtracks[track].current_chunk++;
  249.     return result;
  250. }
  251.  
  252. static int reads_colormodel(quicktime_t *file, 
  253.         int colormodel, 
  254.         int track)
  255. {
  256.     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  257.     quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  258.  
  259.     return (colormodel == BC_RGB888 ||
  260.         colormodel == BC_YUV888 ||
  261.         colormodel == BC_YUV422P ||
  262.         colormodel == BC_YUV422);
  263. }
  264.  
  265. static int writes_colormodel(quicktime_t *file, 
  266.         int colormodel, 
  267.         int track)
  268. {
  269.     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  270.     quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  271.  
  272.     return (colormodel == BC_RGB888 ||
  273.         colormodel == BC_YUV888 ||
  274.         colormodel == BC_YUV422P ||
  275.         colormodel == BC_YUV422);
  276. }
  277.  
  278. void quicktime_init_codec_yuv2(quicktime_video_map_t *vtrack)
  279. {
  280.     int i;
  281.     quicktime_yuv2_codec_t *codec;
  282.  
  283. /* Init public items */
  284.     ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_yuv2_codec_t));
  285.     ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = quicktime_delete_codec_yuv2;
  286.     ((quicktime_codec_t*)vtrack->codec)->decode_video = quicktime_decode_yuv2;
  287.     ((quicktime_codec_t*)vtrack->codec)->encode_video = quicktime_encode_yuv2;
  288.     ((quicktime_codec_t*)vtrack->codec)->decode_audio = 0;
  289.     ((quicktime_codec_t*)vtrack->codec)->encode_audio = 0;
  290.     ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
  291.     ((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
  292.  
  293. /* Init private items */
  294.     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  295.     for(i = 0; i < 256; i++)
  296.     {
  297. /* compression */
  298.         codec->rtoy_tab[i] = (long)( 0.2990 * 65536 * i);
  299.         codec->rtou_tab[i] = (long)(-0.1687 * 65536 * i);
  300.         codec->rtov_tab[i] = (long)( 0.5000 * 65536 * i);
  301.  
  302.         codec->gtoy_tab[i] = (long)( 0.5870 * 65536 * i);
  303.         codec->gtou_tab[i] = (long)(-0.3320 * 65536 * i);
  304.         codec->gtov_tab[i] = (long)(-0.4187 * 65536 * i);
  305.  
  306.         codec->btoy_tab[i] = (long)( 0.1140 * 65536 * i);
  307.         codec->btou_tab[i] = (long)( 0.5000 * 65536 * i);
  308.         codec->btov_tab[i] = (long)(-0.0813 * 65536 * i);
  309.     }
  310.  
  311.     codec->vtor = &(codec->vtor_tab[128]);
  312.     codec->vtog = &(codec->vtog_tab[128]);
  313.     codec->utog = &(codec->utog_tab[128]);
  314.     codec->utob = &(codec->utob_tab[128]);
  315.  
  316.     for(i = -128; i < 128; i++)
  317.     {
  318. /* decompression */
  319.         codec->vtor[i] = (long)( 1.4020 * 65536 * i);
  320.         codec->vtog[i] = (long)(-0.7141 * 65536 * i);
  321.  
  322.         codec->utog[i] = (long)(-0.3441 * 65536 * i);
  323.         codec->utob[i] = (long)( 1.7720 * 65536 * i);
  324.     }
  325.  
  326.     codec->bytes_per_line = vtrack->track->tkhd.track_width * 2;
  327.     if((float)codec->bytes_per_line / 4 > (int)(codec->bytes_per_line / 4))
  328.         codec->bytes_per_line += 2;
  329.  
  330.     codec->work_buffer = malloc(codec->bytes_per_line *
  331.                             vtrack->track->tkhd.track_height);
  332. }
  333.  
  334.