Merge changes from topic "blockobenchmarks"

am: f87ae40621

Change-Id: I11495fdcfc5592dc7faa2d5d326afab61df9b6d4
gugelfrei
Ray Essick 5 years ago committed by android-build-merger
commit c34dc6e2cd

@ -29,6 +29,10 @@ android_test {
"android.test.base",
],
jni_libs: [
"libmediabenchmark_jni",
],
static_libs: [
"libMediaBenchmark",
"junit",

@ -30,7 +30,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.android.media.benchmark"
minSdkVersion 21
minSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "1.0"
@ -48,6 +48,18 @@ android {
manifest.srcFile 'AndroidManifest.xml'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
repositories {

@ -27,6 +27,7 @@ import com.android.media.benchmark.R;
import com.android.media.benchmark.library.CodecUtils;
import com.android.media.benchmark.library.Decoder;
import com.android.media.benchmark.library.Extractor;
import com.android.media.benchmark.library.Native;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -44,6 +45,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
public class DecoderTest {
private static final Context mContext =
@ -194,4 +197,32 @@ public class DecoderTest {
+ mInputFilePath);
}
}
@Test
public void testNativeDecoder() throws IOException {
File inputFile = new File(mInputFilePath + mInputFile);
assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
inputFile.exists());
int status = -1;
FileInputStream fileInput = new FileInputStream(inputFile);
FileDescriptor fileDescriptor = fileInput.getFD();
Extractor extractor = new Extractor();
int trackCount = extractor.setUpExtractor(fileDescriptor);
assertTrue("Extraction failed. No tracks for file: ", trackCount > 0);
for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
String mime = format.getString(MediaFormat.KEY_MIME);
ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
for (String codecName : mediaCodecs) {
Log.i("Test: %s\n", mInputFile);
Native nativeDecoder = new Native();
status = nativeDecoder.Decode(mInputFilePath, mInputFile, codecName, mAsyncMode);
assertTrue(
codecName + " decoder returned error " + status + " for file:" + mInputFile,
status == 0);
}
}
fileInput.close();
}
}

@ -28,6 +28,7 @@ import com.android.media.benchmark.library.CodecUtils;
import com.android.media.benchmark.library.Decoder;
import com.android.media.benchmark.library.Encoder;
import com.android.media.benchmark.library.Extractor;
import com.android.media.benchmark.library.Native;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -43,6 +44,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
public class EncoderTest {
private static final Context mContext =
@ -85,19 +88,16 @@ public class EncoderTest {
public void sampleEncoderTest() throws Exception {
int status;
int frameSize;
//Parameters for video
int width = 0;
int height = 0;
int profile = 0;
int level = 0;
int frameRate = 0;
//Parameters for audio
int bitRate = 0;
int sampleRate = 0;
int numChannels = 0;
File inputFile = new File(mInputFilePath + mInputFile);
if (inputFile.exists()) {
FileInputStream fileInput = new FileInputStream(inputFile);
@ -129,7 +129,6 @@ public class EncoderTest {
bufInfo.presentationTimeUs + " size = " + bufInfo.size);
}
} while (sampleSize > 0);
int tid = android.os.Process.myTid();
File decodedFile = new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
FileOutputStream decodeOutputStream = new FileOutputStream(decodedFile);
@ -269,4 +268,43 @@ public class EncoderTest {
mInputFilePath);
}
}
@Test
public void testNativeEncoder() throws Exception {
File inputFile = new File(mInputFilePath + mInputFile);
assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
inputFile.exists());
int status = -1;
int tid = android.os.Process.myTid();
final String mDecodedFile = mContext.getFilesDir() + "/decoder_" + tid + ".out";
FileInputStream fileInput = new FileInputStream(inputFile);
FileDescriptor fileDescriptor = fileInput.getFD();
Extractor extractor = new Extractor();
int trackCount = extractor.setUpExtractor(fileDescriptor);
assertTrue("Extraction failed. No tracks for file: ", trackCount > 0);
for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
String mime = format.getString(MediaFormat.KEY_MIME);
ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, true);
// Encoding the decoder's output
for (String codecName : mediaCodecs) {
Native nativeEncoder = new Native();
status = nativeEncoder.Encode(mInputFilePath, mInputFile, mDecodedFile, codecName);
assertTrue(
codecName + " encoder returned error " + status + " for file:" + mInputFile,
status == 0);
}
}
File decodedFile = new File(mDecodedFile);
// Cleanup temporary input file
if (decodedFile.exists()) {
if (decodedFile.delete()) {
Log.i(TAG, "Successfully deleted - " + mDecodedFile);
} else {
Log.e(TAG, "Unable to delete - " + mDecodedFile);
}
}
fileInput.close();
}
}

