1 /*
2  * Copyright Samsung Electronics Co.,LTD.
3  * Copyright (C) 2015 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef __HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
18 #define __HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
19 
20 #include <ExynosExif.h>
21 
22 #include "hwjpeg-internal.h"
23 #include "include/hardware/exynos/ExynosExif.h"
24 
25 #define JPEG_MAX_SEGMENT_SIZE ((1 << 16) - 1)
26 #define JPEG_MARKER_SIZE 2
27 #define JPEG_SEGMENT_LENFIELD_SIZE 2
28 #define JPEG_APP1_OEM_RESERVED 200
29 
30 #define IFD_FIELDCOUNT_SIZE 2
31 #define IFD_NEXTIFDOFFSET_SIZE 4
32 
33 #define IFD_TAG_SIZE 2
34 #define IFD_TYPE_SIZE 2
35 #define IFD_COUNT_SIZE 4
36 #define IFD_VALOFF_SIZE 4
37 
38 #define IFD_FIELD_SIZE (IFD_TAG_SIZE + IFD_TYPE_SIZE + IFD_COUNT_SIZE + IFD_VALOFF_SIZE)
39 
40 #define EXTRA_APPMARKER_MIN 1
41 #define EXTRA_APPMARKER_LIMIT 10
42 
43 #define MAX_GPS_PROCESSINGMETHOD_SIZE 108
44 
45 #define EXIF_SUBSECTIME_LENGTH 5
46 #define EXIF_DATETIME_LENGTH 20
47 #define EXIF_GPSDATESTAMP_LENGTH 11
48 
49 class CAppMarkerWriter {
50     char *m_pAppBase;
51     char *m_pApp1End;
52     size_t m_szMaxThumbSize; // Maximum available thumbnail stream size minus JPEG_MARKER_SIZE
53     uint16_t m_szApp1;       // The size of APP1 segment without marker
54     uint16_t m_szApp11;      // The size of APP11 segment without marker
55     uint16_t m_n0thIFDFields;
56     uint16_t m_n1stIFDFields;
57     uint16_t m_nExifIFDFields;
58     uint16_t m_nGPSIFDFields;
59     exif_attribute_t *m_pExif;
60     extra_appinfo_t *m_pExtra;
61 
62     uint32_t m_szMake;
63     uint32_t m_szSoftware;
64     uint32_t m_szModel;
65     uint32_t m_szUniqueID;
66 
67     char *m_pMainBase;
68     // The address to write compressed stream of the thumbnail image
69     char *m_pThumbBase;
70     // points to the "ValueOffset" field of JPEGInterchangeFormatLen tag of 1st IFD
71     // This should be updated after compression of thumbnail image.
72     // Note that the address may not be aligned by 32-bit.
73     char *m_pThumbSizePlaceholder;
74 
75     void Init();
76 
77     char *WriteAPP1(char *base, bool reserve_thumbnail_space, bool updating = false);
78     char *WriteAPPX(char *base, bool just_reserve);
79     char *WriteAPP11(char *current, size_t dummy, size_t align);
80 
81 public:
82     // dummy: number of dummy bytes written by the compressor of the main image
83     // this dummy size should be added to the APP1 length. Howerver, this dummy area
84     // for the main image stream should not be written by neither of appwriter nor
85     // thumbnail compressor.
86     CAppMarkerWriter();
87     CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug);
88 
~CAppMarkerWriter()89     ~CAppMarkerWriter() {}
90 
91     void PrepareAppWriter(char *base, exif_attribute_t *exif, extra_appinfo_t *info);
92 
GetMainStreamBase()93     char *GetMainStreamBase() { return m_pMainBase; }
GetThumbStreamBase()94     char *GetThumbStreamBase() { return m_pThumbBase; }
GetThumbStreamSizeAddr()95     char *GetThumbStreamSizeAddr() {
96         char *p = m_pThumbSizePlaceholder;
97         m_pThumbSizePlaceholder = NULL;
98         return p;
99     }
GetMaxThumbnailSize()100     size_t GetMaxThumbnailSize() { return m_szMaxThumbSize; }
GetAPP1ResrevedSize()101     size_t GetAPP1ResrevedSize() { return JPEG_APP1_OEM_RESERVED; }
102     // CalculateAPPSize() is valid after Write() is successful.
103     size_t CalculateAPPSize(size_t thumblen = JPEG_MAX_SEGMENT_SIZE) {
104         size_t appsize = 0;
105         if (m_szApp1 > 0) appsize += m_szApp1 + JPEG_MARKER_SIZE;
106         if (m_pExtra) {
107             for (int idx = 0; idx < m_pExtra->num_of_appmarker; idx++)
108                 appsize += m_pExtra->appInfo[idx].dataSize + +JPEG_MARKER_SIZE +
109                         JPEG_SEGMENT_LENFIELD_SIZE;
110         }
111         if (IsThumbSpaceReserved())
112             appsize += m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED;
113         else
114             appsize += min(m_szMaxThumbSize, thumblen);
115 
116         return appsize + m_szApp11;
117     }
118 
GetApp1End()119     char *GetApp1End() { return m_pApp1End; }
120 
121     void Write(bool reserve_thumbnail_space, size_t dummy, size_t align,
122                bool reserve_debug = false) {
123         m_pApp1End = WriteAPP1(m_pAppBase, reserve_thumbnail_space);
124         char *appXend = WriteAPPX(m_pApp1End, reserve_debug);
125         char *app11end = WriteAPP11(appXend, dummy, align);
126         m_szApp11 = PTR_DIFF(appXend, app11end);
127         m_pMainBase = app11end - dummy;
128     }
129 
Update()130     void Update() { WriteAPP1(m_pAppBase, false, true); }
131 
IsThumbSpaceReserved()132     bool IsThumbSpaceReserved() {
133         return PTR_DIFF(m_pAppBase, m_pApp1End) ==
134                 (m_szApp1 + m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED + JPEG_MARKER_SIZE);
135     }
136 
137     void Finalize(size_t thumbsize);
138 
139     void UpdateApp1Size(size_t amount);
140 };
141 #endif //__HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
142