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 <memory>
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/stat.h>
26
27 #include <android/log.h>
28
29 #include "Decoder.h"
30
Java_com_android_media_benchmark_library_Native_Decode(JNIEnv * env,jobject thiz,jstring jFilePath,jstring jFileName,jstring jStatsFile,jstring jCodecName,jboolean asyncMode)31 extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Decode(
32 JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jStatsFile,
33 jstring jCodecName, jboolean asyncMode) {
34 const char *filePath = env->GetStringUTFChars(jFilePath, nullptr);
35 const char *fileName = env->GetStringUTFChars(jFileName, nullptr);
36 string sFilePath = string(filePath) + string(fileName);
37 UNUSED(thiz);
38 FILE *inputFp = fopen(sFilePath.c_str(), "rb");
39 env->ReleaseStringUTFChars(jFileName, fileName);
40 env->ReleaseStringUTFChars(jFilePath, filePath);
41 if (!inputFp) {
42 ALOGE("Unable to open input file for reading");
43 return -1;
44 }
45
46 std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
47 Extractor *extractor = decoder->getExtractor();
48 if (!extractor) {
49 ALOGE("Extractor creation failed");
50 return -1;
51 }
52
53 // Read file properties
54 struct stat buf;
55 stat(sFilePath.c_str(), &buf);
56 size_t fileSize = buf.st_size;
57 if (fileSize > kMaxBufferSize) {
58 ALOGE("File size greater than maximum buffer size");
59 return -1;
60 }
61 int32_t fd = fileno(inputFp);
62 int32_t trackCount = extractor->initExtractor(fd, fileSize);
63 if (trackCount <= 0) {
64 ALOGE("initExtractor failed");
65 return -1;
66 }
67 for (int curTrack = 0; curTrack < trackCount; curTrack++) {
68 int32_t status = extractor->setupTrackFormat(curTrack);
69 if (status != 0) {
70 ALOGE("Track Format invalid");
71 return -1;
72 }
73
74 uint8_t *inputBuffer = (uint8_t *) malloc(fileSize);
75 if (!inputBuffer) {
76 ALOGE("Insufficient memory");
77 return -1;
78 }
79
80 vector<AMediaCodecBufferInfo> frameInfo;
81 AMediaCodecBufferInfo info;
82 uint32_t inputBufferOffset = 0;
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 == nullptr ? "" : 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 return 0;
129 }
130