OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include "webrtc/base/logging.h" | 37 #include "webrtc/base/logging.h" |
38 | 38 |
39 namespace cricket { | 39 namespace cricket { |
40 | 40 |
41 // Round to 2 pixels because Chroma channels are half size. | 41 // Round to 2 pixels because Chroma channels are half size. |
42 #define ROUNDTO2(v) (v & ~1) | 42 #define ROUNDTO2(v) (v & ~1) |
43 | 43 |
44 rtc::StreamResult VideoFrame::Write(rtc::StreamInterface* stream, | 44 rtc::StreamResult VideoFrame::Write(rtc::StreamInterface* stream, |
45 int* error) const { | 45 int* error) const { |
46 rtc::StreamResult result = rtc::SR_SUCCESS; | 46 rtc::StreamResult result = rtc::SR_SUCCESS; |
47 const uint8* src_y = GetYPlane(); | 47 const uint8_t* src_y = GetYPlane(); |
48 const uint8* src_u = GetUPlane(); | 48 const uint8_t* src_u = GetUPlane(); |
49 const uint8* src_v = GetVPlane(); | 49 const uint8_t* src_v = GetVPlane(); |
50 if (!src_y || !src_u || !src_v) { | 50 if (!src_y || !src_u || !src_v) { |
51 return result; // Nothing to write. | 51 return result; // Nothing to write. |
52 } | 52 } |
53 const int32 y_pitch = GetYPitch(); | 53 const int32_t y_pitch = GetYPitch(); |
54 const int32 u_pitch = GetUPitch(); | 54 const int32_t u_pitch = GetUPitch(); |
55 const int32 v_pitch = GetVPitch(); | 55 const int32_t v_pitch = GetVPitch(); |
56 const size_t width = GetWidth(); | 56 const size_t width = GetWidth(); |
57 const size_t height = GetHeight(); | 57 const size_t height = GetHeight(); |
58 const size_t half_width = (width + 1) >> 1; | 58 const size_t half_width = (width + 1) >> 1; |
59 const size_t half_height = (height + 1) >> 1; | 59 const size_t half_height = (height + 1) >> 1; |
60 // Write Y. | 60 // Write Y. |
61 for (size_t row = 0; row < height; ++row) { | 61 for (size_t row = 0; row < height; ++row) { |
62 result = stream->Write(src_y + row * y_pitch, width, NULL, error); | 62 result = stream->Write(src_y + row * y_pitch, width, NULL, error); |
63 if (result != rtc::SR_SUCCESS) { | 63 if (result != rtc::SR_SUCCESS) { |
64 return result; | 64 return result; |
65 } | 65 } |
66 } | 66 } |
67 // Write U. | 67 // Write U. |
68 for (size_t row = 0; row < half_height; ++row) { | 68 for (size_t row = 0; row < half_height; ++row) { |
69 result = stream->Write(src_u + row * u_pitch, half_width, NULL, error); | 69 result = stream->Write(src_u + row * u_pitch, half_width, NULL, error); |
70 if (result != rtc::SR_SUCCESS) { | 70 if (result != rtc::SR_SUCCESS) { |
71 return result; | 71 return result; |
72 } | 72 } |
73 } | 73 } |
74 // Write V. | 74 // Write V. |
75 for (size_t row = 0; row < half_height; ++row) { | 75 for (size_t row = 0; row < half_height; ++row) { |
76 result = stream->Write(src_v + row * v_pitch, half_width, NULL, error); | 76 result = stream->Write(src_v + row * v_pitch, half_width, NULL, error); |
77 if (result != rtc::SR_SUCCESS) { | 77 if (result != rtc::SR_SUCCESS) { |
78 return result; | 78 return result; |
79 } | 79 } |
80 } | 80 } |
81 return result; | 81 return result; |
82 } | 82 } |
83 | 83 |
84 size_t VideoFrame::CopyToBuffer(uint8* buffer, size_t size) const { | 84 size_t VideoFrame::CopyToBuffer(uint8_t* buffer, size_t size) const { |
85 const size_t y_size = GetHeight() * GetYPitch(); | 85 const size_t y_size = GetHeight() * GetYPitch(); |
86 const size_t u_size = GetUPitch() * GetChromaHeight(); | 86 const size_t u_size = GetUPitch() * GetChromaHeight(); |
87 const size_t v_size = GetVPitch() * GetChromaHeight(); | 87 const size_t v_size = GetVPitch() * GetChromaHeight(); |
88 const size_t needed = y_size + u_size + v_size; | 88 const size_t needed = y_size + u_size + v_size; |
89 if (size < needed) | 89 if (size < needed) |
90 return needed; | 90 return needed; |
91 CopyToPlanes(buffer, buffer + y_size, buffer + y_size + u_size, | 91 CopyToPlanes(buffer, buffer + y_size, buffer + y_size + u_size, |
92 GetYPitch(), GetUPitch(), GetVPitch()); | 92 GetYPitch(), GetUPitch(), GetVPitch()); |
93 return needed; | 93 return needed; |
94 } | 94 } |
95 | 95 |
96 bool VideoFrame::CopyToPlanes( | 96 bool VideoFrame::CopyToPlanes(uint8_t* dst_y, |
97 uint8* dst_y, uint8* dst_u, uint8* dst_v, | 97 uint8_t* dst_u, |
98 int32 dst_pitch_y, int32 dst_pitch_u, int32 dst_pitch_v) const { | 98 uint8_t* dst_v, |
| 99 int32_t dst_pitch_y, |
| 100 int32_t dst_pitch_u, |
| 101 int32_t dst_pitch_v) const { |
99 if (!GetYPlane() || !GetUPlane() || !GetVPlane()) { | 102 if (!GetYPlane() || !GetUPlane() || !GetVPlane()) { |
100 LOG(LS_ERROR) << "NULL plane pointer."; | 103 LOG(LS_ERROR) << "NULL plane pointer."; |
101 return false; | 104 return false; |
102 } | 105 } |
103 int32 src_width = static_cast<int>(GetWidth()); | 106 int32_t src_width = static_cast<int>(GetWidth()); |
104 int32 src_height = static_cast<int>(GetHeight()); | 107 int32_t src_height = static_cast<int>(GetHeight()); |
105 return libyuv::I420Copy(GetYPlane(), GetYPitch(), | 108 return libyuv::I420Copy(GetYPlane(), GetYPitch(), |
106 GetUPlane(), GetUPitch(), | 109 GetUPlane(), GetUPitch(), |
107 GetVPlane(), GetVPitch(), | 110 GetVPlane(), GetVPitch(), |
108 dst_y, dst_pitch_y, | 111 dst_y, dst_pitch_y, |
109 dst_u, dst_pitch_u, | 112 dst_u, dst_pitch_u, |
110 dst_v, dst_pitch_v, | 113 dst_v, dst_pitch_v, |
111 src_width, src_height) == 0; | 114 src_width, src_height) == 0; |
112 } | 115 } |
113 | 116 |
114 void VideoFrame::CopyToFrame(VideoFrame* dst) const { | 117 void VideoFrame::CopyToFrame(VideoFrame* dst) const { |
115 if (!dst) { | 118 if (!dst) { |
116 LOG(LS_ERROR) << "NULL dst pointer."; | 119 LOG(LS_ERROR) << "NULL dst pointer."; |
117 return; | 120 return; |
118 } | 121 } |
119 | 122 |
120 CopyToPlanes(dst->GetYPlane(), dst->GetUPlane(), dst->GetVPlane(), | 123 CopyToPlanes(dst->GetYPlane(), dst->GetUPlane(), dst->GetVPlane(), |
121 dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch()); | 124 dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch()); |
122 } | 125 } |
123 | 126 |
124 size_t VideoFrame::ConvertToRgbBuffer(uint32 to_fourcc, | 127 size_t VideoFrame::ConvertToRgbBuffer(uint32_t to_fourcc, |
125 uint8* buffer, | 128 uint8_t* buffer, |
126 size_t size, | 129 size_t size, |
127 int stride_rgb) const { | 130 int stride_rgb) const { |
128 const size_t needed = std::abs(stride_rgb) * GetHeight(); | 131 const size_t needed = std::abs(stride_rgb) * GetHeight(); |
129 if (size < needed) { | 132 if (size < needed) { |
130 LOG(LS_WARNING) << "RGB buffer is not large enough"; | 133 LOG(LS_WARNING) << "RGB buffer is not large enough"; |
131 return needed; | 134 return needed; |
132 } | 135 } |
133 | 136 |
134 if (libyuv::ConvertFromI420(GetYPlane(), GetYPitch(), GetUPlane(), | 137 if (libyuv::ConvertFromI420(GetYPlane(), GetYPitch(), GetUPlane(), |
135 GetUPitch(), GetVPlane(), GetVPitch(), buffer, | 138 GetUPitch(), GetVPlane(), GetVPitch(), buffer, |
136 stride_rgb, static_cast<int>(GetWidth()), | 139 stride_rgb, static_cast<int>(GetWidth()), |
137 static_cast<int>(GetHeight()), to_fourcc)) { | 140 static_cast<int>(GetHeight()), to_fourcc)) { |
138 LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc; | 141 LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc; |
139 return 0; // 0 indicates error | 142 return 0; // 0 indicates error |
140 } | 143 } |
141 return needed; | 144 return needed; |
142 } | 145 } |
143 | 146 |
144 // TODO(fbarchard): Handle odd width/height with rounding. | 147 // TODO(fbarchard): Handle odd width/height with rounding. |
145 void VideoFrame::StretchToPlanes( | 148 void VideoFrame::StretchToPlanes(uint8_t* dst_y, |
146 uint8* dst_y, uint8* dst_u, uint8* dst_v, | 149 uint8_t* dst_u, |
147 int32 dst_pitch_y, int32 dst_pitch_u, int32 dst_pitch_v, | 150 uint8_t* dst_v, |
148 size_t width, size_t height, bool interpolate, bool vert_crop) const { | 151 int32_t dst_pitch_y, |
| 152 int32_t dst_pitch_u, |
| 153 int32_t dst_pitch_v, |
| 154 size_t width, |
| 155 size_t height, |
| 156 bool interpolate, |
| 157 bool vert_crop) const { |
149 if (!GetYPlane() || !GetUPlane() || !GetVPlane()) { | 158 if (!GetYPlane() || !GetUPlane() || !GetVPlane()) { |
150 LOG(LS_ERROR) << "NULL plane pointer."; | 159 LOG(LS_ERROR) << "NULL plane pointer."; |
151 return; | 160 return; |
152 } | 161 } |
153 | 162 |
154 size_t src_width = GetWidth(); | 163 size_t src_width = GetWidth(); |
155 size_t src_height = GetHeight(); | 164 size_t src_height = GetHeight(); |
156 if (width == src_width && height == src_height) { | 165 if (width == src_width && height == src_height) { |
157 CopyToPlanes(dst_y, dst_u, dst_v, dst_pitch_y, dst_pitch_u, dst_pitch_v); | 166 CopyToPlanes(dst_y, dst_u, dst_v, dst_pitch_y, dst_pitch_u, dst_pitch_v); |
158 return; | 167 return; |
159 } | 168 } |
160 const uint8* src_y = GetYPlane(); | 169 const uint8_t* src_y = GetYPlane(); |
161 const uint8* src_u = GetUPlane(); | 170 const uint8_t* src_u = GetUPlane(); |
162 const uint8* src_v = GetVPlane(); | 171 const uint8_t* src_v = GetVPlane(); |
163 | 172 |
164 if (vert_crop) { | 173 if (vert_crop) { |
165 // Adjust the input width:height ratio to be the same as the output ratio. | 174 // Adjust the input width:height ratio to be the same as the output ratio. |
166 if (src_width * height > src_height * width) { | 175 if (src_width * height > src_height * width) { |
167 // Reduce the input width, but keep size/position aligned for YuvScaler | 176 // Reduce the input width, but keep size/position aligned for YuvScaler |
168 src_width = ROUNDTO2(src_height * width / height); | 177 src_width = ROUNDTO2(src_height * width / height); |
169 int32 iwidth_offset = ROUNDTO2((GetWidth() - src_width) / 2); | 178 int32_t iwidth_offset = ROUNDTO2((GetWidth() - src_width) / 2); |
170 src_y += iwidth_offset; | 179 src_y += iwidth_offset; |
171 src_u += iwidth_offset / 2; | 180 src_u += iwidth_offset / 2; |
172 src_v += iwidth_offset / 2; | 181 src_v += iwidth_offset / 2; |
173 } else if (src_width * height < src_height * width) { | 182 } else if (src_width * height < src_height * width) { |
174 // Reduce the input height. | 183 // Reduce the input height. |
175 src_height = src_width * height / width; | 184 src_height = src_width * height / width; |
176 int32 iheight_offset = static_cast<int32>( | 185 int32_t iheight_offset = |
177 (GetHeight() - src_height) >> 2); | 186 static_cast<int32_t>((GetHeight() - src_height) >> 2); |
178 iheight_offset <<= 1; // Ensure that iheight_offset is even. | 187 iheight_offset <<= 1; // Ensure that iheight_offset is even. |
179 src_y += iheight_offset * GetYPitch(); | 188 src_y += iheight_offset * GetYPitch(); |
180 src_u += iheight_offset / 2 * GetUPitch(); | 189 src_u += iheight_offset / 2 * GetUPitch(); |
181 src_v += iheight_offset / 2 * GetVPitch(); | 190 src_v += iheight_offset / 2 * GetVPitch(); |
182 } | 191 } |
183 } | 192 } |
184 | 193 |
185 // Scale to the output I420 frame. | 194 // Scale to the output I420 frame. |
186 libyuv::Scale(src_y, src_u, src_v, | 195 libyuv::Scale(src_y, src_u, src_v, |
187 GetYPitch(), GetUPitch(), GetVPitch(), | 196 GetYPitch(), GetUPitch(), GetVPitch(), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 GetUPlane(), GetUPitch(), | 232 GetUPlane(), GetUPitch(), |
224 GetVPlane(), GetVPitch(), | 233 GetVPlane(), GetVPitch(), |
225 0, 0, | 234 0, 0, |
226 static_cast<int>(GetWidth()), | 235 static_cast<int>(GetWidth()), |
227 static_cast<int>(GetHeight()), | 236 static_cast<int>(GetHeight()), |
228 16, 128, 128) == 0; | 237 16, 128, 128) == 0; |
229 } | 238 } |
230 | 239 |
231 static const size_t kMaxSampleSize = 1000000000u; | 240 static const size_t kMaxSampleSize = 1000000000u; |
232 // Returns whether a sample is valid. | 241 // Returns whether a sample is valid. |
233 bool VideoFrame::Validate(uint32 fourcc, int w, int h, | 242 bool VideoFrame::Validate(uint32_t fourcc, |
234 const uint8 *sample, size_t sample_size) { | 243 int w, |
| 244 int h, |
| 245 const uint8_t* sample, |
| 246 size_t sample_size) { |
235 if (h < 0) { | 247 if (h < 0) { |
236 h = -h; | 248 h = -h; |
237 } | 249 } |
238 // 16384 is maximum resolution for VP8 codec. | 250 // 16384 is maximum resolution for VP8 codec. |
239 if (w < 1 || w > 16384 || h < 1 || h > 16384) { | 251 if (w < 1 || w > 16384 || h < 1 || h > 16384) { |
240 LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h; | 252 LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h; |
241 return false; | 253 return false; |
242 } | 254 } |
243 uint32 format = CanonicalFourCC(fourcc); | 255 uint32_t format = CanonicalFourCC(fourcc); |
244 int expected_bpp = 8; | 256 int expected_bpp = 8; |
245 switch (format) { | 257 switch (format) { |
246 case FOURCC_I400: | 258 case FOURCC_I400: |
247 case FOURCC_RGGB: | 259 case FOURCC_RGGB: |
248 case FOURCC_BGGR: | 260 case FOURCC_BGGR: |
249 case FOURCC_GRBG: | 261 case FOURCC_GRBG: |
250 case FOURCC_GBRG: | 262 case FOURCC_GBRG: |
251 expected_bpp = 8; | 263 expected_bpp = 8; |
252 break; | 264 break; |
253 case FOURCC_I420: | 265 case FOURCC_I420: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 if (sample == NULL) { | 310 if (sample == NULL) { |
299 LOG(LS_ERROR) << "NULL sample pointer." | 311 LOG(LS_ERROR) << "NULL sample pointer." |
300 << " format: " << GetFourccName(format) | 312 << " format: " << GetFourccName(format) |
301 << " bpp: " << expected_bpp | 313 << " bpp: " << expected_bpp |
302 << " size: " << w << "x" << h | 314 << " size: " << w << "x" << h |
303 << " expected: " << expected_size | 315 << " expected: " << expected_size |
304 << " " << sample_size; | 316 << " " << sample_size; |
305 return false; | 317 return false; |
306 } | 318 } |
307 // TODO(fbarchard): Make function to dump information about frames. | 319 // TODO(fbarchard): Make function to dump information about frames. |
308 uint8 four_samples[4] = { 0, 0, 0, 0 }; | 320 uint8_t four_samples[4] = {0, 0, 0, 0}; |
309 for (size_t i = 0; i < ARRAY_SIZE(four_samples) && i < sample_size; ++i) { | 321 for (size_t i = 0; i < ARRAY_SIZE(four_samples) && i < sample_size; ++i) { |
310 four_samples[i] = sample[i]; | 322 four_samples[i] = sample[i]; |
311 } | 323 } |
312 if (sample_size < expected_size) { | 324 if (sample_size < expected_size) { |
313 LOG(LS_ERROR) << "Size field is too small." | 325 LOG(LS_ERROR) << "Size field is too small." |
314 << " format: " << GetFourccName(format) | 326 << " format: " << GetFourccName(format) |
315 << " bpp: " << expected_bpp | 327 << " bpp: " << expected_bpp |
316 << " size: " << w << "x" << h | 328 << " size: " << w << "x" << h |
317 << " " << sample_size | 329 << " " << sample_size |
318 << " expected: " << expected_size | 330 << " expected: " << expected_size |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 << " expected: " << expected_size | 380 << " expected: " << expected_size |
369 << " sample[0..3]: " << static_cast<int>(four_samples[0]) | 381 << " sample[0..3]: " << static_cast<int>(four_samples[0]) |
370 << ", " << static_cast<int>(four_samples[1]) | 382 << ", " << static_cast<int>(four_samples[1]) |
371 << ", " << static_cast<int>(four_samples[2]) | 383 << ", " << static_cast<int>(four_samples[2]) |
372 << ", " << static_cast<int>(four_samples[3]); | 384 << ", " << static_cast<int>(four_samples[3]); |
373 } | 385 } |
374 return true; | 386 return true; |
375 } | 387 } |
376 | 388 |
377 } // namespace cricket | 389 } // namespace cricket |
OLD | NEW |