media/libyuv/source/convert_to_argb.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
     3  *
     4  *  Use of this source code is governed by a BSD-style license
     5  *  that can be found in the LICENSE file in the root of the source
     6  *  tree. An additional intellectual property rights grant can be found
     7  *  in the file PATENTS. All contributing project authors may
     8  *  be found in the AUTHORS file in the root of the source tree.
     9  */
    11 #include "libyuv/convert_argb.h"
    13 #include "libyuv/cpu_id.h"
    14 #include "libyuv/format_conversion.h"
    15 #ifdef HAVE_JPEG
    16 #include "libyuv/mjpeg_decoder.h"
    17 #endif
    18 #include "libyuv/rotate_argb.h"
    19 #include "libyuv/row.h"
    20 #include "libyuv/video_common.h"
    22 #ifdef __cplusplus
    23 namespace libyuv {
    24 extern "C" {
    25 #endif
    27 // Convert camera sample to I420 with cropping, rotation and vertical flip.
    28 // src_width is used for source stride computation
    29 // src_height is used to compute location of planes, and indicate inversion
    30 // sample_size is measured in bytes and is the size of the frame.
    31 //   With MJPEG it is the compressed size of the frame.
    32 LIBYUV_API
    33 int ConvertToARGB(const uint8* sample, size_t sample_size,
    34                   uint8* crop_argb, int argb_stride,
    35                   int crop_x, int crop_y,
    36                   int src_width, int src_height,
    37                   int crop_width, int crop_height,
    38                   enum RotationMode rotation,
    39                   uint32 fourcc) {
    40   uint32 format = CanonicalFourCC(fourcc);
    41   int aligned_src_width = (src_width + 1) & ~1;
    42   const uint8* src;
    43   const uint8* src_uv;
    44   int abs_src_height = (src_height < 0) ? -src_height : src_height;
    45   int inv_crop_height = (crop_height < 0) ? -crop_height : crop_height;
    46   int r = 0;
    48   // One pass rotation is available for some formats. For the rest, convert
    49   // to I420 (with optional vertical flipping) into a temporary I420 buffer,
    50   // and then rotate the I420 to the final destination buffer.
    51   // For in-place conversion, if destination crop_argb is same as source sample,
    52   // also enable temporary buffer.
    53   LIBYUV_BOOL need_buf = (rotation && format != FOURCC_ARGB) ||
    54       crop_argb == sample;
    55   uint8* tmp_argb = crop_argb;
    56   int tmp_argb_stride = argb_stride;
    57   uint8* rotate_buffer = NULL;
    58   int abs_crop_height = (crop_height < 0) ? -crop_height : crop_height;
    60   if (crop_argb == NULL || sample == NULL ||
    61       src_width <= 0 || crop_width <= 0 ||
    62       src_height == 0 || crop_height == 0) {
    63     return -1;
    64   }
    65   if (src_height < 0) {
    66     inv_crop_height = -inv_crop_height;
    67   }
    69   if (need_buf) {
    70     int argb_size = crop_width * abs_crop_height * 4;
    71     rotate_buffer = (uint8*)malloc(argb_size);
    72     if (!rotate_buffer) {
    73       return 1;  // Out of memory runtime error.
    74     }
    75     crop_argb = rotate_buffer;
    76     argb_stride = crop_width;
    77   }
    79   switch (format) {
    80     // Single plane formats
    81     case FOURCC_YUY2:
    82       src = sample + (aligned_src_width * crop_y + crop_x) * 2;
    83       r = YUY2ToARGB(src, aligned_src_width * 2,
    84                      crop_argb, argb_stride,
    85                      crop_width, inv_crop_height);
    86       break;
    87     case FOURCC_UYVY:
    88       src = sample + (aligned_src_width * crop_y + crop_x) * 2;
    89       r = UYVYToARGB(src, aligned_src_width * 2,
    90                      crop_argb, argb_stride,
    91                      crop_width, inv_crop_height);
    92       break;
    93     case FOURCC_24BG:
    94       src = sample + (src_width * crop_y + crop_x) * 3;
    95       r = RGB24ToARGB(src, src_width * 3,
    96                       crop_argb, argb_stride,
    97                       crop_width, inv_crop_height);
    98       break;
    99     case FOURCC_RAW:
   100       src = sample + (src_width * crop_y + crop_x) * 3;
   101       r = RAWToARGB(src, src_width * 3,
   102                     crop_argb, argb_stride,
   103                     crop_width, inv_crop_height);
   104       break;
   105     case FOURCC_ARGB:
   106       src = sample + (src_width * crop_y + crop_x) * 4;
   107       r = ARGBToARGB(src, src_width * 4,
   108                      crop_argb, argb_stride,
   109                      crop_width, inv_crop_height);
   110       break;
   111     case FOURCC_BGRA:
   112       src = sample + (src_width * crop_y + crop_x) * 4;
   113       r = BGRAToARGB(src, src_width * 4,
   114                      crop_argb, argb_stride,
   115                      crop_width, inv_crop_height);
   116       break;
   117     case FOURCC_ABGR:
   118       src = sample + (src_width * crop_y + crop_x) * 4;
   119       r = ABGRToARGB(src, src_width * 4,
   120                      crop_argb, argb_stride,
   121                      crop_width, inv_crop_height);
   122       break;
   123     case FOURCC_RGBA:
   124       src = sample + (src_width * crop_y + crop_x) * 4;
   125       r = RGBAToARGB(src, src_width * 4,
   126                      crop_argb, argb_stride,
   127                      crop_width, inv_crop_height);
   128       break;
   129     case FOURCC_RGBP:
   130       src = sample + (src_width * crop_y + crop_x) * 2;
   131       r = RGB565ToARGB(src, src_width * 2,
   132                        crop_argb, argb_stride,
   133                        crop_width, inv_crop_height);
   134       break;
   135     case FOURCC_RGBO:
   136       src = sample + (src_width * crop_y + crop_x) * 2;
   137       r = ARGB1555ToARGB(src, src_width * 2,
   138                          crop_argb, argb_stride,
   139                          crop_width, inv_crop_height);
   140       break;
   141     case FOURCC_R444:
   142       src = sample + (src_width * crop_y + crop_x) * 2;
   143       r = ARGB4444ToARGB(src, src_width * 2,
   144                          crop_argb, argb_stride,
   145                          crop_width, inv_crop_height);
   146       break;
   147     // TODO(fbarchard): Support cropping Bayer by odd numbers
   148     // by adjusting fourcc.
   149     case FOURCC_BGGR:
   150       src = sample + (src_width * crop_y + crop_x);
   151       r = BayerBGGRToARGB(src, src_width,
   152                           crop_argb, argb_stride,
   153                           crop_width, inv_crop_height);
   154       break;
   156     case FOURCC_GBRG:
   157       src = sample + (src_width * crop_y + crop_x);
   158       r = BayerGBRGToARGB(src, src_width,
   159                           crop_argb, argb_stride,
   160                           crop_width, inv_crop_height);
   161       break;
   163     case FOURCC_GRBG:
   164       src = sample + (src_width * crop_y + crop_x);
   165       r = BayerGRBGToARGB(src, src_width,
   166                           crop_argb, argb_stride,
   167                           crop_width, inv_crop_height);
   168       break;
   170     case FOURCC_RGGB:
   171       src = sample + (src_width * crop_y + crop_x);
   172       r = BayerRGGBToARGB(src, src_width,
   173                           crop_argb, argb_stride,
   174                           crop_width, inv_crop_height);
   175       break;
   177     case FOURCC_I400:
   178       src = sample + src_width * crop_y + crop_x;
   179       r = I400ToARGB(src, src_width,
   180                      crop_argb, argb_stride,
   181                      crop_width, inv_crop_height);
   182       break;
   184     // Biplanar formats
   185     case FOURCC_NV12:
   186       src = sample + (src_width * crop_y + crop_x);
   187       src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
   188       r = NV12ToARGB(src, src_width,
   189                      src_uv, aligned_src_width,
   190                      crop_argb, argb_stride,
   191                      crop_width, inv_crop_height);
   192       break;
   193     case FOURCC_NV21:
   194       src = sample + (src_width * crop_y + crop_x);
   195       src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
   196       // Call NV12 but with u and v parameters swapped.
   197       r = NV21ToARGB(src, src_width,
   198                      src_uv, aligned_src_width,
   199                      crop_argb, argb_stride,
   200                      crop_width, inv_crop_height);
   201       break;
   202     case FOURCC_M420:
   203       src = sample + (src_width * crop_y) * 12 / 8 + crop_x;
   204       r = M420ToARGB(src, src_width,
   205                      crop_argb, argb_stride,
   206                      crop_width, inv_crop_height);
   207       break;
   208 //    case FOURCC_Q420:
   209 //      src = sample + (src_width + aligned_src_width * 2) * crop_y + crop_x;
   210 //      src_uv = sample + (src_width + aligned_src_width * 2) * crop_y +
   211 //               src_width + crop_x * 2;
   212 //      r = Q420ToARGB(src, src_width * 3,
   213 //                    src_uv, src_width * 3,
   214 //                    crop_argb, argb_stride,
   215 //                    crop_width, inv_crop_height);
   216 //      break;
   217     // Triplanar formats
   218     case FOURCC_I420:
   219     case FOURCC_YU12:
   220     case FOURCC_YV12: {
   221       const uint8* src_y = sample + (src_width * crop_y + crop_x);
   222       const uint8* src_u;
   223       const uint8* src_v;
   224       int halfwidth = (src_width + 1) / 2;
   225       int halfheight = (abs_src_height + 1) / 2;
   226       if (format == FOURCC_YV12) {
   227         src_v = sample + src_width * abs_src_height +
   228             (halfwidth * crop_y + crop_x) / 2;
   229         src_u = sample + src_width * abs_src_height +
   230             halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
   231       } else {
   232         src_u = sample + src_width * abs_src_height +
   233             (halfwidth * crop_y + crop_x) / 2;
   234         src_v = sample + src_width * abs_src_height +
   235             halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
   236       }
   237       r = I420ToARGB(src_y, src_width,
   238                      src_u, halfwidth,
   239                      src_v, halfwidth,
   240                      crop_argb, argb_stride,
   241                      crop_width, inv_crop_height);
   242       break;
   243     }
   244     case FOURCC_I422:
   245     case FOURCC_YV16: {
   246       const uint8* src_y = sample + src_width * crop_y + crop_x;
   247       const uint8* src_u;
   248       const uint8* src_v;
   249       int halfwidth = (src_width + 1) / 2;
   250       if (format == FOURCC_YV16) {
   251         src_v = sample + src_width * abs_src_height +
   252             halfwidth * crop_y + crop_x / 2;
   253         src_u = sample + src_width * abs_src_height +
   254             halfwidth * (abs_src_height + crop_y) + crop_x / 2;
   255       } else {
   256         src_u = sample + src_width * abs_src_height +
   257             halfwidth * crop_y + crop_x / 2;
   258         src_v = sample + src_width * abs_src_height +
   259             halfwidth * (abs_src_height + crop_y) + crop_x / 2;
   260       }
   261       r = I422ToARGB(src_y, src_width,
   262                      src_u, halfwidth,
   263                      src_v, halfwidth,
   264                      crop_argb, argb_stride,
   265                      crop_width, inv_crop_height);
   266       break;
   267     }
   268     case FOURCC_I444:
   269     case FOURCC_YV24: {
   270       const uint8* src_y = sample + src_width * crop_y + crop_x;
   271       const uint8* src_u;
   272       const uint8* src_v;
   273       if (format == FOURCC_YV24) {
   274         src_v = sample + src_width * (abs_src_height + crop_y) + crop_x;
   275         src_u = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
   276       } else {
   277         src_u = sample + src_width * (abs_src_height + crop_y) + crop_x;
   278         src_v = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
   279       }
   280       r = I444ToARGB(src_y, src_width,
   281                      src_u, src_width,
   282                      src_v, src_width,
   283                      crop_argb, argb_stride,
   284                      crop_width, inv_crop_height);
   285       break;
   286     }
   287     case FOURCC_I411: {
   288       int quarterwidth = (src_width + 3) / 4;
   289       const uint8* src_y = sample + src_width * crop_y + crop_x;
   290       const uint8* src_u = sample + src_width * abs_src_height +
   291           quarterwidth * crop_y + crop_x / 4;
   292       const uint8* src_v = sample + src_width * abs_src_height +
   293           quarterwidth * (abs_src_height + crop_y) + crop_x / 4;
   294       r = I411ToARGB(src_y, src_width,
   295                      src_u, quarterwidth,
   296                      src_v, quarterwidth,
   297                      crop_argb, argb_stride,
   298                      crop_width, inv_crop_height);
   299       break;
   300     }
   301 #ifdef HAVE_JPEG
   302     case FOURCC_MJPG:
   303       r = MJPGToARGB(sample, sample_size,
   304                      crop_argb, argb_stride,
   305                      src_width, abs_src_height, crop_width, inv_crop_height);
   306       break;
   307 #endif
   308     default:
   309       r = -1;  // unknown fourcc - return failure code.
   310   }
   312   if (need_buf) {
   313     if (!r) {
   314       r = ARGBRotate(crop_argb, argb_stride,
   315                      tmp_argb, tmp_argb_stride,
   316                      crop_width, abs_crop_height, rotation);
   317     }
   318     free(rotate_buffer);
   319   }
   321   return r;
   322 }
   324 #ifdef __cplusplus
   325 }  // extern "C"
   326 }  // namespace libyuv
   327 #endif

mercurial