Benchmark: Add JNI test for Extractor and Muxer

Test: adb shell am instrument -w -r -e debug false -e class\
      'com.android.media.benchmark.tests.ExtractorTest#sampleExtractNativeTest' \
      com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner

Test: adb shell am instrument -w -r -e debug false -e class\
      'com.android.media.benchmark.tests.MuxerTest#sampleMuxerNativeTest' \
      com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner

Bug: 140051680

Change-Id: I5c58326f7eef725c12f613b89c75b2987f616a41
gugelfrei
Snehal N Bhamare 5 years ago
parent b523c51d80
commit b146058379

@ -18,6 +18,7 @@ package com.android.media.benchmark.tests;
import com.android.media.benchmark.R;
import com.android.media.benchmark.library.Extractor;
import com.android.media.benchmark.library.Native;
import android.content.Context;
import android.util.Log;
@ -89,4 +90,25 @@ public class ExtractorTest {
}
assertThat(status, is(equalTo(0)));
}
@Test
public void sampleExtractNativeTest() throws IOException {
Native nativeExtractor = new Native();
int status = -1;
File inputFile = new File(mInputFilePath + mInputFileName);
if (inputFile.exists()) {
FileInputStream fileInput = new FileInputStream(inputFile);
status = nativeExtractor.Extract(mInputFilePath, mInputFileName);
fileInput.close();
if (status != 0) {
Log.e(TAG, "Extraction for " + mInputFileName + " failed.");
} else {
Log.i(TAG, "Extracted " + mInputFileName + " successfully.");
}
} else {
Log.e(TAG, "Cannot find " + inputFile + " in directory " +
mInputFilePath);
}
assertThat(status, is(equalTo(0)));
}
}

@ -18,6 +18,7 @@ package com.android.media.benchmark.tests;
import com.android.media.benchmark.R;
import com.android.media.benchmark.library.Extractor;
import com.android.media.benchmark.library.Muxer;
import com.android.media.benchmark.library.Native;
import androidx.test.platform.app.InstrumentationRegistry;
@ -149,4 +150,35 @@ public class MuxerTest {
}
assertThat(status, is(equalTo(0)));
}
@Test
public void sampleMuxerNativeTest() {
int status = -1;
Native nativeMuxer = new Native();
File inputFile = new File(mInputFilePath + mInputFileName);
if (inputFile.exists()) {
int tid = android.os.Process.myTid();
String mMuxOutputFile = (mContext.getFilesDir() + "/mux_" + tid + ".out");
status = nativeMuxer.Mux(mInputFilePath, mInputFileName, mMuxOutputFile,
mFormat);
if (status != 0) {
Log.e(TAG, "Mux for " + mInputFileName + " failed.");
} else {
Log.i(TAG, "Muxed " + mInputFileName + " successfully.");
}
File muxedFile = new File(mMuxOutputFile);
// Cleanup temporary output file
if (muxedFile.exists()) {
if (muxedFile.delete()) {
Log.i(TAG, "Successfully deleted" + mMuxOutputFile + " file.");
} else {
Log.e(TAG, "Unable to delete" + mMuxOutputFile + " file.");
}
}
} else {
Log.e(TAG, "Cannot find " + inputFile + " in directory " +
mInputFilePath);
}
assertThat(status, is(equalTo(0)));
}
}

