1 /*
2  * Copyright (C) 2014 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 /* Original code copied from NDK Native-media sample code */
18 
19 //#define LOG_NDEBUG 0
20 #define TAG "NativeMedia"
21 #include <log/log.h>
22 
23 #include <assert.h>
24 #include <jni.h>
25 #include <pthread.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <semaphore.h>
30 
31 #include <android/native_window_jni.h>
32 #include <EGL/egl.h>
33 #include <EGL/eglext.h>
34 
35 #include "media/NdkMediaExtractor.h"
36 #include "media/NdkMediaCodec.h"
37 #include "media/NdkMediaCrypto.h"
38 #include "media/NdkMediaFormat.h"
39 #include "media/NdkMediaMuxer.h"
40 
41 template <class T>
42 class simplevector {
43     T *storage;
44     int capacity;
45     int numfilled;
46 public:
simplevector()47     simplevector() {
48         capacity = 16;
49         numfilled = 0;
50         storage = new T[capacity];
51     }
~simplevector()52     ~simplevector() {
53         delete[] storage;
54     }
55 
add(T item)56     void add(T item) {
57         if (numfilled == capacity) {
58             T *old = storage;
59             capacity *= 2;
60             storage = new T[capacity];
61             for (int i = 0; i < numfilled; i++) {
62                 storage[i] = old[i];
63             }
64             delete[] old;
65         }
66         storage[numfilled] = item;
67         numfilled++;
68     }
69 
size()70     int size() {
71         return numfilled;
72     }
73 
data()74     T* data() {
75         return storage;
76     }
77 };
78 
79 
80 
testExtractor(AMediaExtractor * ex,JNIEnv * env)81 jobject testExtractor(AMediaExtractor *ex, JNIEnv *env) {
82 
83     simplevector<int> sizes;
84     int numtracks = AMediaExtractor_getTrackCount(ex);
85     sizes.add(numtracks);
86     for (int i = 0; i < numtracks; i++) {
87         AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
88         const char *s = AMediaFormat_toString(format);
89         ALOGI("track %d format: %s", i, s);
90         const char *mime;
91         if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
92             ALOGE("no mime type");
93             return NULL;
94         } else if (!strncmp(mime, "audio/", 6)) {
95             sizes.add(0);
96             int32_t val32;
97             int64_t val64;
98             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &val32);
99             sizes.add(val32);
100             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &val32);
101             sizes.add(val32);
102             AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64);
103             sizes.add(val64);
104         } else if (!strncmp(mime, "video/", 6)) {
105             sizes.add(1);
106             int32_t val32;
107             int64_t val64;
108             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &val32);
109             sizes.add(val32);
110             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &val32);
111             sizes.add(val32);
112             AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64);
113             sizes.add(val64);
114         } else {
115             ALOGE("expected audio or video mime type, got %s", mime);
116         }
117         AMediaFormat_delete(format);
118         AMediaExtractor_selectTrack(ex, i);
119     }
120     int bufsize = 1024*1024;
121     uint8_t *buf = new uint8_t[bufsize];
122     while(true) {
123         int n = AMediaExtractor_readSampleData(ex, buf, bufsize);
124         if (n < 0) {
125             break;
126         }
127         sizes.add(n);
128         sizes.add(AMediaExtractor_getSampleTrackIndex(ex));
129         sizes.add(AMediaExtractor_getSampleFlags(ex));
130         sizes.add(AMediaExtractor_getSampleTime(ex));
131         AMediaExtractor_advance(ex);
132     }
133 
134     // allocate java int array for result and return it
135     int *data = sizes.data();
136     int numsamples = sizes.size();
137     jintArray ret = env->NewIntArray(numsamples);
138     jboolean isCopy;
139     jint *dst = env->GetIntArrayElements(ret, &isCopy);
140     for (int i = 0; i < numsamples; ++i) {
141         dst[i] = data[i];
142     }
143     env->ReleaseIntArrayElements(ret, dst, 0);
144 
145     delete[] buf;
146     AMediaExtractor_delete(ex);
147     return ret;
148 }
149 
150 
151 // get the sample sizes for the file
Java_android_media_cts_NativeDecoderTest_getSampleSizesNative(JNIEnv * env,jclass,int fd,jlong offset,jlong size)152 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNative(JNIEnv *env,
153         jclass /*clazz*/, int fd, jlong offset, jlong size)
154 {
155     AMediaExtractor *ex = AMediaExtractor_new();
156     int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
157     if (err != 0) {
158         ALOGE("setDataSource error: %d", err);
159         return NULL;
160     }
161     return testExtractor(ex, env);
162 }
163 
164 // get the sample sizes for the path
Java_android_media_cts_NativeDecoderTest_getSampleSizesNativePath(JNIEnv * env,jclass,jstring jpath)165 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNativePath(JNIEnv *env,
166         jclass /*clazz*/, jstring jpath)
167 {
168     AMediaExtractor *ex = AMediaExtractor_new();
169 
170     const char *tmp = env->GetStringUTFChars(jpath, NULL);
171     if (tmp == NULL) {  // Out of memory
172         return NULL;
173     }
174 
175     int err = AMediaExtractor_setDataSource(ex, tmp);
176 
177     env->ReleaseStringUTFChars(jpath, tmp);
178 
179     if (err != 0) {
180         ALOGE("setDataSource error: %d", err);
181         return NULL;
182     }
183     return testExtractor(ex, env);
184 }
185 
adler32(const uint8_t * input,int len)186 static int adler32(const uint8_t *input, int len) {
187 
188     int a = 1;
189     int b = 0;
190     for (int i = 0; i < len; i++) {
191         a += input[i];
192         b += a;
193     }
194     a = a % 65521;
195     b = b % 65521;
196     int ret = b * 65536 + a;
197     ALOGV("adler %d/%d", len, ret);
198     return ret;
199 }
200 
checksum(const uint8_t * in,int len,AMediaFormat * format)201 static int checksum(const uint8_t *in, int len, AMediaFormat *format) {
202     int width, stride, height;
203     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width)) {
204         width = len;
205     }
206     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_STRIDE, &stride)) {
207         stride = width;
208     }
209     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height)) {
210         height = 1;
211     }
212     uint8_t *bb = new uint8_t[width * height];
213     for (int i = 0; i < height; i++) {
214         memcpy(bb + i * width, in + i * stride, width);
215     }
216     // bb is filled with data
217     int sum = adler32(bb, width * height);
218     delete[] bb;
219     return sum;
220 }
221 
Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv * env,jclass,int fd,jlong offset,jlong size)222 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv *env,
223         jclass /*clazz*/, int fd, jlong offset, jlong size) {
224     ALOGV("getDecodedDataNative");
225 
226     AMediaExtractor *ex = AMediaExtractor_new();
227     int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
228     if (err != 0) {
229         ALOGE("setDataSource error: %d", err);
230         return NULL;
231     }
232 
233     int numtracks = AMediaExtractor_getTrackCount(ex);
234 
235     AMediaCodec **codec = new AMediaCodec*[numtracks];
236     AMediaFormat **format = new AMediaFormat*[numtracks];
237     bool *sawInputEOS = new bool[numtracks];
238     bool *sawOutputEOS = new bool[numtracks];
239     simplevector<int> *sizes = new simplevector<int>[numtracks];
240 
241     ALOGV("input has %d tracks", numtracks);
242     for (int i = 0; i < numtracks; i++) {
243         AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
244         const char *s = AMediaFormat_toString(format);
245         ALOGI("track %d format: %s", i, s);
246         const char *mime;
247         if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
248             ALOGE("no mime type");
249             return NULL;
250         } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) {
251             codec[i] = AMediaCodec_createDecoderByType(mime);
252             AMediaCodec_configure(codec[i], format, NULL /* surface */, NULL /* crypto */, 0);
253             AMediaCodec_start(codec[i]);
254             sawInputEOS[i] = false;
255             sawOutputEOS[i] = false;
256         } else {
257             ALOGE("expected audio or video mime type, got %s", mime);
258             return NULL;
259         }
260         AMediaFormat_delete(format);
261         AMediaExtractor_selectTrack(ex, i);
262     }
263     int eosCount = 0;
264     while(eosCount < numtracks) {
265         int t = AMediaExtractor_getSampleTrackIndex(ex);
266         if (t >=0) {
267             ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec[t], 5000);
268             ALOGV("track %d, input buffer %zd", t, bufidx);
269             if (bufidx >= 0) {
270                 size_t bufsize;
271                 uint8_t *buf = AMediaCodec_getInputBuffer(codec[t], bufidx, &bufsize);
272                 int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
273                 ALOGV("read %d", sampleSize);
274                 if (sampleSize < 0) {
275                     sampleSize = 0;
276                     sawInputEOS[t] = true;
277                     ALOGV("EOS");
278                     //break;
279                 }
280                 int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
281 
282                 AMediaCodec_queueInputBuffer(codec[t], bufidx, 0, sampleSize, presentationTimeUs,
283                         sawInputEOS[t] ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
284                 AMediaExtractor_advance(ex);
285             }
286         } else {
287             ALOGV("@@@@ no more input samples");
288             for (int tt = 0; tt < numtracks; tt++) {
289                 if (!sawInputEOS[tt]) {
290                     // we ran out of samples without ever signaling EOS to the codec,
291                     // so do that now
292                     int bufidx = AMediaCodec_dequeueInputBuffer(codec[tt], 5000);
293                     if (bufidx >= 0) {
294                         AMediaCodec_queueInputBuffer(codec[tt], bufidx, 0, 0, 0,
295                                 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
296                         sawInputEOS[tt] = true;
297                     }
298                 }
299             }
300         }
301 
302         // check all codecs for available data
303         AMediaCodecBufferInfo info;
304         for (int tt = 0; tt < numtracks; tt++) {
305             if (!sawOutputEOS[tt]) {
306                 int status = AMediaCodec_dequeueOutputBuffer(codec[tt], &info, 1);
307                 ALOGV("dequeueoutput on track %d: %d", tt, status);
308                 if (status >= 0) {
309                     if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
310                         ALOGV("EOS on track %d", tt);
311                         sawOutputEOS[tt] = true;
312                         eosCount++;
313                     }
314                     ALOGV("got decoded buffer for track %d, size %d", tt, info.size);
315                     if (info.size > 0) {
316                         size_t bufsize;
317                         uint8_t *buf = AMediaCodec_getOutputBuffer(codec[tt], status, &bufsize);
318                         int adler = checksum(buf, info.size, format[tt]);
319                         sizes[tt].add(adler);
320                     }
321                     AMediaCodec_releaseOutputBuffer(codec[tt], status, false);
322                 } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
323                     ALOGV("output buffers changed for track %d", tt);
324                 } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
325                     format[tt] = AMediaCodec_getOutputFormat(codec[tt]);
326                     ALOGV("format changed for track %d: %s", tt, AMediaFormat_toString(format[tt]));
327                 } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
328                     ALOGV("no output buffer right now for track %d", tt);
329                 } else {
330                     ALOGV("unexpected info code for track %d : %d", tt, status);
331                 }
332             } else {
333                 ALOGV("already at EOS on track %d", tt);
334             }
335         }
336     }
337     ALOGV("decoding loop done");
338 
339     // allocate java int array for result and return it
340     int numsamples = 0;
341     for (int i = 0; i < numtracks; i++) {
342         numsamples += sizes[i].size();
343     }
344     ALOGV("checksums: %d", numsamples);
345     jintArray ret = env->NewIntArray(numsamples);
346     jboolean isCopy;
347     jint *org = env->GetIntArrayElements(ret, &isCopy);
348     jint *dst = org;
349     for (int i = 0; i < numtracks; i++) {
350         int *data = sizes[i].data();
351         int len = sizes[i].size();
352         ALOGV("copying %d", len);
353         for (int j = 0; j < len; j++) {
354             *dst++ = data[j];
355         }
356     }
357     env->ReleaseIntArrayElements(ret, org, 0);
358 
359     delete[] sizes;
360     delete[] sawOutputEOS;
361     delete[] sawInputEOS;
362     for (int i = 0; i < numtracks; i++) {
363         AMediaFormat_delete(format[i]);
364         AMediaCodec_stop(codec[i]);
365         AMediaCodec_delete(codec[i]);
366     }
367     delete[] format;
368     delete[] codec;
369     AMediaExtractor_delete(ex);
370     return ret;
371 }
372 
Java_android_media_cts_NativeDecoderTest_testPlaybackNative(JNIEnv * env,jclass,jobject surface,int fd,jlong offset,jlong size)373 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPlaybackNative(JNIEnv *env,
374         jclass /*clazz*/, jobject surface, int fd, jlong offset, jlong size) {
375 
376     ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
377     ALOGI("@@@@ native window: %p", window);
378 
379     AMediaExtractor *ex = AMediaExtractor_new();
380     int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
381     if (err != 0) {
382         ALOGE("setDataSource error: %d", err);
383         return false;
384     }
385 
386     int numtracks = AMediaExtractor_getTrackCount(ex);
387 
388     AMediaCodec *codec = NULL;
389     AMediaFormat *format = NULL;
390     bool sawInputEOS = false;
391     bool sawOutputEOS = false;
392 
393     ALOGV("input has %d tracks", numtracks);
394     for (int i = 0; i < numtracks; i++) {
395         AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
396         const char *s = AMediaFormat_toString(format);
397         ALOGI("track %d format: %s", i, s);
398         const char *mime;
399         if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
400             ALOGE("no mime type");
401             return false;
402         } else if (!strncmp(mime, "video/", 6)) {
403             codec = AMediaCodec_createDecoderByType(mime);
404             AMediaCodec_configure(codec, format, window, NULL, 0);
405             AMediaCodec_start(codec);
406             AMediaExtractor_selectTrack(ex, i);
407         }
408         AMediaFormat_delete(format);
409     }
410 
411     while (!sawOutputEOS) {
412         ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
413         ALOGV("input buffer %zd", bufidx);
414         if (bufidx >= 0) {
415             size_t bufsize;
416             uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
417             int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
418             ALOGV("read %d", sampleSize);
419             if (sampleSize < 0) {
420                 sampleSize = 0;
421                 sawInputEOS = true;
422                 ALOGV("EOS");
423             }
424             int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
425 
426             AMediaCodec_queueInputBuffer(codec, bufidx, 0, sampleSize, presentationTimeUs,
427                     sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
428             AMediaExtractor_advance(ex);
429         }
430 
431         AMediaCodecBufferInfo info;
432         int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1);
433         ALOGV("dequeueoutput returned: %d", status);
434         if (status >= 0) {
435             if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
436                 ALOGV("output EOS");
437                 sawOutputEOS = true;
438             }
439             ALOGV("got decoded buffer size %d", info.size);
440             AMediaCodec_releaseOutputBuffer(codec, status, true);
441             usleep(20000);
442         } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
443             ALOGV("output buffers changed");
444         } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
445             format = AMediaCodec_getOutputFormat(codec);
446             ALOGV("format changed to: %s", AMediaFormat_toString(format));
447         } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
448             ALOGV("no output buffer right now");
449         } else {
450             ALOGV("unexpected info code: %d", status);
451         }
452     }
453 
454     AMediaCodec_stop(codec);
455     AMediaCodec_delete(codec);
456     AMediaExtractor_delete(ex);
457     return true;
458 }
459 
Java_android_media_cts_NativeDecoderTest_testMuxerNative(JNIEnv *,jclass,int infd,jlong inoffset,jlong insize,int outfd,jboolean webm)460 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testMuxerNative(JNIEnv */*env*/,
461         jclass /*clazz*/, int infd, jlong inoffset, jlong insize, int outfd, jboolean webm) {
462 
463 
464     AMediaMuxer *muxer = AMediaMuxer_new(outfd,
465             webm ? AMEDIAMUXER_OUTPUT_FORMAT_WEBM : AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4);
466 
467     AMediaExtractor *ex = AMediaExtractor_new();
468     int err = AMediaExtractor_setDataSourceFd(ex, infd, inoffset, insize);
469     if (err != 0) {
470         ALOGE("setDataSource error: %d", err);
471         return false;
472     }
473 
474     int numtracks = AMediaExtractor_getTrackCount(ex);
475     ALOGI("input tracks: %d", numtracks);
476     for (int i = 0; i < numtracks; i++) {
477         AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
478         const char *s = AMediaFormat_toString(format);
479         ALOGI("track %d format: %s", i, s);
480         const char *mime;
481         if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
482             ALOGE("no mime type");
483             return false;
484         } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) {
485             ssize_t tidx = AMediaMuxer_addTrack(muxer, format);
486             ALOGI("track %d -> %zd format %s", i, tidx, s);
487             AMediaExtractor_selectTrack(ex, i);
488         } else {
489             ALOGE("expected audio or video mime type, got %s", mime);
490             return false;
491         }
492         AMediaFormat_delete(format);
493         AMediaExtractor_selectTrack(ex, i);
494     }
495     AMediaMuxer_start(muxer);
496 
497     int bufsize = 1024*1024;
498     uint8_t *buf = new uint8_t[bufsize];
499     AMediaCodecBufferInfo info;
500     while(true) {
501         int n = AMediaExtractor_readSampleData(ex, buf, bufsize);
502         if (n < 0) {
503             break;
504         }
505         info.offset = 0;
506         info.size = n;
507         info.presentationTimeUs = AMediaExtractor_getSampleTime(ex);
508         info.flags = AMediaExtractor_getSampleFlags(ex);
509 
510         size_t idx = (size_t) AMediaExtractor_getSampleTrackIndex(ex);
511         AMediaMuxer_writeSampleData(muxer, idx, buf, &info);
512 
513         AMediaExtractor_advance(ex);
514     }
515 
516     AMediaExtractor_delete(ex);
517     AMediaMuxer_stop(muxer);
518     AMediaMuxer_delete(muxer);
519     return true;
520 
521 }
522 
Java_android_media_cts_NativeDecoderTest_testFormatNative(JNIEnv *,jclass)523 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testFormatNative(JNIEnv * /*env*/,
524         jclass /*clazz*/) {
525     AMediaFormat* format = AMediaFormat_new();
526     if (!format) {
527         return false;
528     }
529 
530     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, 8000);
531     int32_t bitrate = 0;
532     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate) || bitrate != 8000) {
533         ALOGE("AMediaFormat_getInt32 fail: %d", bitrate);
534         return false;
535     }
536 
537     AMediaFormat_setInt64(format, AMEDIAFORMAT_KEY_DURATION, 123456789123456789ll);
538     int64_t duration = 0;
539     if (!AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &duration)
540             || duration != 123456789123456789ll) {
541         ALOGE("AMediaFormat_getInt64 fail: %lld", (long long) duration);
542         return false;
543     }
544 
545     AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, 25.0f);
546     float framerate = 0.0f;
547     if (!AMediaFormat_getFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, &framerate)
548             || framerate != 25.0f) {
549         ALOGE("AMediaFormat_getFloat fail: %f", framerate);
550         return false;
551     }
552 
553     const char* value = "audio/mpeg";
554     AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, value);
555     const char* readback = NULL;
556     if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &readback)
557             || strcmp(value, readback) || value == readback) {
558         ALOGE("AMediaFormat_getString fail");
559         return false;
560     }
561 
562     uint32_t foo = 0xdeadbeef;
563     AMediaFormat_setBuffer(format, "csd-0", &foo, sizeof(foo));
564     foo = 0xabadcafe;
565     void *bytes;
566     size_t bytesize = 0;
567     if(!AMediaFormat_getBuffer(format, "csd-0", &bytes, &bytesize)
568             || bytesize != sizeof(foo) || *((uint32_t*)bytes) != 0xdeadbeef) {
569         ALOGE("AMediaFormat_getBuffer fail");
570         return false;
571     }
572 
573     return true;
574 }
575 
576 
Java_android_media_cts_NativeDecoderTest_testPsshNative(JNIEnv *,jclass,int fd,jlong offset,jlong size)577 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPsshNative(JNIEnv * /*env*/,
578         jclass /*clazz*/, int fd, jlong offset, jlong size) {
579 
580     AMediaExtractor *ex = AMediaExtractor_new();
581     int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
582     if (err != 0) {
583         ALOGE("setDataSource error: %d", err);
584         return false;
585     }
586 
587     PsshInfo* info = AMediaExtractor_getPsshInfo(ex);
588     if (info == NULL) {
589         ALOGI("null pssh");
590         return false;
591     }
592 
593     ALOGI("pssh has %zd entries", info->numentries);
594     if (info->numentries != 2) {
595         return false;
596     }
597 
598     for (size_t i = 0; i < info->numentries; i++) {
599         PsshEntry *entry = &info->entries[i];
600         ALOGI("entry uuid %02x%02x..%02x%02x, data size %zd",
601                 entry->uuid[0],
602                 entry->uuid[1],
603                 entry->uuid[14],
604                 entry->uuid[15],
605                 entry->datalen);
606 
607         AMediaCrypto *crypto = AMediaCrypto_new(entry->uuid, entry->data, entry->datalen);
608         if (crypto) {
609             ALOGI("got crypto");
610             AMediaCrypto_delete(crypto);
611         } else {
612             ALOGI("no crypto");
613         }
614     }
615     return true;
616 }
617 
Java_android_media_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv *,jclass)618 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv * /*env*/,
619         jclass /*clazz*/) {
620 
621     size_t numsubsamples = 4;
622     uint8_t key[16] = { 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4 };
623     uint8_t iv[16] = { 4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1 };
624     size_t clearbytes[4] = { 5, 6, 7, 8 };
625     size_t encryptedbytes[4] = { 8, 7, 6, 5 };
626 
627     AMediaCodecCryptoInfo *ci =
628             AMediaCodecCryptoInfo_new(numsubsamples, key, iv, AMEDIACODECRYPTOINFO_MODE_CLEAR, clearbytes, encryptedbytes);
629 
630     if (AMediaCodecCryptoInfo_getNumSubSamples(ci) != 4) {
631         ALOGE("numsubsamples mismatch");
632         return false;
633     }
634     uint8_t bytes[16];
635     AMediaCodecCryptoInfo_getKey(ci, bytes);
636     if (memcmp(key, bytes, 16) != 0) {
637         ALOGE("key mismatch");
638         return false;
639     }
640     AMediaCodecCryptoInfo_getIV(ci, bytes);
641     if (memcmp(iv, bytes, 16) != 0) {
642         ALOGE("IV mismatch");
643         return false;
644     }
645     if (AMediaCodecCryptoInfo_getMode(ci) != AMEDIACODECRYPTOINFO_MODE_CLEAR) {
646         ALOGE("mode mismatch");
647         return false;
648     }
649     size_t sizes[numsubsamples];
650     AMediaCodecCryptoInfo_getClearBytes(ci, sizes);
651     if (memcmp(clearbytes, sizes, sizeof(size_t) * numsubsamples)) {
652         ALOGE("clear size mismatch");
653         return false;
654     }
655     AMediaCodecCryptoInfo_getEncryptedBytes(ci, sizes);
656     if (memcmp(encryptedbytes, sizes, sizeof(size_t) * numsubsamples)) {
657         ALOGE("encrypted size mismatch");
658         return false;
659     }
660     return true;
661 }
662 
663 // === NdkMediaCodec
664 
Java_android_media_cts_NdkMediaCodec_AMediaCodecCreateCodecByName(JNIEnv * env,jclass,jstring name)665 extern "C" jlong Java_android_media_cts_NdkMediaCodec_AMediaCodecCreateCodecByName(
666         JNIEnv *env, jclass /*clazz*/, jstring name) {
667 
668     if (name == NULL) {
669         return 0;
670     }
671 
672     const char *tmp = env->GetStringUTFChars(name, NULL);
673     if (tmp == NULL) {
674         return 0;
675     }
676 
677     AMediaCodec *codec = AMediaCodec_createCodecByName(tmp);
678     if (codec == NULL) {
679         env->ReleaseStringUTFChars(name, tmp);
680         return 0;
681     }
682 
683     env->ReleaseStringUTFChars(name, tmp);
684     return reinterpret_cast<jlong>(codec);
685 
686 }
687 
Java_android_media_cts_NdkMediaCodec_AMediaCodecDelete(JNIEnv *,jclass,jlong codec)688 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecDelete(
689         JNIEnv * /*env*/, jclass /*clazz*/, jlong codec) {
690     media_status_t err = AMediaCodec_delete(reinterpret_cast<AMediaCodec *>(codec));
691     return err == AMEDIA_OK;
692 }
693 
Java_android_media_cts_NdkMediaCodec_AMediaCodecStart(JNIEnv *,jclass,jlong codec)694 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecStart(
695         JNIEnv * /*env*/, jclass /*clazz*/, jlong codec) {
696     media_status_t err = AMediaCodec_start(reinterpret_cast<AMediaCodec *>(codec));
697     return err == AMEDIA_OK;
698 }
699 
Java_android_media_cts_NdkMediaCodec_AMediaCodecStop(JNIEnv *,jclass,jlong codec)700 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecStop(
701         JNIEnv * /*env*/, jclass /*clazz*/, jlong codec) {
702     media_status_t err = AMediaCodec_stop(reinterpret_cast<AMediaCodec *>(codec));
703     return err == AMEDIA_OK;
704 }
705 
Java_android_media_cts_NdkMediaCodec_AMediaCodecConfigure(JNIEnv * env,jclass,jlong codec,jstring mime,jint width,jint height,jint colorFormat,jint bitRate,jint frameRate,jint iFrameInterval,jobject csd,jint flags)706 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecConfigure(
707         JNIEnv *env,
708         jclass /*clazz*/,
709         jlong codec,
710         jstring mime,
711         jint width,
712         jint height,
713         jint colorFormat,
714         jint bitRate,
715         jint frameRate,
716         jint iFrameInterval,
717         jobject csd,
718         jint flags) {
719 
720     AMediaFormat* format = AMediaFormat_new();
721     if (format == NULL) {
722         return false;
723     }
724 
725     const char *tmp = env->GetStringUTFChars(mime, NULL);
726     if (tmp == NULL) {
727         AMediaFormat_delete(format);
728         return false;
729     }
730 
731     AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, tmp);
732     env->ReleaseStringUTFChars(mime, tmp);
733 
734     const char *keys[] = {
735             AMEDIAFORMAT_KEY_WIDTH,
736             AMEDIAFORMAT_KEY_HEIGHT,
737             AMEDIAFORMAT_KEY_COLOR_FORMAT,
738             AMEDIAFORMAT_KEY_BIT_RATE,
739             AMEDIAFORMAT_KEY_FRAME_RATE,
740             AMEDIAFORMAT_KEY_I_FRAME_INTERVAL
741     };
742 
743     jint values[] = {width, height, colorFormat, bitRate, frameRate, iFrameInterval};
744     for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
745         if (values[i] >= 0) {
746             AMediaFormat_setInt32(format, keys[i], values[i]);
747         }
748     }
749 
750     if (csd != NULL) {
751         void *csdPtr = env->GetDirectBufferAddress(csd);
752         jlong csdSize = env->GetDirectBufferCapacity(csd);
753         AMediaFormat_setBuffer(format, "csd-0", csdPtr, csdSize);
754     }
755 
756     media_status_t err = AMediaCodec_configure(
757             reinterpret_cast<AMediaCodec *>(codec),
758             format,
759             NULL,
760             NULL,
761             flags);
762 
763     AMediaFormat_delete(format);
764     return err == AMEDIA_OK;
765 
766 }
767 
Java_android_media_cts_NdkMediaCodec_AMediaCodecSetInputSurface(JNIEnv * env,jclass,jlong codec,jobject surface)768 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecSetInputSurface(
769         JNIEnv* env, jclass /*clazz*/, jlong codec, jobject surface) {
770 
771     media_status_t err = AMediaCodec_setInputSurface(
772             reinterpret_cast<AMediaCodec *>(codec),
773             ANativeWindow_fromSurface(env, surface));
774 
775     return err == AMEDIA_OK;
776 
777 }
778 
Java_android_media_cts_NdkMediaCodec_AMediaCodecSetNativeInputSurface(JNIEnv *,jclass,jlong codec,jlong nativeWindow)779 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecSetNativeInputSurface(
780         JNIEnv* /*env*/, jclass /*clazz*/, jlong codec, jlong nativeWindow) {
781 
782     media_status_t err = AMediaCodec_setInputSurface(
783             reinterpret_cast<AMediaCodec *>(codec),
784             reinterpret_cast<ANativeWindow *>(nativeWindow));
785 
786     return err == AMEDIA_OK;
787 
788 }
789 
Java_android_media_cts_NdkMediaCodec_AMediaCodecCreateInputSurface(JNIEnv *,jclass,jlong codec)790 extern "C" jlong Java_android_media_cts_NdkMediaCodec_AMediaCodecCreateInputSurface(
791         JNIEnv* /*env*/, jclass /*clazz*/, jlong codec) {
792 
793     ANativeWindow *nativeWindow;
794     media_status_t err = AMediaCodec_createInputSurface(
795             reinterpret_cast<AMediaCodec *>(codec),
796             &nativeWindow);
797 
798      if (err == AMEDIA_OK) {
799          return reinterpret_cast<jlong>(nativeWindow);
800      }
801 
802      return 0;
803 
804 }
805 
Java_android_media_cts_NdkMediaCodec_AMediaCodecCreatePersistentInputSurface(JNIEnv *,jclass)806 extern "C" jlong Java_android_media_cts_NdkMediaCodec_AMediaCodecCreatePersistentInputSurface(
807         JNIEnv* /*env*/, jclass /*clazz*/) {
808 
809     ANativeWindow *nativeWindow;
810     media_status_t err = AMediaCodec_createPersistentInputSurface(&nativeWindow);
811 
812      if (err == AMEDIA_OK) {
813          return reinterpret_cast<jlong>(nativeWindow);
814      }
815 
816      return 0;
817 
818 }
819 
Java_android_media_cts_NdkMediaCodec_AMediaCodecGetOutputFormatString(JNIEnv * env,jclass,jlong codec)820 extern "C" jstring Java_android_media_cts_NdkMediaCodec_AMediaCodecGetOutputFormatString(
821         JNIEnv* env, jclass /*clazz*/, jlong codec) {
822 
823     AMediaFormat *format = AMediaCodec_getOutputFormat(reinterpret_cast<AMediaCodec *>(codec));
824     const char *str = AMediaFormat_toString(format);
825     jstring jstr = env->NewStringUTF(str);
826     AMediaFormat_delete(format);
827     return jstr;
828 
829 }
830 
Java_android_media_cts_NdkMediaCodec_AMediaCodecSignalEndOfInputStream(JNIEnv *,jclass,jlong codec)831 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecSignalEndOfInputStream(
832         JNIEnv* /*env*/, jclass /*clazz*/, jlong codec) {
833 
834     media_status_t err = AMediaCodec_signalEndOfInputStream(reinterpret_cast<AMediaCodec *>(codec));
835     return err == AMEDIA_OK;
836 
837 }
838 
Java_android_media_cts_NdkMediaCodec_AMediaCodecReleaseOutputBuffer(JNIEnv *,jclass,jlong codec,jint index,jboolean render)839 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecReleaseOutputBuffer(
840         JNIEnv* /*env*/, jclass /*clazz*/, jlong codec, jint index, jboolean render) {
841 
842     media_status_t err = AMediaCodec_releaseOutputBuffer(
843             reinterpret_cast<AMediaCodec *>(codec),
844             index,
845             render);
846 
847     return err == AMEDIA_OK;
848 
849 }
850 
AMediaCodecGetBuffer(JNIEnv * env,jlong codec,jint index,uint8_t * (* getBuffer)(AMediaCodec *,size_t,size_t *))851 static jobject AMediaCodecGetBuffer(
852         JNIEnv* env,
853         jlong codec,
854         jint index,
855         uint8_t *(*getBuffer)(AMediaCodec*, size_t, size_t*)) {
856 
857     size_t bufsize;
858     uint8_t *buf = getBuffer(
859             reinterpret_cast<AMediaCodec *>(codec),
860             index,
861             &bufsize);
862 
863     return env->NewDirectByteBuffer(buf, bufsize);
864 
865 }
866 
Java_android_media_cts_NdkMediaCodec_AMediaCodecGetOutputBuffer(JNIEnv * env,jclass,jlong codec,jint index)867 extern "C" jobject Java_android_media_cts_NdkMediaCodec_AMediaCodecGetOutputBuffer(
868         JNIEnv* env, jclass /*clazz*/, jlong codec, jint index) {
869 
870     return AMediaCodecGetBuffer(env, codec, index, AMediaCodec_getOutputBuffer);
871 
872 }
873 
Java_android_media_cts_NdkMediaCodec_AMediaCodecDequeueOutputBuffer(JNIEnv * env,jclass,jlong codec,jlong timeoutUs)874 extern "C" jlongArray Java_android_media_cts_NdkMediaCodec_AMediaCodecDequeueOutputBuffer(
875         JNIEnv* env, jclass /*clazz*/, jlong codec, jlong timeoutUs) {
876 
877     AMediaCodecBufferInfo info;
878     memset(&info, 0, sizeof(info));
879     int status = AMediaCodec_dequeueOutputBuffer(
880         reinterpret_cast<AMediaCodec *>(codec),
881         &info,
882         timeoutUs);
883 
884     jlong ret[5] = {0};
885     ret[0] = status;
886     ret[1] = 0; // NdkMediaCodec calls ABuffer::data, which already adds offset
887     ret[2] = info.size;
888     ret[3] = info.presentationTimeUs;
889     ret[4] = info.flags;
890 
891     jlongArray jret = env->NewLongArray(5);
892     env->SetLongArrayRegion(jret, 0, 5, ret);
893     return jret;
894 
895 }
896 
Java_android_media_cts_NdkMediaCodec_AMediaCodecGetInputBuffer(JNIEnv * env,jclass,jlong codec,jint index)897 extern "C" jobject Java_android_media_cts_NdkMediaCodec_AMediaCodecGetInputBuffer(
898         JNIEnv* env, jclass /*clazz*/, jlong codec, jint index) {
899 
900     return AMediaCodecGetBuffer(env, codec, index, AMediaCodec_getInputBuffer);
901 
902 }
903 
Java_android_media_cts_NdkMediaCodec_AMediaCodecDequeueInputBuffer(JNIEnv *,jclass,jlong codec,jlong timeoutUs)904 extern "C" jint Java_android_media_cts_NdkMediaCodec_AMediaCodecDequeueInputBuffer(
905         JNIEnv* /*env*/, jclass /*clazz*/, jlong codec, jlong timeoutUs) {
906 
907     return AMediaCodec_dequeueInputBuffer(
908             reinterpret_cast<AMediaCodec *>(codec),
909             timeoutUs);
910 
911 }
912 
Java_android_media_cts_NdkMediaCodec_AMediaCodecQueueInputBuffer(JNIEnv *,jclass,jlong codec,jint index,jint offset,jint size,jlong presentationTimeUs,jint flags)913 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecQueueInputBuffer(
914         JNIEnv* /*env*/,
915         jclass /*clazz*/,
916         jlong codec,
917         jint index,
918         jint offset,
919         jint size,
920         jlong presentationTimeUs,
921         jint flags) {
922 
923     media_status_t err = AMediaCodec_queueInputBuffer(
924             reinterpret_cast<AMediaCodec *>(codec),
925             index,
926             offset,
927             size,
928             presentationTimeUs,
929             flags);
930 
931     return err == AMEDIA_OK;
932 
933 }
934 
Java_android_media_cts_NdkMediaCodec_AMediaCodecSetParameter(JNIEnv * env,jclass,jlong codec,jstring jkey,jint value)935 extern "C" jboolean Java_android_media_cts_NdkMediaCodec_AMediaCodecSetParameter(
936         JNIEnv* env, jclass /*clazz*/, jlong codec, jstring jkey, jint value) {
937 
938     AMediaFormat* params = AMediaFormat_new();
939     if (params == NULL) {
940         return false;
941     }
942 
943     const char *key = env->GetStringUTFChars(jkey, NULL);
944     if (key == NULL) {
945         AMediaFormat_delete(params);
946         return false;
947     }
948 
949     AMediaFormat_setInt32(params, key, value);
950     media_status_t err = AMediaCodec_setParameters(
951             reinterpret_cast<AMediaCodec *>(codec),
952             params);
953     env->ReleaseStringUTFChars(jkey, key);
954     AMediaFormat_delete(params);
955     return err == AMEDIA_OK;
956 
957 }
958 
959 // === NdkInputSurface
960 
Java_android_media_cts_NdkInputSurface_eglGetDisplay(JNIEnv *,jclass)961 extern "C" jlong Java_android_media_cts_NdkInputSurface_eglGetDisplay(JNIEnv * /*env*/, jclass /*clazz*/) {
962 
963     EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
964     if (eglDisplay == EGL_NO_DISPLAY) {
965         return 0;
966     }
967 
968     EGLint major, minor;
969     if (!eglInitialize(eglDisplay, &major, &minor)) {
970         return 0;
971     }
972 
973     return reinterpret_cast<jlong>(eglDisplay);
974 
975 }
976 
Java_android_media_cts_NdkInputSurface_eglChooseConfig(JNIEnv *,jclass,jlong eglDisplay)977 extern "C" jlong Java_android_media_cts_NdkInputSurface_eglChooseConfig(
978         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay) {
979 
980     // Configure EGL for recordable and OpenGL ES 2.0.  We want enough RGB bits
981     // to minimize artifacts from possible YUV conversion.
982     EGLint attribList[] = {
983             EGL_RED_SIZE, 8,
984             EGL_GREEN_SIZE, 8,
985             EGL_BLUE_SIZE, 8,
986             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
987             EGL_RECORDABLE_ANDROID, 1,
988             EGL_NONE
989     };
990 
991     EGLConfig configs[1];
992     EGLint numConfigs[1];
993     if (!eglChooseConfig(reinterpret_cast<EGLDisplay>(eglDisplay), attribList, configs, 1, numConfigs)) {
994         return 0;
995     }
996     return reinterpret_cast<jlong>(configs[0]);
997 
998 }
999 
Java_android_media_cts_NdkInputSurface_eglCreateContext(JNIEnv *,jclass,jlong eglDisplay,jlong eglConfig)1000 extern "C" jlong Java_android_media_cts_NdkInputSurface_eglCreateContext(
1001         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglConfig) {
1002 
1003     // Configure context for OpenGL ES 2.0.
1004     int attrib_list[] = {
1005             EGL_CONTEXT_CLIENT_VERSION, 2,
1006             EGL_NONE
1007     };
1008 
1009     EGLConfig eglContext = eglCreateContext(
1010             reinterpret_cast<EGLDisplay>(eglDisplay),
1011             reinterpret_cast<EGLConfig>(eglConfig),
1012             EGL_NO_CONTEXT,
1013             attrib_list);
1014 
1015     if (eglGetError() != EGL_SUCCESS) {
1016         return 0;
1017     }
1018 
1019     return reinterpret_cast<jlong>(eglContext);
1020 
1021 }
1022 
Java_android_media_cts_NdkInputSurface_createEGLSurface(JNIEnv *,jclass,jlong eglDisplay,jlong eglConfig,jlong nativeWindow)1023 extern "C" jlong Java_android_media_cts_NdkInputSurface_createEGLSurface(
1024         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglConfig, jlong nativeWindow) {
1025 
1026     int surfaceAttribs[] = {EGL_NONE};
1027     EGLSurface eglSurface = eglCreateWindowSurface(
1028             reinterpret_cast<EGLDisplay>(eglDisplay),
1029             reinterpret_cast<EGLConfig>(eglConfig),
1030             reinterpret_cast<EGLNativeWindowType>(nativeWindow),
1031             surfaceAttribs);
1032 
1033     if (eglGetError() != EGL_SUCCESS) {
1034         return 0;
1035     }
1036 
1037     return reinterpret_cast<jlong>(eglSurface);
1038 
1039 }
1040 
Java_android_media_cts_NdkInputSurface_eglMakeCurrent(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface,jlong eglContext)1041 extern "C" jboolean Java_android_media_cts_NdkInputSurface_eglMakeCurrent(
1042         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface, jlong eglContext) {
1043 
1044     return eglMakeCurrent(
1045             reinterpret_cast<EGLDisplay>(eglDisplay),
1046             reinterpret_cast<EGLSurface>(eglSurface),
1047             reinterpret_cast<EGLSurface>(eglSurface),
1048             reinterpret_cast<EGLContext>(eglContext));
1049 
1050 }
1051 
Java_android_media_cts_NdkInputSurface_eglSwapBuffers(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface)1052 extern "C" jboolean Java_android_media_cts_NdkInputSurface_eglSwapBuffers(
1053         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface) {
1054 
1055     return eglSwapBuffers(
1056             reinterpret_cast<EGLDisplay>(eglDisplay),
1057             reinterpret_cast<EGLSurface>(eglSurface));
1058 
1059 }
1060 
Java_android_media_cts_NdkInputSurface_eglPresentationTimeANDROID(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface,jlong nsecs)1061 extern "C" jboolean Java_android_media_cts_NdkInputSurface_eglPresentationTimeANDROID(
1062         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface, jlong nsecs) {
1063 
1064     return eglPresentationTimeANDROID(
1065             reinterpret_cast<EGLDisplay>(eglDisplay),
1066             reinterpret_cast<EGLSurface>(eglSurface),
1067             reinterpret_cast<EGLnsecsANDROID>(nsecs));
1068 
1069 }
1070 
Java_android_media_cts_NdkInputSurface_eglGetWidth(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface)1071 extern "C" jint Java_android_media_cts_NdkInputSurface_eglGetWidth(
1072         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface) {
1073 
1074     EGLint width;
1075     eglQuerySurface(
1076             reinterpret_cast<EGLDisplay>(eglDisplay),
1077             reinterpret_cast<EGLSurface>(eglSurface),
1078             EGL_WIDTH,
1079             &width);
1080 
1081     return width;
1082 
1083 }
1084 
Java_android_media_cts_NdkInputSurface_eglGetHeight(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface)1085 extern "C" jint Java_android_media_cts_NdkInputSurface_eglGetHeight(
1086         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface) {
1087 
1088     EGLint height;
1089     eglQuerySurface(
1090             reinterpret_cast<EGLDisplay>(eglDisplay),
1091             reinterpret_cast<EGLSurface>(eglSurface),
1092             EGL_HEIGHT,
1093             &height);
1094 
1095     return height;
1096 
1097 }
1098 
Java_android_media_cts_NdkInputSurface_eglDestroySurface(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface)1099 extern "C" jboolean Java_android_media_cts_NdkInputSurface_eglDestroySurface(
1100         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface) {
1101 
1102     return eglDestroySurface(
1103             reinterpret_cast<EGLDisplay>(eglDisplay),
1104             reinterpret_cast<EGLSurface>(eglSurface));
1105 
1106 }
1107 
Java_android_media_cts_NdkInputSurface_nativeRelease(JNIEnv *,jclass,jlong eglDisplay,jlong eglSurface,jlong eglContext,jlong nativeWindow)1108 extern "C" void Java_android_media_cts_NdkInputSurface_nativeRelease(
1109         JNIEnv * /*env*/, jclass /*clazz*/, jlong eglDisplay, jlong eglSurface, jlong eglContext, jlong nativeWindow) {
1110 
1111     if (eglDisplay != 0) {
1112 
1113         EGLDisplay _eglDisplay = reinterpret_cast<EGLDisplay>(eglDisplay);
1114         EGLSurface _eglSurface = reinterpret_cast<EGLSurface>(eglSurface);
1115         EGLContext _eglContext = reinterpret_cast<EGLContext>(eglContext);
1116 
1117         eglDestroySurface(_eglDisplay, _eglSurface);
1118         eglDestroyContext(_eglDisplay, _eglContext);
1119         eglReleaseThread();
1120         eglTerminate(_eglDisplay);
1121 
1122     }
1123 
1124     ANativeWindow_release(reinterpret_cast<ANativeWindow *>(nativeWindow));
1125 
1126 }
1127