1ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin/* 2ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Copyright (C) 2014 The Android Open Source Project 3ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * 4ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * you may not use this file except in compliance with the License. 6ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * You may obtain a copy of the License at 7ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * 8ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * http://www.apache.org/licenses/LICENSE-2.0 9ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * 10ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Unless required by applicable law or agreed to in writing, software 11ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * distributed under the License is distributed on an "AS IS" BASIS, 12ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * See the License for the specific language governing permissions and 14ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * limitations under the License. 15ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin */ 16ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 173830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberlingpackage com.android.camera.processing.imagebackend; 18ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 19ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport android.graphics.ImageFormat; 20ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 21725059d4d1ab78b5ffaa99cbba397b2dafc717d2I-Jong Linimport android.graphics.Rect; 22ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport com.android.camera.debug.Log; 236e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport com.android.camera.one.v2.camera2proxy.ImageProxy; 2430ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Linimport com.android.camera.session.CaptureSession; 25ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 266e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Linimport java.util.List; 27ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.util.concurrent.Executor; 28ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 29ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin/** 306e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin * Implements the conversion of a YUV_420_888 image to compressed JPEG byte 316e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin * array, as two separate tasks: the first to copy from the image to NV21 memory 326e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin * layout, and the second to convert the image into JPEG, using the built-in 336e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin * Android compressor. 34725059d4d1ab78b5ffaa99cbba397b2dafc717d2I-Jong Lin * 35725059d4d1ab78b5ffaa99cbba397b2dafc717d2I-Jong Lin * TODO: Implement cropping, if required. 36ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin */ 37ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linclass TaskChainedCompressImageToJpeg extends TaskJpegEncode { 38ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin private final static Log.Tag TAG = new Log.Tag("TaskChainJpg"); 39ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 403830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberling TaskChainedCompressImageToJpeg(ImageToProcess image, Executor executor, 413c7b7ec6aa2e51859718a6d6dead3c12d10ea370I-Jong Lin ImageTaskManager imageTaskManager, CaptureSession captureSession) { 423c7b7ec6aa2e51859718a6d6dead3c12d10ea370I-Jong Lin super(image, executor, imageTaskManager, ProcessingPriority.SLOW, captureSession); 43ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 44ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 45ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin private void logWrapper(String message) { 46ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin // Do nothing. 47ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 48ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 49ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin @Override 50ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void run() { 513830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberling ImageToProcess img = mImage; 52725059d4d1ab78b5ffaa99cbba397b2dafc717d2I-Jong Lin Rect safeCrop = guaranteedSafeCrop(img.proxy, img.crop); 536e981cafa9cc57ebc7100cb84f68fb74dbd163daI-Jong Lin final List<ImageProxy.Plane> planeList = img.proxy.getPlanes(); 54ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 553830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberling final TaskImage inputImage = new TaskImage(mImage.rotation, img.proxy.getWidth(), 56725059d4d1ab78b5ffaa99cbba397b2dafc717d2I-Jong Lin img.proxy.getHeight(), img.proxy.getFormat(), safeCrop); 573830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberling final TaskImage resultImage = new TaskImage(mImage.rotation, img.proxy.getWidth(), 58725059d4d1ab78b5ffaa99cbba397b2dafc717d2I-Jong Lin img.proxy.getHeight(), ImageFormat.JPEG , safeCrop); 594dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin byte[] dataCopy; 60ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin int[] strides = new int[3]; 614dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin 624dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin try { 634dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin onStart(mId, inputImage, resultImage, TaskInfo.Destination.FINAL_IMAGE); 644dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin 654dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin // Do the byte copy 664dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin strides[0] = planeList.get(0).getRowStride() 674dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin / planeList.get(0).getPixelStride(); 684dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin strides[1] = planeList.get(1).getRowStride() 694dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin / planeList.get(1).getPixelStride(); 704dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin strides[2] = 2 * planeList.get(2).getRowStride() 714dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin / planeList.get(2).getPixelStride(); 724dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin 734dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin // TODO: For performance, use a cache subsystem for buffer reuse. 744dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin dataCopy = convertYUV420ImageToPackedNV21(img.proxy); 754dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin } finally { 764dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin // Release the image now that you have a usable copy 774dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin mImageTaskManager.releaseSemaphoreReference(img, mExecutor); 784dc301a073dab22b9bc12e0b846530d3a80bf8f7I-Jong Lin } 79ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 80ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin final byte[] chainedDataCopy = dataCopy; 81ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin final int[] chainedStrides = strides; 82ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 83ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin // This task drops the image reference. 84ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin TaskImageContainer chainedTask = new TaskJpegEncode(this, ProcessingPriority.SLOW) { 85ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 86ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin @Override 87ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void run() { 88ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin // Image is closed by now. Do NOT reference image directly. 89ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin byte[] compressedData = convertNv21toJpeg(chainedDataCopy, 90ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin resultImage.height, resultImage.width, chainedStrides); 9130ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin onJpegEncodeDone(mId, inputImage, resultImage, compressedData, 9230ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin TaskInfo.Destination.FINAL_IMAGE); 93ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin logWrapper("Finished off a chained task now that image is released."); 94ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 95ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin }; 96ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 97ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin // Passed null, since the image has already been released. 983c7b7ec6aa2e51859718a6d6dead3c12d10ea370I-Jong Lin mImageTaskManager.appendTasks(null, chainedTask); 99ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin logWrapper("Kicking off a chained task now that image is released."); 100ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 101ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin} 102