• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #undef NDEBUG
20 #include <assert.h>
21 #include <jni.h>
22 #include <pthread.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <semaphore.h>
27 
28 #include <android/native_window_jni.h>
29 
30 // for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message");
31 #include <android/log.h>
32 #define TAG "NativeMedia"
33 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
34 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
35 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
36 
37 #include "ndk/NdkMediaExtractor.h"
38 #include "ndk/NdkMediaCodec.h"
39 #include "ndk/NdkMediaCrypto.h"
40 #include "ndk/NdkMediaFormat.h"
41 #include "ndk/NdkMediaMuxer.h"
42 
43 template <class T>
44 class simplevector {
45     T *storage;
46     int capacity;
47     int numfilled;
48 public:
simplevector()49     simplevector() {
50         capacity = 16;
51         numfilled = 0;
52         storage = new T[capacity];
53     }
~simplevector()54     ~simplevector() {
55         delete[] storage;
56     }
57 
add(T item)58     void add(T item) {
59         if (numfilled == capacity) {
60             T *old = storage;
61             capacity *= 2;
62             storage = new T[capacity];
63             for (int i = 0; i < numfilled; i++) {
64                 storage[i] = old[i];
65             }
66             delete[] old;
67         }
68         storage[numfilled] = item;
69         numfilled++;
70     }
71 
size()72     int size() {
73         return numfilled;
74     }
75 
data()76     T* data() {
77         return storage;
78     }
79 };
80 
81 
82 
testExtractor(AMediaExtractor * ex,JNIEnv * env)83 jobject testExtractor(AMediaExtractor *ex, JNIEnv *env) {
84 
85     simplevector<int> sizes;
86     int numtracks = AMediaExtractor_getTrackCount(ex);
87     sizes.add(numtracks);
88     for (int i = 0; i < numtracks; i++) {
89         AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
90         const char *s = AMediaFormat_toString(format);
91         ALOGI("track %d format: %s", i, s);
92         const char *mime;
93         if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
94             ALOGE("no mime type");
95             return NULL;
96         } else if (!strncmp(mime, "audio/", 6)) {
97             sizes.add(0);
98             int32_t val32;
99             int64_t val64;
100             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &val32);
101             sizes.add(val32);
102             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &val32);
103             sizes.add(val32);
104             AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64);
105             sizes.add(val64);
106         } else if (!strncmp(mime, "video/", 6)) {
107             sizes.add(1);
108             int32_t val32;
109             int64_t val64;
110             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &val32);
111             sizes.add(val32);
112             AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &val32);
113             sizes.add(val32);
114             AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64);
115             sizes.add(val64);
116         } else {
117             ALOGE("expected audio or video mime type, got %s", mime);
118         }
119         AMediaFormat_delete(format);
120         AMediaExtractor_selectTrack(ex, i);
121     }
122     int bufsize = 1024*1024;
123     uint8_t *buf = new uint8_t[bufsize];
124     while(true) {
125         int n = AMediaExtractor_readSampleData(ex, buf, bufsize);
126         if (n < 0) {
127             break;
128         }
129         sizes.add(n);
130         sizes.add(AMediaExtractor_getSampleTrackIndex(ex));
131         sizes.add(AMediaExtractor_getSampleFlags(ex));
132         sizes.add(AMediaExtractor_getSampleTime(ex));
133         AMediaExtractor_advance(ex);
134     }
135 
136     // allocate java int array for result and return it
137     int *data = sizes.data();
138     int numsamples = sizes.size();
139     jintArray ret = env->NewIntArray(numsamples);
140     jboolean isCopy;
141     jint *dst = env->GetIntArrayElements(ret, &isCopy);
142     for (int i = 0; i < numsamples; ++i) {
143         dst[i] = data[i];
144     }
145     env->ReleaseIntArrayElements(ret, dst, 0);
146 
147     delete[] buf;
148     AMediaExtractor_delete(ex);
149     return ret;
150 }
151 
152 
153 // get the sample sizes for the file
Java_android_media_cts_NativeDecoderTest_getSampleSizesNative(JNIEnv * env,jclass,int fd,jlong offset,jlong size)154 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNative(JNIEnv *env,
155         jclass /*clazz*/, int fd, jlong offset, jlong size)
156 {
157     AMediaExtractor *ex = AMediaExtractor_new();
158     int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
159     if (err != 0) {
160         ALOGE("setDataSource error: %d", err);
161         return NULL;
162     }
163     return testExtractor(ex, env);
164 }
165 
166 // get the sample sizes for the path
Java_android_media_cts_NativeDecoderTest_getSampleSizesNativePath(JNIEnv * env,jclass,jstring jpath)167 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNativePath(JNIEnv *env,
168         jclass /*clazz*/, jstring jpath)
169 {
170     AMediaExtractor *ex = AMediaExtractor_new();
171 
172     const char *tmp = env->GetStringUTFChars(jpath, NULL);
173     if (tmp == NULL) {  // Out of memory
174         return NULL;
175     }
176 
177     int err = AMediaExtractor_setDataSource(ex, tmp);
178 
179     env->ReleaseStringUTFChars(jpath, tmp);
180 
181     if (err != 0) {
182         ALOGE("setDataSource error: %d", err);
183         return NULL;
184     }
185     return testExtractor(ex, env);
186 }
187 
adler32(const uint8_t * input,int len)188 static int adler32(const uint8_t *input, int len) {
189 
190     int a = 1;
191     int b = 0;
192     for (int i = 0; i < len; i++) {
193         a += input[i];
194         b += a;
195     }
196     a = a % 65521;
197     b = b % 65521;
198     int ret = b * 65536 + a;
199     ALOGV("adler %d/%d", len, ret);
200     return ret;
201 }
202 
checksum(const uint8_t * in,int len,AMediaFormat * format)203 static int checksum(const uint8_t *in, int len, AMediaFormat *format) {
204     int width, stride, height;
205     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width)) {
206         width = len;
207     }
208     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_STRIDE, &stride)) {
209         stride = width;
210     }
211     if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height)) {
212         height = 1;
213     }
214     uint8_t *bb = new uint8_t[width * height];
215     for (int i = 0; i < height; i++) {
216         memcpy(bb + i * width, in + i * stride, width);
217     }
218     // bb is filled with data
219     int sum = adler32(bb, width * height);
220     delete[] bb;
221     return sum;
222 }
223 
Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv * env,jclass,int fd,jlong offset,jlong size)224 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv *env,
225         jclass /*clazz*/, int fd, jlong offset, jlong size) {
226     ALOGV("getDecodedDataNative");
227 
228     AMediaExtractor *ex = AMediaExtractor_new();
229     int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
230     if (err != 0) {
231         ALOGE("setDataSource error: %d", err);
232         return NULL;
233     }
234 
235     int numtracks = AMediaExtractor_getTrackCount(ex);
236 
237     AMediaCodec **codec = new AMediaCodec*[numtracks];
238     AMediaFormat **format = new AMediaFormat*[numtracks];
239     bool *sawInputEOS = new bool[numtracks];
240     bool *sawOutputEOS = new bool[numtracks];
241     simplevector<int> sizes[numtracks];
242 
243     ALOGV("input has %d tracks", numtracks);
244     for (int i = 0; i < numtracks; i++) {
245         AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
246         const char *s = AMediaFormat_toString(format);
247         ALOGI("track %d format: %s", i, s);
248         const char *mime;
249         if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
250             ALOGE("no mime type");
251             return NULL;
252         } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) {
253             codec[i] = AMediaCodec_createDecoderByType(mime);
254             AMediaCodec_configure(codec[i], format, NULL /* surface */, NULL /* crypto */, 0);
255             AMediaCodec_start(codec[i]);
256             sawInputEOS[i] = false;
257             sawOutputEOS[i] = false;
258         } else {
259             ALOGE("expected audio or video mime type, got %s", mime);
260             return NULL;
261         }
262         AMediaFormat_delete(format);
263         AMediaExtractor_selectTrack(ex, i);
264     }
265     int eosCount = 0;
266     while(eosCount < numtracks) {
267         int t = AMediaExtractor_getSampleTrackIndex(ex);
268         if (t >=0) {
269             ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec[t], 5000);
270             ALOGV("track %d, input buffer %d", t, bufidx);
271             if (bufidx >= 0) {
272                 size_t bufsize;
273                 uint8_t *buf = AMediaCodec_getInputBuffer(codec[t], bufidx, &bufsize);
274                 int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
275                 ALOGV("read %d", sampleSize);
276                 if (sampleSize < 0) {
277                     sampleSize = 0;
278                     sawInputEOS[t] = true;
279                     ALOGV("EOS");
280                     //break;
281                 }
282                 int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
283 
284                 AMediaCodec_queueInputBuffer(codec[t], bufidx, 0, sampleSize, presentationTimeUs,
285                         sawInputEOS[t] ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
286                 AMediaExtractor_advance(ex);
287             }
288         } else {
289             ALOGV("@@@@ no more input samples");
290             for (int tt = 0; tt < numtracks; tt++) {
291                 if (!sawInputEOS[tt]) {
292                     // we ran out of samples without ever signaling EOS to the codec,
293                     // so do that now
294                     int bufidx = AMediaCodec_dequeueInputBuffer(codec[tt], 5000);
295                     if (bufidx >= 0) {
296                         AMediaCodec_queueInputBuffer(codec[tt], bufidx, 0, 0, 0,
297                                 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
298                         sawInputEOS[tt] = true;
299                     }
300                 }
301             }
302         }
303 
304         // check all codecs for available data
305         AMediaCodecBufferInfo info;
306         for (int tt = 0; tt < numtracks; tt++) {
307             if (!sawOutputEOS[tt]) {
308                 int status = AMediaCodec_dequeueOutputBuffer(codec[tt], &info, 1);
309                 ALOGV("dequeueoutput on track %d: %d", tt, status);
310                 if (status >= 0) {
311                     if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
312                         ALOGV("EOS on track %d", tt);
313                         sawOutputEOS[tt] = true;
314                         eosCount++;
315                     }
316                     ALOGV("got decoded buffer for track %d, size %d", tt, info.size);
317                     if (info.size > 0) {
318                         size_t bufsize;
319                         uint8_t *buf = AMediaCodec_getOutputBuffer(codec[tt], status, &bufsize);
320                         int adler = checksum(buf, info.size, format[tt]);
321                         sizes[tt].add(adler);
322                     }
323                     AMediaCodec_releaseOutputBuffer(codec[tt], status, false);
324                 } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
325                     ALOGV("output buffers changed for track %d", tt);
326                 } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
327                     format[tt] = AMediaCodec_getOutputFormat(codec[tt]);
328                     ALOGV("format changed for track %d: %s", tt, AMediaFormat_toString(format[tt]));
329                 } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
330                     ALOGV("no output buffer right now for track %d", tt);
331                 } else {
332                     ALOGV("unexpected info code for track %d : %d", tt, status);
333                 }
334             } else {
335                 ALOGV("already at EOS on track %d", tt);
336             }
337         }
338     }
339     ALOGV("decoding loop done");
340 
341     // allocate java int array for result and return it
342     int numsamples = 0;
343     for (int i = 0; i < numtracks; i++) {
344         numsamples += sizes[i].size();
345     }
346     ALOGV("checksums: %d", numsamples);
347     jintArray ret = env->NewIntArray(numsamples);
348     jboolean isCopy;
349     jint *org = env->GetIntArrayElements(ret, &isCopy);
350     jint *dst = org;
351     for (int i = 0; i < numtracks; i++) {
352         int *data = sizes[i].data();
353         int len = sizes[i].size();
354         ALOGV("copying %d", len);
355         for (int j = 0; j < len; j++) {
356             *dst++ = data[j];
357         }
358     }
359     env->ReleaseIntArrayElements(ret, org, 0);
360 
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 %d", 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 -> %d 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", 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