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 JpegYUV420InputJpegYUV420Input46 JpegYUV420Input() : width(0), height(0), buffer_owner(false) { 47 } ~JpegYUV420InputJpegYUV420Input48 ~JpegYUV420Input() { 49 if ((yuv_planes.img_y != nullptr) && buffer_owner) { 50 delete[] yuv_planes.img_y; 51 yuv_planes = {}; 52 } 53 } 54 55 JpegYUV420Input(const JpegYUV420Input&) = delete; 56 JpegYUV420Input& operator=(const JpegYUV420Input&) = delete; 57 }; 58 59 struct JpegYUV420Job { 60 std::unique_ptr<JpegYUV420Input> input; 61 std::unique_ptr<SensorBuffer> output; 62 std::unique_ptr<HalCameraMetadata> result_metadata; 63 std::unique_ptr<ExifUtils> exif_utils; 64 }; 65 66 class JpegCompressor { 67 public: 68 JpegCompressor(); 69 virtual ~JpegCompressor(); 70 71 status_t QueueYUV420(std::unique_ptr<JpegYUV420Job> job); 72 73 private: 74 std::mutex mutex_; 75 std::condition_variable condition_; 76 std::atomic_bool jpeg_done_ = false; 77 std::thread jpeg_processing_thread_; 78 std::queue<std::unique_ptr<JpegYUV420Job>> pending_yuv_jobs_; 79 std::string exif_make_, exif_model_; 80 81 j_common_ptr jpeg_error_info_; 82 bool CheckError(const char* msg); 83 void CompressYUV420(std::unique_ptr<JpegYUV420Job> job); 84 struct YUV420Frame { 85 uint8_t* output_buffer; 86 size_t output_buffer_size; 87 YCbCrPlanes yuv_planes; 88 size_t width; 89 size_t height; 90 const uint8_t* app1_buffer; 91 size_t app1_buffer_size; 92 }; 93 size_t CompressYUV420Frame(YUV420Frame frame); 94 void ThreadLoop(); 95 96 JpegCompressor(const JpegCompressor&) = delete; 97 JpegCompressor& operator=(const JpegCompressor&) = delete; 98 }; 99 100 } // namespace android 101 102 template <> 103 struct std::default_delete<jpeg_compress_struct> { 104 inline void operator()(jpeg_compress_struct* cinfo) const { 105 if (cinfo != nullptr) { 106 jpeg_destroy_compress(cinfo); 107 delete cinfo; 108 } 109 } 110 }; 111 112 #endif 113