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 #include <stdio.h> 23 extern "C" { 24 #include <jpeglib.h> 25 #include <jerror.h> 26 } 27 28 #include <utils/Errors.h> 29 #include <vector> 30 31 #include "../utils/ExifUtils.h" 32 33 struct _ExifData; 34 typedef _ExifData ExifData; 35 36 class NV12Compressor { 37 public: NV12Compressor()38 NV12Compressor() {} 39 40 /* Compress |data| which represents raw NV21 encoded data of dimensions 41 * |width| * |height|. 42 */ 43 bool compress(const unsigned char* data, int width, int height, int quality); 44 bool compressWithExifOrientation(const unsigned char* data, int width, int height, int quality, 45 android::camera3::ExifOrientation exifValue); 46 47 /* Get a reference to the compressed data, this will return an empty vector 48 * if compress has not been called yet 49 */ 50 const std::vector<unsigned char>& getCompressedData() const; 51 52 // Utility methods 53 static android::status_t findJpegSize(uint8_t *jpegBuffer, size_t maxSize, 54 size_t *size /*out*/); 55 56 static android::status_t getExifOrientation(uint8_t *jpegBuffer, 57 size_t jpegBufferSize, android::camera3::ExifOrientation *exifValue /*out*/); 58 59 /* Get Jpeg image dimensions from the first Start Of Frame. Please note that due to the 60 * way the jpeg buffer is scanned if the image contains a thumbnail, then the size returned 61 * will be of the thumbnail and not the main image. 62 */ 63 static android::status_t getJpegImageDimensions(uint8_t *jpegBuffer, size_t jpegBufferSize, 64 size_t *width /*out*/, size_t *height /*out*/); 65 66 private: 67 68 struct DestinationManager : jpeg_destination_mgr { 69 DestinationManager(); 70 71 static void initDestination(j_compress_ptr cinfo); 72 static boolean emptyOutputBuffer(j_compress_ptr cinfo); 73 static void termDestination(j_compress_ptr cinfo); 74 75 std::vector<unsigned char> mBuffer; 76 }; 77 78 struct ErrorManager : jpeg_error_mgr { 79 ErrorManager(); 80 81 static void onJpegError(j_common_ptr cinfo); 82 83 jmp_buf mJumpBuffer; 84 }; 85 86 static const size_t kMarkerLength = 2; // length of a marker 87 static const uint8_t kMarker = 0xFF; // First byte of marker 88 static const uint8_t kStartOfImage = 0xD8; // Start of Image 89 static const uint8_t kEndOfImage = 0xD9; // End of Image 90 static const uint8_t kStartOfFrame = 0xC0; // Start of Frame 91 92 struct __attribute__((packed)) segment_t { 93 uint8_t marker[kMarkerLength]; 94 uint16_t length; 95 }; 96 97 struct __attribute__((packed)) sof_t { 98 uint16_t length; 99 uint8_t precision; 100 uint16_t height; 101 uint16_t width; 102 }; 103 104 // check for start of image marker checkStartOfFrame(uint8_t * buf)105 static bool checkStartOfFrame(uint8_t* buf) { 106 return buf[0] == kMarker && buf[1] == kStartOfFrame; 107 } 108 109 // check for start of image marker checkJpegStart(uint8_t * buf)110 static bool checkJpegStart(uint8_t* buf) { 111 return buf[0] == kMarker && buf[1] == kStartOfImage; 112 } 113 114 // check for End of Image marker checkJpegEnd(uint8_t * buf)115 static bool checkJpegEnd(uint8_t *buf) { 116 return buf[0] == kMarker && buf[1] == kEndOfImage; 117 } 118 119 // check for arbitrary marker, returns marker type (second byte) 120 // returns 0 if no marker found. Note: 0x00 is not a valid marker type checkJpegMarker(uint8_t * buf)121 static uint8_t checkJpegMarker(uint8_t *buf) { 122 return (buf[0] == kMarker) ? buf[1] : 0; 123 } 124 125 jpeg_compress_struct mCompressInfo; 126 DestinationManager mDestManager; 127 ErrorManager mErrorManager; 128 129 bool configureCompressor(int width, int height, int quality); 130 bool compressData(const unsigned char* data, ExifData* exifData); 131 bool attachExifData(ExifData* exifData); 132 }; 133 134 #endif // TEST_CAMERA_JPEG_STUB_NV12_COMPRESSOR_H 135 136