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