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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 GetUPlane(), GetUPitch(), | 233 GetUPlane(), GetUPitch(), |
225 GetVPlane(), GetVPitch(), | 234 GetVPlane(), GetVPitch(), |
226 0, 0, | 235 0, 0, |
227 static_cast<int>(GetWidth()), | 236 static_cast<int>(GetWidth()), |
228 static_cast<int>(GetHeight()), | 237 static_cast<int>(GetHeight()), |
229 16, 128, 128) == 0; | 238 16, 128, 128) == 0; |
230 } | 239 } |
231 | 240 |
232 static const size_t kMaxSampleSize = 1000000000u; | 241 static const size_t kMaxSampleSize = 1000000000u; |
233 // Returns whether a sample is valid. | 242 // Returns whether a sample is valid. |
234 bool VideoFrame::Validate(uint32 fourcc, int w, int h, | 243 bool VideoFrame::Validate(uint32_t fourcc, |
235 const uint8 *sample, size_t sample_size) { | 244 int w, |
| 245 int h, |
| 246 const uint8_t* sample, |
| 247 size_t sample_size) { |
236 if (h < 0) { | 248 if (h < 0) { |
237 h = -h; | 249 h = -h; |
238 } | 250 } |
239 // 16384 is maximum resolution for VP8 codec. | 251 // 16384 is maximum resolution for VP8 codec. |
240 if (w < 1 || w > 16384 || h < 1 || h > 16384) { | 252 if (w < 1 || w > 16384 || h < 1 || h > 16384) { |
241 LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h; | 253 LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h; |
242 return false; | 254 return false; |
243 } | 255 } |
244 uint32 format = CanonicalFourCC(fourcc); | 256 uint32_t format = CanonicalFourCC(fourcc); |
245 int expected_bpp = 8; | 257 int expected_bpp = 8; |
246 switch (format) { | 258 switch (format) { |
247 case FOURCC_I400: | 259 case FOURCC_I400: |
248 case FOURCC_RGGB: | 260 case FOURCC_RGGB: |
249 case FOURCC_BGGR: | 261 case FOURCC_BGGR: |
250 case FOURCC_GRBG: | 262 case FOURCC_GRBG: |
251 case FOURCC_GBRG: | 263 case FOURCC_GBRG: |
252 expected_bpp = 8; | 264 expected_bpp = 8; |
253 break; | 265 break; |
254 case FOURCC_I420: | 266 case FOURCC_I420: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 if (sample == NULL) { | 311 if (sample == NULL) { |
300 LOG(LS_ERROR) << "NULL sample pointer." | 312 LOG(LS_ERROR) << "NULL sample pointer." |
301 << " format: " << GetFourccName(format) | 313 << " format: " << GetFourccName(format) |
302 << " bpp: " << expected_bpp | 314 << " bpp: " << expected_bpp |
303 << " size: " << w << "x" << h | 315 << " size: " << w << "x" << h |
304 << " expected: " << expected_size | 316 << " expected: " << expected_size |
305 << " " << sample_size; | 317 << " " << sample_size; |
306 return false; | 318 return false; |
307 } | 319 } |
308 // TODO(fbarchard): Make function to dump information about frames. | 320 // TODO(fbarchard): Make function to dump information about frames. |
309 uint8 four_samples[4] = { 0, 0, 0, 0 }; | 321 uint8_t four_samples[4] = {0, 0, 0, 0}; |
310 for (size_t i = 0; i < ARRAY_SIZE(four_samples) && i < sample_size; ++i) { | 322 for (size_t i = 0; i < ARRAY_SIZE(four_samples) && i < sample_size; ++i) { |
311 four_samples[i] = sample[i]; | 323 four_samples[i] = sample[i]; |
312 } | 324 } |
313 if (sample_size < expected_size) { | 325 if (sample_size < expected_size) { |
314 LOG(LS_ERROR) << "Size field is too small." | 326 LOG(LS_ERROR) << "Size field is too small." |
315 << " format: " << GetFourccName(format) | 327 << " format: " << GetFourccName(format) |
316 << " bpp: " << expected_bpp | 328 << " bpp: " << expected_bpp |
317 << " size: " << w << "x" << h | 329 << " size: " << w << "x" << h |
318 << " " << sample_size | 330 << " " << sample_size |
319 << " expected: " << expected_size | 331 << " expected: " << expected_size |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 << " expected: " << expected_size | 381 << " expected: " << expected_size |
370 << " sample[0..3]: " << static_cast<int>(four_samples[0]) | 382 << " sample[0..3]: " << static_cast<int>(four_samples[0]) |
371 << ", " << static_cast<int>(four_samples[1]) | 383 << ", " << static_cast<int>(four_samples[1]) |
372 << ", " << static_cast<int>(four_samples[2]) | 384 << ", " << static_cast<int>(four_samples[2]) |
373 << ", " << static_cast<int>(four_samples[3]); | 385 << ", " << static_cast<int>(four_samples[3]); |
374 } | 386 } |
375 return true; | 387 return true; |
376 } | 388 } |
377 | 389 |
378 } // namespace cricket | 390 } // namespace cricket |
OLD | NEW |