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 HW_EMULATOR_CAMERA_JPEG_H 18 #define HW_EMULATOR_CAMERA_JPEG_H 19 20 #include <hwl_types.h> 21 22 #include <condition_variable> 23 #include <mutex> 24 #include <queue> 25 #include <thread> 26 27 #include "Base.h" 28 29 extern "C" { 30 #include <jpeglib.h> 31 } 32 33 #include "utils/ExifUtils.h" 34 35 namespace android { 36 37 using google_camera_hal::BufferStatus; 38 using google_camera_hal::HwlPipelineCallback; 39 using google_camera_hal::HwlPipelineResult; 40 41 struct JpegYUV420Input { 42 uint32_t width, height; 43 bool buffer_owner; 44 YCbCrPlanes yuv_planes; 45 int32_t color_space; 46 JpegYUV420InputJpegYUV420Input47 JpegYUV420Input() : width(0), height(0), buffer_owner(false) { 48 } ~JpegYUV420InputJpegYUV420Input49 ~JpegYUV420Input() { 50 if ((yuv_planes.img_y != nullptr) && buffer_owner) { 51 delete[] yuv_planes.img_y; 52 yuv_planes = {}; 53 } 54 } 55 56 JpegYUV420Input(const JpegYUV420Input&) = delete; 57 JpegYUV420Input& operator=(const JpegYUV420Input&) = delete; 58 }; 59 60 struct JpegYUV420Job { 61 std::unique_ptr<JpegYUV420Input> input; 62 std::unique_ptr<SensorBuffer> output; 63 std::unique_ptr<HalCameraMetadata> result_metadata; 64 std::unique_ptr<ExifUtils> exif_utils; 65 }; 66 67 class JpegCompressor { 68 public: 69 JpegCompressor(); 70 virtual ~JpegCompressor(); 71 72 status_t QueueYUV420(std::unique_ptr<JpegYUV420Job> job); 73 74 private: 75 std::mutex mutex_; 76 std::condition_variable condition_; 77 std::atomic_bool jpeg_done_ = false; 78 std::thread jpeg_processing_thread_; 79 std::queue<std::unique_ptr<JpegYUV420Job>> pending_yuv_jobs_; 80 std::string exif_make_, exif_model_; 81 82 j_common_ptr jpeg_error_info_; 83 bool CheckError(const char* msg); 84 void CompressYUV420(std::unique_ptr<JpegYUV420Job> job); 85 struct YUV420Frame { 86 uint8_t* output_buffer; 87 size_t output_buffer_size; 88 YCbCrPlanes yuv_planes; 89 size_t width; 90 size_t height; 91 const uint8_t* app1_buffer; 92 size_t app1_buffer_size; 93 int32_t color_space; 94 }; 95 size_t CompressYUV420Frame(YUV420Frame frame); 96 void ThreadLoop(); 97 98 JpegCompressor(const JpegCompressor&) = delete; 99 JpegCompressor& operator=(const JpegCompressor&) = delete; 100 }; 101 102 } // namespace android 103 104 template <> 105 struct std::default_delete<jpeg_compress_struct> { 106 inline void operator()(jpeg_compress_struct* cinfo) const { 107 if (cinfo != nullptr) { 108 jpeg_destroy_compress(cinfo); 109 delete cinfo; 110 } 111 } 112 }; 113 114 #endif 115