@ -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)));
}
}

@ -0,0 +1,36 @@
cc_test_library {
name: "libmediabenchmark_jni",
defaults: [
"libmediabenchmark_common-defaults",
"libmediabenchmark_soft_sanitize_all-defaults",
],
srcs: [
"NativeExtractor.cpp",
"NativeMuxer.cpp",
"NativeEncoder.cpp",
"NativeDecoder.cpp",
],
shared_libs: [
"liblog",
],
sdk_version: "current",
static_libs: [
"libmediabenchmark_common",
"libmediabenchmark_extractor",
"libmediabenchmark_muxer",
"libmediabenchmark_decoder",
"libmediabenchmark_encoder",
],
stl: "c++_static",
cflags: [
"-Wall",
"-Werror",
],
}

@ -0,0 +1,44 @@
#
# 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.
#
cmake_minimum_required(VERSION 3.4.1)
set(native_source_path "../../../../src/native")
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)
find_library(log-lib log)
target_link_libraries(mediabenchmark_jni mediandk ${log-lib})

@ -0,0 +1,126 @@
/*
* 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 "NativeDecoder"
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <android/log.h>
#include "Decoder.h"
extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Decode(
JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jCodecName,
jboolean asyncMode) {
const char *filePath = env->GetStringUTFChars(jFilePath, nullptr);
const char *fileName = env->GetStringUTFChars(jFileName, nullptr);
string sFilePath = string(filePath) + string(fileName);
UNUSED(thiz);
FILE *inputFp = fopen(sFilePath.c_str(), "rb");
env->ReleaseStringUTFChars(jFileName, fileName);
env->ReleaseStringUTFChars(jFilePath, filePath);
if (!inputFp) {
ALOGE("Unable to open input file for reading");
return -1;
}
Decoder *decoder = new Decoder();
Extractor *extractor = decoder->getExtractor();
if (!extractor) {
ALOGE("Extractor creation failed");
return -1;
}
// Read file properties
struct stat buf;
stat(sFilePath.c_str(), &buf);
size_t fileSize = buf.st_size;
if (fileSize > kMaxBufferSize) {
ALOGE("File size greater than maximum buffer size");
return -1;
}
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("Insufficient memory");
return -1;
}
vector<AMediaCodecBufferInfo> frameInfo;
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 decoder
if (inputBufferOffset + info.size > kMaxBufferSize) {
ALOGE("Memory allocated not sufficient");
free(inputBuffer);
return -1;
}
memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
const char *codecName = env->GetStringUTFChars(jCodecName, nullptr);
string sCodecName = string(codecName);
decoder->setupDecoder();
status = decoder->decode(inputBuffer, frameInfo, sCodecName, asyncMode);
if (status != AMEDIA_OK) {
ALOGE("Decode returned error");
free(inputBuffer);
env->ReleaseStringUTFChars(jCodecName, codecName);
return -1;
}
decoder->deInitCodec();
env->ReleaseStringUTFChars(jCodecName, codecName);
const char *inputReference = env->GetStringUTFChars(jFileName, nullptr);
string sInputReference = string(inputReference);
decoder->dumpStatistics(sInputReference);
env->ReleaseStringUTFChars(jFileName, inputReference);
if(inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
decoder->resetDecoder();
}
if(inputFp) {
fclose(inputFp);
inputFp = nullptr;
}
extractor->deInitExtractor();
delete decoder;
return 0;
}

@ -0,0 +1,199 @@
/*
* 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 "NativeEncoder"
#include <jni.h>
#include <fstream>
#include <iostream>
#include <sys/stat.h>
#include <android/log.h>
#include "Decoder.h"
#include "Encoder.h"
#include <stdio.h>
extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Encode(
JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jOutFilePath,
jstring jCodecName) {
const char *filePath = env->GetStringUTFChars(jFilePath, nullptr);
const char *fileName = env->GetStringUTFChars(jFileName, nullptr);
string sFilePath = string(filePath) + string(fileName);
UNUSED(thiz);
FILE *inputFp = fopen(sFilePath.c_str(), "rb");
env->ReleaseStringUTFChars(jFileName, fileName);
env->ReleaseStringUTFChars(jFilePath, filePath);
if (!inputFp) {
ALOGE("Unable to open input file for reading");
return -1;
}
Decoder *decoder = new Decoder();
Extractor *extractor = decoder->getExtractor();
if (!extractor) {
ALOGE("Extractor creation failed");
return -1;
}
// Read file properties
struct stat buf;
stat(sFilePath.c_str(), &buf);
size_t fileSize = buf.st_size;
if (fileSize > kMaxBufferSize) {
ALOGE("File size greater than maximum buffer size");
return -1;
}
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("Insufficient memory");
return -1;
}
vector<AMediaCodecBufferInfo> frameInfo;
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 decoder
if (inputBufferOffset + info.size > kMaxBufferSize) {
ALOGE("Memory allocated not sufficient");
free(inputBuffer);
return -1;
}
memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
string decName = "";
const char *outputFilePath = env->GetStringUTFChars(jOutFilePath, nullptr);
FILE *outFp = fopen(outputFilePath, "wb");
if (outFp == nullptr) {
ALOGE("%s - File failed to open for writing!", outputFilePath);
free(inputBuffer);
return -1;
}
decoder->setupDecoder();
status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
if (status != AMEDIA_OK) {
ALOGE("Decode returned error");
free(inputBuffer);
return -1;
}
AMediaFormat *format = extractor->getFormat();
if(inputBuffer) {
free(inputBuffer);
inputBuffer = nullptr;
}
const char *mime = nullptr;
AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
if (!mime) {
ALOGE("Error in AMediaFormat_getString");
return -1;
}
ifstream eleStream;
eleStream.open(outputFilePath, ifstream::binary | ifstream::ate);
if (!eleStream.is_open()) {
ALOGE("%s - File failed to open for reading!", outputFilePath);
env->ReleaseStringUTFChars(jOutFilePath, outputFilePath);
return -1;
}
const char *codecName = env->GetStringUTFChars(jCodecName, NULL);
const char *inputReference = env->GetStringUTFChars(jFileName, nullptr);
string sCodecName = string(codecName);
string sInputReference = string(inputReference);
bool asyncMode[2] = {true, false};
for (int i = 0; i < 2; i++) {
size_t eleSize = eleStream.tellg();
eleStream.seekg(0, ifstream::beg);
// Get encoder params
encParameter encParams;
if (!strncmp(mime, "video/", 6)) {
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &encParams.width);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &encParams.height);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &encParams.frameRate);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &encParams.bitrate);
if (encParams.bitrate <= 0 || encParams.frameRate <= 0) {
encParams.frameRate = 25;
if (!strcmp(mime, "video/3gpp") || !strcmp(mime, "video/mp4v-es")) {
encParams.bitrate = 600000 /* 600 Kbps */;
} else {
encParams.bitrate = 8000000 /* 8 Mbps */;
}
}
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_PROFILE, &encParams.profile);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_LEVEL, &encParams.level);
} else {
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &encParams.sampleRate);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
&encParams.numChannels);
encParams.bitrate =
encParams.sampleRate * encParams.numChannels * 16 /* bitsPerSample */;
}
Encoder *encoder = new Encoder();
encoder->setupEncoder();
status = encoder->encode(sCodecName, eleStream, eleSize, asyncMode[i], encParams,
(char *)mime);
encoder->deInitCodec();
cout << "codec : " << codecName << endl;
ALOGV(" asyncMode = %d \n", asyncMode[i]);
encoder->dumpStatistics(sInputReference, extractor->getClipDuration());
encoder->resetEncoder();
delete encoder;
encoder = nullptr;
}
eleStream.close();
if (outFp) {
fclose(outFp);
outFp = nullptr;
}
env->ReleaseStringUTFChars(jFileName, inputReference);
env->ReleaseStringUTFChars(jCodecName, codecName);
env->ReleaseStringUTFChars(jOutFilePath, outputFilePath);
if (format) {
AMediaFormat_delete(format);
format = nullptr;
}
decoder->deInitCodec();
decoder->resetDecoder();
}
if(inputFp) {
fclose(inputFp);
inputFp = nullptr;
}
extractor->deInitExtractor();
delete decoder;
return 0;
}

