am: f87ae40621
Change-Id: I11495fdcfc5592dc7faa2d5d326afab61df9b6d4
gugelfrei
commit
c34dc6e2cd
@ -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);
|
||||
}
|
Loading…
Reference in new issue