]> granicus.if.org Git - libvpx/blob - third_party/libwebm/common/hdr_util.cc
vp8 encoder: fix some integer overflows
[libvpx] / third_party / libwebm / common / hdr_util.cc
1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS.  All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #include "hdr_util.h"
9
10 #include <climits>
11 #include <cstddef>
12 #include <new>
13
14 #include "mkvparser/mkvparser.h"
15
16 namespace libwebm {
17 const int Vp9CodecFeatures::kValueNotPresent = INT_MAX;
18
19 bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
20                              PrimaryChromaticityPtr* muxer_pc) {
21   muxer_pc->reset(new (std::nothrow)
22                       mkvmuxer::PrimaryChromaticity(parser_pc.x, parser_pc.y));
23   if (!muxer_pc->get())
24     return false;
25   return true;
26 }
27
28 bool MasteringMetadataValuePresent(double value) {
29   return value != mkvparser::MasteringMetadata::kValueNotPresent;
30 }
31
32 bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm,
33                            mkvmuxer::MasteringMetadata* muxer_mm) {
34   if (MasteringMetadataValuePresent(parser_mm.luminance_max))
35     muxer_mm->set_luminance_max(parser_mm.luminance_max);
36   if (MasteringMetadataValuePresent(parser_mm.luminance_min))
37     muxer_mm->set_luminance_min(parser_mm.luminance_min);
38
39   PrimaryChromaticityPtr r_ptr(nullptr);
40   PrimaryChromaticityPtr g_ptr(nullptr);
41   PrimaryChromaticityPtr b_ptr(nullptr);
42   PrimaryChromaticityPtr wp_ptr(nullptr);
43
44   if (parser_mm.r) {
45     if (!CopyPrimaryChromaticity(*parser_mm.r, &r_ptr))
46       return false;
47   }
48   if (parser_mm.g) {
49     if (!CopyPrimaryChromaticity(*parser_mm.g, &g_ptr))
50       return false;
51   }
52   if (parser_mm.b) {
53     if (!CopyPrimaryChromaticity(*parser_mm.b, &b_ptr))
54       return false;
55   }
56   if (parser_mm.white_point) {
57     if (!CopyPrimaryChromaticity(*parser_mm.white_point, &wp_ptr))
58       return false;
59   }
60
61   if (!muxer_mm->SetChromaticity(r_ptr.get(), g_ptr.get(), b_ptr.get(),
62                                  wp_ptr.get())) {
63     return false;
64   }
65
66   return true;
67 }
68
69 bool ColourValuePresent(long long value) {
70   return value != mkvparser::Colour::kValueNotPresent;
71 }
72
73 bool CopyColour(const mkvparser::Colour& parser_colour,
74                 mkvmuxer::Colour* muxer_colour) {
75   if (!muxer_colour)
76     return false;
77
78   if (ColourValuePresent(parser_colour.matrix_coefficients))
79     muxer_colour->set_matrix_coefficients(parser_colour.matrix_coefficients);
80   if (ColourValuePresent(parser_colour.bits_per_channel))
81     muxer_colour->set_bits_per_channel(parser_colour.bits_per_channel);
82   if (ColourValuePresent(parser_colour.chroma_subsampling_horz)) {
83     muxer_colour->set_chroma_subsampling_horz(
84         parser_colour.chroma_subsampling_horz);
85   }
86   if (ColourValuePresent(parser_colour.chroma_subsampling_vert)) {
87     muxer_colour->set_chroma_subsampling_vert(
88         parser_colour.chroma_subsampling_vert);
89   }
90   if (ColourValuePresent(parser_colour.cb_subsampling_horz))
91     muxer_colour->set_cb_subsampling_horz(parser_colour.cb_subsampling_horz);
92   if (ColourValuePresent(parser_colour.cb_subsampling_vert))
93     muxer_colour->set_cb_subsampling_vert(parser_colour.cb_subsampling_vert);
94   if (ColourValuePresent(parser_colour.chroma_siting_horz))
95     muxer_colour->set_chroma_siting_horz(parser_colour.chroma_siting_horz);
96   if (ColourValuePresent(parser_colour.chroma_siting_vert))
97     muxer_colour->set_chroma_siting_vert(parser_colour.chroma_siting_vert);
98   if (ColourValuePresent(parser_colour.range))
99     muxer_colour->set_range(parser_colour.range);
100   if (ColourValuePresent(parser_colour.transfer_characteristics)) {
101     muxer_colour->set_transfer_characteristics(
102         parser_colour.transfer_characteristics);
103   }
104   if (ColourValuePresent(parser_colour.primaries))
105     muxer_colour->set_primaries(parser_colour.primaries);
106   if (ColourValuePresent(parser_colour.max_cll))
107     muxer_colour->set_max_cll(parser_colour.max_cll);
108   if (ColourValuePresent(parser_colour.max_fall))
109     muxer_colour->set_max_fall(parser_colour.max_fall);
110
111   if (parser_colour.mastering_metadata) {
112     mkvmuxer::MasteringMetadata muxer_mm;
113     if (!CopyMasteringMetadata(*parser_colour.mastering_metadata, &muxer_mm))
114       return false;
115     if (!muxer_colour->SetMasteringMetadata(muxer_mm))
116       return false;
117   }
118   return true;
119 }
120
121 // Format of VPx private data:
122 //
123 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
124 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 //  |    ID Byte    |   Length      |                               |
126 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
127 //  |                                                               |
128 //  :               Bytes 1..Length of Codec Feature                :
129 //  |                                                               |
130 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 //
132 // ID Byte Format
133 // ID byte is an unsigned byte.
134 //   0 1 2 3 4 5 6 7
135 //  +-+-+-+-+-+-+-+-+
136 //  |X|    ID       |
137 //  +-+-+-+-+-+-+-+-+
138 //
139 // The X bit is reserved.
140 //
141 // See the following link for more information:
142 // http://www.webmproject.org/vp9/profiles/
143 bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length,
144                           Vp9CodecFeatures* features) {
145   const int kVpxCodecPrivateMinLength = 3;
146   if (!private_data || !features || length < kVpxCodecPrivateMinLength)
147     return false;
148
149   const uint8_t kVp9ProfileId = 1;
150   const uint8_t kVp9LevelId = 2;
151   const uint8_t kVp9BitDepthId = 3;
152   const uint8_t kVp9ChromaSubsamplingId = 4;
153   const int kVpxFeatureLength = 1;
154   int offset = 0;
155
156   // Set features to not set.
157   features->profile = Vp9CodecFeatures::kValueNotPresent;
158   features->level = Vp9CodecFeatures::kValueNotPresent;
159   features->bit_depth = Vp9CodecFeatures::kValueNotPresent;
160   features->chroma_subsampling = Vp9CodecFeatures::kValueNotPresent;
161   do {
162     const uint8_t id_byte = private_data[offset++];
163     const uint8_t length_byte = private_data[offset++];
164     if (length_byte != kVpxFeatureLength)
165       return false;
166     if (id_byte == kVp9ProfileId) {
167       const int priv_profile = static_cast<int>(private_data[offset++]);
168       if (priv_profile < 0 || priv_profile > 3)
169         return false;
170       if (features->profile != Vp9CodecFeatures::kValueNotPresent &&
171           features->profile != priv_profile) {
172         return false;
173       }
174       features->profile = priv_profile;
175     } else if (id_byte == kVp9LevelId) {
176       const int priv_level = static_cast<int>(private_data[offset++]);
177
178       const int kNumLevels = 14;
179       const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
180                                       41, 50, 51, 52, 60, 61, 62};
181
182       for (int i = 0; i < kNumLevels; ++i) {
183         if (priv_level == levels[i]) {
184           if (features->level != Vp9CodecFeatures::kValueNotPresent &&
185               features->level != priv_level) {
186             return false;
187           }
188           features->level = priv_level;
189           break;
190         }
191       }
192       if (features->level == Vp9CodecFeatures::kValueNotPresent)
193         return false;
194     } else if (id_byte == kVp9BitDepthId) {
195       const int priv_profile = static_cast<int>(private_data[offset++]);
196       if (priv_profile != 8 && priv_profile != 10 && priv_profile != 12)
197         return false;
198       if (features->bit_depth != Vp9CodecFeatures::kValueNotPresent &&
199           features->bit_depth != priv_profile) {
200         return false;
201       }
202       features->bit_depth = priv_profile;
203     } else if (id_byte == kVp9ChromaSubsamplingId) {
204       const int priv_profile = static_cast<int>(private_data[offset++]);
205       if (priv_profile != 0 && priv_profile != 2 && priv_profile != 3)
206         return false;
207       if (features->chroma_subsampling != Vp9CodecFeatures::kValueNotPresent &&
208           features->chroma_subsampling != priv_profile) {
209         return false;
210       }
211       features->chroma_subsampling = priv_profile;
212     } else {
213       // Invalid ID.
214       return false;
215     }
216   } while (offset + kVpxCodecPrivateMinLength <= length);
217
218   return true;
219 }
220 }  // namespace libwebm