1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef TEST_CAMERA_JPEG_STUB_NV12_COMPRESSOR_H 18 #define TEST_CAMERA_JPEG_STUB_NV12_COMPRESSOR_H 19 20 #include <setjmp.h> 21 #include <stdlib.h> 22 extern "C" { 23 #include <jpeglib.h> 24 #include <jerror.h> 25 } 26 27 #include <utils/Errors.h> 28 #include <vector> 29 30 #include "../utils/ExifUtils.h" 31 32 struct _ExifData; 33 typedef _ExifData ExifData; 34 35 class NV12Compressor { 36 public: NV12Compressor()37 NV12Compressor() {} 38 39 /* Compress |data| which represents raw NV21 encoded data of dimensions 40 * |width| * |height|. 41 */ 42 bool compress(const unsigned char* data, int width, int height, int quality); 43 bool compressWithExifOrientation(const unsigned char* data, int width, int height, int quality, 44 android::camera3::ExifOrientation exifValue); 45 46 /* Get a reference to the compressed data, this will return an empty vector 47 * if compress has not been called yet 48 */ 49 const std::vector<unsigned char>& getCompressedData() const; 50 51 // Utility methods 52 static android::status_t findJpegSize(uint8_t *jpegBuffer, size_t maxSize, 53 size_t *size /*out*/); 54 55 static android::status_t getExifOrientation(uint8_t *jpegBuffer, 56 size_t jpegBufferSize, android::camera3::ExifOrientation *exifValue /*out*/); 57 58 /* Get Jpeg image dimensions from the first Start Of Frame. Please note that due to the 59 * way the jpeg buffer is scanned if the image contains a thumbnail, then the size returned 60 * will be of the thumbnail and not the main image. 61 */ 62 static android::status_t getJpegImageDimensions(uint8_t *jpegBuffer, size_t jpegBufferSize, 63 size_t *width /*out*/, size_t *height /*out*/); 64 65 private: 66 67 struct DestinationManager : jpeg_destination_mgr { 68 DestinationManager(); 69 70 static void initDestination(j_compress_ptr cinfo); 71 static boolean emptyOutputBuffer(j_compress_ptr cinfo); 72 static void termDestination(j_compress_ptr cinfo); 73 74 std::vector<unsigned char> mBuffer; 75 }; 76 77 struct ErrorManager : jpeg_error_mgr { 78 ErrorManager(); 79 80 static void onJpegError(j_common_ptr cinfo); 81 82 jmp_buf mJumpBuffer; 83 }; 84 85 static const size_t kMarkerLength = 2; // length of a marker 86 static const uint8_t kMarker = 0xFF; // First byte of marker 87 static const uint8_t kStartOfImage = 0xD8; // Start of Image 88 static const uint8_t kEndOfImage = 0xD9; // End of Image 89 static const uint8_t kStartOfFrame = 0xC0; // Start of Frame 90 91 struct __attribute__((packed)) segment_t { 92 uint8_t marker[kMarkerLength]; 93 uint16_t length; 94 }; 95 96 struct __attribute__((packed)) sof_t { 97 uint16_t length; 98 uint8_t precision; 99 uint16_t height; 100 uint16_t width; 101 }; 102 103 // check for start of image marker checkStartOfFrame(uint8_t * buf)104 static bool checkStartOfFrame(uint8_t* buf) { 105 return buf[0] == kMarker && buf[1] == kStartOfFrame; 106 } 107 108 // check for start of image marker checkJpegStart(uint8_t * buf)109 static bool checkJpegStart(uint8_t* buf) { 110 return buf[0] == kMarker && buf[1] == kStartOfImage; 111 } 112 113 // check for End of Image marker checkJpegEnd(uint8_t * buf)114 static bool checkJpegEnd(uint8_t *buf) { 115 return buf[0] == kMarker && buf[1] == kEndOfImage; 116 } 117 118 // check for arbitrary marker, returns marker type (second byte) 119 // returns 0 if no marker found. Note: 0x00 is not a valid marker type checkJpegMarker(uint8_t * buf)120 static uint8_t checkJpegMarker(uint8_t *buf) { 121 return (buf[0] == kMarker) ? buf[1] : 0; 122 } 123 124 jpeg_compress_struct mCompressInfo; 125 DestinationManager mDestManager; 126 ErrorManager mErrorManager; 127 128 bool configureCompressor(int width, int height, int quality); 129 bool compressData(const unsigned char* data, ExifData* exifData); 130 bool attachExifData(ExifData* exifData); 131 }; 132 133 #endif // TEST_CAMERA_JPEG_STUB_NV12_COMPRESSOR_H 134 135