/*
* Copyright 2015 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 "SoftAVCEnc"
#include <utils/Log.h>
#include <utils/misc.h>
#include "OMX_Video.h"
#include <HardwareAPI.h>
#include <MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
#include <OMX_IndexExt.h>
#include <OMX_VideoExt.h>
#include <ui/Rect.h>
#include "ih264_typedefs.h"
#include "iv2.h"
#include "ive2.h"
#include "ih264e.h"
#include "SoftAVCEnc.h"
namespace android {
#define ive_api_function ih264e_api_function
template<class T>
static void InitOMXParams(T *params) {
params->nSize = sizeof(T);
params->nVersion.s.nVersionMajor = 1;
params->nVersion.s.nVersionMinor = 0;
params->nVersion.s.nRevision = 0;
params->nVersion.s.nStep = 0;
}
struct LevelConversion {
OMX_VIDEO_AVCLEVELTYPE omxLevel;
WORD32 avcLevel;
};
static LevelConversion ConversionTable[] = {
{ OMX_VIDEO_AVCLevel1, 10 },
{ OMX_VIDEO_AVCLevel1b, 9 },
{ OMX_VIDEO_AVCLevel11, 11 },
{ OMX_VIDEO_AVCLevel12, 12 },
{ OMX_VIDEO_AVCLevel13, 13 },
{ OMX_VIDEO_AVCLevel2, 20 },
{ OMX_VIDEO_AVCLevel21, 21 },
{ OMX_VIDEO_AVCLevel22, 22 },
{ OMX_VIDEO_AVCLevel3, 30 },
{ OMX_VIDEO_AVCLevel31, 31 },
{ OMX_VIDEO_AVCLevel32, 32 },
{ OMX_VIDEO_AVCLevel4, 40 },
{ OMX_VIDEO_AVCLevel41, 41 },
{ OMX_VIDEO_AVCLevel42, 42 },
{ OMX_VIDEO_AVCLevel5, 50 },
{ OMX_VIDEO_AVCLevel51, 51 },
};
static const CodecProfileLevel kProfileLevels[] = {
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 },
{ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4 },
{ OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
};
static size_t GetCPUCoreCount() {
long cpuCoreCount = 1;
#if defined(_SC_NPROCESSORS_ONLN)
cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
#else
// _SC_NPROC_ONLN must be defined...
cpuCoreCount = sysconf(_SC_NPROC_ONLN);
#endif
CHECK(cpuCoreCount >= 1);
ALOGV("Number of CPU cores: %ld", cpuCoreCount);
return (size_t)cpuCoreCount;
}
static status_t ConvertOmxAvcLevelToAvcSpecLevel(
OMX_VIDEO_AVCLEVELTYPE omxLevel, WORD32 *avcLevel) {
for (size_t i = 0; i < NELEM(ConversionTable); ++i) {
if (omxLevel == ConversionTable[i].omxLevel) {
*avcLevel = ConversionTable[i].avcLevel;
return OK;
}
}
ALOGE("ConvertOmxAvcLevelToAvcSpecLevel: %d level not supported",
(int32_t)omxLevel);
return BAD_VALUE;
}
static status_t ConvertAvcSpecLevelToOmxAvcLevel(
WORD32 avcLevel, OMX_VIDEO_AVCLEVELTYPE *omxLevel) {
for (size_t i = 0; i < NELEM(ConversionTable); ++i) {
if (avcLevel == ConversionTable[i].avcLevel) {
*omxLevel = ConversionTable[i].omxLevel;
return OK;
}
}
ALOGE("ConvertAvcSpecLevelToOmxAvcLevel: %d level not supported",
(int32_t)avcLevel);
return BAD_VALUE;
}
SoftAVC::SoftAVC(
const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
: SoftVideoEncoderOMXComponent(
name, "video_encoder.avc", OMX_VIDEO_CodingAVC,
kProfileLevels, NELEM(kProfileLevels),
176 /* width */, 144 /* height */,
callbacks, appData, component),
mUpdateFlag(0),
mIvVideoColorFormat(IV_YUV_420P),
mAVCEncProfile(IV_PROFILE_BASE),
mAVCEncLevel(41),
mStarted(false),
mSawInputEOS(false),
mSawOutputEOS(false),
mSignalledError(false),
mCodecCtx(NULL) {
initPorts(kNumBuffers, kNumBuffers, ((mWidth * mHeight * 3) >> 1),
MEDIA_MIMETYPE_VIDEO_AVC, 2);
// If dump is enabled, then open create an empty file
GENERATE_FILE_NAMES();
CREATE_DUMP_FILE(mInFile);
CREATE_DUMP_FILE(mOutFile);
memset(mConversionBuffers, 0, sizeof(mConversionBuffers));
memset(mInputBufferInfo, 0, sizeof(mInputBufferInfo));
initEncParams();
}
SoftAVC::~SoftAVC() {
releaseEncoder();
List<BufferInfo *> &outQueue = getPortQueue(1);
List<BufferInfo *> &inQueue = getPortQueue(0);
CHECK(outQueue.empty());
CHECK(inQueue.empty());
}
bool SoftAVC::addwatermask(char *buf)
{
int width = mWidth;
int height = mHeight;
int rows = 203;
int cols = 43;
char table[43 * 203] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 0, 0, 51, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 0, 0, 51, 51, 51, 51, 0, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 0, 51, 51, 0, 51, 51, 0, 0, 51, 51, 0, 0, 0, 51, 51, 0, 0, 51, 51, 0, 0, 0, 51, 51, 0, 0, 0, 0, 0, 0,