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 #include "HandleImporter.h" 29 30 extern "C" { 31 #include <jpeglib.h> 32 } 33 34 #include "utils/ExifUtils.h" 35 36 namespace android { 37 38 using android::hardware::camera::common::V1_0::helper::HandleImporter; 39 using google_camera_hal::BufferStatus; 40 using google_camera_hal::HwlPipelineCallback; 41 using google_camera_hal::HwlPipelineResult; 42 43 struct JpegYUV420Input { 44 uint32_t width, height; 45 bool buffer_owner; 46 YCbCrPlanes yuv_planes; 47 JpegYUV420InputJpegYUV420Input48 JpegYUV420Input() : width(0), height(0), buffer_owner(false) { 49 } ~JpegYUV420InputJpegYUV420Input50 ~JpegYUV420Input() { 51 if ((yuv_planes.img_y != nullptr) && buffer_owner) { 52 delete[] yuv_planes.img_y; 53 yuv_planes = {}; 54 } 55 } 56 57 JpegYUV420Input(const JpegYUV420Input&) = delete; 58 JpegYUV420Input& operator=(const JpegYUV420Input&) = delete; 59 }; 60 61 struct JpegYUV420Job { 62 std::unique_ptr<JpegYUV420Input> input; 63 std::unique_ptr<SensorBuffer> output; 64 std::unique_ptr<HalCameraMetadata> result_metadata; 65 std::unique_ptr<ExifUtils> exif_utils; 66 }; 67 68 class JpegCompressor { 69 public: 70 JpegCompressor(); 71 virtual ~JpegCompressor(); 72 73 status_t QueueYUV420(std::unique_ptr<JpegYUV420Job> job); 74 75 private: 76 std::mutex mutex_; 77 std::condition_variable condition_; 78 std::atomic_bool jpeg_done_ = false; 79 std::thread jpeg_processing_thread_; 80 std::queue<std::unique_ptr<JpegYUV420Job>> pending_yuv_jobs_; 81 std::string exif_make_, exif_model_; 82 83 j_common_ptr jpeg_error_info_; 84 bool CheckError(const char* msg); 85 void CompressYUV420(std::unique_ptr<JpegYUV420Job> job); 86 struct YUV420Frame { 87 uint8_t* output_buffer; 88 size_t output_buffer_size; 89 YCbCrPlanes yuv_planes; 90 size_t width; 91 size_t height; 92 const uint8_t* app1_buffer; 93 size_t app1_buffer_size; 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