Chromium Code Reviews| Index: media/video/capture/video_capture_color_conversion.cc |
| =================================================================== |
| --- media/video/capture/video_capture_color_conversion.cc (revision 0) |
| +++ media/video/capture/video_capture_color_conversion.cc (revision 0) |
| @@ -0,0 +1,164 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/logging.h" |
| +#include "media/video/capture/video_capture_color_conversion.h" |
| + |
| +namespace media { |
| + |
| +void VideoCaptureColorConversion::ConvertToI420( |
| + VideoCaptureDevice::Format src_format, |
| + const uint8* src, |
| + int width, |
| + int height, |
| + uint8* dst) { |
| + DCHECK(src_format != VideoCaptureDevice::kColorUnknown); |
| + switch (src_format) { |
| + case VideoCaptureDevice::kColorUnknown: // Color format not set |
| + break; |
| + case VideoCaptureDevice::kI420: |
| + memcpy(dst, src, (width * height * 3) / 2); |
| + break; |
| + case VideoCaptureDevice::kYUY2: |
| + ConvertYUY2ToI420(src, width, height, dst); |
| + break; |
| + case VideoCaptureDevice::kRGB24: |
| + ConvertRGB24ToI420(src, width, height, dst); |
| + break; |
| + case VideoCaptureDevice::kARGB: |
| + ConvertARGBToI420(src, width, height, dst); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| +} |
| + |
| +void VideoCaptureColorConversion::ConvertYUY2ToI420(const uint8* src, |
| + int width, |
| + int height, |
| + uint8* dst) { |
| + DCHECK(width>1 && height>1); |
| + if (width < 1 || height < 1) { |
| + return; |
| + } |
| + int i =0; |
| + int j =0; |
| + uint8* out_I = dst; |
| + uint8* out_Cr = dst + (width) * height; |
| + uint8* out_Cb = dst + (width) * height + (width) * (height >> 2); |
| + for (; i < (height >> 1); i++) { |
| + for (j = 0; j < (width >> 1); j++) { |
| + out_I[0] = src[0]; |
| + *out_Cr = src[1]; |
| + out_I[1] = src[2]; |
| + *out_Cb = src[3]; |
| + src += 4; |
| + out_I += 2; |
| + out_Cr++; |
| + out_Cb++; |
| + } |
| + for (j = 0; j < (width >> 1); j++) { |
| + out_I[0] = src[0]; |
| + out_I[1] = src[2]; |
| + src += 4; |
| + out_I += 2; |
| + } |
| + } |
| +} |
| + |
| +void VideoCaptureColorConversion::ConvertRGB24ToI420(const uint8* src, |
| + int width, |
| + int height, |
| + uint8* dst) { |
| + if (height < 1 || width < 1) { |
| + return; |
| + } |
| + |
| + // assuming RGB in a bottom up orientation. |
| + uint8* y_start_ptr = dst; |
| + uint8* y_start_ptr2 = y_start_ptr + width; |
| + uint8* u_start_ptr = dst + (width * height); |
| + uint8* v_start_ptr = u_start_ptr + (width * height >> 2); |
| + const uint8* inp_ptr = src + width * height * 3 - 3 * width; |
| + const uint8* inp_ptr2 = inp_ptr - 3 * width; |
| + |
| + for (int h = 0; h < (height >> 1); h++) { |
| + for (int w = 0; w < (width >> 1); w++) { |
| + // Y |
| + y_start_ptr[0] = ((66 * inp_ptr[2] + 129 * inp_ptr[1] + 25 * inp_ptr[0] + |
| + 128) >> 8) + 16; |
| + y_start_ptr2[0] = ((66 * inp_ptr2[2] + 129 * inp_ptr2[1] + 25 * |
| + inp_ptr2[0] + 128) >> 8) + 16; |
| + // moving to next column |
| + y_start_ptr[1] = ((66 * inp_ptr[5] + 129 * inp_ptr[4] + 25 * inp_ptr[3] + |
| + 128) >> 8) + 16; |
| + y_start_ptr2[1] = ((66 * inp_ptr2[5] + 129 * inp_ptr2[4] + 25 * |
| + inp_ptr2[3] + 128) >> 8) + 16; |
| + // U |
| + u_start_ptr[0] = ((-38 * inp_ptr[2] - 74 * inp_ptr[1] + 112 * inp_ptr[0] + |
| + 128) >> 8) + 128; |
| + // V |
| + v_start_ptr[0] = ((112 * inp_ptr[2] - 94 * inp_ptr[1] - 18 * inp_ptr[0] + |
| + 128) >> 8) + 128; |
|
wjia(left Chromium)
2011/05/11 23:23:31
looks like downsampled U and V are located at [0,0
Per K
2011/05/16 11:49:39
Would you prefer if the conversion functions are p
|
| + y_start_ptr += 2; |
| + y_start_ptr2 += 2; |
| + u_start_ptr++; |
| + v_start_ptr++; |
| + inp_ptr += 6; |
| + inp_ptr2 += 6; |
| + } // end for w |
| + y_start_ptr += width; |
| + y_start_ptr2 += width; |
| + inp_ptr -= 9 * width; |
| + inp_ptr2 -= 9 * width; |
| + } // end for h |
| +} |
| + |
| +void VideoCaptureColorConversion::ConvertARGBToI420(const uint8* src, |
| + int width, |
| + int height, |
| + uint8* dst) { |
| + if (height < 1 || width < 1) { |
| + return; |
| + } |
| + |
| + uint8* y_start_ptr = dst; |
| + uint8* y_start_ptr2 = y_start_ptr + width; |
| + uint8* u_start_ptr = dst + (width * height); |
| + uint8* v_start_ptr = u_start_ptr + (width * height >> 2); |
| + const uint8* inp_ptr = src; |
| + const uint8* inp_ptr2 = inp_ptr + 4 * width; |
| + int h, w; |
| + for (h = 0; h < (height >> 1); h++) { |
| + for (w = 0; w < (width >> 1); w++) { // Y |
| + y_start_ptr[0] = (((66 * inp_ptr[1] + 129 * inp_ptr[2] + 25 * inp_ptr[3] + |
| + 128) >> 8) + 16); |
| + y_start_ptr2[0] = ((66 * inp_ptr2[1] + 129 * inp_ptr2[2] + 25 * |
| + inp_ptr2[3] + 128) >> 8) + 16; |
| + // moving to next column |
| + y_start_ptr[1] = ((66 * inp_ptr[5] + 129 * inp_ptr[6] + 25 * inp_ptr[7] + |
| + 128) >> 8) + 16; |
| + y_start_ptr2[1] = ((66 * inp_ptr2[5] + 129 * inp_ptr2[6] + 25 * |
| + inp_ptr2[7] + 128) >> 8) + 16; |
| + // U |
| + u_start_ptr[0] = ((-38 * inp_ptr[1] - 74 * inp_ptr[2] + 112 * inp_ptr[3] + |
| + 128) >> 8) + 128; |
| + // V |
| + v_start_ptr[0] = ((112 * inp_ptr[1] - 94 * inp_ptr[2] - 18 * inp_ptr[3] + |
| + 128) >> 8) + 128; |
| + y_start_ptr += 2; |
| + y_start_ptr2 += 2; |
| + u_start_ptr++; |
| + v_start_ptr++; |
| + inp_ptr += 8; |
| + inp_ptr2 += 8; |
| + } |
| + y_start_ptr += width; |
| + y_start_ptr2 += width; |
| + inp_ptr += 4 * width; |
| + inp_ptr2 += 4 * width; |
| + } |
| +} |
| + |
| +} // namespace media |