DO NOT MERGE MTP: Implement GetThumb command

This allows the PC to access thumbnails in JPEG files over MTP/PTP

Bug: 3219495

Change-Id: I565be1fb84e8a204f2be11342b5b952e8965afdf
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2011-04-24 18:40:17 -07:00
parent af50821bac
commit a792c80402
7 changed files with 100 additions and 2 deletions

View File

@@ -27,9 +27,11 @@ LOCAL_SHARED_LIBRARIES := \
libcamera_client \ libcamera_client \
libsqlite \ libsqlite \
libmtp \ libmtp \
libusbhost libusbhost \
libexif
LOCAL_C_INCLUDES += \ LOCAL_C_INCLUDES += \
external/jhead \
external/tremor/Tremor \ external/tremor/Tremor \
frameworks/base/core/jni \ frameworks/base/core/jni \
frameworks/base/media/libmedia \ frameworks/base/media/libmedia \

View File

@@ -35,6 +35,10 @@
#include "MtpUtils.h" #include "MtpUtils.h"
#include "mtp.h" #include "mtp.h"
extern "C" {
#include "jhead.h"
}
using namespace android; using namespace android;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -141,6 +145,8 @@ public:
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle, virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info); MtpObjectInfo& info);
virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath, MtpString& outFilePath,
int64_t& outFileLength, int64_t& outFileLength,
@@ -778,10 +784,67 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
info.mName = strdup((const char *)temp); info.mName = strdup((const char *)temp);
env->ReleaseCharArrayElements(mStringBuffer, str, 0); env->ReleaseCharArrayElements(mStringBuffer, str, 0);
// read EXIF data for thumbnail information
if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
MtpString path;
int64_t length;
MtpObjectFormat format;
if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
ResetJpgfile();
// Start with an empty image information structure.
memset(&ImageInfo, 0, sizeof(ImageInfo));
ImageInfo.FlashUsed = -1;
ImageInfo.MeteringMode = -1;
ImageInfo.Whitebalance = -1;
strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
if (ReadJpegFile((const char*)path, READ_METADATA)) {
Section_t* section = FindSection(M_EXIF);
if (section) {
info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
info.mImagePixWidth = ImageInfo.Width;
info.mImagePixHeight = ImageInfo.Height;
}
}
DiscardData();
}
}
checkAndClearExceptionFromCallback(env, __FUNCTION__); checkAndClearExceptionFromCallback(env, __FUNCTION__);
return MTP_RESPONSE_OK; return MTP_RESPONSE_OK;
} }
void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
MtpString path;
int64_t length;
MtpObjectFormat format;
void* result = NULL;
outThumbSize = 0;
if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
&& (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
ResetJpgfile();
// Start with an empty image information structure.
memset(&ImageInfo, 0, sizeof(ImageInfo));
ImageInfo.FlashUsed = -1;
ImageInfo.MeteringMode = -1;
ImageInfo.Whitebalance = -1;
strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
if (ReadJpegFile((const char*)path, READ_METADATA)) {
Section_t* section = FindSection(M_EXIF);
if (section) {
outThumbSize = ImageInfo.ThumbnailSize;
result = malloc(outThumbSize);
if (result)
memcpy(result, section->Data + ImageInfo.ThumbnailOffset + 8, outThumbSize);
}
DiscardData();
}
}
return result;
}
MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath, MtpString& outFilePath,
int64_t& outFileLength, int64_t& outFileLength,

View File

@@ -388,6 +388,16 @@ int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
return (ret < 0 ? ret : 0); return (ret < 0 ? ret : 0);
} }
int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length + MTP_CONTAINER_HEADER_SIZE);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
if (ret == MTP_CONTAINER_HEADER_SIZE)
ret = ::write(fd, data, length);
return (ret < 0 ? ret : 0);
}
#endif // MTP_DEVICE #endif // MTP_DEVICE
#ifdef MTP_HOST #ifdef MTP_HOST

View File

@@ -100,6 +100,7 @@ public:
// write our data to the given file descriptor // write our data to the given file descriptor
int write(int fd); int write(int fd);
int writeDataHeader(int fd, uint32_t length); int writeDataHeader(int fd, uint32_t length);
int writeData(int fd, void* data, uint32_t length);
#endif #endif
#ifdef MTP_HOST #ifdef MTP_HOST

View File

@@ -84,6 +84,8 @@ public:
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle, virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) = 0; MtpObjectInfo& info) = 0;
virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) = 0;
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath, MtpString& outFilePath,
int64_t& outFileLength, int64_t& outFileLength,

View File

@@ -50,7 +50,7 @@ static const MtpOperationCode kSupportedOperationCodes[] = {
MTP_OPERATION_GET_OBJECT_HANDLES, MTP_OPERATION_GET_OBJECT_HANDLES,
MTP_OPERATION_GET_OBJECT_INFO, MTP_OPERATION_GET_OBJECT_INFO,
MTP_OPERATION_GET_OBJECT, MTP_OPERATION_GET_OBJECT,
// MTP_OPERATION_GET_THUMB, MTP_OPERATION_GET_THUMB,
MTP_OPERATION_DELETE_OBJECT, MTP_OPERATION_DELETE_OBJECT,
MTP_OPERATION_SEND_OBJECT_INFO, MTP_OPERATION_SEND_OBJECT_INFO,
MTP_OPERATION_SEND_OBJECT, MTP_OPERATION_SEND_OBJECT,
@@ -370,6 +370,9 @@ bool MtpServer::handleRequest() {
case MTP_OPERATION_GET_OBJECT: case MTP_OPERATION_GET_OBJECT:
response = doGetObject(); response = doGetObject();
break; break;
case MTP_OPERATION_GET_THUMB:
response = doGetThumb();
break;
case MTP_OPERATION_GET_PARTIAL_OBJECT: case MTP_OPERATION_GET_PARTIAL_OBJECT:
case MTP_OPERATION_GET_PARTIAL_OBJECT_64: case MTP_OPERATION_GET_PARTIAL_OBJECT_64:
response = doGetPartialObject(operation); response = doGetPartialObject(operation);
@@ -736,6 +739,22 @@ MtpResponseCode MtpServer::doGetObject() {
return MTP_RESPONSE_OK; return MTP_RESPONSE_OK;
} }
MtpResponseCode MtpServer::doGetThumb() {
MtpObjectHandle handle = mRequest.getParameter(1);
size_t thumbSize;
void* thumb = mDatabase->getThumbnail(handle, thumbSize);
if (thumb) {
// send data
mData.setOperationCode(mRequest.getOperationCode());
mData.setTransactionID(mRequest.getTransactionID());
mData.writeData(mFD, thumb, thumbSize);
free(thumb);
return MTP_RESPONSE_OK;
} else {
return MTP_RESPONSE_GENERAL_ERROR;
}
}
MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
if (!hasStorage()) if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE; return MTP_RESPONSE_INVALID_OBJECT_HANDLE;

View File

@@ -133,6 +133,7 @@ private:
MtpResponseCode doGetObjectPropList(); MtpResponseCode doGetObjectPropList();
MtpResponseCode doGetObjectInfo(); MtpResponseCode doGetObjectInfo();
MtpResponseCode doGetObject(); MtpResponseCode doGetObject();
MtpResponseCode doGetThumb();
MtpResponseCode doGetPartialObject(MtpOperationCode operation); MtpResponseCode doGetPartialObject(MtpOperationCode operation);
MtpResponseCode doSendObjectInfo(); MtpResponseCode doSendObjectInfo();
MtpResponseCode doSendObject(); MtpResponseCode doSendObject();