@ -7,6 +7,8 @@ cc_test_library {
],
srcs: [
"NativeExtractor.cpp",
"NativeMuxer.cpp",
"NativeEncoder.cpp",
"NativeDecoder.cpp",
],
@ -20,6 +22,7 @@ cc_test_library {
static_libs: [
"libmediabenchmark_common",
"libmediabenchmark_extractor",
"libmediabenchmark_muxer",
"libmediabenchmark_decoder",
"libmediabenchmark_encoder",
],

@ -21,17 +21,21 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
add_library(
mediabenchmark_jni SHARED
NativeExtractor.cpp
NativeMuxer.cpp
NativeDecoder.cpp
NativeEncoder.cpp
${native_source_path}/common/BenchmarkCommon.cpp
${native_source_path}/common/Stats.cpp
${native_source_path}/common/utils/Timers.cpp
${native_source_path}/extractor/Extractor.cpp
${native_source_path}/muxer/Muxer.cpp
${native_source_path}/decoder/Decoder.cpp
${native_source_path}/encoder/Encoder.cpp)
include_directories(${native_source_path}/common)
include_directories(${native_source_path}/extractor)
include_directories(${native_source_path}/muxer)
include_directories(${native_source_path}/decoder)
include_directories(${native_source_path}/encoder)

@ -0,0 +1,68 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "NativeExtractor"
#include <jni.h>
#include <string>
#include <sys/stat.h>
#include "Extractor.h"
extern "C"
JNIEXPORT int32_t JNICALL
Java_com_android_media_benchmark_library_Native_Extract(JNIEnv *env, jobject thiz,
jstring jInputFilePath,
jstring jInputFileName) {
UNUSED(thiz);
const char *inputFilePath = env->GetStringUTFChars(jInputFilePath, nullptr);
const char *inputFileName = env->GetStringUTFChars(jInputFileName, nullptr);
string sFilePath = string(inputFilePath) + string(inputFileName);
FILE *inputFp = fopen(sFilePath.c_str(), "rb");
// Read file properties
struct stat buf;
stat(sFilePath.c_str(), &buf);
size_t fileSize = buf.st_size;
int32_t fd = fileno(inputFp);
Extractor *extractObj = new Extractor();
int32_t trackCount = extractObj->initExtractor((long)fd, fileSize);
if (trackCount <= 0) {
ALOGE("initExtractor failed");
return -1;
}
int32_t trackID = 0;
int32_t status = extractObj->extract(trackID);
if (status != AMEDIA_OK) {
ALOGE("Extraction failed");
return -1;
}
if (inputFp) {
fclose(inputFp);
inputFp = nullptr;
}
extractObj->deInitExtractor();
extractObj->dumpStatistics(inputFileName);
env->ReleaseStringUTFChars(jInputFilePath, inputFilePath);
env->ReleaseStringUTFChars(jInputFileName, inputFileName);
delete extractObj;
return status;
}

@ -0,0 +1,182 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "NativeMuxer"
#include <jni.h>
#include <string>
#include <sys/stat.h>
#include "Muxer.h"
MUXER_OUTPUT_T getMuxerOutFormat(const char *fmt);
extern "C"
JNIEXPORT int32_t JNICALL
Java_com_android_media_benchmark_library_Native_Mux(JNIEnv *env, jobject thiz,
jstring jInputFilePath, jstring jInputFileName,
jstring jOutputFilePath, jstring jFormat) {
UNUSED(thiz);
ALOGV("Mux the samples given by extractor");
const char *inputFilePath = env->GetStringUTFChars(jInputFilePath, nullptr);
const char *inputFileName = env->GetStringUTFChars(jInputFileName, nullptr);
string sInputFile = string(inputFilePath) + string(inputFileName);
FILE *inputFp = fopen(sInputFile.c_str(), "rb");
if (!inputFp) {
ALOGE("Unable to open input file for reading");
return -1;
}
const char *fmt = env->GetStringUTFChars(jFormat, nullptr);
MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
env->ReleaseStringUTFChars(jFormat, fmt);
if (outputFormat == MUXER_OUTPUT_FORMAT_INVALID) {
ALOGE("output format is MUXER_OUTPUT_FORMAT_INVALID");
return MUXER_OUTPUT_FORMAT_INVALID;
}
Muxer *muxerObj = new Muxer();
Extractor *extractor = muxerObj->getExtractor();
if (!extractor) {
ALOGE("Extractor creation failed");
return -1;
}
// Read file properties
struct stat buf;
stat(sInputFile.c_str(), &buf);
size_t fileSize = buf.st_size;
int32_t fd = fileno(inputFp);
int32_t trackCount = extractor->initExtractor(fd, fileSize);
if (trackCount <= 0) {
ALOGE("initExtractor failed");
return -1;
}
for (int curTrack = 0; curTrack < trackCount; curTrack++) {
int32_t status = extractor->setupTrackFormat(curTrack);
if (status != 0) {
ALOGE("Track Format invalid");
return -1;
}
uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
if (!inputBuffer) {
ALOGE("Allocation Failed");
return -1;
}
vector<AMediaCodecBufferInfo> frameInfos;
AMediaCodecBufferInfo info;
uint32_t inputBufferOffset = 0;
// Get Frame Data
while (1) {
status = extractor->getFrameSample(info);
if (status || !info.size) break;
// copy the meta data and buffer to be passed to muxer
if (inputBufferOffset + info.size > fileSize) {
ALOGE("Memory allocated not sufficient");
if (inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
return -1;
}
memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(),
static_cast<size_t>(info.size));
info.offset = inputBufferOffset;
frameInfos.push_back(info);
inputBufferOffset += info.size;
}
const char *outputFilePath = env->GetStringUTFChars(jOutputFilePath, nullptr);
FILE *outputFp = fopen(((string)outputFilePath).c_str(), "w+b");
env->ReleaseStringUTFChars(jOutputFilePath, outputFilePath);
if (!outputFp) {
ALOGE("Unable to open output file for writing");
if (inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
return -1;
}
int32_t outFd = fileno(outputFp);
status = muxerObj->initMuxer(outFd, (MUXER_OUTPUT_T)outputFormat);
if (status != 0) {
ALOGE("initMuxer failed");
if (inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
return -1;
}
status = muxerObj->mux(inputBuffer, frameInfos);
if (status != 0) {
ALOGE("Mux failed");
if (inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
return -1;
}
muxerObj->deInitMuxer();
muxerObj->dumpStatistics(inputFileName);
env->ReleaseStringUTFChars(jInputFilePath, inputFilePath);
env->ReleaseStringUTFChars(jInputFileName, inputFileName);
if (inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
if (outputFp) {
fclose(outputFp);
outputFp = nullptr;
}
muxerObj->resetMuxer();
}
if (inputFp) {
fclose(inputFp);
inputFp = nullptr;
}
extractor->deInitExtractor();
delete muxerObj;
return 0;
}
MUXER_OUTPUT_T getMuxerOutFormat(const char *fmt) {
static const struct {
const char *name;
int value;
} kFormatMaps[] = {{"mp4", MUXER_OUTPUT_FORMAT_MPEG_4},
{"webm", MUXER_OUTPUT_FORMAT_WEBM},
{"3gpp", MUXER_OUTPUT_FORMAT_3GPP},
{"ogg", MUXER_OUTPUT_FORMAT_OGG}};
int32_t muxOutputFormat = MUXER_OUTPUT_FORMAT_INVALID;
for (auto kFormatMap : kFormatMaps) {
if (!strcmp(fmt, kFormatMap.name)) {
muxOutputFormat = kFormatMap.value;
break;
}
}
return (MUXER_OUTPUT_T)muxOutputFormat;
}

@ -19,6 +19,11 @@ package com.android.media.benchmark.library;
public class Native {
static { System.loadLibrary("mediabenchmark_jni"); }
public native int Extract(String inputFilePath, String inputFileName);
public native int Mux(String inputFilePath, String inputFileName, String outputFilePath,
String format);
public native int Decode(String inputFilePath, String inputFileName, String codecName,
boolean asyncMode);

Loading…
Cancel
Save