1 /*
2 * Copyright (C) 2019 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "NativeDecoder"
19
20 #include <jni.h>
21 #include <fstream>
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/stat.h>
25
26 #include <android/log.h>
27
28 #include "Decoder.h"
29
Java_com_android_media_benchmark_library_Native_Decode(JNIEnv * env,jobject thiz,jstring jFilePath,jstring jFileName,jstring jStatsFile,jstring jCodecName,jboolean asyncMode)30 extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Decode(
31 JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jStatsFile,
32 jstring jCodecName, jboolean asyncMode) {
33 const char *filePath = env->GetStringUTFChars(jFilePath, nullptr);
34 const char *fileName = env->GetStringUTFChars(jFileName, nullptr);
35 string sFilePath = string(filePath) + string(fileName);
36 UNUSED(thiz);
37 FILE *inputFp = fopen(sFilePath.c_str(), "rb");
38 env->ReleaseStringUTFChars(jFileName, fileName);
39 env->ReleaseStringUTFChars(jFilePath, filePath);
40 if (!inputFp) {
41 ALOGE("Unable to open input file for reading");
42 return -1;
43 }
44
45 Decoder *decoder = new Decoder();
46 Extractor *extractor = decoder->getExtractor();
47 if (!extractor) {
48 ALOGE("Extractor creation failed");
49 return -1;
50 }
51
52 // Read file properties
53 struct stat buf;
54 stat(sFilePath.c_str(), &buf);
55 size_t fileSize = buf.st_size;
56 if (fileSize > kMaxBufferSize) {
57 ALOGE("File size greater than maximum buffer size");
58 return -1;
59 }
60 int32_t fd = fileno(inputFp);
61 int32_t trackCount = extractor->initExtractor(fd, fileSize);
62 if (trackCount <= 0) {
63 ALOGE("initExtractor failed");
64 return -1;
65 }
66 for (int curTrack = 0; curTrack < trackCount; curTrack++) {
67 int32_t status = extractor->setupTrackFormat(curTrack);
68 if (status != 0) {
69 ALOGE("Track Format invalid");
70 return -1;
71 }
72
73 uint8_t *inputBuffer = (uint8_t *) malloc(fileSize);
74 if (!inputBuffer) {
75 ALOGE("Insufficient memory");
76 return -1;
77 }
78
79 vector<AMediaCodecBufferInfo> frameInfo;
80 AMediaCodecBufferInfo info;
81 uint32_t inputBufferOffset = 0;
82
83 // Get frame data
84 while (1) {
85 status = extractor->getFrameSample(info);
86 if (status || !info.size) break;
87 // copy the meta data and buffer to be passed to decoder
88 if (inputBufferOffset + info.size > kMaxBufferSize) {
89 ALOGE("Memory allocated not sufficient");
90 free(inputBuffer);
91 return -1;
92 }
93 memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
94 frameInfo.push_back(info);
95 inputBufferOffset += info.size;
96 }
97
98 const char *codecName = env->GetStringUTFChars(jCodecName, nullptr);
99 string sCodecName = string(codecName);
100 decoder->setupDecoder();
101 status = decoder->decode(inputBuffer, frameInfo, sCodecName, asyncMode);
102 if (status != AMEDIA_OK) {
103 ALOGE("Decode returned error");
104 free(inputBuffer);
105 env->ReleaseStringUTFChars(jCodecName, codecName);
106 return -1;
107 }
108 decoder->deInitCodec();
109 const char *inputReference = env->GetStringUTFChars(jFileName, nullptr);
110 const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
111 string sInputReference = string(inputReference);
112 decoder->dumpStatistics(sInputReference, sCodecName, (asyncMode ? "async" : "sync"),
113 statsFile);
114 env->ReleaseStringUTFChars(jCodecName, codecName);
115 env->ReleaseStringUTFChars(jStatsFile, statsFile);
116 env->ReleaseStringUTFChars(jFileName, inputReference);
117 if (inputBuffer) {
118 free(inputBuffer);
119 inputBuffer = nullptr;
120 }
121 decoder->resetDecoder();
122 }
123 if (inputFp) {
124 fclose(inputFp);
125 inputFp = nullptr;
126 }
127 extractor->deInitExtractor();
128 delete decoder;
129 return 0;
130 }
131