@ -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;
}

@ -0,0 +1,32 @@
/*
* 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.
*/
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);
public native int Encode(String inputFilePath, String inputFileName, String outputFilePath,
String codecName);
}

@ -29,7 +29,7 @@ cc_library_static {
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
ldflags: ["-Wl,-Bsymbolic"],
}
cc_defaults {
@ -52,10 +52,14 @@ cc_defaults {
"liblog",
],
stl: "libc++_static",
sdk_version: "current",
cflags: [
"-Wall",
"-Werror",
]
],
}
cc_library_static {
@ -66,18 +70,20 @@ cc_library_static {
srcs: [
"BenchmarkC2Common.cpp",
"BenchmarkCommon.cpp",
"Stats.cpp",
"utils/Timers.cpp",
],
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
ldflags: ["-Wl,-Bsymbolic"],
}
cc_defaults {
name: "libmediabenchmark_codec2_common-defaults",
defaults: [
"libmediabenchmark_common-defaults",
"libcodec2-hidl-client-defaults",
"libmediabenchmark_soft_sanitize_all-defaults",
],
@ -88,7 +94,14 @@ cc_defaults {
shared_libs: [
"libcodec2_client",
]
"libmediandk",
"liblog",
],
cflags: [
"-Wall",
"-Werror",
],
}
// public dependency for native implementation
@ -102,5 +115,5 @@ cc_defaults {
"signed-integer-overflow",
],
cfi: true,
}
},
}

