| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  *  Copyright 2015 The WebRTC project authors. All Rights Reserved. |    2  *  Copyright 2015 The WebRTC project authors. All Rights Reserved. | 
|    3  * |    3  * | 
|    4  *  Use of this source code is governed by a BSD-style license |    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 |    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 |    6  *  tree. An additional intellectual property rights grant can be found | 
|    7  *  in the file PATENTS.  All contributing project authors may |    7  *  in the file PATENTS.  All contributing project authors may | 
|    8  *  be found in the AUTHORS file in the root of the source tree. |    8  *  be found in the AUTHORS file in the root of the source tree. | 
|    9  */ |    9  */ | 
|   10  |   10  | 
|   11 #include "webrtc/api/java/jni/native_handle_impl.h" |   11 #include "webrtc/api/java/jni/native_handle_impl.h" | 
|   12  |   12  | 
|   13 #include <memory> |   13 #include <memory> | 
|   14  |   14  | 
|   15 #include "webrtc/api/java/jni/jni_helpers.h" |   15 #include "webrtc/api/java/jni/jni_helpers.h" | 
|   16 #include "webrtc/base/bind.h" |   16 #include "webrtc/base/bind.h" | 
|   17 #include "webrtc/base/checks.h" |   17 #include "webrtc/base/checks.h" | 
|   18 #include "webrtc/base/keep_ref_until_done.h" |   18 #include "webrtc/base/keep_ref_until_done.h" | 
|   19 #include "webrtc/base/logging.h" |   19 #include "webrtc/base/logging.h" | 
|   20 #include "webrtc/base/scoped_ref_ptr.h" |   20 #include "webrtc/base/scoped_ref_ptr.h" | 
|   21  |   21  | 
|   22 using webrtc::NativeHandleBuffer; |   22 using webrtc::NativeHandleBuffer; | 
|   23  |   23  | 
|   24 namespace { |   24 namespace webrtc_jni { | 
|   25  |   25  | 
|   26 void RotateMatrix(float a[16], webrtc::VideoRotation rotation) { |   26 void NativeHandleImpl::Matrix::Rotate(webrtc::VideoRotation rotation) { | 
|   27   // Texture coordinates are in the range 0 to 1. The transformation of the last |   27   // Texture coordinates are in the range 0 to 1. The transformation of the last | 
|   28   // row in each rotation matrix is needed for proper translation, e.g, to |   28   // row in each rotation matrix is needed for proper translation, e.g, to | 
|   29   // mirror x, we don't replace x by -x, but by 1-x. |   29   // mirror x, we don't replace x by -x, but by 1-x. | 
|   30   switch (rotation) { |   30   switch (rotation) { | 
|   31     case webrtc::kVideoRotation_0: |   31     case webrtc::kVideoRotation_0: | 
|   32       break; |   32       break; | 
|   33     case webrtc::kVideoRotation_90: { |   33     case webrtc::kVideoRotation_90: { | 
|   34       const float ROTATE_90[16] = |   34       const Matrix ROTATE_90 = { | 
|   35           { a[4], a[5], a[6], a[7], |   35           {elem[4], elem[5], elem[6], elem[7], | 
|   36             -a[0], -a[1], -a[2], -a[3], |   36            -elem[0], -elem[1], -elem[2], -elem[3], | 
|   37             a[8], a[9], a[10], a[11], |   37            elem[8], elem[9], elem[10], elem[11], | 
|   38             a[0] + a[12], a[1] + a[13], a[2] + a[14], a[3] + a[15]}; |   38            elem[0] + elem[12], elem[1] + elem[13], | 
|   39       memcpy(a, ROTATE_90, sizeof(ROTATE_90)); |   39            elem[2] + elem[14], elem[3] + elem[15]}}; | 
 |   40       *this = ROTATE_90; | 
|   40     } break; |   41     } break; | 
|   41     case webrtc::kVideoRotation_180: { |   42     case webrtc::kVideoRotation_180: { | 
|   42       const float ROTATE_180[16] = |   43       const Matrix ROTATE_180 = { | 
|   43           { -a[0], -a[1], -a[2], -a[3], |   44           {-elem[0], -elem[1], -elem[2], -elem[3], | 
|   44             -a[4], -a[5], -a[6], -a[7], |   45            -elem[4], -elem[5], -elem[6], -elem[7], | 
|   45             a[8], a[9], a[10], a[11], |   46            elem[8], elem[9], elem[10], elem[11], | 
|   46             a[0] + a[4] + a[12], a[1] +a[5] + a[13], a[2] + a[6] + a[14], |   47            elem[0] + elem[4] + elem[12], elem[1] + elem[5] + elem[13], | 
|   47             a[3] + a[11]+ a[15]}; |   48            elem[2] + elem[6] + elem[14], elem[3] + elem[11] + elem[15]}}; | 
|   48         memcpy(a, ROTATE_180, sizeof(ROTATE_180)); |   49       *this = ROTATE_180; | 
|   49       } |   50       } | 
|   50       break; |   51       break; | 
|   51     case webrtc::kVideoRotation_270: { |   52     case webrtc::kVideoRotation_270: { | 
|   52       const float ROTATE_270[16] = |   53       const Matrix ROTATE_270 = { | 
|   53           { -a[4], -a[5], -a[6], -a[7], |   54           {-elem[4], -elem[5], -elem[6], -elem[7], | 
|   54             a[0], a[1], a[2], a[3], |   55            elem[0], elem[1], elem[2], elem[3], | 
|   55             a[8], a[9], a[10], a[11], |   56            elem[8], elem[9], elem[10], elem[11], | 
|   56             a[4] + a[12], a[5] + a[13], a[6] + a[14], a[7] + a[15]}; |   57            elem[4] + elem[12], elem[5] + elem[13], | 
|   57         memcpy(a, ROTATE_270, sizeof(ROTATE_270)); |   58            elem[6] + elem[14], elem[7] + elem[15]}}; | 
 |   59       *this = ROTATE_270; | 
|   58     } break; |   60     } break; | 
|   59   } |   61   } | 
|   60 } |   62 } | 
|   61  |   63  | 
|   62 // Calculates result = a * b, in column-major order. |   64 // Calculates result = a * b, in column-major order. | 
|   63 void MultiplyMatrix(const float a[16], const float b[16], float result[16]) { |   65 void NativeHandleImpl::Matrix::Multiply(const Matrix& a, | 
 |   66                                         const Matrix& b, | 
 |   67                                         Matrix* result) { | 
|   64   for (int i = 0; i < 4; ++i) { |   68   for (int i = 0; i < 4; ++i) { | 
|   65     for (int j = 0; j < 4; ++j) { |   69     for (int j = 0; j < 4; ++j) { | 
|   66       float sum = 0; |   70       float sum = 0; | 
|   67       for (int k = 0; k < 4; ++k) { |   71       for (int k = 0; k < 4; ++k) { | 
|   68         sum += a[k * 4 + j] * b[i * 4 + k]; |   72         sum += a.elem[k * 4 + j] * b.elem[i * 4 + k]; | 
|   69       } |   73       } | 
|   70       result[i * 4 + j] = sum; |   74       result->elem[i * 4 + j] = sum; | 
|   71     } |   75     } | 
|   72   } |   76   } | 
|   73 } |   77 } | 
|   74  |   78  | 
|   75 // Center crop by keeping xFraction of the width and yFraction of the height, |   79 // Center crop by keeping xFraction of the width and yFraction of the height, | 
|   76 // so e.g. cropping from 640x480 to 640x360 would use |   80 // so e.g. cropping from 640x480 to 640x360 would use | 
|   77 // xFraction=1, yFraction=360/480. |   81 // xFraction=1, yFraction=360/480. | 
|   78 void CropMatrix(float a[16], float xFraction, float yFraction) { |   82 void NativeHandleImpl::Matrix::Crop(float xFraction, | 
|   79   // Move cropped area to the center of the frame by offsetting half the |   83                                     float yFraction, | 
|   80   // removed area. |   84                                     float xOffset, | 
|   81   const float xOffset = (1 - xFraction) / 2; |   85                                     float yOffset) { | 
|   82   const float yOffset = (1 - yFraction) / 2; |   86   const Matrix crop_matrix = { | 
|   83   const float crop_matrix[16] = { |   87       {xFraction, 0, 0, 0, | 
|   84     xFraction, 0, 0, 0, |   88        0, yFraction, 0, 0, | 
|   85     0, yFraction, 0, 0, |   89        0, 0, 1, 0, | 
|   86     0, 0, 1, 0, |   90        xOffset, yOffset, 0, 1}}; | 
|   87     xOffset, yOffset, 0, 1}; |   91   Matrix result; | 
|   88   float mul_result[16]; |   92   Multiply(crop_matrix, *this, &result); | 
|   89   MultiplyMatrix(crop_matrix, a, mul_result); |   93   *this = result; | 
|   90   memcpy(a, mul_result, sizeof(mul_result)); |  | 
|   91 } |   94 } | 
|   92  |   95  | 
|   93 }  // anonymouse namespace |  | 
|   94  |  | 
|   95 namespace webrtc_jni { |  | 
|   96  |  | 
|   97 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. |   96 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. | 
|   98 static const int kBufferAlignment = 64; |   97 static const int kBufferAlignment = 64; | 
|   99  |   98  | 
 |   99 NativeHandleImpl::NativeHandleImpl(int id, const Matrix& matrix) | 
 |  100     : oes_texture_id(id), sampling_matrix(matrix) {} | 
 |  101  | 
|  100 NativeHandleImpl::NativeHandleImpl(JNIEnv* jni, |  102 NativeHandleImpl::NativeHandleImpl(JNIEnv* jni, | 
|  101                                    jint j_oes_texture_id, |  103                                    jint j_oes_texture_id, | 
|  102                                    jfloatArray j_transform_matrix) |  104                                    jfloatArray j_transform_matrix) | 
|  103   : oes_texture_id(j_oes_texture_id) { |  105   : oes_texture_id(j_oes_texture_id) { | 
|  104   RTC_CHECK_EQ(16, jni->GetArrayLength(j_transform_matrix)); |  106   RTC_CHECK_EQ(16, jni->GetArrayLength(j_transform_matrix)); | 
|  105   jfloat* transform_matrix_ptr = |  107   jfloat* transform_matrix_ptr = | 
|  106       jni->GetFloatArrayElements(j_transform_matrix, nullptr); |  108       jni->GetFloatArrayElements(j_transform_matrix, nullptr); | 
|  107   for (int i = 0; i < 16; ++i) { |  109   for (int i = 0; i < 16; ++i) { | 
|  108     sampling_matrix[i] = transform_matrix_ptr[i]; |  110     sampling_matrix.elem[i] = transform_matrix_ptr[i]; | 
|  109   } |  111   } | 
|  110   jni->ReleaseFloatArrayElements(j_transform_matrix, transform_matrix_ptr, 0); |  112   jni->ReleaseFloatArrayElements(j_transform_matrix, transform_matrix_ptr, 0); | 
|  111 } |  113 } | 
 |  114 #if 0 | 
 |  115 NativeHandleImpl NativeHandleImpl::Crop( | 
 |  116     float cropped_width, | 
 |  117     float cropped_height, | 
 |  118     float crop_x, | 
 |  119     float crop_y) const { | 
 |  120   float matrix[16]; | 
 |  121   memcpy(matrix, sampling_matrix, sizeof(matrix)); | 
 |  122  | 
 |  123   CropMatrix(matrix, cropped_width, cropped_height, crop_x, crop_y); | 
 |  124  | 
 |  125   return NativeHandleImpl(oes_texture_id, matrix); | 
 |  126 } | 
 |  127  | 
 |  128 NativeHandleImpl NativeHandleImpl::Rotate( | 
 |  129     webrtc::VideoRotation rotation) const { | 
 |  130   float matrix[16]; | 
 |  131   memcpy(matrix, sampling_matrix, sizeof(matrix)); | 
 |  132  | 
 |  133   RotateMatrix(matrix, rotation); | 
 |  134   return NativeHandleImpl(oes_texture_id, matrix); | 
 |  135 } | 
 |  136 #endif | 
|  112  |  137  | 
|  113 AndroidTextureBuffer::AndroidTextureBuffer( |  138 AndroidTextureBuffer::AndroidTextureBuffer( | 
|  114     int width, |  139     int width, | 
|  115     int height, |  140     int height, | 
|  116     const NativeHandleImpl& native_handle, |  141     const NativeHandleImpl& native_handle, | 
|  117     jobject surface_texture_helper, |  142     jobject surface_texture_helper, | 
|  118     const rtc::Callback0<void>& no_longer_used) |  143     const rtc::Callback0<void>& no_longer_used) | 
|  119     : webrtc::NativeHandleBuffer(&native_handle_, width, height), |  144     : webrtc::NativeHandleBuffer(&native_handle_, width, height), | 
|  120       native_handle_(native_handle), |  145       native_handle_(native_handle), | 
|  121       surface_texture_helper_(surface_texture_helper), |  146       surface_texture_helper_(surface_texture_helper), | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  158       jni, |  183       jni, | 
|  159       GetObjectClass(jni, surface_texture_helper_), |  184       GetObjectClass(jni, surface_texture_helper_), | 
|  160       "textureToYUV", |  185       "textureToYUV", | 
|  161       "(Ljava/nio/ByteBuffer;IIII[F)V"); |  186       "(Ljava/nio/ByteBuffer;IIII[F)V"); | 
|  162  |  187  | 
|  163   jobject byte_buffer = jni->NewDirectByteBuffer(y_data, size); |  188   jobject byte_buffer = jni->NewDirectByteBuffer(y_data, size); | 
|  164  |  189  | 
|  165   // TODO(nisse): Keep java transform matrix around. |  190   // TODO(nisse): Keep java transform matrix around. | 
|  166   jfloatArray sampling_matrix = jni->NewFloatArray(16); |  191   jfloatArray sampling_matrix = jni->NewFloatArray(16); | 
|  167   jni->SetFloatArrayRegion(sampling_matrix, 0, 16, |  192   jni->SetFloatArrayRegion(sampling_matrix, 0, 16, | 
|  168                            native_handle_.sampling_matrix); |  193                            native_handle_.sampling_matrix.elem); | 
|  169  |  194  | 
|  170   jni->CallVoidMethod(surface_texture_helper_, |  195   jni->CallVoidMethod(surface_texture_helper_, | 
|  171                       transform_mid, |  196                       transform_mid, | 
|  172                       byte_buffer, width(), height(), stride, |  197                       byte_buffer, width(), height(), stride, | 
|  173                       native_handle_.oes_texture_id, sampling_matrix); |  198                       native_handle_.oes_texture_id, sampling_matrix); | 
|  174   CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; |  199   CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; | 
|  175  |  200  | 
|  176   return copy; |  201   return copy; | 
|  177 } |  202 } | 
|  178  |  203  | 
|  179 rtc::scoped_refptr<AndroidTextureBuffer> |  204 rtc::scoped_refptr<AndroidTextureBuffer> | 
|  180 AndroidTextureBuffer::CropScaleAndRotate(int cropped_width, |  205 AndroidTextureBuffer::CropScaleAndRotate(int cropped_width, | 
|  181                                          int cropped_height, |  206                                          int cropped_height, | 
 |  207                                          int crop_x, | 
 |  208                                          int crop_y, | 
|  182                                          int dst_width, |  209                                          int dst_width, | 
|  183                                          int dst_height, |  210                                          int dst_height, | 
|  184                                          webrtc::VideoRotation rotation) { |  211                                          webrtc::VideoRotation rotation) { | 
|  185   if (cropped_width == dst_width && cropped_height == dst_height && |  212   if (cropped_width == dst_width && cropped_height == dst_height && | 
|  186       width() == dst_width && height() == dst_height && |  213       width() == dst_width && height() == dst_height && | 
|  187       rotation == webrtc::kVideoRotation_0) { |  214       rotation == webrtc::kVideoRotation_0) { | 
|  188     return this; |  215     return this; | 
|  189   } |  216   } | 
|  190   int rotated_width = (rotation % 180 == 0) ? dst_width : dst_height; |  217   int rotated_width = (rotation % 180 == 0) ? dst_width : dst_height; | 
|  191   int rotated_height = (rotation % 180 == 0) ? dst_height : dst_width; |  218   int rotated_height = (rotation % 180 == 0) ? dst_height : dst_width; | 
|  192  |  219  | 
|  193   // Here we use Bind magic to add a reference count to |this| until the newly |  220   // Here we use Bind magic to add a reference count to |this| until the newly | 
|  194   // created AndroidTextureBuffer is destructed |  221   // created AndroidTextureBuffer is destructed | 
|  195   rtc::scoped_refptr<AndroidTextureBuffer> buffer( |  222   rtc::scoped_refptr<AndroidTextureBuffer> buffer( | 
|  196       new rtc::RefCountedObject<AndroidTextureBuffer>( |  223       new rtc::RefCountedObject<AndroidTextureBuffer>( | 
|  197           rotated_width, rotated_height, native_handle_, |  224           rotated_width, rotated_height, native_handle_, | 
|  198           surface_texture_helper_, rtc::KeepRefUntilDone(this))); |  225           surface_texture_helper_, rtc::KeepRefUntilDone(this))); | 
|  199  |  226  | 
|  200   if (cropped_width != width() || cropped_height != height()) { |  227   if (cropped_width != width() || cropped_height != height()) { | 
|  201     CropMatrix(buffer->native_handle_.sampling_matrix, |  228     buffer->native_handle_.sampling_matrix.Crop( | 
|  202                cropped_width / static_cast<float>(width()), |  229         cropped_width / static_cast<float>(width()), | 
|  203                cropped_height / static_cast<float>(height())); |  230         cropped_height / static_cast<float>(height()), | 
 |  231         crop_x / static_cast<float>(width()), | 
 |  232         crop_y / static_cast<float>(height())); | 
|  204   } |  233   } | 
|  205   RotateMatrix(buffer->native_handle_.sampling_matrix, rotation); |  234   buffer->native_handle_.sampling_matrix.Rotate(rotation); | 
|  206   return buffer; |  235   return buffer; | 
|  207 } |  236 } | 
|  208  |  237  | 
|  209 }  // namespace webrtc_jni |  238 }  // namespace webrtc_jni | 
| OLD | NEW |