Loading services/camera/libcameraservice/camera2/JpegProcessor.cpp +14 −35 Original line number Original line Diff line number Diff line Loading @@ -233,10 +233,8 @@ status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) { } } // Find size of JPEG image // Find size of JPEG image uint8_t *jpegStart; // points to start of buffer in imgBuffer.data size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width); size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width, &jpegStart); if (jpegSize == 0) { // failed to find size, default to whole buffer if (jpegSize == 0) { // failed to find size, default to whole buffer jpegStart = imgBuffer.data; jpegSize = imgBuffer.width; jpegSize = imgBuffer.width; } } size_t heapSize = mCaptureHeap->getSize(); size_t heapSize = mCaptureHeap->getSize(); Loading @@ -250,7 +248,7 @@ status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) { // TODO: Optimize this to avoid memcopy // TODO: Optimize this to avoid memcopy sp<MemoryBase> captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); sp<MemoryBase> captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); void* captureMemory = mCaptureHeap->getBase(); void* captureMemory = mCaptureHeap->getBase(); memcpy(captureMemory, jpegStart, jpegSize); memcpy(captureMemory, imgBuffer.data, jpegSize); mCaptureConsumer->unlockBuffer(imgBuffer); mCaptureConsumer->unlockBuffer(imgBuffer); Loading Loading @@ -322,24 +320,20 @@ uint8_t checkJpegMarker(uint8_t *buf) { } } // Return the size of the JPEG, 0 indicates failure // Return the size of the JPEG, 0 indicates failure size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t maxSize) { size_t maxSize, uint8_t** jpegStart) { uint8_t *start; size_t size; size_t size; // First check for JPEG transport header // First check for JPEG transport header at the end of the buffer struct camera2_jpeg_blob *blob = (struct camera2_jpeg_blob*)(jpegBuffer); uint8_t *header = jpegBuffer + (maxSize - sizeof(struct camera2_jpeg_blob)); struct camera2_jpeg_blob *blob = (struct camera2_jpeg_blob*)(header); if (blob->jpeg_blob_id == CAMERA2_JPEG_BLOB_ID) { if (blob->jpeg_blob_id == CAMERA2_JPEG_BLOB_ID) { size = blob->jpeg_size; size = blob->jpeg_size; if (size > 0 && size <= maxSize - sizeof(struct camera2_jpeg_blob)) { if (size > 0 && size <= maxSize - sizeof(struct camera2_jpeg_blob)) { // Verify SOI and EOI markers // Verify SOI and EOI markers uint8_t *start = blob->jpeg_data; size_t offset = size - MARKER_LENGTH; size_t offset = size - MARKER_LENGTH; uint8_t *end = blob->jpeg_data + offset; uint8_t *end = jpegBuffer + offset; if (checkJpegStart(start) && checkJpegEnd(end)) { if (checkJpegStart(jpegBuffer) && checkJpegEnd(end)) { ALOGV("Found JPEG transport header, img size %d", size); ALOGV("Found JPEG transport header, img size %d", size); *jpegStart = start; return size; return size; } else { } else { ALOGW("Found JPEG transport header with bad Image Start/End"); ALOGW("Found JPEG transport header with bad Image Start/End"); Loading @@ -349,30 +343,16 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, } } } } // Find Start of Image // Check Start of Image // This lets us handle malformed transport headers by skipping them if ( !checkJpegStart(jpegBuffer) ) { bool foundStart = false; for (size = 0; size <= sizeof(struct camera2_jpeg_blob); size++) { if ( checkJpegStart(jpegBuffer + size) ) { foundStart = true; start = jpegBuffer + size; maxSize = maxSize - size; // adjust accordingly break; } } if (!foundStart) { ALOGE("Could not find start of JPEG marker"); ALOGE("Could not find start of JPEG marker"); return 0; return 0; } } if (size != 0) { // Image starts at offset from beginning // We want the jpeg to start at the first byte; so emit warning ALOGW("JPEG Image starts at offset %d", size); } // Read JFIF segment markers, skip over segment data // Read JFIF segment markers, skip over segment data size = 0; size = 0; while (size <= maxSize - MARKER_LENGTH) { while (size <= maxSize - MARKER_LENGTH) { segment_t *segment = (segment_t*)(start + size); segment_t *segment = (segment_t*)(jpegBuffer + size); uint8_t type = checkJpegMarker(segment->marker); uint8_t type = checkJpegMarker(segment->marker); if (type == 0) { // invalid marker, no more segments, begin JPEG data if (type == 0) { // invalid marker, no more segments, begin JPEG data ALOGV("JPEG stream found beginning at offset %d", size); ALOGV("JPEG stream found beginning at offset %d", size); Loading @@ -390,8 +370,8 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, // Find End of Image // Find End of Image // Scan JPEG buffer until End of Image (EOI) // Scan JPEG buffer until End of Image (EOI) bool foundEnd = false; bool foundEnd = false; for (size; size <= maxSize; size++) { for (size; size <= maxSize - MARKER_LENGTH; size++) { if ( checkJpegEnd(start + size) ) { if ( checkJpegEnd(jpegBuffer + size) ) { foundEnd = true; foundEnd = true; size += MARKER_LENGTH; size += MARKER_LENGTH; break; break; Loading @@ -406,8 +386,7 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, ALOGW("JPEG size %d too large, reducing to maxSize %d", size, maxSize); ALOGW("JPEG size %d too large, reducing to maxSize %d", size, maxSize); size = maxSize; size = maxSize; } } ALOGV("Final JPEG size %d, starting at %p", size, start); ALOGV("Final JPEG size %d", size); *jpegStart = start; return size; return size; } } Loading services/camera/libcameraservice/camera2/JpegProcessor.h +1 −3 Original line number Original line Diff line number Diff line Loading @@ -72,9 +72,7 @@ class JpegProcessor: virtual bool threadLoop(); virtual bool threadLoop(); status_t processNewCapture(sp<Camera2Client> &client); status_t processNewCapture(sp<Camera2Client> &client); size_t findJpegSize(uint8_t* jpegBuffer, size_t findJpegSize(uint8_t* jpegBuffer, size_t maxSize); size_t maxSize, uint8_t** jpegStart); }; }; Loading Loading
services/camera/libcameraservice/camera2/JpegProcessor.cpp +14 −35 Original line number Original line Diff line number Diff line Loading @@ -233,10 +233,8 @@ status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) { } } // Find size of JPEG image // Find size of JPEG image uint8_t *jpegStart; // points to start of buffer in imgBuffer.data size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width); size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width, &jpegStart); if (jpegSize == 0) { // failed to find size, default to whole buffer if (jpegSize == 0) { // failed to find size, default to whole buffer jpegStart = imgBuffer.data; jpegSize = imgBuffer.width; jpegSize = imgBuffer.width; } } size_t heapSize = mCaptureHeap->getSize(); size_t heapSize = mCaptureHeap->getSize(); Loading @@ -250,7 +248,7 @@ status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) { // TODO: Optimize this to avoid memcopy // TODO: Optimize this to avoid memcopy sp<MemoryBase> captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); sp<MemoryBase> captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); void* captureMemory = mCaptureHeap->getBase(); void* captureMemory = mCaptureHeap->getBase(); memcpy(captureMemory, jpegStart, jpegSize); memcpy(captureMemory, imgBuffer.data, jpegSize); mCaptureConsumer->unlockBuffer(imgBuffer); mCaptureConsumer->unlockBuffer(imgBuffer); Loading Loading @@ -322,24 +320,20 @@ uint8_t checkJpegMarker(uint8_t *buf) { } } // Return the size of the JPEG, 0 indicates failure // Return the size of the JPEG, 0 indicates failure size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t maxSize) { size_t maxSize, uint8_t** jpegStart) { uint8_t *start; size_t size; size_t size; // First check for JPEG transport header // First check for JPEG transport header at the end of the buffer struct camera2_jpeg_blob *blob = (struct camera2_jpeg_blob*)(jpegBuffer); uint8_t *header = jpegBuffer + (maxSize - sizeof(struct camera2_jpeg_blob)); struct camera2_jpeg_blob *blob = (struct camera2_jpeg_blob*)(header); if (blob->jpeg_blob_id == CAMERA2_JPEG_BLOB_ID) { if (blob->jpeg_blob_id == CAMERA2_JPEG_BLOB_ID) { size = blob->jpeg_size; size = blob->jpeg_size; if (size > 0 && size <= maxSize - sizeof(struct camera2_jpeg_blob)) { if (size > 0 && size <= maxSize - sizeof(struct camera2_jpeg_blob)) { // Verify SOI and EOI markers // Verify SOI and EOI markers uint8_t *start = blob->jpeg_data; size_t offset = size - MARKER_LENGTH; size_t offset = size - MARKER_LENGTH; uint8_t *end = blob->jpeg_data + offset; uint8_t *end = jpegBuffer + offset; if (checkJpegStart(start) && checkJpegEnd(end)) { if (checkJpegStart(jpegBuffer) && checkJpegEnd(end)) { ALOGV("Found JPEG transport header, img size %d", size); ALOGV("Found JPEG transport header, img size %d", size); *jpegStart = start; return size; return size; } else { } else { ALOGW("Found JPEG transport header with bad Image Start/End"); ALOGW("Found JPEG transport header with bad Image Start/End"); Loading @@ -349,30 +343,16 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, } } } } // Find Start of Image // Check Start of Image // This lets us handle malformed transport headers by skipping them if ( !checkJpegStart(jpegBuffer) ) { bool foundStart = false; for (size = 0; size <= sizeof(struct camera2_jpeg_blob); size++) { if ( checkJpegStart(jpegBuffer + size) ) { foundStart = true; start = jpegBuffer + size; maxSize = maxSize - size; // adjust accordingly break; } } if (!foundStart) { ALOGE("Could not find start of JPEG marker"); ALOGE("Could not find start of JPEG marker"); return 0; return 0; } } if (size != 0) { // Image starts at offset from beginning // We want the jpeg to start at the first byte; so emit warning ALOGW("JPEG Image starts at offset %d", size); } // Read JFIF segment markers, skip over segment data // Read JFIF segment markers, skip over segment data size = 0; size = 0; while (size <= maxSize - MARKER_LENGTH) { while (size <= maxSize - MARKER_LENGTH) { segment_t *segment = (segment_t*)(start + size); segment_t *segment = (segment_t*)(jpegBuffer + size); uint8_t type = checkJpegMarker(segment->marker); uint8_t type = checkJpegMarker(segment->marker); if (type == 0) { // invalid marker, no more segments, begin JPEG data if (type == 0) { // invalid marker, no more segments, begin JPEG data ALOGV("JPEG stream found beginning at offset %d", size); ALOGV("JPEG stream found beginning at offset %d", size); Loading @@ -390,8 +370,8 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, // Find End of Image // Find End of Image // Scan JPEG buffer until End of Image (EOI) // Scan JPEG buffer until End of Image (EOI) bool foundEnd = false; bool foundEnd = false; for (size; size <= maxSize; size++) { for (size; size <= maxSize - MARKER_LENGTH; size++) { if ( checkJpegEnd(start + size) ) { if ( checkJpegEnd(jpegBuffer + size) ) { foundEnd = true; foundEnd = true; size += MARKER_LENGTH; size += MARKER_LENGTH; break; break; Loading @@ -406,8 +386,7 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, ALOGW("JPEG size %d too large, reducing to maxSize %d", size, maxSize); ALOGW("JPEG size %d too large, reducing to maxSize %d", size, maxSize); size = maxSize; size = maxSize; } } ALOGV("Final JPEG size %d, starting at %p", size, start); ALOGV("Final JPEG size %d", size); *jpegStart = start; return size; return size; } } Loading
services/camera/libcameraservice/camera2/JpegProcessor.h +1 −3 Original line number Original line Diff line number Diff line Loading @@ -72,9 +72,7 @@ class JpegProcessor: virtual bool threadLoop(); virtual bool threadLoop(); status_t processNewCapture(sp<Camera2Client> &client); status_t processNewCapture(sp<Camera2Client> &client); size_t findJpegSize(uint8_t* jpegBuffer, size_t findJpegSize(uint8_t* jpegBuffer, size_t maxSize); size_t maxSize, uint8_t** jpegStart); }; }; Loading