@ -56,6 +56,7 @@ void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format)
void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
const char *detail) {
(void)codec;
ALOGE("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
CallBackHandle *self = (CallBackHandle *)userdata;
self->mSawError = true;
@ -91,7 +92,7 @@ AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string cod
/* Configure codec with the given format*/
const char *s = AMediaFormat_toString(format);
ALOGV("Input format: %s\n", s);
ALOGI("Input format: %s\n", s);
media_status_t status = AMediaCodec_configure(codec, format, nullptr, nullptr, isEncoder);
if (status != AMEDIA_OK) {
@ -99,4 +100,4 @@ AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string cod
return nullptr;
}
return codec;
}
}

@ -27,6 +27,7 @@
#include <media/NdkMediaError.h>
#include "Stats.h"
#define UNUSED(x) (void)(x)
using namespace std;

@ -53,14 +53,14 @@ void Stats::dumpStatistics(std::string operation, std::string inputReference, in
}
// Print the Stats
std::cout << "Input Reference : " << inputReference << endl;
std::cout << "Setup Time in nano sec : " << mInitTimeNs << endl;
std::cout << "Average Time in nano sec : " << totalTimeTakenNs / mOutputTimer.size() << endl;
std::cout << "Time to first frame in nano sec : " << timeToFirstFrameNs << endl;
std::cout << "Time taken (in nano sec) to " << operation
<< " 1 sec of content : " << timeTakenPerSec << endl;
std::cout << "Total bytes " << operation << "ed : " << size << endl;
std::cout << "Minimum Time in nano sec : " << minTimeTakenNs << endl;
std::cout << "Maximum Time in nano sec : " << maxTimeTakenNs << endl;
std::cout << "Destroy Time in nano sec : " << mDeInitTimeNs << endl;
ALOGI("Input Reference : %s \n", inputReference.c_str());
ALOGI("Setup Time in nano sec : %" PRId64 "\n", mInitTimeNs);
ALOGI("Average Time in nano sec : %" PRId64 "\n", totalTimeTakenNs / mOutputTimer.size());
ALOGI("Time to first frame in nano sec : %" PRId64 "\n", timeToFirstFrameNs);
ALOGI("Time taken (in nano sec) to %s 1 sec of content : %" PRId64 "\n", operation.c_str(),
timeTakenPerSec);
ALOGI("Total bytes %sed : %d\n", operation.c_str(), size);
ALOGI("Minimum Time in nano sec : %" PRId64 "\n", minTimeTakenNs);
ALOGI("Maximum Time in nano sec : %" PRId64 "\n", maxTimeTakenNs);
ALOGI("Destroy Time in nano sec : %" PRId64 "\n", mDeInitTimeNs);
}

