1/* 2 * Copyright (C) 2007 Marc Hoffman <marc.hoffman@analog.com> 3 * 4 * Blackfin video color space converter operations 5 * convert I420 YV12 to RGB in various formats 6 * 7 * This file is part of Libav. 8 * 9 * Libav is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * Libav is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with Libav; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 */ 23 24#include <stdio.h> 25#include <stdlib.h> 26#include <string.h> 27#include <inttypes.h> 28#include <assert.h> 29#include "config.h" 30#include <unistd.h> 31#include "libswscale/rgb2rgb.h" 32#include "libswscale/swscale.h" 33#include "libswscale/swscale_internal.h" 34 35#if defined(__FDPIC__) && CONFIG_SRAM 36#define L1CODE __attribute__ ((l1_text)) 37#else 38#define L1CODE 39#endif 40 41void ff_bfin_yuv2rgb555_line(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, 42 int w, uint32_t *coeffs) L1CODE; 43 44void ff_bfin_yuv2rgb565_line(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, 45 int w, uint32_t *coeffs) L1CODE; 46 47void ff_bfin_yuv2rgb24_line(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, 48 int w, uint32_t *coeffs) L1CODE; 49 50typedef void (* ltransform)(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, 51 int w, uint32_t *coeffs); 52 53 54static void bfin_prepare_coefficients(SwsContext *c, int rgb, int masks) 55{ 56 int oy; 57 oy = c->yOffset&0xffff; 58 oy = oy >> 3; // keep everything U8.0 for offset calculation 59 60 c->oc = 128*0x01010101U; 61 c->oy = oy*0x01010101U; 62 63 /* copy 64bit vector coeffs down to 32bit vector coeffs */ 64 c->cy = c->yCoeff; 65 c->zero = 0; 66 67 if (rgb) { 68 c->crv = c->vrCoeff; 69 c->cbu = c->ubCoeff; 70 c->cgu = c->ugCoeff; 71 c->cgv = c->vgCoeff; 72 } else { 73 c->crv = c->ubCoeff; 74 c->cbu = c->vrCoeff; 75 c->cgu = c->vgCoeff; 76 c->cgv = c->ugCoeff; 77 } 78 79 80 if (masks == 555) { 81 c->rmask = 0x001f * 0x00010001U; 82 c->gmask = 0x03e0 * 0x00010001U; 83 c->bmask = 0x7c00 * 0x00010001U; 84 } else if (masks == 565) { 85 c->rmask = 0x001f * 0x00010001U; 86 c->gmask = 0x07e0 * 0x00010001U; 87 c->bmask = 0xf800 * 0x00010001U; 88 } 89} 90 91static int core_yuv420_rgb(SwsContext *c, 92 uint8_t **in, int *instrides, 93 int srcSliceY, int srcSliceH, 94 uint8_t **oplanes, int *outstrides, 95 ltransform lcscf, int rgb, int masks) 96{ 97 uint8_t *py,*pu,*pv,*op; 98 int w = instrides[0]; 99 int h2 = srcSliceH>>1; 100 int i; 101 102 bfin_prepare_coefficients(c, rgb, masks); 103 104 py = in[0]; 105 pu = in[1+(1^rgb)]; 106 pv = in[1+(0^rgb)]; 107 108 op = oplanes[0] + srcSliceY*outstrides[0]; 109 110 for (i=0;i<h2;i++) { 111 112 lcscf(py, pu, pv, op, w, &c->oy); 113 114 py += instrides[0]; 115 op += outstrides[0]; 116 117 lcscf(py, pu, pv, op, w, &c->oy); 118 119 py += instrides[0]; 120 pu += instrides[1]; 121 pv += instrides[2]; 122 op += outstrides[0]; 123 } 124 125 return srcSliceH; 126} 127 128 129static int bfin_yuv420_rgb555(SwsContext *c, 130 uint8_t **in, int *instrides, 131 int srcSliceY, int srcSliceH, 132 uint8_t **oplanes, int *outstrides) 133{ 134 return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, 135 outstrides, ff_bfin_yuv2rgb555_line, 1, 555); 136} 137 138static int bfin_yuv420_bgr555(SwsContext *c, 139 uint8_t **in, int *instrides, 140 int srcSliceY, int srcSliceH, 141 uint8_t **oplanes, int *outstrides) 142{ 143 return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, 144 outstrides, ff_bfin_yuv2rgb555_line, 0, 555); 145} 146 147static int bfin_yuv420_rgb24(SwsContext *c, 148 uint8_t **in, int *instrides, 149 int srcSliceY, int srcSliceH, 150 uint8_t **oplanes, int *outstrides) 151{ 152 return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, 153 outstrides, ff_bfin_yuv2rgb24_line, 1, 888); 154} 155 156static int bfin_yuv420_bgr24(SwsContext *c, 157 uint8_t **in, int *instrides, 158 int srcSliceY, int srcSliceH, 159 uint8_t **oplanes, int *outstrides) 160{ 161 return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, 162 outstrides, ff_bfin_yuv2rgb24_line, 0, 888); 163} 164 165static int bfin_yuv420_rgb565(SwsContext *c, 166 uint8_t **in, int *instrides, 167 int srcSliceY, int srcSliceH, 168 uint8_t **oplanes, int *outstrides) 169{ 170 return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, 171 outstrides, ff_bfin_yuv2rgb565_line, 1, 565); 172} 173 174static int bfin_yuv420_bgr565(SwsContext *c, 175 uint8_t **in, int *instrides, 176 int srcSliceY, int srcSliceH, 177 uint8_t **oplanes, int *outstrides) 178{ 179 return core_yuv420_rgb(c, in, instrides, srcSliceY, srcSliceH, oplanes, 180 outstrides, ff_bfin_yuv2rgb565_line, 0, 565); 181} 182 183 184SwsFunc ff_yuv2rgb_get_func_ptr_bfin(SwsContext *c) 185{ 186 SwsFunc f; 187 188 switch(c->dstFormat) { 189 case PIX_FMT_RGB555: f = bfin_yuv420_rgb555; break; 190 case PIX_FMT_BGR555: f = bfin_yuv420_bgr555; break; 191 case PIX_FMT_RGB565: f = bfin_yuv420_rgb565; break; 192 case PIX_FMT_BGR565: f = bfin_yuv420_bgr565; break; 193 case PIX_FMT_RGB24: f = bfin_yuv420_rgb24; break; 194 case PIX_FMT_BGR24: f = bfin_yuv420_bgr24; break; 195 default: 196 return 0; 197 } 198 199 av_log(c, AV_LOG_INFO, "BlackFin accelerated color space converter %s\n", 200 sws_format_name (c->dstFormat)); 201 202 return f; 203} 204