1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cpu-features.h>
18 #ifdef __ARM_NEON__
19 #include <arm_neon.h>
20 #endif
21 #include <jni.h>
22 
23 #include <android/log.h>
24 #include <android/native_window.h>
25 #include <android/native_window_jni.h>
26 #include <pthread.h>
27 #include <algorithm>
28 #include <cstdio>
29 #include <cstdlib>
30 #include <cstring>
31 #include <new>
32 
33 #define VPX_CODEC_DISABLE_COMPAT 1
34 #include "vpx/vpx_decoder.h"
35 #include "vpx/vp8dx.h"
36 
37 #define LOG_TAG "vpx_jni"
38 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
39                                              __VA_ARGS__))
40 
41 #define DECODER_FUNC(RETURN_TYPE, NAME, ...)                        \
42   extern "C" {                                                      \
43   JNIEXPORT RETURN_TYPE                                             \
44       Java_com_google_android_exoplayer2_ext_vp9_VpxDecoder_##NAME( \
45           JNIEnv* env, jobject thiz, ##__VA_ARGS__);                \
46   }                                                                 \
47   JNIEXPORT RETURN_TYPE                                             \
48       Java_com_google_android_exoplayer2_ext_vp9_VpxDecoder_##NAME( \
49           JNIEnv* env, jobject thiz, ##__VA_ARGS__)
50 
51 #define LIBRARY_FUNC(RETURN_TYPE, NAME, ...)                        \
52   extern "C" {                                                      \
53   JNIEXPORT RETURN_TYPE                                             \
54       Java_com_google_android_exoplayer2_ext_vp9_VpxLibrary_##NAME( \
55           JNIEnv* env, jobject thiz, ##__VA_ARGS__);                \
56   }                                                                 \
57   JNIEXPORT RETURN_TYPE                                             \
58       Java_com_google_android_exoplayer2_ext_vp9_VpxLibrary_##NAME( \
59           JNIEnv* env, jobject thiz, ##__VA_ARGS__)
60 
61 // JNI references for VideoDecoderOutputBuffer class.
62 static jmethodID initForYuvFrame;
63 static jmethodID initForPrivateFrame;
64 static jfieldID dataField;
65 static jfieldID outputModeField;
66 static jfieldID decoderPrivateField;
67 
68 // android.graphics.ImageFormat.YV12.
69 static const int kHalPixelFormatYV12 = 0x32315659;
70 static const int kDecoderPrivateBase = 0x100;
71 static int errorCode;
72 
JNI_OnLoad(JavaVM * vm,void * reserved)73 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
74   JNIEnv* env;
75   if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
76     return -1;
77   }
78   return JNI_VERSION_1_6;
79 }
80 
81 #ifdef __ARM_NEON__
convert_16_to_8_neon(const vpx_image_t * const img,jbyte * const data,const int32_t uvHeight,const int32_t yLength,const int32_t uvLength)82 static int convert_16_to_8_neon(const vpx_image_t* const img, jbyte* const data,
83                                 const int32_t uvHeight, const int32_t yLength,
84                                 const int32_t uvLength) {
85   if (!(android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)) return 0;
86   uint32x2_t lcg_val = vdup_n_u32(random());
87   lcg_val = vset_lane_u32(random(), lcg_val, 1);
88   // LCG values recommended in good ol' "Numerical Recipes"
89   const uint32x2_t LCG_MULT = vdup_n_u32(1664525);
90   const uint32x2_t LCG_INCR = vdup_n_u32(1013904223);
91 
92   const uint16_t* srcBase =
93       reinterpret_cast<uint16_t*>(img->planes[VPX_PLANE_Y]);
94   uint8_t* dstBase = reinterpret_cast<uint8_t*>(data);
95   // In units of uint16_t, so /2 from raw stride
96   const int srcStride = img->stride[VPX_PLANE_Y] / 2;
97   const int dstStride = img->stride[VPX_PLANE_Y];
98 
99   for (int y = 0; y < img->d_h; y++) {
100     const uint16_t* src = srcBase;
101     uint8_t* dst = dstBase;
102 
103     // Each read consumes 4 2-byte samples, but to reduce branches and
104     // random steps we unroll to four rounds, so each loop consumes 16
105     // samples.
106     const int imax = img->d_w & ~15;
107     int i;
108     for (i = 0; i < imax; i += 16) {
109       // Run a round of the RNG.
110       lcg_val = vmla_u32(LCG_INCR, lcg_val, LCG_MULT);
111 
112       // The lower two bits of this LCG parameterization are garbage,
113       // leaving streaks on the image. We access the upper bits of each
114       // 16-bit lane by shifting. (We use this both as an 8- and 16-bit
115       // vector, so the choice of which one to keep it as is arbitrary.)
116       uint8x8_t randvec =
117           vreinterpret_u8_u16(vshr_n_u16(vreinterpret_u16_u32(lcg_val), 8));
118 
119       // We retrieve the values and shift them so that the bits we'll
120       // shift out (after biasing) are in the upper 8 bits of each 16-bit
121       // lane.
122       uint16x4_t values = vshl_n_u16(vld1_u16(src), 6);
123       src += 4;
124 
125       // We add the bias bits in the lower 8 to the shifted values to get
126       // the final values in the upper 8 bits.
127       uint16x4_t added1 = vqadd_u16(values, vreinterpret_u16_u8(randvec));
128 
129       // Shifting the randvec bits left by 2 bits, as an 8-bit vector,
130       // should leave us with enough bias to get the needed rounding
131       // operation.
132       randvec = vshl_n_u8(randvec, 2);
133 
134       // Retrieve and sum the next 4 pixels.
135       values = vshl_n_u16(vld1_u16(src), 6);
136       src += 4;
137       uint16x4_t added2 = vqadd_u16(values, vreinterpret_u16_u8(randvec));
138 
139       // Reinterpret the two added vectors as 8x8, zip them together, and
140       // discard the lower portions.
141       uint8x8_t zipped =
142           vuzp_u8(vreinterpret_u8_u16(added1), vreinterpret_u8_u16(added2))
143               .val[1];
144       vst1_u8(dst, zipped);
145       dst += 8;
146 
147       // Run it again with the next two rounds using the remaining
148       // entropy in randvec.
149       randvec = vshl_n_u8(randvec, 2);
150       values = vshl_n_u16(vld1_u16(src), 6);
151       src += 4;
152       added1 = vqadd_u16(values, vreinterpret_u16_u8(randvec));
153       randvec = vshl_n_u8(randvec, 2);
154       values = vshl_n_u16(vld1_u16(src), 6);
155       src += 4;
156       added2 = vqadd_u16(values, vreinterpret_u16_u8(randvec));
157       zipped = vuzp_u8(vreinterpret_u8_u16(added1), vreinterpret_u8_u16(added2))
158                    .val[1];
159       vst1_u8(dst, zipped);
160       dst += 8;
161     }
162 
163     uint32_t randval = 0;
164     // For the remaining pixels in each row - usually none, as most
165     // standard sizes are divisible by 32 - convert them "by hand".
166     while (i < img->d_w) {
167       if (!randval) randval = random();
168       dstBase[i] = (srcBase[i] + (randval & 3)) >> 2;
169       i++;
170       randval >>= 2;
171     }
172 
173     srcBase += srcStride;
174     dstBase += dstStride;
175   }
176 
177   const uint16_t* srcUBase =
178       reinterpret_cast<uint16_t*>(img->planes[VPX_PLANE_U]);
179   const uint16_t* srcVBase =
180       reinterpret_cast<uint16_t*>(img->planes[VPX_PLANE_V]);
181   const int32_t uvWidth = (img->d_w + 1) / 2;
182   uint8_t* dstUBase = reinterpret_cast<uint8_t*>(data + yLength);
183   uint8_t* dstVBase = reinterpret_cast<uint8_t*>(data + yLength + uvLength);
184   const int srcUVStride = img->stride[VPX_PLANE_V] / 2;
185   const int dstUVStride = img->stride[VPX_PLANE_V];
186 
187   for (int y = 0; y < uvHeight; y++) {
188     const uint16_t* srcU = srcUBase;
189     const uint16_t* srcV = srcVBase;
190     uint8_t* dstU = dstUBase;
191     uint8_t* dstV = dstVBase;
192 
193     // As before, each i++ consumes 4 samples (8 bytes). For simplicity we
194     // don't unroll these loops more than we have to, which is 8 samples.
195     const int imax = uvWidth & ~7;
196     int i;
197     for (i = 0; i < imax; i += 8) {
198       lcg_val = vmla_u32(LCG_INCR, lcg_val, LCG_MULT);
199       uint8x8_t randvec =
200           vreinterpret_u8_u16(vshr_n_u16(vreinterpret_u16_u32(lcg_val), 8));
201       uint16x4_t uVal1 = vqadd_u16(vshl_n_u16(vld1_u16(srcU), 6),
202                                    vreinterpret_u16_u8(randvec));
203       srcU += 4;
204       randvec = vshl_n_u8(randvec, 2);
205       uint16x4_t vVal1 = vqadd_u16(vshl_n_u16(vld1_u16(srcV), 6),
206                                    vreinterpret_u16_u8(randvec));
207       srcV += 4;
208       randvec = vshl_n_u8(randvec, 2);
209       uint16x4_t uVal2 = vqadd_u16(vshl_n_u16(vld1_u16(srcU), 6),
210                                    vreinterpret_u16_u8(randvec));
211       srcU += 4;
212       randvec = vshl_n_u8(randvec, 2);
213       uint16x4_t vVal2 = vqadd_u16(vshl_n_u16(vld1_u16(srcV), 6),
214                                    vreinterpret_u16_u8(randvec));
215       srcV += 4;
216       vst1_u8(dstU,
217               vuzp_u8(vreinterpret_u8_u16(uVal1), vreinterpret_u8_u16(uVal2))
218                   .val[1]);
219       dstU += 8;
220       vst1_u8(dstV,
221               vuzp_u8(vreinterpret_u8_u16(vVal1), vreinterpret_u8_u16(vVal2))
222                   .val[1]);
223       dstV += 8;
224     }
225 
226     uint32_t randval = 0;
227     while (i < uvWidth) {
228       if (!randval) randval = random();
229       dstUBase[i] = (srcUBase[i] + (randval & 3)) >> 2;
230       randval >>= 2;
231       dstVBase[i] = (srcVBase[i] + (randval & 3)) >> 2;
232       randval >>= 2;
233       i++;
234     }
235 
236     srcUBase += srcUVStride;
237     srcVBase += srcUVStride;
238     dstUBase += dstUVStride;
239     dstVBase += dstUVStride;
240   }
241 
242   return 1;
243 }
244 
245 #endif  // __ARM_NEON__
246 
convert_16_to_8_standard(const vpx_image_t * const img,jbyte * const data,const int32_t uvHeight,const int32_t yLength,const int32_t uvLength)247 static void convert_16_to_8_standard(const vpx_image_t* const img,
248                                      jbyte* const data, const int32_t uvHeight,
249                                      const int32_t yLength,
250                                      const int32_t uvLength) {
251   // Y
252   int sampleY = 0;
253   for (int y = 0; y < img->d_h; y++) {
254     const uint16_t* srcBase = reinterpret_cast<uint16_t*>(
255         img->planes[VPX_PLANE_Y] + img->stride[VPX_PLANE_Y] * y);
256     int8_t* destBase = data + img->stride[VPX_PLANE_Y] * y;
257     for (int x = 0; x < img->d_w; x++) {
258       // Lightweight dither. Carryover the remainder of each 10->8 bit
259       // conversion to the next pixel.
260       sampleY += *srcBase++;
261       *destBase++ = sampleY >> 2;
262       sampleY = sampleY & 3;  // Remainder.
263     }
264   }
265   // UV
266   int sampleU = 0;
267   int sampleV = 0;
268   const int32_t uvWidth = (img->d_w + 1) / 2;
269   for (int y = 0; y < uvHeight; y++) {
270     const uint16_t* srcUBase = reinterpret_cast<uint16_t*>(
271         img->planes[VPX_PLANE_U] + img->stride[VPX_PLANE_U] * y);
272     const uint16_t* srcVBase = reinterpret_cast<uint16_t*>(
273         img->planes[VPX_PLANE_V] + img->stride[VPX_PLANE_V] * y);
274     int8_t* destUBase = data + yLength + img->stride[VPX_PLANE_U] * y;
275     int8_t* destVBase =
276         data + yLength + uvLength + img->stride[VPX_PLANE_V] * y;
277     for (int x = 0; x < uvWidth; x++) {
278       // Lightweight dither. Carryover the remainder of each 10->8 bit
279       // conversion to the next pixel.
280       sampleU += *srcUBase++;
281       *destUBase++ = sampleU >> 2;
282       sampleU = sampleU & 3;  // Remainder.
283       sampleV += *srcVBase++;
284       *destVBase++ = sampleV >> 2;
285       sampleV = sampleV & 3;  // Remainder.
286     }
287   }
288 }
289 
290 struct JniFrameBuffer {
291   friend class JniBufferManager;
292 
293   int stride[4];
294   uint8_t* planes[4];
295   int d_w;
296   int d_h;
297 
298  private:
299   int id;
300   int ref_count;
301   vpx_codec_frame_buffer_t vpx_fb;
302 };
303 
304 class JniBufferManager {
305   static const int MAX_FRAMES = 32;
306 
307   JniFrameBuffer* all_buffers[MAX_FRAMES];
308   int all_buffer_count = 0;
309 
310   JniFrameBuffer* free_buffers[MAX_FRAMES];
311   int free_buffer_count = 0;
312 
313   pthread_mutex_t mutex;
314 
315  public:
JniBufferManager()316   JniBufferManager() { pthread_mutex_init(&mutex, NULL); }
317 
~JniBufferManager()318   ~JniBufferManager() {
319     while (all_buffer_count--) {
320       free(all_buffers[all_buffer_count]->vpx_fb.data);
321     }
322   }
323 
get_buffer(size_t min_size,vpx_codec_frame_buffer_t * fb)324   int get_buffer(size_t min_size, vpx_codec_frame_buffer_t* fb) {
325     pthread_mutex_lock(&mutex);
326     JniFrameBuffer* out_buffer;
327     if (free_buffer_count) {
328       out_buffer = free_buffers[--free_buffer_count];
329       if (out_buffer->vpx_fb.size < min_size) {
330         free(out_buffer->vpx_fb.data);
331         out_buffer->vpx_fb.data = (uint8_t*)malloc(min_size);
332         out_buffer->vpx_fb.size = min_size;
333       }
334     } else {
335       out_buffer = new JniFrameBuffer();
336       out_buffer->id = all_buffer_count;
337       all_buffers[all_buffer_count++] = out_buffer;
338       out_buffer->vpx_fb.data = (uint8_t*)malloc(min_size);
339       out_buffer->vpx_fb.size = min_size;
340       out_buffer->vpx_fb.priv = &out_buffer->id;
341     }
342     *fb = out_buffer->vpx_fb;
343     int retVal = 0;
344     if (!out_buffer->vpx_fb.data || all_buffer_count >= MAX_FRAMES) {
345       LOGE("JniBufferManager get_buffer OOM.");
346       retVal = -1;
347     } else {
348       memset(fb->data, 0, fb->size);
349     }
350     out_buffer->ref_count = 1;
351     pthread_mutex_unlock(&mutex);
352     return retVal;
353   }
354 
get_buffer(int id) const355   JniFrameBuffer* get_buffer(int id) const {
356     if (id < 0 || id >= all_buffer_count) {
357       LOGE("JniBufferManager get_buffer invalid id %d.", id);
358       return NULL;
359     }
360     return all_buffers[id];
361   }
362 
add_ref(int id)363   void add_ref(int id) {
364     if (id < 0 || id >= all_buffer_count) {
365       LOGE("JniBufferManager add_ref invalid id %d.", id);
366       return;
367     }
368     pthread_mutex_lock(&mutex);
369     all_buffers[id]->ref_count++;
370     pthread_mutex_unlock(&mutex);
371   }
372 
release(int id)373   int release(int id) {
374     if (id < 0 || id >= all_buffer_count) {
375       LOGE("JniBufferManager release invalid id %d.", id);
376       return -1;
377     }
378     pthread_mutex_lock(&mutex);
379     JniFrameBuffer* buffer = all_buffers[id];
380     if (!buffer->ref_count) {
381       LOGE("JniBufferManager release, buffer already released.");
382       pthread_mutex_unlock(&mutex);
383       return -1;
384     }
385     if (!--buffer->ref_count) {
386       free_buffers[free_buffer_count++] = buffer;
387     }
388     pthread_mutex_unlock(&mutex);
389     return 0;
390   }
391 };
392 
393 struct JniCtx {
JniCtxJniCtx394   JniCtx() { buffer_manager = new JniBufferManager(); }
395 
~JniCtxJniCtx396   ~JniCtx() {
397     if (native_window) {
398       ANativeWindow_release(native_window);
399     }
400     if (buffer_manager) {
401       delete buffer_manager;
402     }
403   }
404 
acquire_native_windowJniCtx405   void acquire_native_window(JNIEnv* env, jobject new_surface) {
406     if (surface != new_surface) {
407       if (native_window) {
408         ANativeWindow_release(native_window);
409       }
410       native_window = ANativeWindow_fromSurface(env, new_surface);
411       surface = new_surface;
412       width = 0;
413     }
414   }
415 
416   JniBufferManager* buffer_manager = NULL;
417   vpx_codec_ctx_t* decoder = NULL;
418   ANativeWindow* native_window = NULL;
419   jobject surface = NULL;
420   int width = 0;
421   int height = 0;
422 };
423 
vpx_get_frame_buffer(void * priv,size_t min_size,vpx_codec_frame_buffer_t * fb)424 int vpx_get_frame_buffer(void* priv, size_t min_size,
425                          vpx_codec_frame_buffer_t* fb) {
426   JniBufferManager* const buffer_manager =
427       reinterpret_cast<JniBufferManager*>(priv);
428   return buffer_manager->get_buffer(min_size, fb);
429 }
430 
vpx_release_frame_buffer(void * priv,vpx_codec_frame_buffer_t * fb)431 int vpx_release_frame_buffer(void* priv, vpx_codec_frame_buffer_t* fb) {
432   JniBufferManager* const buffer_manager =
433       reinterpret_cast<JniBufferManager*>(priv);
434   return buffer_manager->release(*(int*)fb->priv);
435 }
436 
DECODER_FUNC(jlong,vpxInit,jboolean disableLoopFilter,jboolean enableRowMultiThreadMode,jint threads)437 DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter,
438              jboolean enableRowMultiThreadMode, jint threads) {
439   JniCtx* context = new JniCtx();
440   context->decoder = new vpx_codec_ctx_t();
441   vpx_codec_dec_cfg_t cfg = {0, 0, 0};
442   cfg.threads = threads;
443   errorCode = 0;
444   vpx_codec_err_t err =
445       vpx_codec_dec_init(context->decoder, &vpx_codec_vp9_dx_algo, &cfg, 0);
446   if (err) {
447     LOGE("Failed to initialize libvpx decoder, error = %d.", err);
448     errorCode = err;
449     return 0;
450   }
451 #ifdef VPX_CTRL_VP9_DECODE_SET_ROW_MT
452   err = vpx_codec_control(context->decoder, VP9D_SET_ROW_MT,
453                           enableRowMultiThreadMode);
454   if (err) {
455     LOGE("Failed to enable row multi thread mode, error = %d.", err);
456   }
457 #endif
458   if (disableLoopFilter) {
459     err = vpx_codec_control(context->decoder, VP9_SET_SKIP_LOOP_FILTER, true);
460     if (err) {
461       LOGE("Failed to shut off libvpx loop filter, error = %d.", err);
462     }
463 #ifdef VPX_CTRL_VP9_SET_LOOP_FILTER_OPT
464   } else {
465     err = vpx_codec_control(context->decoder, VP9D_SET_LOOP_FILTER_OPT, true);
466     if (err) {
467       LOGE("Failed to enable loop filter optimization, error = %d.", err);
468     }
469 #endif
470   }
471   err = vpx_codec_set_frame_buffer_functions(
472       context->decoder, vpx_get_frame_buffer, vpx_release_frame_buffer,
473       context->buffer_manager);
474   if (err) {
475     LOGE("Failed to set libvpx frame buffer functions, error = %d.", err);
476   }
477 
478   // Populate JNI References.
479   const jclass outputBufferClass = env->FindClass(
480       "com/google/android/exoplayer2/video/VideoDecoderOutputBuffer");
481   initForYuvFrame = env->GetMethodID(outputBufferClass, "initForYuvFrame",
482                                      "(IIIII)Z");
483   initForPrivateFrame =
484       env->GetMethodID(outputBufferClass, "initForPrivateFrame", "(II)V");
485   dataField = env->GetFieldID(outputBufferClass, "data",
486                               "Ljava/nio/ByteBuffer;");
487   outputModeField = env->GetFieldID(outputBufferClass, "mode", "I");
488   decoderPrivateField =
489       env->GetFieldID(outputBufferClass, "decoderPrivate", "I");
490   return reinterpret_cast<intptr_t>(context);
491 }
492 
DECODER_FUNC(jlong,vpxDecode,jlong jContext,jobject encoded,jint len)493 DECODER_FUNC(jlong, vpxDecode, jlong jContext, jobject encoded, jint len) {
494   JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
495   const uint8_t* const buffer =
496       reinterpret_cast<const uint8_t*>(env->GetDirectBufferAddress(encoded));
497   const vpx_codec_err_t status =
498       vpx_codec_decode(context->decoder, buffer, len, NULL, 0);
499   errorCode = 0;
500   if (status != VPX_CODEC_OK) {
501     LOGE("vpx_codec_decode() failed, status= %d", status);
502     errorCode = status;
503     return -1;
504   }
505   return 0;
506 }
507 
DECODER_FUNC(jlong,vpxSecureDecode,jlong jContext,jobject encoded,jint len,jobject mediaCrypto,jint inputMode,jbyteArray &,jbyteArray &,jint inputNumSubSamples,jintArray numBytesOfClearData,jintArray numBytesOfEncryptedData)508 DECODER_FUNC(jlong, vpxSecureDecode, jlong jContext, jobject encoded, jint len,
509     jobject mediaCrypto, jint inputMode, jbyteArray&, jbyteArray&,
510     jint inputNumSubSamples, jintArray numBytesOfClearData,
511     jintArray numBytesOfEncryptedData) {
512   // Doesn't support
513   // Java client should have checked vpxSupportSecureDecode
514   // and avoid calling this
515   // return -2 (DRM Error)
516   return -2;
517 }
518 
DECODER_FUNC(jlong,vpxClose,jlong jContext)519 DECODER_FUNC(jlong, vpxClose, jlong jContext) {
520   JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
521   vpx_codec_destroy(context->decoder);
522   delete context;
523   return 0;
524 }
525 
DECODER_FUNC(jint,vpxGetFrame,jlong jContext,jobject jOutputBuffer)526 DECODER_FUNC(jint, vpxGetFrame, jlong jContext, jobject jOutputBuffer) {
527   JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
528   vpx_codec_iter_t iter = NULL;
529   const vpx_image_t* const img = vpx_codec_get_frame(context->decoder, &iter);
530 
531   if (img == NULL) {
532     return 1;
533   }
534 
535   // LINT.IfChange
536   const int kOutputModeYuv = 0;
537   const int kOutputModeSurfaceYuv = 1;
538   // LINT.ThenChange(../../../../../library/common/src/main/java/com/google/android/exoplayer2/C.java)
539 
540   int outputMode = env->GetIntField(jOutputBuffer, outputModeField);
541   if (outputMode == kOutputModeYuv) {
542     // LINT.IfChange
543     const int kColorspaceUnknown = 0;
544     const int kColorspaceBT601 = 1;
545     const int kColorspaceBT709 = 2;
546     const int kColorspaceBT2020 = 3;
547     // LINT.ThenChange(../../../../../library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java)
548 
549     int colorspace = kColorspaceUnknown;
550     switch (img->cs) {
551       case VPX_CS_BT_601:
552         colorspace = kColorspaceBT601;
553         break;
554       case VPX_CS_BT_709:
555         colorspace = kColorspaceBT709;
556         break;
557     case VPX_CS_BT_2020:
558         colorspace = kColorspaceBT2020;
559         break;
560       default:
561         break;
562     }
563 
564     // resize buffer if required.
565     jboolean initResult = env->CallBooleanMethod(
566         jOutputBuffer, initForYuvFrame, img->d_w, img->d_h,
567         img->stride[VPX_PLANE_Y], img->stride[VPX_PLANE_U], colorspace);
568     if (env->ExceptionCheck() || !initResult) {
569       return -1;
570     }
571 
572     // get pointer to the data buffer.
573     const jobject dataObject = env->GetObjectField(jOutputBuffer, dataField);
574     jbyte* const data =
575         reinterpret_cast<jbyte*>(env->GetDirectBufferAddress(dataObject));
576 
577     const int32_t uvHeight = (img->d_h + 1) / 2;
578     const uint64_t yLength = img->stride[VPX_PLANE_Y] * img->d_h;
579     const uint64_t uvLength = img->stride[VPX_PLANE_U] * uvHeight;
580     if (img->fmt == VPX_IMG_FMT_I42016) {  // HBD planar 420.
581       // Note: The stride for BT2020 is twice of what we use so this is wasting
582       // memory. The long term goal however is to upload half-float/short so
583       // it's not important to optimize the stride at this time.
584       int converted = 0;
585 #ifdef __ARM_NEON__
586       converted = convert_16_to_8_neon(img, data, uvHeight, yLength, uvLength);
587 #endif  // __ARM_NEON__
588       if (!converted) {
589         convert_16_to_8_standard(img, data, uvHeight, yLength, uvLength);
590       }
591     } else {
592       // TODO: This copy can be eliminated by using external frame
593       // buffers. This is insignificant for smaller videos but takes ~1.5ms
594       // for 1080p clips. So this should eventually be gotten rid of.
595       memcpy(data, img->planes[VPX_PLANE_Y], yLength);
596       memcpy(data + yLength, img->planes[VPX_PLANE_U], uvLength);
597       memcpy(data + yLength + uvLength, img->planes[VPX_PLANE_V], uvLength);
598     }
599   } else if (outputMode == kOutputModeSurfaceYuv) {
600     if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
601       LOGE(
602           "High bit depth output format %d not supported in surface YUV output "
603           "mode",
604           img->fmt);
605       return -1;
606     }
607     int id = *(int*)img->fb_priv;
608     context->buffer_manager->add_ref(id);
609     JniFrameBuffer* jfb = context->buffer_manager->get_buffer(id);
610     for (int i = 2; i >= 0; i--) {
611       jfb->stride[i] = img->stride[i];
612       jfb->planes[i] = (uint8_t*)img->planes[i];
613     }
614     jfb->d_w = img->d_w;
615     jfb->d_h = img->d_h;
616     env->CallVoidMethod(jOutputBuffer, initForPrivateFrame, img->d_w, img->d_h);
617     if (env->ExceptionCheck()) {
618       return -1;
619     }
620     env->SetIntField(jOutputBuffer, decoderPrivateField,
621                      id + kDecoderPrivateBase);
622   }
623   return 0;
624 }
625 
DECODER_FUNC(jint,vpxRenderFrame,jlong jContext,jobject jSurface,jobject jOutputBuffer)626 DECODER_FUNC(jint, vpxRenderFrame, jlong jContext, jobject jSurface,
627              jobject jOutputBuffer) {
628   JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
629   const int id = env->GetIntField(jOutputBuffer, decoderPrivateField) -
630                  kDecoderPrivateBase;
631   JniFrameBuffer* srcBuffer = context->buffer_manager->get_buffer(id);
632   context->acquire_native_window(env, jSurface);
633   if (context->native_window == NULL || !srcBuffer) {
634     return 1;
635   }
636   if (context->width != srcBuffer->d_w || context->height != srcBuffer->d_h) {
637     ANativeWindow_setBuffersGeometry(context->native_window, srcBuffer->d_w,
638                                      srcBuffer->d_h, kHalPixelFormatYV12);
639     context->width = srcBuffer->d_w;
640     context->height = srcBuffer->d_h;
641   }
642   ANativeWindow_Buffer buffer;
643   int result = ANativeWindow_lock(context->native_window, &buffer, NULL);
644   if (buffer.bits == NULL || result) {
645     return -1;
646   }
647   // Y
648   const size_t src_y_stride = srcBuffer->stride[VPX_PLANE_Y];
649   int stride = srcBuffer->d_w;
650   const uint8_t* src_base =
651       reinterpret_cast<uint8_t*>(srcBuffer->planes[VPX_PLANE_Y]);
652   uint8_t* dest_base = (uint8_t*)buffer.bits;
653   for (int y = 0; y < srcBuffer->d_h; y++) {
654     memcpy(dest_base, src_base, stride);
655     src_base += src_y_stride;
656     dest_base += buffer.stride;
657   }
658   // UV
659   const int src_uv_stride = srcBuffer->stride[VPX_PLANE_U];
660   const int dest_uv_stride = (buffer.stride / 2 + 15) & (~15);
661   const int32_t buffer_uv_height = (buffer.height + 1) / 2;
662   const int32_t height =
663       std::min((int32_t)(srcBuffer->d_h + 1) / 2, buffer_uv_height);
664   stride = (srcBuffer->d_w + 1) / 2;
665   src_base = reinterpret_cast<uint8_t*>(srcBuffer->planes[VPX_PLANE_U]);
666   const uint8_t* src_v_base =
667       reinterpret_cast<uint8_t*>(srcBuffer->planes[VPX_PLANE_V]);
668   uint8_t* dest_v_base =
669       ((uint8_t*)buffer.bits) + buffer.stride * buffer.height;
670   dest_base = dest_v_base + buffer_uv_height * dest_uv_stride;
671   for (int y = 0; y < height; y++) {
672     memcpy(dest_base, src_base, stride);
673     memcpy(dest_v_base, src_v_base, stride);
674     src_base += src_uv_stride;
675     src_v_base += src_uv_stride;
676     dest_base += dest_uv_stride;
677     dest_v_base += dest_uv_stride;
678   }
679   return ANativeWindow_unlockAndPost(context->native_window);
680 }
681 
DECODER_FUNC(void,vpxReleaseFrame,jlong jContext,jobject jOutputBuffer)682 DECODER_FUNC(void, vpxReleaseFrame, jlong jContext, jobject jOutputBuffer) {
683   JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
684   const int id = env->GetIntField(jOutputBuffer, decoderPrivateField) -
685                  kDecoderPrivateBase;
686   env->SetIntField(jOutputBuffer, decoderPrivateField, -1);
687   context->buffer_manager->release(id);
688 }
689 
DECODER_FUNC(jstring,vpxGetErrorMessage,jlong jContext)690 DECODER_FUNC(jstring, vpxGetErrorMessage, jlong jContext) {
691   JniCtx* const context = reinterpret_cast<JniCtx*>(jContext);
692   return env->NewStringUTF(vpx_codec_error(context->decoder));
693 }
694 
DECODER_FUNC(jint,vpxGetErrorCode,jlong jContext)695 DECODER_FUNC(jint, vpxGetErrorCode, jlong jContext) { return errorCode; }
696 
LIBRARY_FUNC(jstring,vpxIsSecureDecodeSupported)697 LIBRARY_FUNC(jstring, vpxIsSecureDecodeSupported) {
698   // Doesn't support
699   return 0;
700 }
701 
LIBRARY_FUNC(jstring,vpxGetVersion)702 LIBRARY_FUNC(jstring, vpxGetVersion) {
703   return env->NewStringUTF(vpx_codec_version_str());
704 }
705 
LIBRARY_FUNC(jstring,vpxGetBuildConfig)706 LIBRARY_FUNC(jstring, vpxGetBuildConfig) {
707   return env->NewStringUTF(vpx_codec_build_config());
708 }
709