camera-format-converters.c revision 88fceb022e53ede2f6a7e57a8cbd63f5ac2e1bb3
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdint.h> 18#include <stdio.h> 19#include <stdlib.h> 20#ifdef _WIN32 21#elif _DARWIN_C_SOURCE 22#else 23#include <linux/videodev2.h> 24#endif 25#include "android/camera/camera-format-converters.h" 26 27/* Describes a convertor for one pixel format to another. */ 28typedef struct FormatConverterEntry { 29 /* Pixel format to convert from. */ 30 uint32_t from_format; 31 /* Pixel format to convert to. */ 32 uint32_t to_format; 33 /* Address of the conversion routine. */ 34 FormatConverter converter; 35} FormatConverterEntry; 36 37/* Converts frame from RGB24 (8 bits per color) to NV12 (YUV420) 38 * Param: 39 * rgb - RGB frame to convert. 40 * width, height - Width, and height of the RGB frame. 41 * yuv - Buffer to receive the converted frame. Note that this buffer must 42 * be big enough to contain all the converted pixels! 43 */ 44static void 45_RGB8_to_YUV420(const uint8_t* rgb, 46 int width, 47 int height, 48 uint8_t* yuv) 49{ 50 const uint8_t* rgb_current = rgb; 51 int x, y, yi = 0; 52 const int num_pixels = width * height; 53 int ui = num_pixels; 54 int vi = num_pixels + num_pixels / 4; 55 56 for (y = 0; y < height; y++) { 57 for (x = 0; x < width; x++) { 58 const uint32_t b = rgb_current[0]; 59 const uint32_t g = rgb_current[1]; 60 const uint32_t r = rgb_current[2]; 61 rgb_current += 3; 62 yuv[yi++] = (uint8_t)((66*r + 129*g + 25*b + 128) >> 8) + 16; 63 if((x % 2 ) == 0 && (y % 2) == 0) { 64 yuv[ui++] = (uint8_t)((-38*r - 74*g + 112*b + 128) >> 8 ) + 128; 65 yuv[vi++] = (uint8_t)((112*r - 94*g - 18*b + 128) >> 8 ) + 128; 66 } 67 } 68 } 69} 70 71/* Converts frame from RGB24 (8 bits per color) to NV21 (YVU420) 72 * Param: 73 * rgb - RGB frame to convert. 74 * width, height - Width, and height of the RGB frame. 75 * yuv - Buffer to receive the converted frame. Note that this buffer must 76 * be big enough to contain all the converted pixels! 77 */ 78static void 79_RGB8_to_YVU420(const uint8_t* rgb, 80 int width, 81 int height, 82 uint8_t* yuv) 83{ 84 const uint8_t* rgb_current = rgb; 85 int x, y, yi = 0; 86 const int num_pixels = width * height; 87 int vi = num_pixels; 88 int ui = num_pixels + num_pixels / 4; 89 90 for (y = 0; y < height; y++) { 91 for (x = 0; x < width; x++) { 92 const uint32_t b = rgb_current[0]; 93 const uint32_t g = rgb_current[1]; 94 const uint32_t r = rgb_current[2]; 95 rgb_current += 3; 96 yuv[yi++] = (uint8_t)((66*r + 129*g + 25*b + 128) >> 8) + 16; 97 if((x % 2 ) == 0 && (y % 2) == 0) { 98 yuv[ui++] = (uint8_t)((-38*r - 74*g + 112*b + 128) >> 8 ) + 128; 99 yuv[vi++] = (uint8_t)((112*r - 94*g - 18*b + 128) >> 8 ) + 128; 100 } 101 } 102 } 103} 104 105/* Lists currently implemented converters. */ 106static const FormatConverterEntry _converters[] = { 107 /* RGB24 -> NV12 */ 108 { V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_NV12, _RGB8_to_YUV420 }, 109 /* RGB24 -> YUV420 */ 110 { V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_YUV420, _RGB8_to_YUV420 }, 111 /* RGB24 -> NV21 */ 112 { V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_NV21, _RGB8_to_YVU420 }, 113}; 114 115FormatConverter 116get_format_converted(uint32_t from, uint32_t to) 117{ 118 const int num_converters = sizeof(_converters) / sizeof(*_converters); 119 int n; 120 for (n = 0; n < num_converters; n++) { 121 if (_converters[n].from_format == from && 122 _converters[n].to_format == to) { 123 return _converters[n].converter; 124 } 125 } 126 127 return NULL; 128} 129