@ -18,6 +18,7 @@
#define __STATS_H__
#include <android/log.h>
#include <inttypes.h>
#ifndef ALOG
#define ALOG(priority, tag, ...) ((void)__android_log_print(ANDROID_##priority, tag, __VA_ARGS__))
@ -25,6 +26,12 @@
#define ALOGI(...) ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define ALOGD(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)
#ifndef LOG_NDEBUG
#define LOG_NDEBUG 1
#endif
#if LOG_NDEBUG
#define ALOGV(cond, ...) ((void)0)
#else

@ -27,24 +27,26 @@ cc_library_static {
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
ldflags: ["-Wl,-Bsymbolic"],
}
cc_library_static {
name: "libmediabenchmark_codec2_decoder",
defaults: [
"libmediabenchmark_common-defaults",
"libmediabenchmark_codec2_common-defaults",
],
srcs: ["C2Decoder.cpp"],
srcs: [
"C2Decoder.cpp",
"Decoder.cpp",
],
static_libs: [
"libmediabenchmark_codec2_common",
"libmediabenchmark_extractor",
"libmediabenchmark_codec2_extractor",
],
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
ldflags: ["-Wl,-Bsymbolic"],
}

@ -23,19 +23,19 @@ cc_library_static {
srcs: ["Encoder.cpp"],
static_libs: ["libmediabenchmark_extractor",
"libmediabenchmark_decoder",
static_libs: [
"libmediabenchmark_extractor",
"libmediabenchmark_decoder",
],
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
ldflags: ["-Wl,-Bsymbolic"],
}
cc_library_static {
name: "libmediabenchmark_codec2_encoder",
defaults: [
"libmediabenchmark_common-defaults",
"libmediabenchmark_codec2_common-defaults",
],
@ -43,11 +43,11 @@ cc_library_static {
static_libs: [
"libmediabenchmark_codec2_common",
"libmediabenchmark_extractor",
"libmediabenchmark_decoder",
"libmediabenchmark_codec2_extractor",
"libmediabenchmark_codec2_decoder",
],
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
ldflags: ["-Wl,-Bsymbolic"],
}

@ -206,7 +206,7 @@ int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize,
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_BIT_RATE, mParams.bitrate);
}
const char *s = AMediaFormat_toString(mFormat);
ALOGV("Input format: %s\n", s);
ALOGI("Input format: %s\n", s);
int64_t sTime = mStats->getCurTime();
mCodec = createMediaCodec(mFormat, mMime, codecName, true /*isEncoder*/);

@ -27,3 +27,20 @@ cc_library_static {
ldflags: ["-Wl,-Bsymbolic"]
}
cc_library_static {
name: "libmediabenchmark_codec2_extractor",
defaults: [
"libmediabenchmark_codec2_common-defaults",
],
srcs: ["Extractor.cpp"],
static_libs: [
"libmediabenchmark_codec2_common",
],
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
}

@ -87,7 +87,7 @@ cc_test {
srcs: ["C2DecoderTest.cpp"],
static_libs: [
"libmediabenchmark_extractor",
"libmediabenchmark_codec2_extractor",
"libmediabenchmark_codec2_common",
"libmediabenchmark_codec2_decoder",
],
@ -103,8 +103,8 @@ cc_test {
srcs: ["C2EncoderTest.cpp"],
static_libs: [
"libmediabenchmark_extractor",
"libmediabenchmark_decoder",
"libmediabenchmark_codec2_extractor",
"libmediabenchmark_codec2_decoder",
"libmediabenchmark_codec2_common",
"libmediabenchmark_codec2_encoder",
],

Loading…
Cancel
Save