summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libhwjpeg/Android.mk2
-rw-r--r--libhwjpeg/AppMarkerWriter.cpp164
-rw-r--r--libhwjpeg/AppMarkerWriter.h11
-rw-r--r--libhwjpeg/ExynosJpegEncoder.cpp24
-rw-r--r--libhwjpeg/ExynosJpegEncoderForCamera.cpp91
-rw-r--r--libhwjpeg/LibScalerForJpeg.cpp307
-rw-r--r--libhwjpeg/LibScalerForJpeg.h106
-rw-r--r--libhwjpeg/ThumbnailScaler.cpp26
-rw-r--r--libhwjpeg/ThumbnailScaler.h21
-rw-r--r--libhwjpeg/include/ExynosJpegEncoderForCamera.h15
-rw-r--r--libhwjpeg/include/LibScalerForJpeg.h61
-rw-r--r--libhwjpeg/include/hardware/exynos/ExynosExif.h37
12 files changed, 513 insertions, 352 deletions
diff --git a/libhwjpeg/Android.mk b/libhwjpeg/Android.mk
index 448fb01..77ef17e 100644
--- a/libhwjpeg/Android.mk
+++ b/libhwjpeg/Android.mk
@@ -25,7 +25,7 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := hwjpeg-base.cpp hwjpeg-v4l2.cpp ExynosJpegEncoder.cpp \
LibScalerForJpeg.cpp AppMarkerWriter.cpp ExynosJpegEncoderForCamera.cpp \
- libhwjpeg-exynos.cpp
+ libhwjpeg-exynos.cpp ThumbnailScaler.cpp
LOCAL_MODULE := libhwjpeg
LOCAL_MODULE_TAGS := optional
diff --git a/libhwjpeg/AppMarkerWriter.cpp b/libhwjpeg/AppMarkerWriter.cpp
index 5334115..4a5edbb 100644
--- a/libhwjpeg/AppMarkerWriter.cpp
+++ b/libhwjpeg/AppMarkerWriter.cpp
@@ -44,14 +44,24 @@ CEndianessChecker::CEndianessChecker()
CAppMarkerWriter::CAppMarkerWriter()
- : m_pAppBase(NULL), m_pApp1End(NULL), m_pExif(NULL), m_pDebug(NULL)
+ : m_pAppBase(NULL), m_pApp1End(NULL), m_pExif(NULL), m_pExtra(NULL)
{
Init();
}
CAppMarkerWriter::CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug)
{
- PrepareAppWriter(base, exif, debug);
+ extra_appinfo_t extraInfo;
+ app_info_t appInfo[15];
+
+ memset(&extraInfo, 0, sizeof(extraInfo));
+ memset(&appInfo, 0, sizeof(appInfo));
+
+ extraInfo.appInfo = appInfo;
+
+ ExtractDebugAttributeInfo(debug, &extraInfo);
+
+ PrepareAppWriter(base, exif, &extraInfo);
}
void CAppMarkerWriter::Init()
@@ -75,7 +85,7 @@ void CAppMarkerWriter::Init()
m_pThumbSizePlaceholder = NULL;
}
-void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug)
+void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extra_appinfo_t *extra)
{
m_pAppBase = base;
m_pExif = exif;
@@ -101,19 +111,25 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, debu
m_szMake = strlen(m_pExif->maker);
if (m_szMake > 0) {
m_n0thIFDFields++;
- applen += IFD_FIELD_SIZE + m_szMake + 1;
+ applen += IFD_FIELD_SIZE;
+ if (m_szMake > 3)
+ applen += m_szMake + 1;
}
m_szSoftware = strlen(m_pExif->software);
if (m_szSoftware > 0) {
m_n0thIFDFields++;
- applen += IFD_FIELD_SIZE + m_szSoftware + 1;
+ applen += IFD_FIELD_SIZE;
+ if (m_szSoftware > 3)
+ applen += m_szSoftware + 1;
}
m_szModel = strlen(m_pExif->model);
if (m_szModel > 0) {
m_n0thIFDFields++;
- applen += IFD_FIELD_SIZE + m_szModel + 1;
+ applen += IFD_FIELD_SIZE;
+ if (m_szModel > 3)
+ applen += m_szModel + 1;
}
if (m_pExif->enableGps) {
@@ -157,17 +173,23 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, debu
m_szUniqueID = strlen(m_pExif->unique_id); // len should be 32!
if (m_szUniqueID > 0) {
m_nExifIFDFields++;
- applen += IFD_FIELD_SIZE + m_szUniqueID + 1;
+ applen += IFD_FIELD_SIZE;
+ if (m_szUniqueID > 3)
+ applen += m_szUniqueID + 1;
}
if (m_pExif->maker_note_size > 0) {
m_nExifIFDFields++;
- applen += IFD_FIELD_SIZE + m_pExif->maker_note_size;
+ applen += IFD_FIELD_SIZE;
+ if (m_pExif->maker_note_size > 4)
+ applen += m_pExif->maker_note_size;
}
if (m_pExif->user_comment_size > 0) {
m_nExifIFDFields++;
- applen += IFD_FIELD_SIZE + m_pExif->user_comment_size;
+ applen += IFD_FIELD_SIZE;
+ if (m_pExif->user_comment_size > 4)
+ applen += m_pExif->user_comment_size;
}
// Interoperability SubIFD
@@ -227,33 +249,23 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, debu
m_szApp1 = applen;
}
- if (debug) {
- if (debug->num_of_appmarker > (EXTRA_APPMARKER_LIMIT - EXTRA_APPMARKER_MIN)) {
- ALOGE("Too many extra APP markers %d", debug->num_of_appmarker);
- return;
- }
-
- for (int idx = 0; idx < debug->num_of_appmarker; idx++) {
- int appid;
- unsigned int len;
-
- appid = debug->idx[idx][0];
- if ((appid < EXTRA_APPMARKER_MIN) || (appid >= EXTRA_APPMARKER_LIMIT)) {
- ALOGE("Invalid extra APP segment ID %d", appid);
+ if (extra) {
+ for (int idx = 0; idx < extra->num_of_appmarker; idx++) {
+ if ((extra->appInfo[idx].appid < EXTRA_APPMARKER_MIN) || (extra->appInfo[idx].appid >= EXTRA_APPMARKER_LIMIT)) {
+ ALOGE("Invalid extra APP segment ID %d", extra->appInfo[idx].appid);
return;
}
- len = debug->debugSize[appid];
- if ((len == 0) || (len > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
- ALOGE("Invalid APP%d segment size, %u bytes", appid, len);
+ if ((extra->appInfo[idx].dataSize == 0) || (extra->appInfo[idx].dataSize > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
+ ALOGE("Invalid APP%d segment size, %u bytes", extra->appInfo[idx].appid, extra->appInfo[idx].dataSize);
return;
}
- ALOGD("APP%d: %u bytes", appid, len + JPEG_SEGMENT_LENFIELD_SIZE);
+ ALOGD("APP%d: %u bytes", extra->appInfo[idx].appid, extra->appInfo[idx].dataSize);
}
}
- m_pDebug = debug;
+ m_pExtra = extra;
// |<- m_szApp1 ->|<- m_szMaxThumbSize ->|<-m_szAppX->|
// |<----- size of total APP1 and APP4 segments ----->|<-APP11->|<-- main image
@@ -278,7 +290,7 @@ char *CAppMarkerWriter::WriteAPP11(char *current, size_t dummy, size_t align)
if ((dummy == 0) && (align == 1))
return current;
- if (!m_pExif && !m_pDebug)
+ if (!m_pExif && !m_pExtra)
return current;
uint16_t len = PTR_TO_ULONG(current + APPMARKLEN) & (align - 1);
@@ -297,12 +309,12 @@ char *CAppMarkerWriter::WriteAPP11(char *current, size_t dummy, size_t align)
char *CAppMarkerWriter::WriteAPPX(char *current, bool just_reserve)
{
- if (!m_pDebug)
+ if (!m_pExtra)
return current;
- for (int idx = 0; idx < m_pDebug->num_of_appmarker; idx++) {
- int appid = m_pDebug->idx[idx][0];
- uint16_t len = m_pDebug->debugSize[appid] + JPEG_SEGMENT_LENFIELD_SIZE;
+ for (int idx = 0; idx < m_pExtra->num_of_appmarker; idx++) {
+ int appid = m_pExtra->appInfo[idx].appid;
+ uint16_t len = m_pExtra->appInfo[idx].dataSize + JPEG_SEGMENT_LENFIELD_SIZE;
// APPx marker
*current++ = 0xFF;
@@ -311,8 +323,8 @@ char *CAppMarkerWriter::WriteAPPX(char *current, bool just_reserve)
current = WriteDataInBig(current, len);
// APPx data
if (!just_reserve)
- memcpy(current, m_pDebug->debugData[appid], m_pDebug->debugSize[appid]);
- current += m_pDebug->debugSize[appid];
+ memcpy(current, m_pExtra->appInfo[idx].appData, m_pExtra->appInfo[idx].dataSize);
+ current += m_pExtra->appInfo[idx].dataSize;
}
return current;
@@ -508,26 +520,22 @@ static inline size_t GetSegLen(char *p)
return len | (*reinterpret_cast<unsigned char *>(p + 1) & 0xFF);
}
-static inline size_t GetExtraAPPSize(debug_attribute_t *debug, unsigned int *appid_bits)
+static inline size_t GetExtraAPPSize(extra_appinfo_t *info)
{
size_t len = 0;
- for (int idx = 0; idx < debug->num_of_appmarker; idx++) {
- int appid = debug->idx[idx][0];
- unsigned int applen = debug->debugSize[appid];
-
- if ((appid < EXTRA_APPMARKER_MIN) || (appid >= EXTRA_APPMARKER_LIMIT)) {
- ALOGE("%s: Invalid extra APP segment ID %d", dbgerrmsg, appid);
+ for (int idx = 0; idx < info->num_of_appmarker; idx++) {
+ if ((info->appInfo[idx].appid < EXTRA_APPMARKER_MIN) || (info->appInfo[idx].appid >= EXTRA_APPMARKER_LIMIT)) {
+ ALOGE("%s: Invalid extra APP segment ID %d", dbgerrmsg, info->appInfo[idx].appid);
return 0;
}
- if ((applen == 0) || (applen > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
- ALOGE("%s: Invalid APP%d segment size, %u bytes.", dbgerrmsg, appid, applen);
+ if ((info->appInfo[idx].dataSize == 0) || (info->appInfo[idx].dataSize > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
+ ALOGE("%s: Invalid APP%d segment size, %u bytes.", dbgerrmsg, info->appInfo[idx].appid, info->appInfo[idx].dataSize);
return 0;
}
- len += applen + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
- *appid_bits |= 1 << appid;
+ len += info->appInfo[idx].dataSize + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
}
return len;
@@ -535,18 +543,29 @@ static inline size_t GetExtraAPPSize(debug_attribute_t *debug, unsigned int *app
bool UpdateDebugData(char *jpeg, size_t jpeglen, debug_attribute_t *debug) // include/ExynosExif.h
{
- if (!debug) {
+ extra_appinfo_t extraInfo;
+ app_info_t appInfo[15];
+
+ memset(&extraInfo, 0, sizeof(extraInfo));
+ memset(&appInfo, 0, sizeof(appInfo));
+
+ extraInfo.appInfo = appInfo;
+
+ ExtractDebugAttributeInfo(debug, &extraInfo);
+
+ UpdateDebugData(jpeg, jpeglen, &extraInfo);
+
+ return true;
+}
+
+bool UpdateDebugData(char *jpeg, size_t jpeglen, extra_appinfo_t *extra) // include/ExynosExif.h
+{
+ if (!extra) {
ALOGI("No data to update in APPx");
return true;
}
- if (debug->num_of_appmarker > (EXTRA_APPMARKER_LIMIT - EXTRA_APPMARKER_MIN)) {
- ALOGE("%s: Too many extra APP markers %d", dbgerrmsg, debug->num_of_appmarker);
- return false;
- }
-
- unsigned int validappid_bits = 0;
- size_t validlen = GetExtraAPPSize(debug, &validappid_bits);
+ size_t validlen = GetExtraAPPSize(extra);
if (jpeglen < (validlen + JPEG_MARKER_SIZE)) {
ALOGE("%s: Too small JPEG stream length %zu", dbgerrmsg, jpeglen);
@@ -559,6 +578,8 @@ bool UpdateDebugData(char *jpeg, size_t jpeglen, debug_attribute_t *debug) // in
}
jpeglen -= 2;
+ int idx = 0;
+
while ((*jpeg++ == 0xFF) && (validlen > 0) && (jpeglen > validlen)) {
size_t seglen;
char marker;
@@ -573,21 +594,26 @@ bool UpdateDebugData(char *jpeg, size_t jpeglen, debug_attribute_t *debug) // in
}
appid = marker & 0xF;
- if (((marker & 0xF0) == 0xE0) && !!(validappid_bits & (1 << appid))) {
- // validappid_bits always has valid index bits
- // length check is performed in GetExtraAPPSize()
+ if (((marker & 0xF0) == 0xE0) && ((appid >= EXTRA_APPMARKER_MIN) && (appid <= EXTRA_APPMARKER_LIMIT))) {
+ if (appid != extra->appInfo[idx].appid) {
+ ALOGE("%s: stored appid(%d) is different with updated appid(%d)",
+ dbgerrmsg, appid, extra->appInfo[idx].appid);
+ return false;
+ }
+
seglen = GetSegLen(jpeg);
- if (seglen < (debug->debugSize[appid] + JPEG_SEGMENT_LENFIELD_SIZE)) {
+ if (seglen < (extra->appInfo[idx].dataSize + JPEG_SEGMENT_LENFIELD_SIZE)) {
ALOGE("%s: too small APP%d length %zu to store %u bytes",
- dbgerrmsg, appid, seglen, debug->debugSize[appid]);
+ dbgerrmsg, appid, seglen, extra->appInfo[idx].dataSize);
return false;
}
memcpy(jpeg + JPEG_SEGMENT_LENFIELD_SIZE,
- debug->debugData[appid], debug->debugSize[appid]);
- ALOGD("Successfully updated %u bytes to APP%d", debug->debugSize[appid], appid);
+ extra->appInfo[idx].appData, extra->appInfo[idx].dataSize);
+ ALOGD("Successfully updated %u bytes to APP%d", extra->appInfo[idx].dataSize, appid);
- validlen -= debug->debugSize[appid] + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
+ validlen -= extra->appInfo[idx].dataSize + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
+ idx++;
} else {
// just skip all other segments
seglen = GetSegLen(jpeg);
@@ -641,3 +667,19 @@ bool UpdateExif(char *jpeg, size_t jpeglen, exif_attribute_t *exif)
return true;
}
+
+void ExtractDebugAttributeInfo(debug_attribute_t *debug, extra_appinfo_t *extra)
+{
+ if (!debug) {
+ extra->num_of_appmarker = 0;
+ return;
+ }
+
+ extra->num_of_appmarker = debug->num_of_appmarker;
+ for (int idx = 0; idx < debug->num_of_appmarker; idx++) {
+ int appid = debug->idx[idx][0];
+ extra->appInfo[idx].appid = appid;
+ extra->appInfo[idx].appData = debug->debugData[appid];
+ extra->appInfo[idx].dataSize = debug->debugSize[appid];
+ }
+}
diff --git a/libhwjpeg/AppMarkerWriter.h b/libhwjpeg/AppMarkerWriter.h
index 0f3b502..5232e31 100644
--- a/libhwjpeg/AppMarkerWriter.h
+++ b/libhwjpeg/AppMarkerWriter.h
@@ -18,6 +18,7 @@
#define __HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
#include <ExynosExif.h>
+#include "include/hardware/exynos/ExynosExif.h"
#define JPEG_MAX_SEGMENT_SIZE ((1 << 16) - 1)
#define JPEG_MARKER_SIZE 2
@@ -55,7 +56,7 @@ class CAppMarkerWriter {
uint16_t m_nExifIFDFields;
uint16_t m_nGPSIFDFields;
exif_attribute_t *m_pExif;
- debug_attribute_t *m_pDebug;
+ extra_appinfo_t *m_pExtra;
uint32_t m_szMake;
uint32_t m_szSoftware;
@@ -85,7 +86,7 @@ public:
~CAppMarkerWriter() { }
- void PrepareAppWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug);
+ void PrepareAppWriter(char *base, exif_attribute_t *exif, extra_appinfo_t *info);
char *GetMainStreamBase() { return m_pMainBase; }
char *GetThumbStreamBase() { return m_pThumbBase; }
@@ -101,9 +102,9 @@ public:
size_t appsize = 0;
if (m_szApp1 > 0)
appsize += m_szApp1 + JPEG_MARKER_SIZE;
- if (m_pDebug) {
- for (int idx = 0; idx < m_pDebug->num_of_appmarker; idx++)
- appsize += m_pDebug->debugSize[m_pDebug->idx[idx][0]]
+ if (m_pExtra) {
+ for (int idx = 0; idx < m_pExtra->num_of_appmarker; idx++)
+ appsize += m_pExtra->appInfo[idx].dataSize +
+ JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
}
if (IsThumbSpaceReserved())
diff --git a/libhwjpeg/ExynosJpegEncoder.cpp b/libhwjpeg/ExynosJpegEncoder.cpp
index 9a4ca3d..39e7a2e 100644
--- a/libhwjpeg/ExynosJpegEncoder.cpp
+++ b/libhwjpeg/ExynosJpegEncoder.cpp
@@ -224,28 +224,6 @@ bool ExynosJpegEncoder::__EnsureFormatIsApplied() {
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;
+ return m_hwjpeg.SetQuality(q_table) ? 0 : -1;
}
diff --git a/libhwjpeg/ExynosJpegEncoderForCamera.cpp b/libhwjpeg/ExynosJpegEncoderForCamera.cpp
index 45695ae..ed09cb8 100644
--- a/libhwjpeg/ExynosJpegEncoderForCamera.cpp
+++ b/libhwjpeg/ExynosJpegEncoderForCamera.cpp
@@ -27,7 +27,7 @@
#include "hwjpeg-internal.h"
#include "AppMarkerWriter.h"
-#include "LibScalerForJpeg.h"
+#include "ThumbnailScaler.h"
#include "IFDWriter.h"
// Data length written by H/W without the scan data.
@@ -103,6 +103,10 @@ ExynosJpegEncoderForCamera::ExynosJpegEncoderForCamera(bool bBTBComp)
if (IsBTBCompressionSupported())
SetState(STATE_THUMBSIZE_CHANGED);
+ m_extraInfo.appInfo = m_appInfo;
+
+ mThumbnailScaler.reset(ThumbnailScaler::createInstance());
+
ALOGD("ExynosJpegEncoderForCamera Created: %p, ION %d", this, m_fdIONClient);
}
@@ -219,7 +223,7 @@ void *ExynosJpegEncoderForCamera::tCompressThumbnail(void *p)
bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit,
exif_attribute_t *exifInfo,
- debug_attribute_t *debuginfo)
+ extra_appinfo_t *extra)
{
// PREREQUISITES: The main and the thumbnail image size should be configured before.
@@ -252,7 +256,7 @@ bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit,
if (!!(GetDeviceCapabilities() & V4L2_CAP_EXYNOS_JPEG_NO_STREAMBASE_ALIGN))
align = 1;
- m_pAppWriter->PrepareAppWriter(base + JPEG_MARKER_SIZE, exifInfo, debuginfo);
+ m_pAppWriter->PrepareAppWriter(base + JPEG_MARKER_SIZE, exifInfo, extra);
if (limit <= (m_pAppWriter->CalculateAPPSize(0) + NECESSARY_JPEG_LENGTH)) {
ALOGE("Too small JPEG stream buffer size, %zu bytes", limit);
@@ -332,6 +336,23 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
int fdJpegBuffer, char** pcJpegBuffer,
debug_attribute_t *debugInfo)
{
+ if ((!debugInfo) || (debugInfo->num_of_appmarker == 0)) {
+ extra_appinfo_t *extra = NULL;
+ return encode(size, exifInfo, fdJpegBuffer, pcJpegBuffer, extra);
+ }
+
+ m_extraInfo.num_of_appmarker = 0;
+ memset(m_appInfo, 0, sizeof(m_appInfo));
+
+ ExtractDebugAttributeInfo(debugInfo, &m_extraInfo);
+
+ return encode(size, exifInfo, fdJpegBuffer, pcJpegBuffer, &m_extraInfo);
+}
+
+int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
+ int fdJpegBuffer, char** pcJpegBuffer,
+ extra_appinfo_t *appInfo)
+{
if (!(*pcJpegBuffer)) {
ALOGE("Target stream buffer is not specified");
return -1;
@@ -348,13 +369,13 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
char *jpeg_base = m_pStreamBase;
ALOGI_IF(!exifInfo, "Exif is not specified. Skipping writing APP1 marker");
- ALOGI_IF(!debugInfo,
+ ALOGI_IF(!appInfo,
"Debugging information is not specified. Skipping writing APP4 marker");
ALOGD("Given stream buffer size: %d bytes", *size);
CStopWatch stopwatch(true);
- if (!ProcessExif(jpeg_base, m_nStreamSize, exifInfo, debugInfo))
+ if (!ProcessExif(jpeg_base, m_nStreamSize, exifInfo, appInfo))
return -1;
int offset = PTR_DIFF(m_pStreamBase, m_pAppWriter->GetMainStreamBase());
@@ -562,47 +583,47 @@ bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
ALOGD("Generating thumbnail image: %dx%d -> %dx%d",
main_width, main_height, m_nThumbWidth, m_nThumbHeight);
- int len_srcbufs[3] = {0, 0, 0};
- void *srcbufs[3] = {NULL, NULL, NULL};
- int memtype;
+ if (!mThumbnailScaler) {
+ ALOGE("Thumbnail scaler is not prepared");
+ return false;
+ }
+
+ if (!mThumbnailScaler->SetSrcImage(main_width, main_height, v4l2Format)) {
+ ALOGE("Failed to configure the main image to the thumbnail scaler");
+ return false;
+ }
+
+
+ if (!mThumbnailScaler->SetDstImage(m_nThumbWidth, m_nThumbHeight, GetThumbnailFormat(v4l2Format))) {
+ ALOGE("Failed to configure the target image to the thumbnail scaler");
+ return false;
+ }
+
+ bool okay = false;
if (checkInBufType() == JPEG_BUF_TYPE_USER_PTR) {
- char *bufs[3];
- if (getInBuf(bufs, len_srcbufs, 3) < 0) {
+ char *bufs[ThumbnailScaler::SCALER_MAX_PLANES];
+ int len_srcbufs[ThumbnailScaler::SCALER_MAX_PLANES];
+
+ if (getInBuf(bufs, len_srcbufs, ThumbnailScaler::SCALER_MAX_PLANES) < 0) {
ALOGE("Failed to retrieve the main image buffers");
return false;
}
- memtype = V4L2_MEMORY_USERPTR;
- srcbufs[0] = reinterpret_cast<void *>(bufs[0]);
- srcbufs[1] = reinterpret_cast<void *>(bufs[1]);
- srcbufs[2] = reinterpret_cast<void *>(bufs[2]);
+
+ okay = mThumbnailScaler->RunStream(bufs, len_srcbufs, m_fdIONThumbImgBuffer, m_szIONThumbImgBuffer);
} else { // mainbuftype == JPEG_BUF_TYPE_DMA_BUF
- int bufs[3];
- if (getInBuf(bufs, len_srcbufs, 3) < 0) {
+ int bufs[ThumbnailScaler::SCALER_MAX_PLANES];
+ int len_srcbufs[ThumbnailScaler::SCALER_MAX_PLANES];
+
+ if (getInBuf(bufs, len_srcbufs, ThumbnailScaler::SCALER_MAX_PLANES) < 0) {
ALOGE("Failed to retrieve the main image buffers");
return false;
}
- memtype = V4L2_MEMORY_DMABUF;
- srcbufs[0] = reinterpret_cast<void *>(bufs[0]);
- srcbufs[1] = reinterpret_cast<void *>(bufs[1]);
- srcbufs[2] = reinterpret_cast<void *>(bufs[2]);
- }
-
- void *dstbuf[3] = {NULL, NULL, NULL};
- dstbuf[0] = reinterpret_cast<void *>(m_fdIONThumbImgBuffer);
-
- if (!m_pLibScaler.SetSrcImage(main_width, main_height, v4l2Format, srcbufs, memtype)) {
- ALOGE("Failed to configure the main image format to LibScalerForJpeg");
- return false;
- }
- if (!m_pLibScaler.SetDstImage(m_nThumbWidth, m_nThumbHeight,
- GetThumbnailFormat(v4l2Format), dstbuf, V4L2_MEMORY_DMABUF)) {
- ALOGE("Failed to configure the target image format to LibScalerForJpeg");
- return false;
+ okay = mThumbnailScaler->RunStream(bufs, len_srcbufs, m_fdIONThumbImgBuffer, m_szIONThumbImgBuffer);
}
- if (!m_pLibScaler.RunStream()) {
- ALOGE("Failed to convert the main image to thumbnail with LibScalerForJpeg");
+ if (!okay) {
+ ALOGE("Failed to convert the main image to thumbnail with the thumbnail scaler");
return false;
}
diff --git a/libhwjpeg/LibScalerForJpeg.cpp b/libhwjpeg/LibScalerForJpeg.cpp
index 333a7a0..1165495 100644
--- a/libhwjpeg/LibScalerForJpeg.cpp
+++ b/libhwjpeg/LibScalerForJpeg.cpp
@@ -18,253 +18,236 @@
#include "hwjpeg-internal.h"
#include "LibScalerForJpeg.h"
-LibScalerForJpeg::LibScalerForJpeg()
+#define SCALER_DEV_NODE "/dev/video50"
+
+static const char *getBufTypeString(unsigned int buftype)
{
- memset(&m_srcFmt, 0, sizeof(m_srcFmt));
- memset(&m_dstFmt, 0, sizeof(m_dstFmt));
- memset(&m_srcBuf, 0, sizeof(m_srcBuf));
- memset(&m_dstBuf, 0, sizeof(m_dstBuf));
- memset(&m_srcPlanes, 0, sizeof(m_srcPlanes));
- memset(&m_dstPlanes, 0, sizeof(m_dstPlanes));
-
- m_srcFmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- m_dstFmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- m_srcBuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- m_dstBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-
- m_srcBuf.m.planes = m_srcPlanes;
- m_dstBuf.m.planes = m_dstPlanes;
-
- m_fdScaler = open(SCALER_DEV_NODE, O_RDWR);
-
- if (m_fdScaler < 0) {
- ALOGE("Failed to open %s", SCALER_DEV_NODE);
- return;
- }
+ if (buftype == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ return "destination";
+ if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return "source";
+ return "unknown";
+}
- m_needReqbuf = true;
+bool LibScalerForJpeg::RunStream(int srcBuf[SCALER_MAX_PLANES], int __unused srcLen[SCALER_MAX_PLANES], int dstBuf, size_t __unused dstLen)
+{
+ if (!mSrcImage.begin(V4L2_MEMORY_DMABUF) || !mDstImage.begin(V4L2_MEMORY_DMABUF))
+ return false;
- ALOGD("LibScalerForJpeg Created: %p", this);
+ return queue(srcBuf, dstBuf);
}
-LibScalerForJpeg::~LibScalerForJpeg()
+bool LibScalerForJpeg::RunStream(char *srcBuf[SCALER_MAX_PLANES], int __unused srcLen[SCALER_MAX_PLANES], int dstBuf, size_t __unused dstLen)
{
- if (m_fdScaler > 0)
- close(m_fdScaler);
-
- m_fdScaler = -1;
+ if (!mSrcImage.begin(V4L2_MEMORY_USERPTR) || !mDstImage.begin(V4L2_MEMORY_DMABUF))
+ return false;
- ALOGD("LibScalerForJpeg Destroyed: %p", this);
+ return queue(srcBuf, dstBuf);
}
-bool LibScalerForJpeg::SetImage(
- v4l2_format &m_fmt, v4l2_buffer &m_buf, v4l2_plane m_planes[SCALER_MAX_PLANES],
- unsigned int width, unsigned int height, unsigned int v4l2_format,
- void *addrs[SCALER_MAX_PLANES], int mem_type)
+bool LibScalerForJpeg::Image::set(unsigned int width, unsigned int height, unsigned int format)
{
- /* Format information update*/
- if ((m_needReqbuf == true) ||
- (m_fmt.fmt.pix_mp.pixelformat != v4l2_format ||
- m_fmt.fmt.pix_mp.width != width ||
- m_fmt.fmt.pix_mp.height != height ||
- m_buf.memory != static_cast<v4l2_memory>(mem_type))) {
- m_fmt.fmt.pix_mp.pixelformat = v4l2_format;
- m_fmt.fmt.pix_mp.width = width;
- m_fmt.fmt.pix_mp.height = height;
- m_buf.memory = static_cast<v4l2_memory>(mem_type);
-
- // The driver returns the number and length of planes through TRY_FMT.
- if (ioctl(m_fdScaler, VIDIOC_TRY_FMT, &m_fmt) < 0) {
- ALOGE("Failed to TRY_FMT for source");
- m_needReqbuf = true;
+ if (same(width, height, format))
+ return true;
+
+ if (memoryType != 0) {
+ if (!mDevice.requestBuffers(bufferType, memoryType, 0))
return false;
- }
- m_needReqbuf = true;
}
- /* Buffer information update*/
- m_buf.index = 0;
- m_buf.length = m_fmt.fmt.pix_mp.num_planes;
-
- for (unsigned long i = 0; i < m_buf.length; i++) {
- m_planes[i].length = m_fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
- m_planes[i].bytesused = m_planes[i].length;
- if (m_buf.memory == V4L2_MEMORY_DMABUF)
- m_planes[i].m.fd = static_cast<__s32>(reinterpret_cast<long>(addrs[i]));
- else
- m_planes[i].m.userptr = reinterpret_cast<unsigned long>(addrs[i]);
- }
+ if (!mDevice.setFormat(bufferType, format, width, height, planeLen))
+ return false;
- SC_LOGD("%s Success", __func__);
+ memoryType = 0; // new reqbufs is required.
return true;
}
-bool LibScalerForJpeg::SetFormat()
+bool LibScalerForJpeg::Image::begin(unsigned int memtype)
{
- if (ioctl(m_fdScaler, VIDIOC_S_FMT, &m_srcFmt) < 0) {
- ALOGE("Failed to S_FMT for the source");
- return false;
+ if (memoryType != memtype) {
+ if (memoryType != 0) {
+ if (!mDevice.requestBuffers(bufferType, memoryType, 0))
+ return false;
+ }
+
+ if (!mDevice.requestBuffers(bufferType, memtype, 1))
+ return false;
+
+ if (!mDevice.streamOn(bufferType))
+ return false;
+
+ memoryType = memtype;
}
- if (ioctl(m_fdScaler, VIDIOC_S_FMT, &m_dstFmt) < 0) {
- ALOGE("Failed to S_FMT for the target");
+ return true;
+}
+
+bool LibScalerForJpeg::Image::cancelBuffer()
+{
+ if (!mDevice.streamOff(bufferType))
return false;
- }
- SC_LOGD("%s Success", __func__);
+ if (!mDevice.streamOn(bufferType))
+ return false;
return true;
}
-bool LibScalerForJpeg::ReqBufs(int count)
+LibScalerForJpeg::Device::Device()
{
- v4l2_requestbuffers reqbufs;
+ mFd = ::open(SCALER_DEV_NODE, O_RDWR);
+ if (mFd < 0)
+ ALOGERR("failed to open %s", SCALER_DEV_NODE);
+}
- memset(&reqbufs, 0, sizeof(reqbufs));
- reqbufs.type = m_srcBuf.type;
- reqbufs.memory = m_srcBuf.memory;
- reqbufs.count = count;
+LibScalerForJpeg::Device::~Device()
+{
+ if (mFd >= 0)
+ ::close(mFd);
+}
- if (ioctl(m_fdScaler, VIDIOC_REQBUFS, &reqbufs) < 0) {
- ALOGE("Failed to REQBUFS for the source buffer");
- return false;
- }
+bool LibScalerForJpeg::Device::requestBuffers(unsigned int buftype, unsigned int memtype, unsigned int count)
+{
+ // count==0 means this port should be reconfigured and it is successful under streaming is finished.
+ if (!count)
+ streamOff(buftype);
+
+ v4l2_requestbuffers reqbufs{};
- memset(&reqbufs, 0, sizeof(reqbufs));
- reqbufs.type = m_dstBuf.type;
- reqbufs.memory = m_dstBuf.memory;
+ reqbufs.type = buftype;
+ reqbufs.memory = memtype;
reqbufs.count = count;
- if (ioctl(m_fdScaler, VIDIOC_REQBUFS, &reqbufs) < 0) {
- ALOGE("Failed to REQBUFS for the target buffer");
- // rolling back the reqbufs for the source image
- reqbufs.type = m_srcBuf.type;
- reqbufs.memory = m_srcBuf.memory;
- reqbufs.count = 0;
- ioctl(m_fdScaler, VIDIOC_REQBUFS, &reqbufs);
+ if (ioctl(mFd, VIDIOC_REQBUFS, &reqbufs) < 0) {
+ ALOGERR("failed REQBUFS(%s, mem=%d, count=%d)", getBufTypeString(buftype), memtype, count);
return false;
}
- SC_LOGD("%s Success", __func__);
-
return true;
}
-bool LibScalerForJpeg::StreamOn()
+bool LibScalerForJpeg::Device::setFormat(unsigned int buftype, unsigned int format, unsigned int width, unsigned int height, unsigned int planelen[SCALER_MAX_PLANES])
{
- if (ioctl(m_fdScaler, VIDIOC_STREAMON, &m_srcBuf.type) < 0) {
- ALOGE("Failed StreamOn for the source buffer");
- return false;
- }
+ v4l2_format fmt{};
+
+ fmt.type = buftype;
+ fmt.fmt.pix_mp.pixelformat = format;
+ fmt.fmt.pix_mp.width = width;
+ fmt.fmt.pix_mp.height = height;
- if (ioctl(m_fdScaler, VIDIOC_STREAMON, &m_dstBuf.type) < 0) {
- ALOGE("Failed StreamOn for the target buffer");
- // cancel the streamon for the source image
- ioctl(m_fdScaler, VIDIOC_STREAMOFF, &m_srcBuf.type);
+ if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) {
+ ALOGERR("failed S_FMT(%s, fmt=h'%x, %ux%u)", getBufTypeString(buftype), format, width, height);
return false;
}
- SC_LOGD("%s Success", __func__);
+ for (uint32_t i = 0; i < fmt.fmt.pix_mp.num_planes ; i++) {
+ planelen[i] = fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
+ }
return true;
}
-bool LibScalerForJpeg::QBuf()
+bool LibScalerForJpeg::Device::streamOn(unsigned int buftype)
{
- if (ioctl(m_fdScaler, VIDIOC_QBUF, &m_srcBuf) < 0) {
- ALOGE("Failed to QBUF for the source buffer");
- return false;
- }
-
- if (ioctl(m_fdScaler, VIDIOC_QBUF, &m_dstBuf) < 0) {
- ALOGE("Failed to QBUF for the target buffer");
- // cancel the previous queued buffer
- StopStreaming();
+ if (ioctl(mFd, VIDIOC_STREAMON, &buftype) < 0) {
+ ALOGERR("failed STREAMON for %s", getBufTypeString(buftype));
return false;
}
- SC_LOGD("%s Success", __func__);
-
return true;
}
-bool LibScalerForJpeg::StreamOff()
+bool LibScalerForJpeg::Device::streamOff(unsigned int buftype)
{
- if (ioctl(m_fdScaler, VIDIOC_STREAMOFF, &m_srcBuf.type) < 0) {
- ALOGE("Failed STREAMOFF for the source");
- return false;
- }
-
- if (ioctl(m_fdScaler, VIDIOC_STREAMOFF, &m_dstBuf.type) < 0) {
- ALOGE("Failed STREAMOFF for the target");
+ if (ioctl(mFd, VIDIOC_STREAMOFF, &buftype) < 0) {
+ ALOGERR("failed STREAMOFF for %s", getBufTypeString(buftype));
return false;
}
- SC_LOGD("%s Success", __func__);
-
return true;
}
-bool LibScalerForJpeg::StopStreaming()
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, std::function<void(v4l2_buffer &)> bufferFiller)
{
- if (!StreamOff())
- return false;
+ v4l2_buffer buffer{};
+ v4l2_plane plane[SCALER_MAX_PLANES];
- if (!ReqBufs(0))
- return false;
+ memset(&plane, 0, sizeof(plane));
- SC_LOGD("%s Success", __func__);
+ buffer.type = buftype;
+ buffer.m.planes = plane;
- return true;
+ bufferFiller(buffer);
+
+ return ioctl(mFd, VIDIOC_QBUF, &buffer) >= 0;
}
-bool LibScalerForJpeg::DQBuf()
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES])
{
- if (ioctl(m_fdScaler, VIDIOC_DQBUF, &m_srcBuf) < 0 ) {
- ALOGE("Failed to DQBuf the source buffer");
+ if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer) {
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.length = SCALER_MAX_PLANES;
+ for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
+ buffer.m.planes[i].m.fd = buf[i];
+ buffer.m.planes[i].length = len[i];
+ } })) {
+ ALOGERR("failed QBUF(%s, fd[]=%d %d, len[0]=%d %d)", getBufTypeString(buftype), buf[0], buf[1], len[0], len[1]);
return false;
}
- if (ioctl(m_fdScaler, VIDIOC_DQBUF, &m_dstBuf) < 0 ) {
- ALOGE("Failed to DQBuf the target buffer");
+ return true;
+}
+
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES])
+{
+ if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer) {
+ buffer.memory = V4L2_MEMORY_USERPTR;
+ buffer.length = SCALER_MAX_PLANES;
+ for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
+ buffer.m.planes[i].m.userptr = reinterpret_cast<unsigned long>(buf[i]);
+ buffer.m.planes[i].length = len[i];
+ } })) {
+ ALOGERR("failed QBUF(%s, ptr[]=%p %p, len[0]=%d %d)", getBufTypeString(buftype), buf[0], buf[1], len[0], len[1]);
return false;
}
- SC_LOGD("%s Success", __func__);
-
return true;
}
-bool LibScalerForJpeg::RunStream()
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf, unsigned int len[SCALER_MAX_PLANES])
{
- if (m_needReqbuf == true) {
- if (!StopStreaming())
- goto err;
-
- if (!SetFormat())
- goto err;
+ if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer)
+ {
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.length = 1;
+ buffer.m.planes[0].m.fd = buf;
+ buffer.m.planes[0].length = len[0];
+ })) {
+ ALOGERR("failed QBUF(%s, fd=%d, len=%d", getBufTypeString(buftype), buf, len[0]);
+ return false;
+ }
- if (!ReqBufs())
- goto err;
+ return true;
+}
- if (!StreamOn())
- goto err;
- }
+bool LibScalerForJpeg::Device::dequeueBuffer(unsigned int buftype, unsigned int memtype)
+{
+ v4l2_buffer buffer{};
+ v4l2_plane plane[SCALER_MAX_PLANES];
- if (!QBuf())
- goto err;
+ memset(&plane, 0, sizeof(plane));
- if (!DQBuf())
- goto err;
+ buffer.type = buftype;
+ buffer.memory = memtype;
+ buffer.length = SCALER_MAX_PLANES;
- m_needReqbuf = false;
+ buffer.m.planes = plane;
- SC_LOGD("%s Success", __func__);
+ if (ioctl(mFd, VIDIOC_DQBUF, &buffer) < 0 ) {
+ ALOGERR("failed DQBUF(%s)", getBufTypeString(buftype));
+ return false;
+ }
return true;
-
-err:
- m_needReqbuf = true;
- return false;
}
diff --git a/libhwjpeg/LibScalerForJpeg.h b/libhwjpeg/LibScalerForJpeg.h
new file mode 100644
index 0000000..7753e04
--- /dev/null
+++ b/libhwjpeg/LibScalerForJpeg.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 Samsung Electronics Co.,LTD.
+ *
+ * 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.
+ */
+#ifndef __HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
+#define __HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
+
+#include <functional>
+
+#include <linux/videodev2.h>
+
+#include "ThumbnailScaler.h"
+
+class LibScalerForJpeg : public ThumbnailScaler {
+public:
+ LibScalerForJpeg() { }
+ ~LibScalerForJpeg() { }
+
+ bool SetSrcImage(unsigned int width, unsigned int height, unsigned int v4l2_format) {
+ return mSrcImage.set(width, height, v4l2_format);
+ }
+
+ bool SetDstImage(unsigned int width, unsigned int height, unsigned int v4l2_format) {
+ return mDstImage.set(width, height, v4l2_format);
+ }
+
+ bool RunStream(int srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen);
+ bool RunStream(char *srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen);
+
+private:
+ struct Device {
+ int mFd;
+
+ Device();
+ ~Device();
+ bool requestBuffers(unsigned int buftype, unsigned int memtype, unsigned int count);
+ bool setFormat(unsigned int buftype, unsigned int format, unsigned int width, unsigned int height, unsigned int planelen[SCALER_MAX_PLANES]);
+ bool streamOn(unsigned int buftype);
+ bool streamOff(unsigned int buftype);
+ bool queueBuffer(unsigned int buftype, std::function<void(v4l2_buffer &)> bufferFiller);
+ bool queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES]);
+ bool queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES]);
+ bool queueBuffer(unsigned int buftype, int buf, unsigned int len[SCALER_MAX_PLANES]);
+ bool dequeueBuffer(unsigned int buftype, unsigned int memtype);
+ };
+
+ struct Image {
+ Device &mDevice;
+ unsigned int width;
+ unsigned int height;
+ unsigned int format;
+ unsigned int memoryType = 0;
+ const unsigned int bufferType;
+ unsigned int planeLen[SCALER_MAX_PLANES];
+
+ Image(Device &dev, unsigned int w, unsigned int h, unsigned int f, unsigned int buftype)
+ : mDevice(dev), width(w), height(h), format(f), bufferType(buftype)
+ { }
+
+ bool set(unsigned int width, unsigned int height, unsigned int format);
+ bool begin(unsigned int memtype);
+ bool cancelBuffer();
+
+ template <class tBuf>
+ bool queueBuffer(tBuf buf) { return mDevice.queueBuffer(bufferType, buf, planeLen); }
+ bool dequeueBuffer() { return mDevice.dequeueBuffer(bufferType, memoryType); }
+
+ bool same(unsigned int w, unsigned int h, unsigned int f) { return width == w && height == h && format == f; }
+ };
+
+ template<class T>
+ bool queue(T srcBuf[SCALER_MAX_PLANES], int dstBuf) {
+ if (!mSrcImage.queueBuffer(srcBuf))
+ return false;
+
+ if (!mDstImage.queueBuffer(dstBuf)) {
+ mSrcImage.cancelBuffer();
+ return false;
+ }
+
+ if (!mSrcImage.dequeueBuffer() || !mDstImage.dequeueBuffer()) {
+ mSrcImage.cancelBuffer();
+ mDstImage.cancelBuffer();
+ return false;
+ }
+
+ return true;
+ }
+
+ Device mDevice;
+ Image mSrcImage{mDevice, 0, 0, V4L2_PIX_FMT_YUYV, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE};
+ Image mDstImage{mDevice, 0, 0, V4L2_PIX_FMT_YUYV, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE};
+};
+
+#endif //__HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
diff --git a/libhwjpeg/ThumbnailScaler.cpp b/libhwjpeg/ThumbnailScaler.cpp
new file mode 100644
index 0000000..4d6e5de
--- /dev/null
+++ b/libhwjpeg/ThumbnailScaler.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 Samsung Electronics Co.,LTD.
+ *
+ * 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 <log/log.h>
+
+#include "ThumbnailScaler.h"
+#include "LibScalerForJpeg.h"
+
+ThumbnailScaler *ThumbnailScaler::createInstance()
+{
+ ALOGD("Created thumbnail scaler: legacy V4L2 Scaler");
+ return new LibScalerForJpeg();
+}
diff --git a/libhwjpeg/ThumbnailScaler.h b/libhwjpeg/ThumbnailScaler.h
new file mode 100644
index 0000000..a1a6a08
--- /dev/null
+++ b/libhwjpeg/ThumbnailScaler.h
@@ -0,0 +1,21 @@
+#ifndef __HARDWARE_EXYNOS_THUMBNAIL_SCALER_H__
+#define __HARDWARE_EXYNOS_THUMBNAIL_SCALER_H__
+
+#include <cstddef>
+
+class ThumbnailScaler {
+public:
+ const static unsigned int SCALER_MAX_PLANES = 3;
+ ThumbnailScaler() { }
+ virtual ~ThumbnailScaler() { }
+
+ virtual bool SetSrcImage(unsigned int width, unsigned int height, unsigned int v4l2_format) = 0;
+ virtual bool SetDstImage(unsigned int width, unsigned int height, unsigned int v4l2_format) = 0;
+
+ virtual bool RunStream(int srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen) = 0;
+ virtual bool RunStream(char *srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen) = 0;
+
+ static ThumbnailScaler *createInstance();
+};
+
+#endif //__HARDWARE_EXYNOS_THUMBNAIL_SCALER_H__
diff --git a/libhwjpeg/include/ExynosJpegEncoderForCamera.h b/libhwjpeg/include/ExynosJpegEncoderForCamera.h
index 1ec5132..a50d884 100644
--- a/libhwjpeg/include/ExynosJpegEncoderForCamera.h
+++ b/libhwjpeg/include/ExynosJpegEncoderForCamera.h
@@ -18,13 +18,16 @@
#ifndef __HARDWARE_EXYNOS_JPEG_ENCODER_FOR_CAMERA_H__
#define __HARDWARE_EXYNOS_JPEG_ENCODER_FOR_CAMERA_H__
+#include <memory>
+
#include <pthread.h>
-#include "ExynosExif.h"
+#include <ExynosExif.h>
#include "ExynosJpegApi.h"
-#include "LibScalerForJpeg.h"
+#include <hardware/exynos/ExynosExif.h>
class CAppMarkerWriter; // defined in libhwjpeg/AppMarkerWriter.h
+class ThumbnailScaler; // defined in libhwjpeg/thumbnail_scaler.h
class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
enum {
@@ -35,7 +38,7 @@ class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
};
CHWJpegCompressor *m_phwjpeg4thumb;
- LibScalerForJpeg m_pLibScaler;
+ std::unique_ptr<ThumbnailScaler> mThumbnailScaler;
int m_fdIONClient;
int m_fdIONThumbImgBuffer;
char *m_pIONThumbImgBuffer;
@@ -69,6 +72,9 @@ class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
pthread_t m_threadWorker;
+ extra_appinfo_t m_extraInfo;
+ app_info_t m_appInfo[15];
+
bool AllocThumbBuffer(int v4l2Format); /* For single compression */
bool AllocThumbJpegBuffer(); /* For BTB compression */
bool GenerateThumbnailImage();
@@ -76,7 +82,7 @@ class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
size_t CompressThumbnailOnly(size_t limit, int quality, unsigned int v4l2Format, int src_buftype);
size_t RemoveTrailingDummies(char *base, size_t len);
ssize_t FinishCompression(size_t mainlen, size_t thumblen);
- bool ProcessExif(char *base, size_t limit, exif_attribute_t *exifInfo, debug_attribute_t *debuginfo);
+ bool ProcessExif(char *base, size_t limit, exif_attribute_t *exifInfo, extra_appinfo_t *extra);
static void *tCompressThumbnail(void *p);
bool PrepareCompression(bool thumbnail);
@@ -98,6 +104,7 @@ public:
int encode(int *size, exif_attribute_t *exifInfo, char** pcJpegBuffer, debug_attribute_t *debugInfo = 0);
int encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer, char** pcJpegBuffer, debug_attribute_t *debugInfo = 0);
+ int encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer, char** pcJpegBuffer, extra_appinfo_t *appInfo = 0);
int setInBuf2(int *piBuf, int *iSize);
int setInBuf2(char **pcBuf, int *iSize);
int setThumbnailSize(int w, int h);
diff --git a/libhwjpeg/include/LibScalerForJpeg.h b/libhwjpeg/include/LibScalerForJpeg.h
deleted file mode 100644
index cd0606a..0000000
--- a/libhwjpeg/include/LibScalerForJpeg.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
-#define __HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
-
-#include <linux/videodev2.h>
-#define SCALER_DEV_NODE "/dev/video50"
-#define SCALER_MAX_PLANES 3
-
-#define SC_LOGE(fmt, args...) ((void)ALOG(LOG_ERROR, LOG_TAG, "%s: " fmt, __func__, ##args))
-
-#ifdef SC_DEBUG
-#define SC_LOGD(args...) ((void)ALOG(LOG_INFO, LOG_TAG, ##args))
-#else
-#define SC_LOGD(args...) do { } while (0)
-#endif
-
-class LibScalerForJpeg {
-public:
- LibScalerForJpeg();
- ~LibScalerForJpeg();
-
- bool SetSrcImage(
- unsigned int width, unsigned int height, unsigned int v4l2_format,
- void *addrs[SCALER_MAX_PLANES], int mem_type) {
- return SetImage(m_srcFmt, m_srcBuf, m_srcPlanes,
- width, height, v4l2_format, addrs, mem_type);
- }
-
- bool SetDstImage(
- unsigned int width, unsigned int height, unsigned int v4l2_format,
- void *addrs[SCALER_MAX_PLANES], int mem_type) {
- return SetImage(m_dstFmt, m_dstBuf, m_dstPlanes,
- width, height, v4l2_format, addrs, mem_type);
- }
-
- bool RunStream();
-private:
- int m_fdScaler;
- bool m_needReqbuf;
-
- v4l2_format m_srcFmt;
- v4l2_format m_dstFmt;
- v4l2_buffer m_srcBuf;
- v4l2_buffer m_dstBuf;
- v4l2_plane m_srcPlanes[SCALER_MAX_PLANES];
- v4l2_plane m_dstPlanes[SCALER_MAX_PLANES];
-
- bool SetImage(
- v4l2_format &m_fmt, v4l2_buffer &m_buf, v4l2_plane m_planes[SCALER_MAX_PLANES],
- unsigned int width, unsigned int height, unsigned int v4l2_format,
- void *addrs[SCALER_MAX_PLANES], int mem_type);
-
- bool SetFormat();
- bool ReqBufs(int count = 1);
- bool StreamOn();
- bool StreamOff();
- bool QBuf();
- bool DQBuf();
- bool StopStreaming();
-};
-
-#endif //__HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
diff --git a/libhwjpeg/include/hardware/exynos/ExynosExif.h b/libhwjpeg/include/hardware/exynos/ExynosExif.h
new file mode 100644
index 0000000..8eddfe8
--- /dev/null
+++ b/libhwjpeg/include/hardware/exynos/ExynosExif.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef __GRAPHIC_BASE_EXYNOS_EXIF_H__
+#define __GRAPHIC_BASE_EXYNOS_EXIF_H__
+
+#include <ExynosExif.h>
+
+typedef struct {
+ int appid;
+ char *appData;
+ unsigned int dataSize;
+} app_info_t;
+
+typedef struct {
+ int num_of_appmarker;
+ app_info_t *appInfo;
+} extra_appinfo_t;
+
+bool UpdateDebugData(char *jpeg, size_t jpeglen, extra_appinfo_t *extra);
+void ExtractDebugAttributeInfo(debug_attribute_t *debug, extra_appinfo_t *extra);
+
+#endif /* __GRAPHIC_BASE_EXYNOS_EXIF_H__ */