blob: 9a4ca3de5e69fe6aef3dc3ffac90989ed4bd2997 [file] [log] [blame]
/*
* Copyright Samsung Electronics Co.,LTD.
* Copyright (C) 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.
*/
#include <linux/videodev2.h>
#include <ExynosJpegApi.h>
#include "hwjpeg-internal.h"
int ExynosJpegEncoder::setJpegConfig(void* pConfig)
{
ExynosJpegEncoder *that = reinterpret_cast<ExynosJpegEncoder *>(pConfig);
if (!setColorFormat(that->m_v4l2Format))
return -1;
if (!setJpegFormat(that->m_jpegFormat))
return -1;
if (!setSize(that->m_nWidth, that->m_nHeight))
return -1;
m_iInBufType = that->m_iInBufType;
m_iOutBufType = that->m_iOutBufType;
return 0;
}
int ExynosJpegEncoder::getInBuf(int *piBuf, int *piInputSize, int iSize)
{
if (iSize < 1) {
ALOGE("Invalid array size %d for getInBuf()", iSize);
return -1;
}
size_t len_buffers[iSize];
if (!m_hwjpeg.GetImageBuffers(piBuf, len_buffers, static_cast<unsigned int>(iSize)))
return -1;
for (int i = 0; i < iSize; i++)
piInputSize[i] = static_cast<int>(len_buffers[i]);
return 0;
}
int ExynosJpegEncoder::getOutBuf(int *piBuf, int *piOutputSize)
{
size_t len;
if (!m_hwjpeg.GetJpegBuffer(piBuf, &len))
return -1;
*piOutputSize = static_cast<int>(len);
return 0;
}
int ExynosJpegEncoder::setInBuf(int *piBuf, int *iSize)
{
size_t buflen[3];
unsigned int bufnum = 3;
if (!EnsureFormatIsApplied())
return -1;
if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum))
return -1;
for (unsigned int i = 0; i < bufnum; i++)
buflen[i] = static_cast<size_t>(iSize[i]);
if (!m_hwjpeg.SetImageBuffer(piBuf, buflen, bufnum))
return -1;
m_iInBufType = JPEG_BUF_TYPE_DMA_BUF;
return 0;
}
int ExynosJpegEncoder::setOutBuf(int iBuf, int iSize, int offset)
{
if (!m_hwjpeg.SetJpegBuffer(iBuf, static_cast<size_t>(iSize), offset))
return -1;
m_iOutBufType = JPEG_BUF_TYPE_DMA_BUF;
return 0;
}
int ExynosJpegEncoder::getInBuf(char **pcBuf, int *piInputSize, int iSize)
{
if (iSize < 1) {
ALOGE("Invalid array size %d for getInBuf()", iSize);
return -1;
}
size_t len_buffers[iSize];
if (!m_hwjpeg.GetImageBuffers(pcBuf, len_buffers, static_cast<unsigned int>(iSize)))
return -1;
for (int i = 0; i < iSize; i++)
piInputSize[i] = static_cast<int>(len_buffers[i]);
return 0;
}
int ExynosJpegEncoder::getOutBuf(char **pcBuf, int *piOutputSize)
{
size_t len;
if (!m_hwjpeg.GetJpegBuffer(pcBuf, &len))
return -1;
*piOutputSize = static_cast<int>(len);
return 0;
}
int ExynosJpegEncoder::setInBuf(char **pcBuf, int *iSize)
{
size_t buflen[3];
unsigned int bufnum = 3;
if (!EnsureFormatIsApplied())
return -1;
if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum))
return -1;
for (unsigned int i = 0; i < bufnum; i++)
buflen[i] = static_cast<size_t>(iSize[i]);
if (!m_hwjpeg.SetImageBuffer(pcBuf, buflen, bufnum))
return -1;
m_iInBufType = JPEG_BUF_TYPE_USER_PTR;
return 0;
}
int ExynosJpegEncoder::setOutBuf(char *pcBuf, int iSize)
{
if (!m_hwjpeg.SetJpegBuffer(pcBuf, static_cast<size_t>(iSize)))
return -1;
m_iOutBufType = JPEG_BUF_TYPE_USER_PTR;
return 0;
}
int ExynosJpegEncoder::setJpegFormat(int iV4l2JpegFormat)
{
if (m_jpegFormat == iV4l2JpegFormat)
return 0;
unsigned int hfactor, vfactor;
switch (iV4l2JpegFormat) {
case V4L2_PIX_FMT_JPEG_444:
hfactor = 1;
vfactor = 1;
break;
case V4L2_PIX_FMT_JPEG_422:
hfactor = 2;
vfactor = 1;
break;
case V4L2_PIX_FMT_JPEG_420:
hfactor = 2;
vfactor = 2;
break;
case V4L2_PIX_FMT_JPEG_GRAY:
hfactor = 0;
vfactor = 0;
break;
case V4L2_PIX_FMT_JPEG_422V:
hfactor = 1;
vfactor = 2;
break;
case V4L2_PIX_FMT_JPEG_411:
hfactor = 4;
vfactor = 1;
break;
default:
ALOGE("Unknown JPEG format `%08Xh", iV4l2JpegFormat);
return -1;
}
if (!m_hwjpeg.SetChromaSampFactor(hfactor, vfactor))
return -1;
m_jpegFormat = iV4l2JpegFormat;
return 0;
}
int ExynosJpegEncoder::setColorBufSize(int *piBufSize, int iSize)
{
size_t len[3];
unsigned int num = static_cast<unsigned int>(iSize);
if (!m_hwjpeg.GetImageBufferSizes(len, &num))
return -1;
for (unsigned int i = 0; i < num; i++)
piBufSize[i] = static_cast<int>(len[i]);
return 0;
}
bool ExynosJpegEncoder::__EnsureFormatIsApplied() {
if (TestStateEither(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED) &&
!m_hwjpeg.SetImageFormat(m_v4l2Format, m_nWidth, m_nHeight))
return false;
ClearState(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED);
return true;
}
static unsigned char jpeg_zigzagorder[] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
int ExynosJpegEncoder::setQuality(const unsigned char q_table[]) {
unsigned char qtbl[128];
for (unsigned int i = 0; i < ARRSIZE(jpeg_zigzagorder); i++)
qtbl[i] = q_table[jpeg_zigzagorder[i]];
for (unsigned int i = 0; i < ARRSIZE(jpeg_zigzagorder); i++)
qtbl[i + 64] = q_table[jpeg_zigzagorder[i] + 64];
if (!m_hwjpeg.SetQuality(qtbl))
return -1;
return 0;
}