diff options
-rw-r--r-- | libhwjpeg/Android.mk | 2 | ||||
-rw-r--r-- | libhwjpeg/AppMarkerWriter.cpp | 164 | ||||
-rw-r--r-- | libhwjpeg/AppMarkerWriter.h | 11 | ||||
-rw-r--r-- | libhwjpeg/ExynosJpegEncoder.cpp | 24 | ||||
-rw-r--r-- | libhwjpeg/ExynosJpegEncoderForCamera.cpp | 91 | ||||
-rw-r--r-- | libhwjpeg/LibScalerForJpeg.cpp | 307 | ||||
-rw-r--r-- | libhwjpeg/LibScalerForJpeg.h | 106 | ||||
-rw-r--r-- | libhwjpeg/ThumbnailScaler.cpp | 26 | ||||
-rw-r--r-- | libhwjpeg/ThumbnailScaler.h | 21 | ||||
-rw-r--r-- | libhwjpeg/include/ExynosJpegEncoderForCamera.h | 15 | ||||
-rw-r--r-- | libhwjpeg/include/LibScalerForJpeg.h | 61 | ||||
-rw-r--r-- | libhwjpeg/include/hardware/exynos/ExynosExif.h | 37 |
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__ */ |