diff options
Diffstat (limited to 'mpeglib/lib/util/render')
58 files changed, 9641 insertions, 0 deletions
diff --git a/mpeglib/lib/util/render/Makefile.am b/mpeglib/lib/util/render/Makefile.am new file mode 100644 index 00000000..24bc691f --- /dev/null +++ b/mpeglib/lib/util/render/Makefile.am @@ -0,0 +1,59 @@ +# player - Makefile.am + +SUBDIRS = dither dither2YUV x11 sdl + +INCLUDES = $(all_includes) + +THIS_EXTRALIBS = dither/libdither.la \ + dither2YUV/libdivxutil_dither.la \ + x11/libutilx11.la + + +noinst_LTLIBRARIES = libutilrender.la + +noinst_HEADERS = imageBase.h \ + renderMachine.h surface.h + + +kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/util/render + +kmpginclude_HEADERS = yuvPicture.h pictureArray.h + + +libutilrender_la_SOURCES = yuvPicture.cpp imageBase.cpp \ + renderMachine.cpp surface.cpp \ + pictureArray.cpp + +libutilrender_la_LIBADD = $(THIS_EXTRALIBS) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mpeglib/lib/util/render/dither/Makefile.am b/mpeglib/lib/util/render/dither/Makefile.am new file mode 100644 index 00000000..166d5ca3 --- /dev/null +++ b/mpeglib/lib/util/render/dither/Makefile.am @@ -0,0 +1,40 @@ +# liboutplugin - Makefile.am + +INCLUDES = $(all_includes) + +EXTRA_DIST = ditherDef.h ditherMMX.h \ + ditherer_mmx16.cpp dither32mmx.cpp + +noinst_LTLIBRARIES = libdither.la + +noinst_HEADERS = ditherWrapper.h \ + dither8Bit.h colorTable8Bit.h \ + colorTableHighBit.h dither16Bit.h \ + dither32Bit.h ditherRGB_flipped.h \ + ditherRGB.h + +libdither_la_SOURCES = ditherWrapper.cpp \ + dither8Bit.cpp \ + colorTable8Bit.cpp colorTableHighBit.cpp \ + dither16Bit.cpp dither32Bit.cpp \ + ditherRGB_flipped.cpp ditherRGB.cpp \ + ditherer_mmx16.cpp dither32mmx.cpp + + + + + + + + + + + + + + + + + + + diff --git a/mpeglib/lib/util/render/dither/colorTable8Bit.cpp b/mpeglib/lib/util/render/dither/colorTable8Bit.cpp new file mode 100644 index 00000000..57c533de --- /dev/null +++ b/mpeglib/lib/util/render/dither/colorTable8Bit.cpp @@ -0,0 +1,147 @@ +/* + colorTables for 8 Bit depth + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "colorTable8Bit.h" + + +ColorTable8Bit::ColorTable8Bit() { + + lum_values = new int[LUM_RANGE]; + cr_values = new int[CR_RANGE]; + cb_values = new int[CB_RANGE]; + + + /* We can exploit cache by allocating contiguous blocks */ + + colortab = new TABTYPE[5*256]; + + Cr_r_tab = &colortab[0*256]; + Cr_g_tab = &colortab[1*256]; + Cb_g_tab = &colortab[2*256]; + Cb_b_tab = &colortab[3*256]; + L_tab = &colortab[4*256]; + + init8BitColor(); +} + + +ColorTable8Bit::~ColorTable8Bit() { + delete lum_values; + delete cr_values; + delete cb_values; + delete colortab; +} + + +void ColorTable8Bit::init8BitColor() { + int i; + + + + for (i=0; i<LUM_RANGE; i++) { + lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2)); + L_tab[i] = lum_values[i]; + if (gammaCorrectFlag) { + L_tab[i] = GAMMA_CORRECTION(L_tab[i]); + } + + } + + + for (i=0; i<CR_RANGE; i++) { + register double tmp; + if (chromaCorrectFlag) { + tmp = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2)); + Cr_r_tab[i]=(TABTYPE) ((0.419/0.299)*CHROMA_CORRECTION128D(tmp-128.0)); + Cr_g_tab[i]=(TABTYPE) (-(0.299/0.419)*CHROMA_CORRECTION128D(tmp-128.0)); + cr_values[i] = CHROMA_CORRECTION256(tmp); + } else { + tmp = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2)); + Cr_r_tab[i] = (TABTYPE) ((0.419/0.299) * (tmp - 128.0)); + Cr_g_tab[i] = (TABTYPE) (-(0.299/0.419) * (tmp - 128.0)); + cr_values[i] = (int) tmp; + } + } + + + for (i=0; i<CB_RANGE; i++) { + register double tmp; + if (chromaCorrectFlag) { + tmp = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2)); + Cb_g_tab[i]=(TABTYPE) (-(0.114/0.331)*CHROMA_CORRECTION128D(tmp-128.0)); + Cb_b_tab[i]=(TABTYPE) ((0.587/0.331)*CHROMA_CORRECTION128D(tmp-128.0)); + cb_values[i] = CHROMA_CORRECTION256(tmp); + } else { + tmp = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2)); + Cb_g_tab[i] = (TABTYPE) (-(0.114/0.331) * (tmp - 128.0)); + Cb_b_tab[i] = (TABTYPE) ((0.587/0.331) * (tmp - 128.0)); + cb_values[i] = (int) tmp; + } + } +} + + + +/* + *-------------------------------------------------------------- + * + * ConvertColor -- + * + * Given a l, cr, cb tuple, converts it to r,g,b. + * + * Results: + * r,g,b values returned in pointers passed as parameters. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void ColorTable8Bit::ConvertColor(unsigned int l, unsigned int cr, + unsigned int cb, unsigned char* r, + unsigned char* g, unsigned char* b) { + + double fl, fr, fg, fb; + + /* + * Old method w/o lookup table + * + * fl = 1.164*(((double) l)-16.0); + * fcr = ((double) cr) - 128.0; + * fcb = ((double) cb) - 128.0; + * + * fr = fl + (1.366 * fcr); + * fg = fl - (0.700 * fcr) - (0.334 * fcb); + * fb = fl + (1.732 * fcb); + */ + + fl = L_tab[l]; + + fr = fl + Cr_r_tab[cr]; + fg = fl + Cr_g_tab[cr] + Cb_g_tab[cb]; + fb = fl + Cb_b_tab[cb]; + + if (fr < 0.0) fr = 0.0; + else if (fr > 255.0) fr = 255.0; + + if (fg < 0.0) fg = 0.0; + else if (fg > 255.0) fg = 255.0; + + if (fb < 0.0) fb = 0.0; + else if (fb > 255.0) fb = 255.0; + + *r = (unsigned char) fr; + *g = (unsigned char) fg; + *b = (unsigned char) fb; + +} diff --git a/mpeglib/lib/util/render/dither/colorTable8Bit.h b/mpeglib/lib/util/render/dither/colorTable8Bit.h new file mode 100644 index 00000000..6d873d1d --- /dev/null +++ b/mpeglib/lib/util/render/dither/colorTable8Bit.h @@ -0,0 +1,57 @@ +/* + colorTables for 8 Bit depth + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __COLORTABLE8BIT_H +#define __COLORTABLE8BIT_H + +#include "ditherDef.h" + + +class ColorTable8Bit { + + // Arrays holding quantized value ranged for lum, cr, and cb. + // (used for 8 Bit) + + int* lum_values; + int* cr_values; + int* cb_values; + + + + + TABTYPE *L_tab; + TABTYPE *Cr_r_tab; + TABTYPE *Cr_g_tab; + TABTYPE *Cb_g_tab; + TABTYPE *Cb_b_tab; + TABTYPE *colortab; + + + public: + ColorTable8Bit(); + ~ColorTable8Bit(); + + inline int* getLumValues() { return lum_values; } + inline int* getCrValues() { return cr_values; } + inline int* getCbValues() { return cb_values; } + + void ConvertColor(unsigned int l, unsigned int cr, unsigned int cb, + unsigned char* r, unsigned char* g, unsigned char* b); + + + private: + void init8BitColor(); + + +}; +#endif diff --git a/mpeglib/lib/util/render/dither/colorTableHighBit.cpp b/mpeglib/lib/util/render/dither/colorTableHighBit.cpp new file mode 100644 index 00000000..171f4e97 --- /dev/null +++ b/mpeglib/lib/util/render/dither/colorTableHighBit.cpp @@ -0,0 +1,248 @@ +/* + colorTables for 16,32 Bit depth + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "colorTableHighBit.h" + +//#define INTERPOLATE + + +/* + * Erik Corry's multi-byte dither routines. + * + * The basic idea is that the Init generates all the necessary tables. + * The tables incorporate the information about the layout of pixels + * in the XImage, so that it should be able to cope with 15-bit, 16-bit + * 24-bit (non-packed) and 32-bit (10-11 bits per color!) screens. + * At present it cannot cope with 24-bit packed mode, since this involves + * getting down to byte level again. It is assumed that the bits for each + * color are contiguous in the longword. + * + * Writing to memory is done in shorts or ints. (Unfortunately, short is not + * very fast on Alpha, so there is room for improvement here). There is no + * dither time check for overflow - instead the tables have slack at + * each end. This is likely to be faster than an 'if' test as many modern + * architectures are really bad at ifs. Potentially, each '&&' causes a + * pipeline flush! + * + * There is no shifting and fixed point arithmetic, as I really doubt you + * can see the difference, and it costs. This may be just my bias, since I + * heard that Intel is really bad at shifting. + */ + + +/* + * How many 1 bits are there in the PIXVALword. + * Low performance, do not call often. + */ +static int number_of_bits_set(unsigned PIXVAL a) { + if(!a) return 0; + if(a & 1) return 1 + number_of_bits_set(a >> 1); + return(number_of_bits_set(a >> 1)); +} + + + +/* + * How many 0 bits are there at most significant end of PIXVALword. + * Low performance, do not call often. + */ +static int free_bits_at_top(unsigned PIXVAL a) { + /* assume char is 8 bits */ + if(!a) return sizeof(unsigned PIXVAL) * 8; + /* assume twos complement */ + if(((PIXVAL)a) < 0l) return 0; + return 1 + free_bits_at_top ( a << 1); +} + +/* + * How many 0 bits are there at least significant end of PIXVALword. + * Low performance, do not call often. + */ +static int free_bits_at_bottom(unsigned PIXVAL a) { + /* assume char is 8 bits */ + if(!a) return sizeof(unsigned PIXVAL) * 8; + if(((PIXVAL)a) & 1l) return 0; + return 1 + free_bits_at_bottom ( a >> 1); +} + + + +ColorTableHighBit::ColorTableHighBit(int bpp,unsigned int redMask, + unsigned int greenMask, + unsigned int blueMask) { + this->bpp=bpp; + this->redMask=redMask; + this->greenMask=greenMask; + this->blueMask=blueMask; + + colortab = new TABTYPE[5*256]; + + Cr_r_tab = &colortab[0*256]; + Cr_g_tab = &colortab[1*256]; + Cb_g_tab = &colortab[2*256]; + Cb_b_tab = &colortab[3*256]; + L_tab = &colortab[4*256]; + + rgb_2_pix = new PIXVAL [3*768]; + + r_2_pix_alloc = &rgb_2_pix[0*768]; + g_2_pix_alloc = &rgb_2_pix[1*768]; + b_2_pix_alloc = &rgb_2_pix[2*768]; + + initHighColor(bpp>=24,redMask,greenMask,blueMask); + +} + + +ColorTableHighBit::~ColorTableHighBit() { + delete colortab; + delete rgb_2_pix; +} + +/* + *-------------------------------------------------------------- + * + * InitColor16Dither -- + * + * To get rid of the multiply and other conversions in color + * dither, we use a lookup table. + * + * Results: + * None. + * + * Side effects: + * The lookup tables are initialized. + * + *-------------------------------------------------------------- + */ + +void ColorTableHighBit::initHighColor(int thirty2,unsigned int redMask, + unsigned int greenMask, + unsigned int blueMask) { + + unsigned PIXVAL red_mask = redMask; + unsigned PIXVAL green_mask =greenMask; + unsigned PIXVAL blue_mask = blueMask; + + int CR, CB, i; + + + for (i=0; i<256; i++) { + L_tab[i] = i; + if (gammaCorrectFlag) { + L_tab[i] = (TABTYPE)GAMMA_CORRECTION(i); + } + + CB = CR = i; + + if (chromaCorrectFlag) { + CB -= 128; + CB = CHROMA_CORRECTION128(CB); + CR -= 128; + CR = CHROMA_CORRECTION128(CR); + } else { + CB -= 128; CR -= 128; + } +/* was + Cr_r_tab[i] = 1.596 * CR; + Cr_g_tab[i] = -0.813 * CR; + Cb_g_tab[i] = -0.391 * CB; + Cb_b_tab[i] = 2.018 * CB; + but they were just messed up. + Then was (_Video Deymstified_): + Cr_r_tab[i] = 1.366 * CR; + Cr_g_tab[i] = -0.700 * CR; + Cb_g_tab[i] = -0.334 * CB; + Cb_b_tab[i] = 1.732 * CB; + but really should be: + (from ITU-R BT.470-2 System B, G and SMPTE 170M ) +*/ + Cr_r_tab[i] = (TABTYPE) ( (0.419/0.299) * CR ); + Cr_g_tab[i] = (TABTYPE) ( -(0.299/0.419) * CR ); + Cb_g_tab[i] = (TABTYPE) ( -(0.114/0.331) * CB ); + Cb_b_tab[i] = (TABTYPE) ( (0.587/0.331) * CB ); + +/* + though you could argue for: + SMPTE 240M + Cr_r_tab[i] = (0.445/0.212) * CR; + Cr_g_tab[i] = -(0.212/0.445) * CR; + Cb_g_tab[i] = -(0.087/0.384) * CB; + Cb_b_tab[i] = (0.701/0.384) * CB; + FCC + Cr_r_tab[i] = (0.421/0.30) * CR; + Cr_g_tab[i] = -(0.30/0.421) * CR; + Cb_g_tab[i] = -(0.11/0.331) * CB; + Cb_b_tab[i] = (0.59/0.331) * CB; + ITU-R BT.709 + Cr_r_tab[i] = (0.454/0.2125) * CR; + Cr_g_tab[i] = -(0.2125/0.454) * CR; + Cb_g_tab[i] = -(0.0721/0.386) * CB; + Cb_b_tab[i] = (0.7154/0.386) * CB; +*/ + } + + /* + * Set up entries 0-255 in rgb-to-pixel value tables. + */ + for (i = 0; i < 256; i++) { + r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(red_mask)); + r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(red_mask); + g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(green_mask)); + g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(green_mask); + b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(blue_mask)); + b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(blue_mask); + /* + * If we have 16-bit output depth, then we double the value + * in the top word. This means that we can write out both + * pixels in the pixel doubling mode with one op. It is + * harmless in the normal case as storing a 32-bit value + * through a short pointer will lose the top bits anyway. + * A similar optimisation for Alpha for 64 bit has been + * prepared for, but is not yet implemented. + */ + if(!thirty2) { + r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16; + g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16; + b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16; + + } +#ifdef SIXTYFOUR_BIT + if(thirty2) { + + r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 32; + g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 32; + b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 32; + + } +#endif + } + + /* + * Spread out the values we have to the rest of the array so that + * we do not need to check for overflow. + */ + for (i = 0; i < 256; i++) { + r_2_pix_alloc[i] = r_2_pix_alloc[256]; + r_2_pix_alloc[i+ 512] = r_2_pix_alloc[511]; + g_2_pix_alloc[i] = g_2_pix_alloc[256]; + g_2_pix_alloc[i+ 512] = g_2_pix_alloc[511]; + b_2_pix_alloc[i] = b_2_pix_alloc[256]; + b_2_pix_alloc[i+ 512] = b_2_pix_alloc[511]; + } + + r_2_pix = r_2_pix_alloc + 256; + g_2_pix = g_2_pix_alloc + 256; + b_2_pix = b_2_pix_alloc + 256; +} diff --git a/mpeglib/lib/util/render/dither/colorTableHighBit.h b/mpeglib/lib/util/render/dither/colorTableHighBit.h new file mode 100644 index 00000000..9945414d --- /dev/null +++ b/mpeglib/lib/util/render/dither/colorTableHighBit.h @@ -0,0 +1,73 @@ +/* + colorTables for 16,32 Bit depth + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __COLORTABLEHIGHBIT_H +#define __COLORTABLEHIGHBIT_H + +#include "ditherDef.h" + + + + +class ColorTableHighBit { + + TABTYPE *L_tab; + TABTYPE *Cr_r_tab; + TABTYPE *Cr_g_tab; + TABTYPE *Cb_g_tab; + TABTYPE *Cb_b_tab; + TABTYPE *colortab; + + + PIXVAL *r_2_pix; + PIXVAL *g_2_pix; + PIXVAL *b_2_pix; + PIXVAL *rgb_2_pix; + + PIXVAL *r_2_pix_alloc; + PIXVAL *g_2_pix_alloc; + PIXVAL *b_2_pix_alloc; + + + + // init stuff + int bpp; + // colorMask + unsigned int redMask; + unsigned int greenMask; + unsigned int blueMask; + + public: + ColorTableHighBit(int bpp,unsigned int redMask, + unsigned int greenMask,unsigned int blueMask); + ~ColorTableHighBit(); + + inline TABTYPE* getL_tab() { return L_tab ; } + inline TABTYPE* getCr_r_tab() { return Cr_r_tab ; } + inline TABTYPE* getCr_g_tab() { return Cr_g_tab ; } + inline TABTYPE* getCb_g_tab() { return Cb_g_tab ; } + inline TABTYPE* getCb_b_tab() { return Cb_b_tab ; } + + + inline PIXVAL* getr_2_pix() { return r_2_pix ; } + inline PIXVAL* getg_2_pix() { return g_2_pix ; } + inline PIXVAL* getb_2_pix() { return b_2_pix ; } + + + + private: + void initHighColor(int thirty2,unsigned int redMask, + unsigned int greenMask,unsigned int blueMask); + +}; +#endif diff --git a/mpeglib/lib/util/render/dither/dither16Bit.cpp b/mpeglib/lib/util/render/dither/dither16Bit.cpp new file mode 100644 index 00000000..0a843ee9 --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither16Bit.cpp @@ -0,0 +1,300 @@ +/* + dither 16 bit depth yuv images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "dither16Bit.h" + + +Dither16Bit::Dither16Bit(unsigned int redMask, + unsigned int greenMask,unsigned int blueMask) { + + + colorTableHighBit=new ColorTableHighBit(16,redMask,greenMask,blueMask); + L_tab=colorTableHighBit->getL_tab(); + Cr_r_tab=colorTableHighBit->getCr_r_tab(); + Cr_g_tab=colorTableHighBit->getCr_g_tab(); + Cb_g_tab=colorTableHighBit->getCb_g_tab(); + Cb_b_tab=colorTableHighBit->getCb_b_tab(); + + r_2_pix=colorTableHighBit->getr_2_pix(); + g_2_pix=colorTableHighBit->getg_2_pix(); + b_2_pix=colorTableHighBit->getb_2_pix(); + +} + + +Dither16Bit::~Dither16Bit() { + delete colorTableHighBit; +} + + +/* + *-------------------------------------------------------------- + * + * Color16DitherImage -- + * + * Converts image into 16 bit color. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void Dither16Bit::ditherImageColor16(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int offset) { + + int L, CR, CB; + unsigned short *row1, *row2; + unsigned char *lum2; + int x, y; + int cr_r; + int cr_g; + int cb_g; + int cb_b; + int cols_2 = cols/2; + + row1 = (unsigned short *)out; + row2=row1+cols_2+cols_2+offset; // start of second row + + offset=2*offset+cols_2+cols_2; + + lum2 = lum + cols_2 + cols_2; + + + for (y=0; y<rows; y+=2) { + for (x=0; x<cols_2; x++) { + int R, G, B; + + CR = *cr++; + CB = *cb++; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + + L = L_tab[(int) *lum++]; + + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + *row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + + +#ifdef INTERPOLATE + if(x != cols_2 - 1) { + CR = (CR + *cr) >> 1; + CB = (CB + *cb) >> 1; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + } +#endif + + L = L_tab[(int) *lum++]; + + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + *row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + + /* + * Now, do second row. + */ +#ifdef INTERPOLATE + if(y != rows - 2) { + CR = (CR + *(cr + cols_2 - 1)) >> 1; + CB = (CB + *(cb + cols_2 - 1)) >> 1; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + } +#endif + + L = L_tab[(int) *lum2++]; + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + *row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + + L = L_tab[(int) *lum2++]; + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + *row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + } + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols_2 + cols_2; + lum2 += cols_2 + cols_2; + row1 += offset; + row2 += offset; + } +} + + +/* + * Erik Corry's pixel doubling routines for 15/16/24/32 bit screens. + */ + + +/* + *-------------------------------------------------------------- + * + * Twox2Color16DitherImage -- + * + * Converts image into 16 bit color at double size. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +/* + * In this function I make use of a nasty trick. The tables have the lower + * 16 bits replicated in the upper 16. This means I can write ints and get + * the horisontal doubling for free (almost). + */ + +void Dither16Bit::ditherImageTwox2Color16(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod) { + int L, CR, CB; + unsigned int *row1 = (unsigned int *)out; + unsigned int *row2 = row1 + cols + mod/2; + unsigned int *row3 = row2 + cols + mod/2; + unsigned int *row4 = row3 + cols + mod/2; + unsigned char *lum2; + int x, y; + int cr_r; + int cr_g; + int cb_g; + int cb_b; + int cols_2 = cols/2; + + lum2 = lum + cols_2 + cols_2; + for (y=0; y<rows; y+=2) { + for (x=0; x<cols_2; x++) { + int R, G, B; + int t; + + CR = *cr++; + CB = *cb++; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + + L = L_tab[(int) *lum++]; + + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row1[0] = t; + row1++; + row2[0] = t; + row2++; + + // INTERPOLATE + if(x != cols_2 - 1) { + CR = (CR + *cr) >> 1; + CB = (CB + *cb) >> 1; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + } + // end + + L = L_tab[(int) *lum++]; + + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row1[0] = t; + row1++; + row2[0] = t; + row2++; + + /* + * Now, do second row. + */ + // INTERPOLATE + if(y != rows - 2) { + CR = (CR + *(cr + cols_2 - 1)) >> 1; + CB = (CB + *(cb + cols_2 - 1)) >> 1; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + } + // end + + L = L_tab[(int) *lum2++]; + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row3[0] = t; + row3++; + row4[0] = t; + row4++; + + L = L_tab[(int) *lum2++]; + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row3[0] = t; + row3++; + row4[0] = t; + row4++; + } + lum += cols_2 + cols_2; + lum2 += cols_2 + cols_2; + row1 += 6 * cols_2 + 2*mod; + row3 += 6 * cols_2 + 2*mod; + row2 += 6 * cols_2 + 2*mod; + row4 += 6 * cols_2 + 2*mod; + } +} diff --git a/mpeglib/lib/util/render/dither/dither16Bit.h b/mpeglib/lib/util/render/dither/dither16Bit.h new file mode 100644 index 00000000..2e47c01c --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither16Bit.h @@ -0,0 +1,55 @@ +/* + dither 16 bit depth yuv images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#ifndef __DITHER16Bit_H +#define __DITHER16Bit_H + +#include "colorTableHighBit.h" + +class Dither16Bit { + + ColorTableHighBit* colorTableHighBit; + + TABTYPE *L_tab; + TABTYPE *Cr_r_tab; + TABTYPE *Cr_g_tab; + TABTYPE *Cb_g_tab; + TABTYPE *Cb_b_tab; + + PIXVAL *r_2_pix; + PIXVAL *g_2_pix; + PIXVAL *b_2_pix; + + public: + Dither16Bit(unsigned int redMask, + unsigned int greenMask,unsigned int blueMask); + ~Dither16Bit(); + + void ditherImageColor16(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int offset); + + void ditherImageTwox2Color16(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod); + +}; + +#endif diff --git a/mpeglib/lib/util/render/dither/dither32Bit.cpp b/mpeglib/lib/util/render/dither/dither32Bit.cpp new file mode 100644 index 00000000..61a1d2dc --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither32Bit.cpp @@ -0,0 +1,253 @@ +/* + dither 32 bit depth yuv images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "dither32Bit.h" + + +#define doRow(row,Lum) *row++=(local_r_2_pix[Lum] | \ + local_g_2_pix[Lum] | local_b_2_pix[Lum]) + + +Dither32Bit::Dither32Bit(unsigned int redMask, + unsigned int greenMask,unsigned int blueMask) { + + + colorTableHighBit=new ColorTableHighBit(32,redMask,greenMask,blueMask); + L_tab=colorTableHighBit->getL_tab(); + Cr_r_tab=colorTableHighBit->getCr_r_tab(); + Cr_g_tab=colorTableHighBit->getCr_g_tab(); + Cb_g_tab=colorTableHighBit->getCb_g_tab(); + Cb_b_tab=colorTableHighBit->getCb_b_tab(); + + r_2_pix=colorTableHighBit->getr_2_pix(); + g_2_pix=colorTableHighBit->getg_2_pix(); + b_2_pix=colorTableHighBit->getb_2_pix(); + +} + + +Dither32Bit::~Dither32Bit() { + delete colorTableHighBit; +} + + +void Dither32Bit::ditherImageColor32(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod) { + + int L; + int n; + int rowWork; + int colWork; + + unsigned int *row1, *row2; + unsigned char *lum2; + PIXVAL* local_r_2_pix; + PIXVAL* local_g_2_pix; + PIXVAL* local_b_2_pix; + + row1 = (unsigned int *)out; + + row2 = row1+cols+mod; + lum2 = lum+cols; + + // because the width/height are a multiply of a macroblocksize + // cols/rows always are even + colWork=cols>>1; + rowWork=rows>>1; + mod=cols+2*mod; + + while(rowWork--) { + n=colWork; + while(n--) { + + local_r_2_pix=r_2_pix+Cr_r_tab[*cr]; + local_g_2_pix=g_2_pix+Cr_g_tab[*cr++] + Cb_g_tab[*cb]; + local_b_2_pix=b_2_pix+Cb_b_tab[*cb++]; + + L = L_tab[*lum++]; + doRow(row1,L); + + L = L_tab[*lum++]; + doRow(row1,L); + + L = L_tab [*lum2++]; + doRow(row2,L); + + L = L_tab [*lum2++]; + doRow(row2,L); + + + } + row2 += mod; + lum += cols; + lum2 += cols; + row1 += mod; + + } + +} + +/* + *-------------------------------------------------------------- + * + * Twox2Color32 -- + * + * Converts image into 24/32 bit color. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void Dither32Bit::ditherImageTwox2Color32(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod) { + int L, CR, CB; + unsigned PIXVAL *row1 = (unsigned PIXVAL *)out; + unsigned PIXVAL *row2 = row1 + cols * ONE_TWO + mod; + unsigned PIXVAL *row3 = row2 + cols * ONE_TWO + mod; + unsigned PIXVAL *row4 = row3 + cols * ONE_TWO + mod; + unsigned char *lum2; + int x, y; + int cr_r; + int cr_g; + int cb_g; + int cb_b; + int cols_2 = cols/2; + int loffset = ONE_TWO * 6 *cols_2 + 4*mod ; + + lum2 = lum + cols_2 + cols_2; + for (y=0; y<rows; y+=2) { + for (x=0; x<cols_2; x++) { + int R, G, B; + PIXVAL t; + + CR = *cr++; + CB = *cb++; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + + L = L_tab[ (int) *lum++]; + + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row1[0] = t; + row2[0] = t; +#ifndef SIXTYFOUR_BIT + row1[1] = t; + row2[1] = t; +#endif + row1 += ONE_TWO; + row2 += ONE_TWO; + + /* INTERPOLATE is now standard */ + // INTERPOLATE + if(x != cols_2 - 1) { + CR = (CR + *cr) >> 1; + CB = (CB + *cb) >> 1; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + } + // end + /* end INTERPOLATE */ + + L = L_tab[ (int) *lum++]; + + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row1[0] = t; + row2[0] = t; +#ifndef SIXTYFOUR_BIT + row1[1] = t; + row2[1] = t; +#endif + row1 += ONE_TWO; + row2 += ONE_TWO; + + /* + * Now, do second row. + */ + /* INTERPOLATE is now standard */ + // INTERPOLATE + if(y != rows - 2) { + CR = (unsigned int) (CR + *(cr + cols_2 - 1)) >> 1; + CB = (unsigned int) (CB + *(cb + cols_2 - 1)) >> 1; + cr_r = Cr_r_tab[CR]; + cr_g = Cr_g_tab[CR]; + cb_g = Cb_g_tab[CB]; + cb_b = Cb_b_tab[CB]; + } + // end + /* endif */ + L = L_tab[ (int) *lum2++]; + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row3[0] = t; + row4[0] = t; +#ifndef SIXTYFOUR_BIT + row3[1] = t; + row4[1] = t; +#endif + row3 += ONE_TWO; + row4 += ONE_TWO; + + L = L_tab[(int) *lum2++]; + R = L + cr_r; + G = L + cr_g + cb_g; + B = L + cb_b; + + t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]); + row3[0] = t; + row4[0] = t; +#ifndef SIXTYFOUR_BIT + row3[1] = t; + row4[1] = t; +#endif + row3 += ONE_TWO; + row4 += ONE_TWO; + } + lum += cols_2 + cols_2; + lum2 += cols_2 + cols_2; + + row1 += loffset; + row3 += loffset; + row2 += loffset; + row4 += loffset; + } +} diff --git a/mpeglib/lib/util/render/dither/dither32Bit.h b/mpeglib/lib/util/render/dither/dither32Bit.h new file mode 100644 index 00000000..440d021a --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither32Bit.h @@ -0,0 +1,55 @@ +/* + dither 32 bit depth yuv images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#ifndef __DITHER32Bit_H +#define __DITHER32Bit_H + +#include "colorTableHighBit.h" + +class Dither32Bit { + + ColorTableHighBit* colorTableHighBit; + + TABTYPE *L_tab; + TABTYPE *Cr_r_tab; + TABTYPE *Cr_g_tab; + TABTYPE *Cb_g_tab; + TABTYPE *Cb_b_tab; + + PIXVAL *r_2_pix; + PIXVAL *g_2_pix; + PIXVAL *b_2_pix; + + public: + Dither32Bit(unsigned int redMask, + unsigned int greenMask,unsigned int blueMask); + ~Dither32Bit(); + + void ditherImageColor32(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int offset); + + void ditherImageTwox2Color32(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod); + +}; + +#endif diff --git a/mpeglib/lib/util/render/dither/dither32mmx.cpp b/mpeglib/lib/util/render/dither/dither32mmx.cpp new file mode 100644 index 00000000..b5fa4807 --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither32mmx.cpp @@ -0,0 +1,272 @@ +/* + MMX ditherer for 32 bit displays + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "ditherMMX.h" + +#include <iostream> + +using namespace std; + + +#ifndef INTEL + void dither32_mmx(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod) { + printf("urgs! dither32_mmx \n"); + printf("never should happen!\n"); + exit(0); +} + +#else + + +static unsigned long MMX32_80w[] = {0x00800080, 0x00800080}; +static unsigned long MMX32_10w[] = {0x00100010, 0x00100010}; +static unsigned long MMX32_00FFw[] = {0x00ff00ff, 0x00ff00ff}; +static unsigned long MMX32_FF00w[] = {0xff00ff00, 0xff00ff00}; +static unsigned short MMX32_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a}; +static unsigned short MMX32_Vredcoeff[] = {0x59, 0x59, 0x59, 0x59}; +static unsigned short MMX32_Ubluecoeff[] = {0x72, 0x72, 0x72, 0x72}; +static unsigned short MMX32_Ugrncoeff[] = {0xffea,0xffea,0xffea,0xffea}; +static unsigned short MMX32_Vgrncoeff[] = {0xffd2,0xffd2,0xffd2,0xffd2}; + +void dummy_dithermmx32() { + cout << "MMX32_10w:"<<MMX32_10w<<endl; + cout << "MMX32_80w:"<<MMX32_80w<<endl; + cout << "MMX32_Ubluecoeff:"<<MMX32_Ubluecoeff<<endl; + cout << "MMX32_Vredcoeff:"<<MMX32_Vredcoeff<<endl; + cout << "MMX32_Ugrncoeff:"<<MMX32_Ugrncoeff<<endl; + cout << "MMX32_Vgrncoeff:"<<MMX32_Vgrncoeff<<endl; + cout << "MMX32_Ycoeff:"<<MMX32_Ycoeff<<endl; + cout << "MMX32_00FFw:"<<MMX32_00FFw<<endl; + cout << "MMX32_FF00w:"<<MMX32_FF00w<<endl; +} + + +/** + This MMX assembler is my first assembler/MMX program ever. + Thus it maybe buggy. + Send patches to: + mvogt@rhrk.uni-kl.de + + After it worked fine I have "obfuscated" the code a bit to have + more parallism in the MMX units. This means I moved + initilisation around and delayed other instruction. + Performance measurement did not show that this brought any advantage + but in theory it _should_ be faster this way. + + The overall performanve gain to the C based dither was 30%-40%. + The MMX routine calculates 256bit=8RGB values in each cycle + (4 for row1 & 4 for row2) + + The red/green/blue.. coefficents are taken from the mpeg_play + player. They look nice, but I dont know if you can have + better values, to avoid integer rounding errors. + + + IMPORTANT: + ========== + + It is a requirement that the cr/cb/lum are 8 byte aligned and + the out are 16byte aligned or you will/may get segfaults + +*/ + +void dither32_mmx(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod) { + + + + unsigned int *row1; + unsigned int *row2; + row1 = (unsigned int *)out; // 32 bit target + + unsigned char* end = lum +cols*rows; // Pointer to the end + int x=cols; + row2=row1+cols+mod; // start of second row + mod=4*cols+8*mod; // increment for row1 in byte + + // buffer for asm function + int buf[6]; + buf[0]=(int)(lum+cols); // lum2 pointer + buf[1]=(int)end; + buf[2]=x; + buf[3]=mod; + buf[4]=0; //tmp0; + buf[5]=cols; + + + __asm__ __volatile__ ( + ".align 32\n" + "1:\n" + + // create Cr (result in mm1) + "movd (%0), %%mm1\n" // 0 0 0 0 v3 v2 v1 v0 + "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00 + "movd (%2), %%mm2\n" // 0 0 0 0 l3 l2 l1 l0 + "punpcklbw %%mm7,%%mm1\n" // 0 v3 0 v2 00 v1 00 v0 + "punpckldq %%mm1,%%mm1\n" // 00 v1 00 v0 00 v1 00 v0 + "psubw MMX32_80w,%%mm1\n" // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0 + + // create Cr_g (result in mm0) + "movq %%mm1,%%mm0\n" // r1 r1 r0 r0 r1 r1 r0 r0 + "pmullw MMX32_Vgrncoeff,%%mm0\n" // red*-46dec=0.7136*64 + "pmullw MMX32_Vredcoeff,%%mm1\n" // red*89dec=1.4013*64 + "psraw $6, %%mm0\n" // red=red/64 + "psraw $6, %%mm1\n" // red=red/64 + + + // create L1 L2 (result in mm2,mm4) + // L2=lum2 + "movl %2,16%5\n" // store register in tmp0 + "movl %5,%2\n" // lum2->register + "movd (%2),%%mm3\n" // 0 0 0 0 L3 L2 L1 L0 + "movl 16%5,%2\n" // tmp0->register + "punpckldq %%mm3,%%mm2\n" // L3 L2 L1 L0 l3 l2 l1 l0 + "movq %%mm2,%%mm4\n" // L3 L2 L1 L0 l3 l2 l1 l0 + "pand MMX32_FF00w, %%mm2\n" // L3 0 L1 0 l3 0 l1 0 + "pand MMX32_00FFw, %%mm4\n" // 0 L2 0 L0 0 l2 0 l0 + "psrlw $8,%%mm2\n" // 0 L3 0 L1 0 l3 0 l1 + + + + // create R (result in mm6) + "movq %%mm2,%%mm5\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm6\n" // 0 L2 0 L0 0 l2 0 l0 + "paddsw %%mm1, %%mm5\n" // lum1+red:x R3 x R1 x r3 x r1 + "paddsw %%mm1, %%mm6\n" // lum1+red:x R2 x R0 x r2 x r0 + "packuswb %%mm5,%%mm5\n" // R3 R1 r3 r1 R3 R1 r3 r1 + "packuswb %%mm6,%%mm6\n" // R2 R0 r2 r0 R2 R0 r2 r0 + "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00 + "punpcklbw %%mm5,%%mm6\n" // R3 R2 R1 R0 r3 r2 r1 r0 + + + // create Cb (result in mm1) + "movd (%1), %%mm1\n" // 0 0 0 0 u3 u2 u1 u0 + "punpcklbw %%mm7,%%mm1\n" // 0 u3 0 u2 00 u1 00 u0 + "punpckldq %%mm1,%%mm1\n" // 00 u1 00 u0 00 u1 00 u0 + "psubw MMX32_80w,%%mm1\n" // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0 + // create Cb_g (result in mm5) + "movq %%mm1,%%mm5\n" // u1 u1 u0 u0 u1 u1 u0 u0 + "pmullw MMX32_Ugrncoeff,%%mm5\n" // blue*-109dec=1.7129*64 + "pmullw MMX32_Ubluecoeff,%%mm1\n" // blue*114dec=1.78125*64 + "psraw $6, %%mm5\n" // blue=red/64 + "psraw $6, %%mm1\n" // blue=blue/64 + + + // create G (result in mm7) + "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm7\n" // 0 L2 0 L0 0 l2 0 l1 + "paddsw %%mm5, %%mm3\n" // lum1+Cb_g:x G3t x G1t x g3t x g1t + "paddsw %%mm5, %%mm7\n" // lum1+Cb_g:x G2t x G0t x g2t x g0t + "paddsw %%mm0, %%mm3\n" // lum1+Cr_g:x G3 x G1 x g3 x g1 + "paddsw %%mm0, %%mm7\n" // lum1+blue:x G2 x G0 x g2 x g0 + "packuswb %%mm3,%%mm3\n" // G3 G1 g3 g1 G3 G1 g3 g1 + "packuswb %%mm7,%%mm7\n" // G2 G0 g2 g0 G2 G0 g2 g0 + "punpcklbw %%mm3,%%mm7\n" // G3 G2 G1 G0 g3 g2 g1 g0 + + + // create B (result in mm5) + "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm5\n" // 0 L2 0 L0 0 l2 0 l1 + "paddsw %%mm1, %%mm3\n" // lum1+blue:x B3 x B1 x b3 x b1 + "paddsw %%mm1, %%mm5\n" // lum1+blue:x B2 x B0 x b2 x b0 + "packuswb %%mm3,%%mm3\n" // B3 B1 b3 b1 B3 B1 b3 b1 + "packuswb %%mm5,%%mm5\n" // B2 B0 b2 b0 B2 B0 b2 b0 + "punpcklbw %%mm3,%%mm5\n" // B3 B2 B1 B0 b3 b2 b1 b0 + + + // fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb) + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "pxor %%mm4,%%mm4\n" // 0 0 0 0 0 0 0 0 + "movq %%mm6,%%mm1\n" // R3 R2 R1 R0 r3 r2 r1 r0 + "movq %%mm5,%%mm3\n" // B3 B2 B1 B0 b3 b2 b1 b0 + // process lower lum + "punpcklbw %%mm4,%%mm1\n" // 0 r3 0 r2 0 r1 0 r0 + "punpcklbw %%mm4,%%mm3\n" // 0 b3 0 b2 0 b1 0 b0 + "movq %%mm1,%%mm2\n" // 0 r3 0 r2 0 r1 0 r0 + "movq %%mm3,%%mm0\n" // 0 b3 0 b2 0 b1 0 b0 + "punpcklwd %%mm1,%%mm3\n" // 0 r1 0 b1 0 r0 0 b0 + "punpckhwd %%mm2,%%mm0\n" // 0 r3 0 b3 0 r2 0 b2 + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "movq %%mm7,%%mm1\n" // G3 G2 G1 G0 g3 g2 g1 g0 + "punpcklbw %%mm1,%%mm2\n" // g3 0 g2 0 g1 0 g0 0 + "punpcklwd %%mm4,%%mm2\n" // 0 0 g1 0 0 0 g0 0 + "por %%mm3, %%mm2\n" // 0 r1 g1 b1 0 r0 g0 b0 + "movq %%mm2,(%3)\n" // wrote out ! row1 + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "punpcklbw %%mm1,%%mm4\n" // g3 0 g2 0 g1 0 g0 0 + "punpckhwd %%mm2,%%mm4\n" // 0 0 g3 0 0 0 g2 0 + "por %%mm0, %%mm4\n" // 0 r3 g3 b3 0 r2 g2 b2 + "movq %%mm4,8(%3)\n" // wrote out ! row1 + + // fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb) + // this can be done "destructive" + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "punpckhbw %%mm2,%%mm6\n" // 0 R3 0 R2 0 R1 0 R0 + "punpckhbw %%mm1,%%mm5\n" // G3 B3 G2 B2 G1 B1 G0 B0 + "movq %%mm5,%%mm1\n" // G3 B3 G2 B2 G1 B1 G0 B0 + "punpcklwd %%mm6,%%mm1\n" // 0 R1 G1 B1 0 R0 G0 B0 + "movq %%mm1,(%4)\n" // wrote out ! row2 + "punpckhwd %%mm6,%%mm5\n" // 0 R3 G3 B3 0 R2 G2 B2 + "movq %%mm5,8(%4)\n" // wrote out ! row2 + + "addl $4,%2\n" // lum+4 + "addl $4,%5\n" // lum2+4 + "leal 16(%3),%3\n" // row1+16 + "leal 16(%4),%4\n" // row2+16 + "addl $2, %0\n" // cr+2 + "addl $2, %1\n" // cb+2 + + "subl $4,8%5\n" // x+4 x is buf[2] + "cmpl $0,8%5\n" + + "jne 1b\n" + "addl 20%5, %2\n" // lum += cols + "movl %2,16%5\n" // store register in tmp0 + "movl 20%5,%2\n" // cols->register + + "addl %2, %5\n" // lum2 += cols + "addl 12%5, %3\n" // row1+= mod is buf[0] + "addl 12%5, %4\n" // row2+= mod is buf[0] + + "movl %2, 8%5\n" // x=cols + "movl 16%5,%2\n" // store tmp0 in register + + "cmpl 4%5, %2\n" // buf[1] is end + "jl 1b\n" + "emms\n" + : + : "r" (cr), "r"(cb),"r"(lum), + "r"(row1),"r"(row2),"m"(buf[0]) + ); + + + +} + + +#endif diff --git a/mpeglib/lib/util/render/dither/dither8Bit.cpp b/mpeglib/lib/util/render/dither/dither8Bit.cpp new file mode 100644 index 00000000..4f85d3fb --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither8Bit.cpp @@ -0,0 +1,306 @@ +/* + dither 8 bit depth yuv images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "dither8Bit.h" + + +Dither8Bit::Dither8Bit(unsigned char pixel[256]) { + + int i; + for(i=0;i<256;i++) { + this->pixel[i]=pixel[i]; + } + colorTable8Bit=new ColorTable8Bit(); + + lum_values = colorTable8Bit->getLumValues(); + cr_values = colorTable8Bit->getCrValues(); + cb_values = colorTable8Bit->getCbValues(); + + + + initOrderedDither(); + +} + + +Dither8Bit::~Dither8Bit() { + int i; + for (i=0; i<DITH_SIZE; i++) { + delete cb_darrays[i]; + delete l_darrays[i]; + delete cr_darrays[i]; + } +} + + + + + +/* + *-------------------------------------------------------------- + * + * InitOrderedDither-- + * + * Structures initialized for ordered dithering. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void Dither8Bit::initOrderedDither() { + int i, j, k, err_range, threshval; + unsigned char *lmark, *cmark; + + for (i=0; i<DITH_SIZE; i++) { + lmark = l_darrays[i] = new unsigned char[256]; + for (j=0; j<lum_values[0]; j++) { + *lmark++ = 0; + } + for (j=0; j<(LUM_RANGE-1); j++) { + err_range = lum_values[j+1] - lum_values[j]; + threshval = ((i * err_range) / DITH_SIZE)+lum_values[j]; + + for (k=lum_values[j]; k<lum_values[j+1]; k++) { + if (k > threshval) { + *lmark++ = ((j+1) * (CR_RANGE * CB_RANGE)); + } + else { + *lmark++ = (j * (CR_RANGE * CB_RANGE)); + } + } + } + for (j=lum_values[LUM_RANGE-1]; j<256; j++) { + *lmark++ = (LUM_RANGE-1)*(CR_RANGE * CB_RANGE); + } + } + for (i=0; i<DITH_SIZE; i++) { + cmark = cr_darrays[i] = new unsigned char[256]; + + for (j=0; j<cr_values[0]; j++) { + *cmark++ = 0; + } + + for (j=0; j<(CR_RANGE-1); j++) { + err_range = cr_values[j+1] - cr_values[j]; + threshval = ((i * err_range) / DITH_SIZE)+cr_values[j]; + + for (k=cr_values[j]; k<cr_values[j+1]; k++) { + if (k > threshval) { + *cmark++ = ((j+1) * CB_RANGE); + } + else { + *cmark++ = (j * CB_RANGE); + } + } + } + + for (j=cr_values[CR_RANGE-1]; j<256; j++) { + *cmark++ = (CR_RANGE-1)*(CB_RANGE); + } + } + + for (i=0; i<DITH_SIZE; i++) { + cmark = cb_darrays[i] = new unsigned char[256]; + + for (j=0; j<cb_values[0]; j++) { + *cmark++ = 0; + } + + for (j=0; j<(CB_RANGE-1); j++) { + err_range = cb_values[j+1] - cb_values[j]; + threshval = ((i * err_range) / DITH_SIZE)+cb_values[j]; + + for (k=cb_values[j]; k<cb_values[j+1]; k++) { + if (k > threshval) { + *cmark++ = j+1; + } + else { + *cmark++ = j; + } + } + } + + for (j=cb_values[CB_RANGE-1]; j<256; j++) { + *cmark++ = CB_RANGE-1; + } + } +} + + + +/* + *-------------------------------------------------------------- + * + * OrderedDitherImage -- + * + * Dithers an image using an ordered dither. + * Assumptions made: + * 1) The color space is allocated y:cr:cb = 8:4:4 + * 2) The spatial resolution of y:cr:cb is 4:1:1 + * The channels are dithered based on the standard + * ordered dither pattern for a 4x4 area. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void Dither8Bit::ditherImageOrdered (unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int h, + int w) { + unsigned char *l, *r, *b, *o1, *o2; + unsigned char *l2; + unsigned char L, R, B; + int i, j; + + l = lum; + l2 = lum+w; + r = cr; + b = cb; + o1 = out; + o2 = out+w; + + + for (i=0; i<h; i+=4) { + + for (j=0; j<w; j+=8) { + + R = r[0]; B = b[0]; + + L = l[0]; + o1[0] = pixel[(l_darrays[0][L] + cr_darrays[0][R] + cb_darrays[0][B])]; + L = l[1]; + o1[1] = pixel[(l_darrays[8][L] + cr_darrays[8][R] + cb_darrays[8][B])]; + L = l2[0]; + o2[0] = pixel[(l_darrays[12][L] + cr_darrays[12][R] + cb_darrays[12][B])]; + L = l2[1]; + o2[1] = pixel[(l_darrays[4][L] + cr_darrays[4][R] + cb_darrays[4][B])]; + + R = r[1]; B = b[1]; + + L = l[2]; + o1[2] = pixel[(l_darrays[2][L] + cr_darrays[2][R] + cb_darrays[2][B])]; + L = l[3]; + o1[3] = pixel[(l_darrays[10][L] + cr_darrays[10][R] + cb_darrays[10][B])]; + L = l2[2]; + o2[2] = pixel[(l_darrays[14][L] + cr_darrays[14][R] + cb_darrays[14][B])]; + L = l2[3]; + o2[3] = pixel[(l_darrays[6][L] + cr_darrays[6][R] + cb_darrays[6][B])]; + + R = r[2]; B = b[2]; + + L = l[4]; + o1[4] = pixel[(l_darrays[0][L] + cr_darrays[0][R] + cb_darrays[0][B])]; + L = l[5]; + o1[5] = pixel[(l_darrays[8][L] + cr_darrays[8][R] + cb_darrays[8][B])]; + L = l2[4]; + o2[4] = pixel[(l_darrays[12][L] + cr_darrays[12][R] + cb_darrays[12][B])]; + L = l2[5]; + o2[5] = pixel[(l_darrays[4][L] + cr_darrays[4][R] + cb_darrays[4][B])]; + + R = r[3]; B = b[3]; + + L = l[6]; + o1[6] = pixel[(l_darrays[2][L] + cr_darrays[2][R] + cb_darrays[2][B])]; + L = l[7]; + o1[7] = pixel[(l_darrays[10][L] + cr_darrays[10][R] + cb_darrays[10][B])]; + L = l2[6]; + o2[6] = pixel[(l_darrays[14][L] + cr_darrays[14][R] + cb_darrays[14][B])]; + L = l2[7]; + o2[7] = pixel[(l_darrays[6][L] + cr_darrays[6][R] + cb_darrays[6][B])]; + + l += 8; + l2 += 8; + r += 4; + b += 4; + o1 += 8; + o2 += 8; + } + + l += w; + l2 += w; + o1 += w; + o2 += w; + + for (j=0; j<w; j+=8) { + + R = r[0]; B = b[0]; + + L = l[0]; + o1[0] = pixel[(l_darrays[3][L] + cr_darrays[3][R] + cb_darrays[3][B])]; + L = l[1]; + o1[1] = pixel[(l_darrays[11][L] + cr_darrays[11][R] + cb_darrays[11][B])]; + L = l2[0]; + o2[0] = pixel[(l_darrays[15][L] + cr_darrays[15][R] + cb_darrays[15][B])]; + L = l2[1]; + o2[1] = pixel[(l_darrays[7][L] + cr_darrays[7][R] + cb_darrays[7][B])]; + + R = r[1]; B = b[1]; + + L = l[2]; + o1[2] = pixel[(l_darrays[1][L] + cr_darrays[1][R] + cb_darrays[1][B])]; + L = l[3]; + o1[3] = pixel[(l_darrays[9][L] + cr_darrays[9][R] + cb_darrays[9][B])]; + L = l2[2]; + o2[2] = pixel[(l_darrays[13][L] + cr_darrays[13][R] + cb_darrays[13][B])]; + L = l2[3]; + o2[3] = pixel[(l_darrays[5][L] + cr_darrays[5][R] + cb_darrays[5][B])]; + + R = r[2]; B = b[2]; + + L = l[4]; + o1[4] = pixel[(l_darrays[3][L] + cr_darrays[3][R] + cb_darrays[3][B])]; + L = l[5]; + o1[5] = pixel[(l_darrays[11][L] + cr_darrays[11][R] + cb_darrays[11][B])]; + L = l2[4]; + o2[4] = pixel[(l_darrays[15][L] + cr_darrays[15][R] + cb_darrays[15][B])]; + L = l2[5]; + o2[5] = pixel[(l_darrays[7][L] + cr_darrays[7][R] + cb_darrays[7][B])]; + + R = r[3]; B = b[3]; + + L = l[6]; + o1[6] = pixel[(l_darrays[1][L] + cr_darrays[1][R] + cb_darrays[1][B])]; + L = l[7]; + o1[7] = pixel[(l_darrays[9][L] + cr_darrays[9][R] + cb_darrays[9][B])]; + L = l2[6]; + o2[6] = pixel[(l_darrays[13][L] + cr_darrays[13][R] + cb_darrays[13][B])]; + L = l2[7]; + o2[7] = pixel[(l_darrays[5][L] + cr_darrays[5][R] + cb_darrays[5][B])]; + + l += 8; + l2 += 8; + r += 4; + b += 4; + o1 += 8; + o2 += 8; + } + + l += w; + l2 += w; + o1 += w; + o2 += w; + } +} + diff --git a/mpeglib/lib/util/render/dither/dither8Bit.h b/mpeglib/lib/util/render/dither/dither8Bit.h new file mode 100644 index 00000000..7bdd4d8f --- /dev/null +++ b/mpeglib/lib/util/render/dither/dither8Bit.h @@ -0,0 +1,63 @@ +/* + dither 8 bit depth yuv images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __DITHER_8BIT_H +#define __DITHER_8BIT_H + + +#include "colorTable8Bit.h" + +#define DITH_SIZE 16 + + +class Dither8Bit { + + /* Structures used to implement hybrid ordered dither/floyd-steinberg + dither algorithm. + */ + + unsigned char *l_darrays[DITH_SIZE]; + unsigned char *cr_darrays[DITH_SIZE]; + unsigned char *cb_darrays[DITH_SIZE]; + + // private colormap + unsigned char pixel[256]; + + ColorTable8Bit* colorTable8Bit; + + // Arrays holding quantized value ranged for lum, cr, and cb. + // (used for 8 Bit) + + int* lum_values; + int* cr_values; + int* cb_values; + + + public: + Dither8Bit(unsigned char pixel[256]); + ~Dither8Bit(); + + void ditherImageOrdered (unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int h, + int w); + + private: + void initOrderedDither(); +}; + +#endif + diff --git a/mpeglib/lib/util/render/dither/ditherDef.h b/mpeglib/lib/util/render/dither/ditherDef.h new file mode 100644 index 00000000..2e8d7d0e --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherDef.h @@ -0,0 +1,100 @@ +/* + global definitions for dithering + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __DITHERDEF_H +#define __DITHERDEF_H + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +extern "C" { +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +} + + +#ifdef __GNUC__ +#if (__GNUC__ < 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ < 91 ) ) +#ifndef _AIX +#warning "inline code disabled! (buggy egcs version)" +#undef __NO_MATH_INLINES +#define __NO_MATH_INLINES 1 +#endif +#endif +#endif +#include <math.h> + + + +/* Gamma correction stuff */ +extern int gammaCorrectFlag; +extern double gammaCorrect; + +/* Chroma correction stuff */ +extern int chromaCorrectFlag; +extern double chromaCorrect; + + +#define CB_BASE 1 +#define CR_BASE (CB_BASE*CB_RANGE) +#define LUM_BASE (CR_BASE*CR_RANGE) + +#define TABTYPE short + +#ifdef SIXTYFOUR_BIT +#define PIXVAL long +#else +#define PIXVAL int +#endif + +#ifdef SIXTYFOUR_BIT +#define ONE_TWO 1 +#else +#define ONE_TWO 2 +#endif + + + +#define Min(x,y) (((x) < (y)) ? (x) : (y)) +#define Max(x,y) (((x) > (y)) ? (x) : (y)) + +#define CHROMA_CORRECTION128(x) ((x) >= 0 \ + ? Min(127, (int)(((x) * chromaCorrect))) \ + : Max(-128, (int)(((x) * chromaCorrect)))) +#define CHROMA_CORRECTION256D(x) ((x) >= 128 \ + ? 128.0 + Min(127.0, (((x)-128.0) * chromaCorrect)) \ + : 128.0 - Min(128.0, (((128.0-(x))* chromaCorrect)))) + + + +#define GAMMA_CORRECTION(x) ((int)(pow((x) / 255.0, 1.0/gammaCorrect)* 255.0)) + +#define CHROMA_CORRECTION128D(x) ((x) >= 0 \ + ? Min(127.0, ((x) * chromaCorrect)) \ + : Max(-128.0, ((x) * chromaCorrect))) + +#define CHROMA_CORRECTION256(x) ((x) >= 128 \ + ? 128 + Min(127, (int)(((x)-128.0) * chromaCorrect)) \ + : 128 - Min(128, (int)((128.0-(x)) * chromaCorrect))) + +// Range values for lum, cr, cb. +#define LUM_RANGE 8 +#define CR_RANGE 4 +#define CB_RANGE 4 + + +#endif diff --git a/mpeglib/lib/util/render/dither/ditherMMX.h b/mpeglib/lib/util/render/dither/ditherMMX.h new file mode 100644 index 00000000..2f08b689 --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherMMX.h @@ -0,0 +1,38 @@ +/* + mmx ditherer + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __DITHERMMX_H +#define __DITHERMMX_H + +#include "ditherDef.h" + + +// The mmx dither routine come from NIST +// NIST is an mpeg2/dvd player +// more: http://home.germany.net/100-5083/ +extern void ditherBlock(unsigned char *lum, + unsigned char *cr, + unsigned char *cb, + unsigned char *out, + int rows, int cols, int mod); + +extern void dither32_mmx(unsigned char* lum, + unsigned char* cr, + unsigned char* cb, + unsigned char* out, + int rows, + int cols, + int mod); + + +#endif diff --git a/mpeglib/lib/util/render/dither/ditherRGB.cpp b/mpeglib/lib/util/render/dither/ditherRGB.cpp new file mode 100644 index 00000000..1bcdb2ff --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherRGB.cpp @@ -0,0 +1,230 @@ +/* + copys RGB images to a destination + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "ditherRGB.h" + +#include <iostream> + +using namespace std; + +DitherRGB::DitherRGB() { +} + + +DitherRGB::~DitherRGB() { +} + + +int DitherRGB::getDepth(int pixel) { + int byteDepth=0; + + switch(pixel) { + case 8: + byteDepth=1; + break; + case 15: + case 16: + byteDepth=2; + break; + case 24: + case 32: + byteDepth=4; + break; + default: + cout << "unknown byteDepth:"<<pixel + << " in DitherRGB_flipped::flipRGBImage"<<endl; + } + return byteDepth; + +} + +void DitherRGB::ditherRGBImage(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset) { + int byteDepth=getDepth(depth); + if (byteDepth == 0) { + return; + } + + + if (offset==0) { + int bytes=height*width*byteDepth; + memcpy(dest,src,bytes); + return; + } + + int i; + int lineSize=width*byteDepth; + + offset=offset*byteDepth+lineSize; + + for (i=0;i<height;i++) { + memcpy(dest,src,lineSize); + src+=lineSize; + dest+=offset; + } + + +} + +void DitherRGB::ditherRGBImage_x2(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset) { + + int byteDepth=getDepth(depth); + if (byteDepth == 0) { + return; + } + + switch(byteDepth) { + case 1: + ditherRGB1Byte_x2(dest,src,1,width, height,offset); + break; + case 2: + ditherRGB2Byte_x2(dest,src,2,width, height,offset); + break; + case 4: + ditherRGB4Byte_x2(dest,src,4,width, height,offset); + break; + default: + cout <<"ditherRGBImage_x2 byteDepth:"<<byteDepth + <<" not supported"<<endl; + } +} + + +void DitherRGB::ditherRGB1Byte_x2(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset) { + + // + // dest destr + // destd destrd + + int lineInc=2*width+offset; + unsigned char* destr=dest+1; + unsigned char* destd=dest+lineInc; + unsigned char* destrd=destd+1; + + int row; + int col; + // + // We copy byte by byte this is slow, but works for + // all byteDepth + // this memcpy can be optimized with MMX very i) good ii) easily + + for(row=0;row<height;row++) { + for(col=0;col<width;col++) { + *dest++=*src; + *destr++=*src; + *destd++=*src; + *destrd++=*src; + dest++; + destr++; + destd++; + destrd++; + + src++; + } + dest+=lineInc; + destr+=lineInc; + destd+=lineInc; + destrd+=lineInc; + } +} + + +void DitherRGB::ditherRGB2Byte_x2(unsigned char* destination, + unsigned char* source, + int depth,int width,int height,int offset) { + // + // dest destr + // destd destrd + + unsigned short int* src=(unsigned short int*) source; + unsigned short int* dest=(unsigned short int*) destination; + + int lineInc=2*width+offset; + unsigned short int* destr=dest+1; + unsigned short int* destd=dest+lineInc; + unsigned short int* destrd=destd+1; + + int row; + int col; + // + // We copy byte by byte this is slow, but works for + // all byteDepth + // this memcpy can be optimized with MMX very i) good ii) easily + + for(row=0;row<height;row++) { + for(col=0;col<width;col++) { + *dest++=*src; + *destr++=*src; + *destd++=*src; + *destrd++=*src; + dest++; + destr++; + destd++; + destrd++; + + src++; + } + dest+=lineInc; + destr+=lineInc; + destd+=lineInc; + destrd+=lineInc; + } +} + + +void DitherRGB::ditherRGB4Byte_x2(unsigned char* destination, + unsigned char* source, + int depth,int width,int height,int offset) { + + // + // dest destr + // destd destrd + + unsigned int* src=(unsigned int*) source; + unsigned int* dest=(unsigned int*) destination; + + int lineInc=2*width+offset; + unsigned int* destr=dest+1; + unsigned int* destd=dest+lineInc; + unsigned int* destrd=destd+1; + + int row; + int col; + // + // We copy byte by byte this is slow, but works for + // all byteDepth + // this memcpy can be optimized with MMX very i) good ii) easily + + for(row=0;row<height;row++) { + for(col=0;col<width;col++) { + *dest++=*src; + *destr++=*src; + *destd++=*src; + *destrd++=*src; + dest++; + destr++; + destd++; + destrd++; + + src++; + } + dest+=lineInc; + destr+=lineInc; + destd+=lineInc; + destrd+=lineInc; + } + +} + diff --git a/mpeglib/lib/util/render/dither/ditherRGB.h b/mpeglib/lib/util/render/dither/ditherRGB.h new file mode 100644 index 00000000..6f24cd8c --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherRGB.h @@ -0,0 +1,45 @@ +/* + copys RGB images to a destination + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#ifndef __DITHERRGB_H +#define __DITHERRGB_H + +#include "colorTableHighBit.h" + +class DitherRGB { + + int flipSize; + unsigned char* flipSpace; + + public: + DitherRGB(); + ~DitherRGB(); + + // Note: this methods swaps the image + // itsself + void ditherRGBImage(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset); + void ditherRGBImage_x2(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset); + private: + int getDepth(int pixel); + // depth is here in byte! + void ditherRGB1Byte_x2(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset); + void ditherRGB2Byte_x2(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset); + void ditherRGB4Byte_x2(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset); + +}; + +#endif diff --git a/mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp b/mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp new file mode 100644 index 00000000..ba177675 --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherRGB_flipped.cpp @@ -0,0 +1,82 @@ +/* + flips RGB images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "ditherRGB_flipped.h" + +#include <iostream> + +using namespace std; + + +DitherRGB_flipped::DitherRGB_flipped() { + flipSpace=NULL; + flipSize=0; +} + +DitherRGB_flipped::~DitherRGB_flipped() { + if (flipSpace != NULL) { + delete flipSpace; + } +} + + + + +void DitherRGB_flipped::flipRGBImage(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int ) { + + int byteDepth; + + switch(depth) { + case 8: + byteDepth=1; + break; + case 15: + case 16: + byteDepth=2; + break; + case 24: + case 32: + byteDepth=4; + break; + default: + cout << "unknown byteDepth:"<<depth + << " in DitherRGB_flipped::flipRGBImage"<<endl; + return; + } + + + int spaceNeeded=width*height*byteDepth; + + if (spaceNeeded > flipSize) { + if (flipSpace != NULL) { + delete flipSpace; + } + cout << "flipSpace:"<<spaceNeeded<<endl; + flipSpace=new unsigned char[spaceNeeded+64]; + flipSize=spaceNeeded; + } + + int i; + int lineSize=width*byteDepth; + unsigned char* end=dest+lineSize*(height-1); + + for (i=0;i<height;i++) { + memcpy(end,src,lineSize); + src+=lineSize; + end-=lineSize; + } + +} + + diff --git a/mpeglib/lib/util/render/dither/ditherRGB_flipped.h b/mpeglib/lib/util/render/dither/ditherRGB_flipped.h new file mode 100644 index 00000000..1d99f7f6 --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherRGB_flipped.h @@ -0,0 +1,34 @@ +/* + flips RGB images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#ifndef __DITHERRGB_FLIPPED_H +#define __DITHERRGB_FLIPPED_H + +#include "colorTableHighBit.h" + +class DitherRGB_flipped { + + int flipSize; + unsigned char* flipSpace; + + public: + DitherRGB_flipped(); + ~DitherRGB_flipped(); + + // Note: this methods swaps the image + // itsself + void flipRGBImage(unsigned char* dest,unsigned char* src, + int depth,int width,int height,int offset); + +}; + +#endif diff --git a/mpeglib/lib/util/render/dither/ditherWrapper.cpp b/mpeglib/lib/util/render/dither/ditherWrapper.cpp new file mode 100644 index 00000000..c6c37a79 --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherWrapper.cpp @@ -0,0 +1,246 @@ +/* + wrapper for X11 Window + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "ditherWrapper.h" + +#include <iostream> + +using namespace std; + + +/* + Flag for gamma correction + Makes images brighter/darker. + It's in the source but not activated (for now) +*/ +int gammaCorrectFlag = 0; +double gammaCorrect = 1.0; + +/* + Flag for chroma correction. + reduce the color intensity.. + It's in the source but not activated (for now) +*/ +int chromaCorrectFlag = 0; +double chromaCorrect = 1.0; + + + +DitherWrapper::DitherWrapper(int bpp,unsigned int redMask, + unsigned int greenMask,unsigned int blueMask, + unsigned char pixel[256]) { + + this->bpp=bpp; + this->redMask=redMask; + this->greenMask=greenMask; + this->blueMask=blueMask; + + + dither8Bit=new Dither8Bit(pixel); + dither16Bit=new Dither16Bit(redMask,greenMask,blueMask); + dither32Bit=new Dither32Bit(redMask,greenMask,blueMask); + ditherRGB_flipped=new DitherRGB_flipped(); + ditherRGB=new DitherRGB(); + + +#ifdef INTEL + lmmx=mm_support(); +#else + lmmx=false; +#endif + + +} + + +DitherWrapper::~DitherWrapper(){ + delete dither16Bit; + delete dither8Bit; + delete dither32Bit; + delete ditherRGB_flipped; + delete ditherRGB; +} + + + + + +void DitherWrapper::doDither(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset) { + + + // + // according to the input imageType and the output area + // handle different dither methods + // + + int inputType=pic->getImageType(); + + if ( (inputType == PICTURE_YUVMODE_CR_CB) || + (inputType == PICTURE_YUVMODE_CB_CR) ) { + doDitherYUV(pic,depth,imageMode,dest,offset); + return; + } + + if ( (inputType == PICTURE_RGB) || + (inputType == PICTURE_RGB_FLIPPED) ){ + doDitherRGB(pic,depth,imageMode,dest,offset); + return; + } + + cout << "unknown inputType:"<<inputType + << " in DitherWrapper::doDither"<<endl; +} + + +void DitherWrapper::doDitherRGB(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset) { + + int inputType=pic->getImageType(); + + switch(inputType) { + case PICTURE_RGB: + doDitherRGB_NORMAL(pic,depth,imageMode,dest,offset); + break; + case PICTURE_RGB_FLIPPED: + doDitherRGB_FLIPPED(pic,depth,imageMode,dest,offset); + break; + default: + cout << "unknown RGB type:"<<inputType<<" in DitherWrapper"<<endl; + exit(0); + } +} + + +void DitherWrapper::doDitherRGB_NORMAL(YUVPicture* pic, + int depth,int imageMode, + unsigned char* dest,int offset) { + + int w=pic->getWidth(); + int h=pic->getHeight(); + + unsigned char* src=pic->getImagePtr(); + + if (imageMode & _IMAGE_DOUBLE) { + ditherRGB->ditherRGBImage_x2(dest,src,depth,w,h,offset); + } else { + ditherRGB->ditherRGBImage(dest,src,depth,w,h,offset); + } +} + +void DitherWrapper::doDitherRGB_FLIPPED(YUVPicture* pic, + int depth,int imageMode, + unsigned char* dest,int offset) { + + int w=pic->getWidth(); + int h=pic->getHeight(); + + unsigned char* src=pic->getImagePtr(); + + ditherRGB_flipped->flipRGBImage(dest,src,depth,w,h,offset); +} + + + +void DitherWrapper::doDitherYUV(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset) { + + if (imageMode & _IMAGE_DOUBLE) { + doDither_x2(pic,depth,dest,offset); + } else { + doDither_std(pic,depth,dest,offset); + } +} + + +void DitherWrapper::doDither_std(YUVPicture* pic,int depth, + unsigned char* dest,int offset){ + + int h=pic->getHeight(); + int w=pic->getWidth(); + unsigned char* lum=pic->getLuminancePtr(); + unsigned char* cr=pic->getCrPtr(); + unsigned char* cb=pic->getCbPtr(); + + + switch (depth) { + case 8: + dither8Bit->ditherImageOrdered(lum, cr, cb,dest , h, w); + break; + case 16: + if (lmmx) { + ditherBlock(lum,cr,cb,dest,h,w,offset); + } else { + dither16Bit->ditherImageColor16(lum,cr,cb,dest,h,w,offset); + } + + break; + case 24: + case 32: + if (lmmx) { + dither32_mmx(lum, cr, cb,dest ,h,w,offset); + } else { + dither32Bit->ditherImageColor32(lum, cr, cb,dest ,h,w,offset); + } + + + break; + default: + cout << "cannot dither depth:"<<depth<<endl; + } + +} + + +void DitherWrapper::doDither_x2(YUVPicture* pic,int depth, + unsigned char* dest,int offset){ + + int h=pic->getHeight(); + int w=pic->getWidth(); + unsigned char* lum=pic->getLuminancePtr(); + unsigned char* cr=pic->getCrPtr(); + unsigned char* cb=pic->getCbPtr(); + + + switch (depth) { + case 8: { + // we do dither with the 8Bit std YUV ditherer to RGB + // and then we do the double part with the + // RGB ditherer. Its obviously much slower but at + // least it works. To not allocate memory twice + // we are a bit tricky. We know that the image + // has space for doubls size. We but the not double size + // image at the bottom of the dest. Maybe that + // the last line gets overwritten + int memPos=3*h*w; + dither8Bit->ditherImageOrdered(lum, cr, cb,dest+memPos, h, w); + unsigned char* src=dest+memPos; + ditherRGB->ditherRGBImage_x2(dest,src,depth,w,h,0); + break; + } + case 16: + dither16Bit->ditherImageTwox2Color16(lum,cr,cb,dest,h,w,offset); + break; + case 24: + case 32: + if (lmmx) { + //dither32x2_mmx(lum, cr, cb,dest ,h,w,offset); + dither32Bit->ditherImageTwox2Color32(lum,cr,cb,dest,h,w,offset); + } else { + dither32Bit->ditherImageTwox2Color32(lum,cr,cb,dest,h,w,offset); + } + break; + default: + cout << "cannot dither depth:" << depth << endl; + } +} diff --git a/mpeglib/lib/util/render/dither/ditherWrapper.h b/mpeglib/lib/util/render/dither/ditherWrapper.h new file mode 100644 index 00000000..b01abff8 --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherWrapper.h @@ -0,0 +1,80 @@ +/* + wrapper for X11 Window + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __DITHERWRAPPER_H +#define __DITHERWRAPPER_H + + +#include "../../mmx/mmx.h" + +#include "../yuvPicture.h" +#include "../imageBase.h" +#include <stdlib.h> +#include "ditherMMX.h" +#include "dither8Bit.h" +#include "dither16Bit.h" +#include "dither32Bit.h" +#include "ditherRGB_flipped.h" +#include "ditherRGB.h" + + +/** + Wraps all calls to software ditherer and the different + resolutions,mmx enhancements, and doublesize ditherers. +*/ + + +class DitherWrapper { + + int lmmx; + + int bpp; + // colorMask + unsigned int redMask; + unsigned int greenMask; + unsigned int blueMask; + + Dither8Bit* dither8Bit; + Dither16Bit* dither16Bit; + Dither32Bit* dither32Bit; + DitherRGB_flipped* ditherRGB_flipped; + DitherRGB* ditherRGB; + + public: + DitherWrapper(int bpp,unsigned int redMask, + unsigned int greenMask,unsigned int blueMask, + unsigned char pixel[256]); + ~DitherWrapper(); + +/* int getDitherSize(); */ +/* void setDitherSize(int ditherMode); */ + + void doDither(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset); + + + private: + void doDitherYUV(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset); + void doDitherRGB(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset); + void doDitherRGB_NORMAL(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset); + void doDitherRGB_FLIPPED(YUVPicture* pic,int depth,int imageMode, + unsigned char* dest,int offset); + + void doDither_std(YUVPicture* pic,int depth,unsigned char* dest,int offset); + void doDither_x2(YUVPicture* pic,int depth,unsigned char* dest,int offset); +}; + +#endif diff --git a/mpeglib/lib/util/render/dither/ditherer_mmx16.cpp b/mpeglib/lib/util/render/dither/ditherer_mmx16.cpp new file mode 100644 index 00000000..757f0676 --- /dev/null +++ b/mpeglib/lib/util/render/dither/ditherer_mmx16.cpp @@ -0,0 +1,256 @@ + +#include "ditherMMX.h" + +#include <iostream> + +using namespace std; + +#ifndef INTEL +// nothing +void ditherBlock(unsigned char *lum, unsigned char *cr, unsigned char *cb, + unsigned char *out, + int cols, int rows, int screen_width) { + printf("call to ditherBlock. this should never happen\n"); + printf("check mmx detection routine.\n"); + exit(0); +} +#else + + +static long long MMX16_0 = 0L; +static unsigned long MMX16_10w[] = {0x00100010, 0x00100010}; +static unsigned long MMX16_80w[] = {0x00800080, 0x00800080}; +static unsigned long MMX16_00FFw[] = {0x00ff00ff, 0x00ff00ff}; +static unsigned short MMX16_Ublucoeff[] = {0x81, 0x81, 0x81, 0x81}; +static unsigned short MMX16_Vredcoeff[] = {0x66, 0x66, 0x66, 0x66}; +static unsigned short MMX16_Ugrncoeff[] = {0xffe8, 0xffe8, 0xffe8, 0xffe8}; +static unsigned short MMX16_Vgrncoeff[] = {0xffcd, 0xffcd, 0xffcd, 0xffcd}; +static unsigned short MMX16_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a}; +static unsigned short MMX16_redmask[] = {0xf800, 0xf800, 0xf800, 0xf800}; +static unsigned short MMX16_grnmask[] = {0x7e0, 0x7e0, 0x7e0, 0x7e0}; + +void dummy_dithermmx16() { + cout << "MMX16_0"<<MMX16_0<<endl; + cout << "MMX16_10w:"<<MMX16_10w<<endl; + cout << "MMX16_80w:"<<MMX16_80w<<endl; + cout << "MMX16_Ublucoeff:"<<MMX16_Ublucoeff<<endl; + cout << "MMX16_Vredcoeff:"<<MMX16_Vredcoeff<<endl; + cout << "MMX16_Ugrncoeff:"<<MMX16_Ugrncoeff<<endl; + cout << "MMX16_Vgrncoeff:"<<MMX16_Vgrncoeff<<endl; + cout << "MMX16_Ycoeff:"<<MMX16_Ycoeff<<endl; + cout << "MMX16_redmask:"<<MMX16_redmask<<endl; + cout << "MMX16_grnmask:"<<MMX16_grnmask<<endl; + cout << "MMX16_00FFw:"<<MMX16_00FFw<<endl; +} + + +void ditherBlock(unsigned char *lum, + unsigned char *cr, + unsigned char *cb, + unsigned char *out, + int rows, + int cols, + int mod) { + + unsigned short *row1; + unsigned short *row2; + row1 = (unsigned short* )out; // 16 bit target + + unsigned char* end = lum +cols*rows; // Pointer to the end + int x=cols; + row2=row1+mod+cols; // start of second row + mod=2*cols+4*mod; // increment for row1 in byte + + // buffer for asm function + int buf[6]; + buf[0]=(int)(lum+cols); // lum2 pointer + buf[1]=(int)end; + buf[2]=x; + buf[3]=mod; + buf[4]=0; //tmp0; + buf[5]=cols; + + + + __asm__ __volatile__( + ".align 32\n" + "1:\n" + "movd (%1), %%mm0\n" // 4 Cb 0 0 0 0 u3 u2 u1 u0 + "pxor %%mm7, %%mm7\n" + "movd (%0), %%mm1\n" // 4 Cr 0 0 0 0 v3 v2 v1 v0 + "punpcklbw %%mm7, %%mm0\n" // 4 W cb 0 u3 0 u2 0 u1 0 u0 + "punpcklbw %%mm7, %%mm1\n" // 4 W cr 0 v3 0 v2 0 v1 0 v0 + "psubw MMX16_80w, %%mm0\n" + "psubw MMX16_80w, %%mm1\n" + "movq %%mm0, %%mm2\n" // Cb 0 u3 0 u2 0 u1 0 u0 + "movq %%mm1, %%mm3\n" // Cr + "pmullw MMX16_Ugrncoeff, %%mm2\n" // Cb2green 0 R3 0 R2 0 R1 0 R0 + "movq (%2), %%mm6\n" // L1 l7 L6 L5 L4 L3 L2 L1 L0 + "pmullw MMX16_Ublucoeff, %%mm0\n" // Cb2blue + "pand MMX16_00FFw, %%mm6\n" // L1 00 L6 00 L4 00 L2 00 L0 + "pmullw MMX16_Vgrncoeff, %%mm3\n" // Cr2green + "movq (%2), %%mm7\n" // L2 + "pmullw MMX16_Vredcoeff, %%mm1\n" // Cr2red + // "psubw MMX16_10w, %%mm6\n" + "psrlw $8, %%mm7\n" // L2 00 L7 00 L5 00 L3 00 L1 + "pmullw MMX16_Ycoeff, %%mm6\n" // lum1 + // "psubw MMX16_10w, %%mm7\n" // L2 + "paddw %%mm3, %%mm2\n" // Cb2green + Cr2green == green + "pmullw MMX16_Ycoeff, %%mm7\n" // lum2 + + "movq %%mm6, %%mm4\n" // lum1 + "paddw %%mm0, %%mm6\n" // lum1 +blue 00 B6 00 B4 00 B2 00 B0 + "movq %%mm4, %%mm5\n" // lum1 + "paddw %%mm1, %%mm4\n" // lum1 +red 00 R6 00 R4 00 R2 00 R0 + "paddw %%mm2, %%mm5\n" // lum1 +green 00 G6 00 G4 00 G2 00 G0 + "psraw $6, %%mm4\n" // R1 0 .. 64 + "movq %%mm7, %%mm3\n" // lum2 00 L7 00 L5 00 L3 00 L1 + "psraw $6, %%mm5\n" // G1 - .. + + "paddw %%mm0, %%mm7\n" // Lum2 +blue 00 B7 00 B5 00 B3 00 B1 + "psraw $6, %%mm6\n" // B1 0 .. 64 + "packuswb %%mm4, %%mm4\n" // R1 R1 + "packuswb %%mm5, %%mm5\n" // G1 G1 + "packuswb %%mm6, %%mm6\n" // B1 B1 + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + + "pand MMX16_redmask, %%mm4\n" + "psllw $3, %%mm5\n" // GREEN 1 + "punpcklbw %%mm6, %%mm6\n" + "pand MMX16_grnmask, %%mm5\n" + "pand MMX16_redmask, %%mm6\n" + "por %%mm5, %%mm4\n" // + "psrlw $11, %%mm6\n" // BLUE 1 + "movq %%mm3, %%mm5\n" // lum2 + "paddw %%mm1, %%mm3\n" // lum2 +red 00 R7 00 R5 00 R3 00 R1 + "paddw %%mm2, %%mm5\n" // lum2 +green 00 G7 00 G5 00 G3 00 G1 + "psraw $6, %%mm3\n" // R2 + "por %%mm6, %%mm4\n" // MM4 + "psraw $6, %%mm5\n" // G2 + + "movl %2,16%5\n" // store register in tmp0 + "movl %5,%2\n" // lum2->register + "movq (%2),%%mm6\n" // 0 0 0 0 L3 L2 L1 L0 (load lum2) + + + //"movq (%2, %5), %%mm6\n" // L3 load lum2 + "psraw $6, %%mm7\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm5, %%mm5\n" + "packuswb %%mm7, %%mm7\n" + "pand MMX16_00FFw, %%mm6\n" // L3 + "punpcklbw %%mm3, %%mm3\n" + // "psubw MMX16_10w, %%mm6\n" // L3 + "punpcklbw %%mm5, %%mm5\n" + "pmullw MMX16_Ycoeff, %%mm6\n" // lum3 + "punpcklbw %%mm7, %%mm7\n" + "psllw $3, %%mm5\n" // GREEN 2 + "pand MMX16_redmask, %%mm7\n" + "pand MMX16_redmask, %%mm3\n" + "psrlw $11, %%mm7\n" // BLUE 2 + "pand MMX16_grnmask, %%mm5\n" + "por %%mm7, %%mm3\n" + + "movq (%2), %%mm7\n" // L4 load lum2 + "movl 16%5,%2\n" // tmp0->register + + "por %%mm5, %%mm3\n" // + "psrlw $8, %%mm7\n" // L4 + "movq %%mm4, %%mm5\n" + // "psubw MMX16_10w, %%mm7\n" // L4 + "punpcklwd %%mm3, %%mm4\n" + "pmullw MMX16_Ycoeff, %%mm7\n" // lum4 + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%3)\n" // write row1 + "movq %%mm5, 8(%3)\n" // write row1 + + "movq %%mm6, %%mm4\n" // Lum3 + "paddw %%mm0, %%mm6\n" // Lum3 +blue + + "movq %%mm4, %%mm5\n" // Lum3 + "paddw %%mm1, %%mm4\n" // Lum3 +red + "paddw %%mm2, %%mm5\n" // Lum3 +green + "psraw $6, %%mm4\n" + "movq %%mm7, %%mm3\n" // Lum4 + "psraw $6, %%mm5\n" + "paddw %%mm0, %%mm7\n" // Lum4 +blue + "psraw $6, %%mm6\n" // Lum3 +blue + "movq %%mm3, %%mm0\n" // Lum4 + "packuswb %%mm4, %%mm4\n" + "paddw %%mm1, %%mm3\n" // Lum4 +red + "packuswb %%mm5, %%mm5\n" + "paddw %%mm2, %%mm0\n" // Lum4 +green + "packuswb %%mm6, %%mm6\n" + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + "punpcklbw %%mm6, %%mm6\n" + "psllw $3, %%mm5\n" // GREEN 3 + "pand MMX16_redmask, %%mm4\n" + "psraw $6, %%mm3\n" // psr 6 + "psraw $6, %%mm0\n" + "pand MMX16_redmask, %%mm6\n" // BLUE + "pand MMX16_grnmask, %%mm5\n" + "psrlw $11, %%mm6\n" // BLUE 3 + "por %%mm5, %%mm4\n" + "psraw $6, %%mm7\n" + "por %%mm6, %%mm4\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm0, %%mm0\n" + "packuswb %%mm7, %%mm7\n" + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm0, %%mm0\n" + "punpcklbw %%mm7, %%mm7\n" + "pand MMX16_redmask, %%mm3\n" + "pand MMX16_redmask, %%mm7\n" // BLUE + "psllw $3, %%mm0\n" // GREEN 4 + "psrlw $11, %%mm7\n" + "pand MMX16_grnmask, %%mm0\n" + "por %%mm7, %%mm3\n" + "por %%mm0, %%mm3\n" + + "movq %%mm4, %%mm5\n" + + "punpcklwd %%mm3, %%mm4\n" + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%4)\n" + "movq %%mm5, 8(%4)\n" + + "subl $8, 8%5\n" // x-=8 + "addl $8, %5\n" // lum2+8 + "addl $8, %2\n" + "addl $4, %0\n" + "addl $4, %1\n" + "cmpl $0, 8%5\n" + "leal 16(%3), %3\n" + "leal 16(%4), %4\n" // row2+16 + + + "jne 1b\n" + "addl 20%5, %2\n" // lum += cols + + "movl %2,16%5\n" // store register in tmp0 + "movl 20%5,%2\n" // cols->register + + "addl %2, %5\n" // lum2 += cols + "addl 12%5, %3\n" // row1+= mod + "addl 12%5, %4\n" // row2+= mod + "movl %2, 8%5\n" // x=cols + "movl 16%5,%2\n" // store tmp0 in register + + "cmpl 4%5, %2\n" + "jl 1b\n" + + : + :"r" (cr), "r"(cb),"r"(lum), + "r"(row1),"r"(row2),"m"(buf[0]) + + ); + __asm__ ( + "emms\n" + ); + + } + +#endif diff --git a/mpeglib/lib/util/render/dither2YUV/Makefile.am b/mpeglib/lib/util/render/dither2YUV/Makefile.am new file mode 100644 index 00000000..374658a3 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/Makefile.am @@ -0,0 +1,22 @@ +# libdivxplugin - Makefile.am + +EXTRA_DIST = README + +INCLUDES = -I.. $(all_includes) + + +noinst_LTLIBRARIES = libdivxutil_dither.la + +noinst_HEADERS = dither2YUV.h rgb2yuvdefs.h rgb2yuv16.h \ + rgb2yuv32.h + +libdivxutil_dither_la_SOURCES = dither2YUV.cpp rgb2yuv16.cpp \ + rgb2yuv32.cpp + + + + + + + + diff --git a/mpeglib/lib/util/render/dither2YUV/README b/mpeglib/lib/util/render/dither2YUV/README new file mode 100644 index 00000000..66246c13 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/README @@ -0,0 +1,13 @@ + + +* we have a Dither2Yuv base class. Currently this is not derived + from a basic ditherWrapper class because we don not have this + in mpeglib yet. + TODO: change in mpeglib DitherWrapper->Dither2RGB and + make DitherWrapper pure virtual and derive Dither2YUV + Dither2RGB from this class. + +* Note we do not support 8 Bit here, thus the constructor looks + dofferent. + + diff --git a/mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp b/mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp new file mode 100644 index 00000000..db4a3288 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/dither2YUV.cpp @@ -0,0 +1,124 @@ +/* + this class dithery RGB picture to yuv12 + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "dither2YUV.h" + +#include <iostream> + +using namespace std; + + +Dither2YUV::Dither2YUV() { + + + lmmx=mm_support(); + +} + + +Dither2YUV::~Dither2YUV(){ +} + + + + + + +void Dither2YUV::doDither(YUVPicture* pic,int depth,int ditherSize, + unsigned char* dest,int offset) { + + int inputType=pic->getImageType(); + + switch(inputType) { + case PICTURE_RGB: + doDitherRGB_NORMAL(pic,depth,ditherSize,dest,offset); + break; + default: + std::cout << "unknown RGB type:"<<inputType<<" in Dither2YUV"<<std::endl; + exit(0); + } +} + + +void Dither2YUV::doDitherRGB_NORMAL(YUVPicture* rgbPic, + int depth,int ditherSize, + unsigned char* dest,int offset) { + + switch (ditherSize) { + case _SIZE_NORMAL: + doDither2YUV_std(rgbPic,depth,dest,offset); + break; + case _SIZE_DOUBLE: + std::cout << "double not supported for RGB"<<std::endl; + break; + default: + std::cout << "unknown size:"<<ditherSize<<" in Dither2YUV"<<std::endl; + exit(0); + } +} + + +void Dither2YUV::doDither2YUV_std(YUVPicture* rgbPic,int depth, + unsigned char* dest,int offset){ + + int h=rgbPic->getHeight(); + int w=rgbPic->getWidth(); + int lumLength=w * h; + int colorLength=(w * h) / 4; + + unsigned char* lum=dest; + unsigned char* cr=lum+lumLength; + unsigned char* cb=cr+colorLength; + unsigned char* rgbSource=rgbPic->getImagePtr(); + + + switch (depth) { + case 8: + std::cout << "8 bit dither to yuv not supported"<<std::endl; + exit(0); + break; + case 16: + if (lmmx) { +#ifdef INTEL + rgb2yuv16bit_mmx(rgbSource,lum,cr,cb,h,w); +#endif + } else { + rgb2yuv16bit(rgbSource,lum,cr,cb,h,w); + } + + break; + case 24: + if (lmmx) { +#ifdef INTEL + rgb2yuv24bit_mmx(rgbSource,lum,cr,cb,h,w); +#endif + } else { + rgb2yuv24bit(rgbSource,lum,cr,cb,h,w); + } + break; + case 32: + if (lmmx) { +#ifdef INTEL + rgb2yuv32bit_mmx(rgbSource,lum,cr,cb,h,w); +#endif + } else { + rgb2yuv32bit(rgbSource,lum,cr,cb,h,w); + } + break; + default: + std::cout << "cannot dither depth:"<<depth<<std::endl; + } + +} + + diff --git a/mpeglib/lib/util/render/dither2YUV/dither2YUV.h b/mpeglib/lib/util/render/dither2YUV/dither2YUV.h new file mode 100644 index 00000000..5ef26b2b --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/dither2YUV.h @@ -0,0 +1,64 @@ +/* + this class dithery RGB picture to yuv12 + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __DITHER2YUV_H +#define __DITHER2YUV_H + + +#include "../../mmx/mmx.h" +#include "../yuvPicture.h" + + +#include <stdlib.h> +#include "rgb2yuv16.h" +#include "rgb2yuv32.h" + +#define _SIZE_NONE 0 +#define _SIZE_NORMAL 1 +#define _SIZE_DOUBLE 2 + + +/** + Wraps all calls to software ditherer and the different + resolutions,mmx enhancements, and doublesize ditherers. +*/ + + +class Dither2YUV { + + int lmmx; + + int bpp; + + + public: + Dither2YUV(); + ~Dither2YUV(); + + int getDitherSize(); + void setDitherSize(int ditherSize); + + void doDither(YUVPicture* pic,int depth,int ditherSize, + unsigned char* dest,int offset); + + + private: + void doDitherRGB_NORMAL(YUVPicture* pic,int depth,int ditherSize, + unsigned char* dest,int offset); + + void doDither2YUV_std(YUVPicture* pic,int depth, + unsigned char* dest,int offset); + +}; + +#endif diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp new file mode 100644 index 00000000..e0d7fc86 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.cpp @@ -0,0 +1,916 @@ +/*************************************************************************** + rgb2yuv16.c - description + ------------------- + begin : Tue Nov 2 2000 + copyright : (C) 2000 by Christian Gerlach + email : cgerlach@rhrk.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "rgb2yuv16.h" +#include <iostream> + +static unsigned short KEEPR[4] = { 63488, 63488, 63488, 63488 }; +unsigned short KEEPG[4] = { 2016, 2016, 2016, 2016 }; +unsigned short KEEPB[4] = { 31, 31, 31, 31 }; + +short Y_RED[4] = { 307, 307, 307, 307 }; +short Y_GREEN[4] = { 302, 302, 302, 302 }; +short Y_BLUE[4] = { 117, 117, 117, 117 }; + +short U_RED[4] = { -150, -150, -150, -150 }; +short U_GREEN[4] = { -147, -147, -147, -147 }; +short U_BLUE[4] = { 444, 444, 444, 444 }; + +short V_RED[4] = { 632, 632, 632, 632 }; +short V_GREEN[4] = { -265, -265, -265, -265 }; +short V_BLUE[4] = { -102, -102, -102, -102 }; + + +// how to avoid these nasty compiler warinings? +// heres one (maybe bad) method +void dummyRGB2YUV16Bit() { + + printf("%p\n",KEEPR); + printf("%p\n",KEEPG); + printf("%p\n",KEEPB); + printf("%p\n",Y_RED); + printf("%p\n",Y_GREEN); + printf("%p\n",Y_BLUE); + printf("%p\n",U_RED); + printf("%p\n",U_GREEN); + printf("%p\n",U_BLUE); + printf("%p\n",V_RED); + printf("%p\n",V_GREEN); + printf("%p\n",V_BLUE); +} + + +#ifndef INTEL +void rgb2yuv16bit_mmx(unsigned char* ,unsigned char* ,unsigned char* , + unsigned char* ,int , int ) { + std::cout << "RGB->YUV not compiled with INTEL" << std::endl; + exit(0); +} + +void rgb2yuv16bit_mmx_fast(unsigned char* ,unsigned char* ,unsigned char* , + unsigned char* ,int , int ) { + std::cout << "RGB->YUV not compiled with INTEL" << std::endl; + exit(0); +} +#endif + + +void rgb2yuv16(unsigned char* rgbSource, unsigned char* dest) +{ + int rgb = *((unsigned short*) rgbSource++ ); + int r = RED(rgb); + int g = GREEN(rgb); + int b = BLUE(rgb); + + dest[0] = Y_RGB(r, g, b); + dest[1] = U_RGB(r, g, b); + dest[2] = V_RGB(r, g, b); +} + +void rgb2yuv16bit(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + + int height2 = height / 2; + int width2 = width / 2; + int r, g, b, row, col, rgb; + + for (row=0 ; row<height2 ; row++) { + for (col=0 ; col<width2 ; col++) { + rgb = *((unsigned short*) rgbSource++ ); + r = RED(rgb); + g = GREEN(rgb); + b = BLUE(rgb); + + *lum++ = Y_RGB(r, g, b); + *cr++ = U_RGB(r, g, b); + *cb++ = V_RGB(r, g, b); + + rgb = *((unsigned short*) rgbSource++ ); + r = RED(rgb); + g = GREEN(rgb); + b = BLUE(rgb); + + *lum++ = Y_RGB(r, g, b); + } + for (col=0 ; col<width ; col++) { + rgb = *((unsigned short*) rgbSource++ ); + r = RED(rgb); + g = GREEN(rgb); + b = BLUE(rgb); + + *lum++ = Y_RGB(r, g, b); + } + } +} + + +#ifdef INTEL + +void rgb2yuv16bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + int height2 = height / 2; + int width2 = width / 2; + int bytesPerLine = width * 2; + + for (int row=0 ; row<height2 ; row++) { + rgb2yuv16bit_mmx422_row(rgbSource, lum, cr, cb, width); + rgbSource += bytesPerLine; + lum += width; + cr += width2; + cb += width2; + + rgb2y16bit_mmx_row(rgbSource, lum, width); + rgbSource += bytesPerLine; + lum += width; + } +} + +void rgb2yuv16bit_mmx_fast(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + + int height2 = height / 2; + int width2 = width / 2; + int bytesPerLine = width * 2; + + for (int row=0 ; row<height2 ; row++) { + rgb2yuv16bit_mmx422_row_fast(rgbSource, lum, cr, cb, width); + rgbSource += bytesPerLine; + lum += width; + cr += width2; + cb += width2; + + rgb2y16bit_mmx_row_fast(rgbSource, lum, width); + rgbSource += bytesPerLine; + lum += width; + } +} + +void rgb2yuv16bit_mmx422_row(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel) { + unsigned int buf[17]; + + // 36%5 = TEMP0 + // 44%5 = TEMPY + // 52%5 = TEMPU + // 60%5 = TEMPV + + __asm__ __volatile__ ( + "1:\n" + + // unpack hicolor ( pixel 1 - 4) + "movq (%0), %%mm0\n" + + "movq %%mm0, %%mm1\n" + "pand KEEPR, %%mm1\n" + "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1 + "movq %%mm0, %%mm2\n" + "pand KEEPG, %%mm2\n" + "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2 + "movq %%mm0, %%mm3\n" + "pand KEEPB, %%mm3\n" + "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3 + + "movq %%mm2, %%mm0\n" + "punpcklbw %%mm1, %%mm2\n" + "punpckhbw %%mm1, %%mm0\n" + + "pxor %%mm5, %%mm5\n" + "movq %%mm3, %%mm4\n" + "punpcklbw %%mm5, %%mm3\n" + "punpckhbw %%mm5, %%mm4\n" + + "psllq $8, %%mm2\n" + "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3 + "psllq $8, %%mm0\n" + "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4 + + "movq %%mm3, %5\n" + "movq %%mm4, 8%5\n" + + // next 4 pixels ------------------------------ + + "movq 8(%0), %%mm0\n" + + "movq %%mm0, %%mm1\n" + "pand KEEPR, %%mm1\n" + "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1 + "movq %%mm0, %%mm2\n" + "pand KEEPG, %%mm2\n" + "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2 + "movq %%mm0, %%mm3\n" + "pand KEEPB, %%mm3\n" + "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3 + + "movq %%mm2, %%mm0\n" + "punpcklbw %%mm1, %%mm2\n" + "punpckhbw %%mm1, %%mm0\n" + + "pxor %%mm5, %%mm5\n" + "movq %%mm3, %%mm4\n" + "punpcklbw %%mm5, %%mm3\n" + "punpckhbw %%mm5, %%mm4\n" + + "psllq $8, %%mm2\n" + "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3 + "psllq $8, %%mm0\n" + "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4 + + "movq %%mm3, 16%5\n" + "movq %%mm4, 24%5\n" + + "add $16, %0\n" + + // standard algorithm -------------------------------------------------- + + // pack rgb + // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + // ------------------------------ + // (uses: mm0, mm1) + "movd 8%5, %%mm0\n" + "psllq $24, %%mm0\n" + "movd 4%5, %%mm1\n" + "por %%mm1, %%mm0\n" + "psllq $24, %%mm0\n" + "movd %5, %%mm1\n" + "por %%mm0, %%mm1\n" + // ------------------------------ + + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5 + + // pack rgb + // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1 + // ------------------------------ + // (uses: mm1, mm6) + "movd 20%5, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 16%5, %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 12%5, %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $8, %%mm1\n" + "movd 8%5, %%mm6\n" + "psrlq $16, %%mm6\n" + "por %%mm6, %%mm1\n" + // ------------------------------ + + "paddd %%mm3, %%mm2\n" // U1U0 -> mm2 + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + "paddd %%mm5, %%mm4\n" // V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, 36%5\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6 + "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2 + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5 + "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "paddd %%mm7, %%mm6\n" // U3U2 -> mm6 + + // pack rgb + // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1 + // ------------------------------ + // (uses: mm1, mm7) + "movd 28%5, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 24%5, %%mm7\n" + "por %%mm7, %%mm1\n" + "psllq $16, %%mm1\n" + "movd 20%5, %%mm7\n" + "psrlq $8, %%mm7\n" + "por %%mm7, %%mm1\n" + // ------------------------------ + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6 + + "paddd %%mm5, %%mm3\n" // V3V2 -> mm3 + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3 + + "movq %%mm0, 44%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + + "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2 + + "movq 36%5, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "movq %%mm2, 52%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm4, 60%5\n" // (V3V2V1V0)/256 -> mm4 + + "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4 + + "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4 + "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0 + + "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4 + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4 + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3 + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "paddd %%mm6, %%mm0\n" // U5U4 -> mm0 + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7 + "paddd %%mm4, %%mm3\n" // V5V4 -> mm3 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4 + + "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4 + "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0 + + //---------------------------------------------------------------------- + + "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0 + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7 + "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3 + + "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "paddd OFFSETDX, %%mm4\n" // add offset to U7U6 + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5 + "paddd %%mm4, %%mm7\n" // U7U6 -> mm7 + + "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7 + + //---------------------------------------------------------------------- + + "movq 44%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0 + + "movq 52%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7 + "paddd %%mm5, %%mm1\n" // V7V6 -> mm1 + + "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256 + "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + + "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4 + "movq 60%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5 + + "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3 + "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0 + "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4 + + "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5 + + "movq CLEARX, %%mm2\n" + "pand %%mm2, %%mm4\n" + "pand %%mm2, %%mm5\n" + + "packuswb %%mm5, %%mm4\n" + + "movd %%mm4, (%2)\n" + "psrlq $32, %%mm4\n" + "movd %%mm4, (%3)\n" + + "add $8, %1\n" + "add $4, %2\n" + "add $4, %3\n" + + "sub $8, %4\n" + "jnz 1b\n" + + "emms\n" + + : + : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), + "m" (pixel), "m" (buf[0]) + + ); +} + +void rgb2yuv16bit_mmx422_row_fast(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel) +{ + __asm__ __volatile__ ( + "1:\n" + + // unpack hicolor ( pixel 0 - 3) + "movq (%0), %%mm0\n" + + "movq %%mm0, %%mm1\n" + "pand KEEPR, %%mm1\n" + "psrlq $11, %%mm1\n" // B3B2B1B0 -> mm1 + + "movq %%mm0, %%mm2\n" + "pand KEEPG, %%mm2\n" + "psrlq $5, %%mm2\n" // G3G2G1G0 -> mm2 + + "movq %%mm0, %%mm3\n" + "pand KEEPB, %%mm3\n" // R3R2R1R0 -> mm3 + + // unpack hicolor ( pixel 4 - 7) + "movq 8(%0), %%mm0\n" + + "movq %%mm0, %%mm4\n" + "pand KEEPR, %%mm4\n" + "psrlq $11, %%mm4\n" // B7B6B5B4 -> mm4 + + "movq %%mm0, %%mm5\n" + "pand KEEPG, %%mm5\n" + "psrlq $5, %%mm5\n" // G7G6G5G4 -> mm5 + + "movq %%mm0, %%mm6\n" + "pand KEEPB, %%mm6\n" // R7R6R5R4 -> mm6 + + // calculate Y + "movq %%mm6, %%mm7\n" + "pmullw Y_RED, %%mm7\n" + + "movq %%mm5, %%mm0\n" + "pmullw Y_GREEN, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "movq %%mm4, %%mm0\n" + "pmullw Y_BLUE, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "psrlw $7, %%mm7\n" // Y3Y2Y1Y0 -> mm7 + + "pxor %%mm0, %%mm0\n" + "packuswb %%mm0, %%mm7\n" + "movd %%mm7, 4(%1)\n" // Y3Y2Y1Y0 -> lum + + // -------- + + "movq %%mm3, %%mm7\n" + "pmullw Y_RED, %%mm7\n" + + "movq %%mm2, %%mm0\n" + "pmullw Y_GREEN, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "movq %%mm1, %%mm0\n" + "pmullw Y_BLUE, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "psrlw $7, %%mm7\n" // Y7Y6Y5Y4 -> mm7 + + "pxor %%mm0, %%mm0\n" + "packuswb %%mm0, %%mm7\n" + "movd %%mm7, (%1)\n" // Y7Y6Y5Y4 -> lum + "add $8, %1\n" + + // pack RGB + "packuswb %%mm4, %%mm1\n" + "pand CLEARX, %%mm1\n" // B6B4B2B0 -> mm1 + "packuswb %%mm5, %%mm2\n" + "pand CLEARX, %%mm2\n" // GRG4G2G0 -> mm2 + "packuswb %%mm6, %%mm3\n" + "pand CLEARX, %%mm3\n" // R6R4R2R0 -> mm3 + + // calculate U + "movq %%mm3, %%mm7\n" + "pmullw U_RED, %%mm7\n" + + "movq %%mm2, %%mm0\n" + "pmullw U_GREEN, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "movq %%mm1, %%mm0\n" + "pmullw U_BLUE, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "psrlw $7, %%mm7\n" // U3U2U1U0 -> mm7 + "paddw OFFSETBX,%%mm7\n" + "pand CLEARX, %%mm7\n" + + "pxor %%mm0, %%mm0\n" + "packuswb %%mm0, %%mm7\n" + "movd %%mm7, (%2)\n" // U3U2U1U0 -> lum + "add $4, %2\n" + + // calculate V + "movq %%mm3, %%mm7\n" + "pmullw V_RED, %%mm7\n" + + "movq %%mm2, %%mm0\n" + "pmullw V_GREEN, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "movq %%mm1, %%mm0\n" + "pmullw V_BLUE, %%mm0\n" + "paddw %%mm0, %%mm7\n" + + "psrlw $7, %%mm7\n" // V3V2V1V0 -> mm7 + "paddw OFFSETBX,%%mm7\n" + "pand CLEARX, %%mm7\n" + + "pxor %%mm0, %%mm0\n" + "packuswb %%mm0, %%mm7\n" + "movd %%mm7, (%3)\n" // V3V2V1V0 -> lum + "add $4, %3\n" + + "add $16, %0\n" + + "sub $8, %4\n" + "jnz 1b\n" + + "emms\n" + + : + : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel) + + ); +} + +void rgb2y16bit_mmx_row(unsigned char* rgbSource, + unsigned char* lum, int pixel) +{ + unsigned int buf[16]; + + // 36%3 = TEMP0 + // 44%3 = TEMPY + + __asm__ __volatile__ ( + "1:\n" + + // unpack hicolor ( pixel 1 - 4) + "movq (%0), %%mm0\n" + + "movq %%mm0, %%mm1\n" + "pand KEEPR, %%mm1\n" + "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1 + "movq %%mm0, %%mm2\n" + "pand KEEPG, %%mm2\n" + "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2 + "movq %%mm0, %%mm3\n" + "pand KEEPB, %%mm3\n" + "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3 + + "movq %%mm2, %%mm0\n" + "punpcklbw %%mm1, %%mm2\n" + "punpckhbw %%mm1, %%mm0\n" + + "pxor %%mm5, %%mm5\n" + "movq %%mm3, %%mm4\n" + "punpcklbw %%mm5, %%mm3\n" + "punpckhbw %%mm5, %%mm4\n" + + "psllq $8, %%mm2\n" + "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3 + "psllq $8, %%mm0\n" + "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4 + + "movq %%mm3, %3\n" + "movq %%mm4, 8%3\n" + + // next 4 pixels ------------------------------ + + "movq 8(%0), %%mm0\n" + + "movq %%mm0, %%mm1\n" + "pand KEEPR, %%mm1\n" + "psrlq $8, %%mm1\n" // B3B2B1B0 -> mm1 + "movq %%mm0, %%mm2\n" + "pand KEEPG, %%mm2\n" + "psrlq $3, %%mm2\n" // G3G2G1G0 -> mm2 + "movq %%mm0, %%mm3\n" + "pand KEEPB, %%mm3\n" + "psllq $3, %%mm3\n" // G3G2G1G0 -> mm3 + + "movq %%mm2, %%mm0\n" + "punpcklbw %%mm1, %%mm2\n" + "punpckhbw %%mm1, %%mm0\n" + + "pxor %%mm5, %%mm5\n" + "movq %%mm3, %%mm4\n" + "punpcklbw %%mm5, %%mm3\n" + "punpckhbw %%mm5, %%mm4\n" + + "psllq $8, %%mm2\n" + "por %%mm2, %%mm3\n" // 0B1G1R10B0G0G0 -> mm3 + "psllq $8, %%mm0\n" + "por %%mm0, %%mm4\n" // 0B3G3R30B2G2G2 -> mm4 + + "movq %%mm3, 16%3\n" + "movq %%mm4, 24%3\n" + + "add $16, %0\n" + + // standard algorithm -------------------------------------------------- + + // pack rgb + // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + // ------------------------------ + // (uses: mm0, mm1) + "movd 8%3, %%mm0\n" + "psllq $24, %%mm0\n" + "movd 4%3, %%mm1\n" + "por %%mm1, %%mm0\n" + "psllq $24, %%mm0\n" + "movd %3, %%mm1\n" + "por %%mm0, %%mm1\n" + // ------------------------------ + + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + // pack rgb + // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1 + // ------------------------------ + // (uses: mm1, mm6) + "movd 20%3, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 16%3, %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 12%3, %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $8, %%mm1\n" + "movd 8%3, %%mm6\n" + "psrlq $16, %%mm6\n" + "por %%mm6, %%mm1\n" + // ------------------------------ + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, 36%3\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + //---------------------------------------------------------------------- + + // pack rgb + // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1 + // ------------------------------ + // (uses: mm1, mm7) + "movd 28%3, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 24%3, %%mm7\n" + "por %%mm7, %%mm1\n" + "psllq $16, %%mm1\n" + "movd 20%3, %%mm7\n" + "psrlq $8, %%mm7\n" + "por %%mm7, %%mm1\n" + // ------------------------------ + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + + "movq %%mm0, 44%3\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + + "movq 36%3, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + + //---------------------------------------------------------------------- + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + + //---------------------------------------------------------------------- + + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "movq 44%3, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + + "add $8, %1\n" + + "sub $8, %2\n" + "jnz 1b\n" + "emms\n" + + : + : "r" (rgbSource), "r" (lum), "m" (pixel), "m" (buf[0]) + + ); +} + +void rgb2y16bit_mmx_row_fast(unsigned char* rgb, unsigned char* lum, int pixel) +{ + __asm__ __volatile__ ( + "1:\n" + + // unpack hicolor ( pixel 1 - 4) + "movq (%0), %%mm0\n" + + "movq %%mm0, %%mm1\n" + "pand KEEPR, %%mm1\n" + "psrlq $11, %%mm1\n" // B3B2B1B0 -> mm1 + + "movq %%mm0, %%mm2\n" + "pand KEEPG, %%mm2\n" + "psrlq $5, %%mm2\n" // G3G2G1G0 -> mm2 + "movq %%mm0, %%mm3\n" + "pand KEEPB, %%mm3\n" // R3R2R1R0 -> mm3 + + // calculate Y + "movq %%mm3, %%mm4\n" + "pmullw Y_RED, %%mm4\n" + + "movq %%mm2, %%mm5\n" + "pmullw Y_GREEN, %%mm5\n" + "paddw %%mm5, %%mm4\n" + + "movq %%mm1, %%mm6\n" + "pmullw Y_BLUE, %%mm6\n" + "paddw %%mm6, %%mm4\n" + + "psrlw $7, %%mm4\n" // Y3Y2Y1Y0 -> mm4 + + "pxor %%mm5, %%mm5\n" + "packuswb %%mm5, %%mm4\n" + + "movd %%mm4, (%1)\n" + "add $4, %1\n" + + "add $8, %0\n" + + "sub $4, %2\n" + "jnz 1b\n" + + "emms\n" + + : + : "r" (rgb), "r" (lum), "m" (pixel) + ); +} + + +#endif +// INTEL + + diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h new file mode 100644 index 00000000..7e4d6508 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv16.h @@ -0,0 +1,74 @@ +/*************************************************************************** + rgb2yuv16.h - description + ------------------- + begin : Tue Nov 2 2000 + copyright : (C) 2000 by Christian Gerlach + email : cgerlach@rhrk.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __RGB2YUV16_H +#define __RGB2YUV16_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../yuvPicture.h" +#include "rgb2yuvdefs.h" + +// slow C implementation +void rgb2yuv16bit(unsigned char* rgbSource, + unsigned char* destLum, + unsigned char* destCr, + unsigned char* destCb,int height, int width); + + + +// +// We compile with MMX if we are on INTEL arch +// (this does not mean that we really support MMX, +// this is a seperate/runtime check) +// + +#ifdef INTEL + +void rgb2yuv16bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + +void rgb2yuv16bit_mmx_fast(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + +void rgb2yuv16bit_mmx422_row(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel); + +void rgb2y16bit_mmx_row(unsigned char* rgbSource, + unsigned char* lum, int pixel); + +void rgb2yuv16bit_mmx422_row_fast(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel); + +void rgb2y16bit_mmx_row_fast(unsigned char* rgb, + unsigned char* lum, int pixel); + + +#endif +// INTEL + + + +#endif diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp new file mode 100644 index 00000000..3e246e25 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.cpp @@ -0,0 +1,1143 @@ +/*************************************************************************** + rgb2yuv32.cpp - description + ------------------- + begin : Tue Nov 2 2000 + copyright : (C) 2000 by Christian Gerlach + email : cgerlach@rhrk.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "rgb2yuv32.h" +#include <iostream> + +void rgb2yuv32(unsigned char* rgb, unsigned char* dest) +{ + dest[0] = Y_RGB(rgb[0], rgb[1], rgb[2]); + dest[1] = U_RGB(rgb[0], rgb[1], rgb[2]); + dest[2] = V_RGB(rgb[0], rgb[1], rgb[2]); +} + +void rgb2yuv24bit(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + int width2 = width / 2; + int height2 = height / 2; + int r, g, b, row, col; + + for (row=0 ; row<height2 ; row++) { + for (col=0 ; col<width2 ; col++) { + r = *rgbSource++; + g = *rgbSource++; + b = *rgbSource++; + + *lum++ = Y_RGB(r, g, b); + *cr++ = U_RGB(r, g, b); + *cb++ = V_RGB(r, g, b); + + r = *rgbSource++; + g = *rgbSource++; + b = *rgbSource++; + + *lum++ = Y_RGB(r, g, b); + } + for (col=0 ; col<width ; col++) { + r = *rgbSource++; + g = *rgbSource++; + b = *rgbSource++; + + *lum++ = Y_RGB(r, g, b); + } + } +} + +void rgb2yuv32bit(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + + int width2 = width / 2; + int height2 = height / 2; + int r, g, b, row, col; + + for (row=0 ; row<height2 ; row++) { + for (col=0 ; col<width2 ; col++) { + r = *rgbSource++; + g = *rgbSource++; + b = *rgbSource++; + rgbSource ++; + + *lum++ = Y_RGB(r, g, b); + *cr++ = U_RGB(r, g, b); + *cb++ = V_RGB(r, g, b); + + r = *rgbSource++; + g = *rgbSource++; + b = *rgbSource++; + rgbSource++; + + *lum++ = Y_RGB(r, g, b); + } + for (col=0 ; col<width ; col++) { + r = *rgbSource++; + g = *rgbSource++; + b = *rgbSource++; + rgbSource ++; + + *lum++ = Y_RGB(r, g, b); + } + } +} + +#ifndef INTEL +void rgb2yuv24bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + std::cout << "RGB->YUV render not compiled for INTEL"<<std::endl; + exit(0); +} + +void rgb2yuv32bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + std::cout << "RGB->YUV render not compiled for INTEL"<<std::endl; + exit(0); +} + +#endif + +#ifdef INTEL + +void rgb2yuv24bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + int width2 = width / 2; + int height2 = height / 2; + int row; + int bytesPerLine = width * 3; + + for (row=0 ; row<height2 ; row++) { + rgb2yuv24bit_mmx422_row(rgbSource, lum, cr, cb, width); + rgbSource += bytesPerLine; + lum += width; + cr += width2; + cb += width2; + + rgb2y24bit_mmx_row(rgbSource, lum, width); + rgbSource += bytesPerLine; + lum += width; + } +} + +void rgb2yuv32bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width) { + + + int width2 = width / 2; + int height2 = height / 2; + int bytesPerLine = width * 4; + + for (int row=0 ; row<height2 ; row++) { + rgb2yuv32bit_mmx422_row(rgbSource, lum,cr, cb, width); + rgbSource += bytesPerLine; + lum += width; + cr += width2; + cb += width2; + + rgb2y32bit_mmx_row(rgbSource, lum, width); + rgbSource += bytesPerLine; + lum += width; + } +} + +void rgb2yuv24bit_mmx444_row(unsigned char* rgb, unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel) +{ + unsigned int buf[8]; + + // %5 = TEMP0 + // 8%5 = TEMPY + // 16%5 = TEMPU + // 24%5 = TEMPV + + __asm__ __volatile__ ( + "1:\n" + + "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5 + + "movq 8(%0),%%mm1\n" // load G2R2B1G1R1B0G0R0 + "paddd %%mm3, %%mm2\n" // U1U0 -> mm2 + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + "paddd %%mm5, %%mm4\n" // V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, %5\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6 + "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2 + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5 + "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm7 + "paddd %%mm7, %%mm6\n" // U3U2 -> mm6 + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6 + + "paddd %%mm5, %%mm3\n" // V3V2 -> mm3 + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3 + + "movq %%mm0, 8%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2 + + "movq %5, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "movq %%mm2, 16%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm4, 24%5\n" // (V3V2V1V0)/256 -> mm4 + + "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4 + + "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4 + "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0 + + "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4 + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4 + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3 + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "paddd %%mm6, %%mm0\n" // U5U4 -> mm0 + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7 + "paddd %%mm4, %%mm3\n" // V5V4 -> mm3 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4 + + "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4 + "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0 + + //---------------------------------------------------------------------- + + "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0 + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7 + "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3 + + "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "paddd OFFSETDX, %%mm4\n" // add offset to U7U6 + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5 + "paddd %%mm4, %%mm7\n" // U7U6 -> mm7 + + "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7 + + //---------------------------------------------------------------------- + + "movq 8%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0 + + "movq 16%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7 + "paddd %%mm5, %%mm1\n" // V7V6 -> mm1 + + "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256 + "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4 + + "movq 24%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5 + "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3 + "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0 + "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4 + + "movq %%mm4, (%2)\n" // store U + "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5 + + "movq %%mm5, (%3)\n" // store V + + "sub $8, %4\n" + "jnz 1b\n" + "emms\n" + + : + : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel), "m" (buf[0]) + ); +} + +void rgb2yuv24bit_mmx422_row(unsigned char* rgb, unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel) +{ + unsigned int buf[8]; + + // %5 = TEMP0 + // 8%5 = TEMPY + // 16%5 = TEMPU + // 24%5 = TEMPV + + __asm__ __volatile__ ( + "1:\n" + + "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5 + + "movq 8(%0),%%mm1\n" // load G2R2B1G1R1B0G0R0 + "paddd %%mm3, %%mm2\n" // U1U0 -> mm2 + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + "paddd %%mm5, %%mm4\n" // V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, %5\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6 + "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2 + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5 + "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm7 + "paddd %%mm7, %%mm6\n" // U3U2 -> mm6 + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6 + + "paddd %%mm5, %%mm3\n" // V3V2 -> mm3 + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3 + + "movq %%mm0, 8%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2 + + "movq %5, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "movq %%mm2, 16%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm4, 24%5\n" // (V3V2V1V0)/256 -> mm4 + + "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4 + + "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4 + "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0 + + "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4 + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4 + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3 + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "paddd %%mm6, %%mm0\n" // U5U4 -> mm0 + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7 + "paddd %%mm4, %%mm3\n" // V5V4 -> mm3 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4 + + "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4 + "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0 + + //---------------------------------------------------------------------- + + "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0 + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7 + "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3 + + "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "paddd OFFSETDX, %%mm4\n" // add offset to U7U6 + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5 + "paddd %%mm4, %%mm7\n" // U7U6 -> mm7 + + "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7 + + //---------------------------------------------------------------------- + + "movq 8%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0 + + "movq 16%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7 + "paddd %%mm5, %%mm1\n" // V7V6 -> mm1 + + "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256 + "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4 + + "movq 24%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5 + "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3 + "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0 + "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4 + + "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5 + + // pack U and V + "movq CLEARX, %%mm2\n" + "pand %%mm2, %%mm4\n" + "pand %%mm2, %%mm5\n" + + "packuswb %%mm5, %%mm4\n" + + "movd %%mm4, (%2)\n" + "psrlq $32, %%mm4\n" + "movd %%mm4, (%3)\n" + + "add $24, %0\n" + "add $8, %1\n" + "add $4, %2\n" + "add $4, %3\n" + + "sub $8, %4\n" + "jnz 1b\n" + "emms\n" + + : + : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel), "m" (buf[0]) + ); +} + +void rgb2yuv32bit_mmx422_row(unsigned char* rgb, unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel) +{ + unsigned int buf[8]; + + // %5 = TEMP0 + // 8%5 = TEMPY + // 16%5 = TEMPU + // 24%5 = TEMPV + + __asm__ __volatile__ ( + "1:\n" + + // pack rgb + // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + // ------------------------------ + // (uses: mm0, mm1) + "movd 8(%0), %%mm0\n" + "psllq $24, %%mm0\n" + "movd 4(%0), %%mm1\n" + "por %%mm1, %%mm0\n" + "psllq $24, %%mm0\n" + "movd (%0), %%mm1\n" + "por %%mm0, %%mm1\n" + // ------------------------------ + + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "pmaddwd UR0GRX, %%mm2\n" // urR1,ugG0+urR0 -> mm2 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "pmaddwd UBG0BX, %%mm3\n" // ubB1+ugG1,ubB0 -> mm3 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "pmaddwd VR0GRX, %%mm4\n" // vrR1,vgG0+vrR0 -> mm4 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB1+vgG1,vbB0 -> mm5 + + // pack rgb + // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1 + // ------------------------------ + // (uses: mm1, mm6) + "movd 20(%0), %%mm1\n" + "psllq $24, %%mm1\n" + "movd 16(%0), %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 12(%0), %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $8, %%mm1\n" + "movd 8(%0), %%mm6\n" + "psrlq $16, %%mm6\n" + "por %%mm6, %%mm1\n" + // ------------------------------ + + "paddd %%mm3, %%mm2\n" // U1U0 -> mm2 + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + "paddd %%mm5, %%mm4\n" // V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, %5\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + "pmaddwd UR0GRX, %%mm6\n" // urR3,ugG2+urR2 -> mm6 + "psrad $15, %%mm2\n" // 32-bit scaled U1U0 -> mm2 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "pmaddwd UBG0BX, %%mm7\n" // ubB3+ugG3,ubB2 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "pmaddwd VR0GRX, %%mm3\n" // vrR3,vgG2+vgR2 + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + "pmaddwd VBG0BX, %%mm5\n" // vbB3+vgG3,vbB2 -> mm5 + "psrad $15, %%mm4\n" // 32-bit scaled V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "paddd %%mm7, %%mm6\n" // U3U2 -> mm6 + + // pack rgb + // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1 + // ------------------------------ + // (uses: mm1, mm7) + "movd 28(%0), %%mm1\n" + "psllq $24, %%mm1\n" + "movd 24(%0), %%mm7\n" + "por %%mm7, %%mm1\n" + "psllq $16, %%mm1\n" + "movd 20(%0), %%mm7\n" + "psrlq $8, %%mm7\n" + "por %%mm7, %%mm1\n" + // ------------------------------ + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled U3U2 -> mm6 + + "paddd %%mm5, %%mm3\n" // V3V2 -> mm3 + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + "psrad $15, %%mm3\n" // 32-bit scaled V3V2 -> mm3 + + "movq %%mm0, 8%5\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + + "packssdw %%mm6, %%mm2\n" // 32-bit scaled U3U2U1U0 -> mm2 + + "movq %5, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "movq %%mm2, 16%5\n" // 32-bit scaled U3U2U1U0 -> TEMPU + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + "movq %%mm7, %%mm0\n" // B5G5R5B4 -> mm0 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + "packssdw %%mm3, %%mm4\n" // 32-bit scaled V3V2V1V0 -> mm4 + + //---------------------------------------------------------------------- + + "movq %%mm4, 24%5\n" // (V3V2V1V0)/256 -> mm4 + + "movq %%mm6, %%mm4\n" // B5B4G4R4 -> mm4 + + "pmaddwd UR0GRX, %%mm6\n" // urR5,ugG4+urR4 + "movq %%mm0, %%mm3\n" // B5G5R5B4 -> mm0 + + "pmaddwd UBG0BX, %%mm0\n" // ubB5+ugG5,ubB4 + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pmaddwd VR0GRX, %%mm4\n" // vrR5,vgG4+vrR4 -> mm4 + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "pmaddwd VBG0BX, %%mm3\n" // vbB5+vgG5,vbB4 -> mm3 + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "paddd %%mm6, %%mm0\n" // U5U4 -> mm0 + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "movq %%mm5, %%mm7\n" // R7B6G6R6 -> mm7 + "paddd %%mm4, %%mm3\n" // V5V4 -> mm3 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + "movq %%mm1, %%mm4\n" // B7G7R7B6 -> mm4 + + "pmaddwd UBG0BX, %%mm4\n" // ubB7+ugG7,ubB6 -> mm4 + "psrad $15, %%mm0\n" // 32-bit scaled U5U4 -> %%mm0 + + //---------------------------------------------------------------------- + + "paddd OFFSETWX, %%mm0\n" // add offset to U5U4 -> mm0 + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "movq %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd UR0GRX, %%mm7\n" // urR7,ugG6+ugR6 -> mm7 + "psrad $15, %%mm3\n" // 32-bit scaled V5V4 -> mm3 + + "pmaddwd VBG0BX, %%mm1\n" // vbB7+vgG7,vbB6 -> mm1 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "paddd OFFSETDX, %%mm4\n" // add offset to U7U6 + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + "pmaddwd VR0GRX, %%mm5\n" // vrR7,vgG6+vrR6 -> mm5 + "paddd %%mm4, %%mm7\n" // U7U6 -> mm7 + + "psrad $15, %%mm7\n" // 32-bit scaled U7U6 -> mm7 + + //---------------------------------------------------------------------- + + "movq 8%5, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packssdw %%mm7, %%mm0\n" // 32-bit scaled U7U6U5U4 -> mm0 + + "movq 16%5, %%mm4\n" // 32-bit scaled U3U2U1U0 -> mm4 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + "movq OFFSETBX, %%mm7\n" // 128,128,128,128 -> mm7 + "paddd %%mm5, %%mm1\n" // V7V6 -> mm1 + + "paddw %%mm7, %%mm4\n" // add offset to U3U2U1U0/256 + "psrad $15, %%mm1\n" // 32-bit scaled V7V6 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + + "packuswb %%mm0, %%mm4\n" // all 8 U values -> mm4 + "movq 24%5, %%mm5\n" // 32-bit scaled V3V2V1V0 -> mm5 + + "packssdw %%mm1, %%mm3\n" // V7V6V5V4 -> mm3 + "paddw %%mm7, %%mm5\n" // add offset to V3V2V1V0 + "paddw %%mm7, %%mm3\n" // add offset to V7V6V5V4 + + "packuswb %%mm3, %%mm5\n" // ALL 8 V values -> mm5 + + "movq CLEARX, %%mm2\n" + "pand %%mm2, %%mm4\n" + "pand %%mm2, %%mm5\n" + + "packuswb %%mm5, %%mm4\n" + + "movd %%mm4, (%2)\n" + "psrlq $32, %%mm4\n" + "movd %%mm4, (%3)\n" + + "add $32, %0\n" + "add $8, %1\n" + "add $4, %2\n" + "add $4, %3\n" + + "sub $8, %4\n" + "jnz 1b\n" + + "emms\n" + + : + : "r" (rgb), "r" (lum), "r" (cr), "r" (cb), "m" (pixel), "m" (buf[0]) + + ); +} + +void rgb2y24bit_mmx_row(unsigned char* rgbSource, unsigned char* lum, int pixel) +{ + unsigned int buf[4]; + + // %3 = TEMP0 + // 8%3 = TEMPY + + __asm__ __volatile__ ( + "1:\n" + + "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + "movq 8(%0),%%mm1\n" // load G2R2B1G1R1B0G0R0 + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, %3\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + //---------------------------------------------------------------------- + + "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm7 + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + + "movq %%mm0, 8%3\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + + "movq %3, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + + //---------------------------------------------------------------------- + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + + //---------------------------------------------------------------------- + + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "movq 8%3, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + + "add $24, %0\n" + "add $8, %1\n" + + "sub $8, %2\n" + "jnz 1b\n" + "emms\n" + + : + : "r" (rgbSource), "r" (lum), "m" (pixel), "m" (buf[0]) + + ); +} + +void rgb2y32bit_mmx_row(unsigned char* rgbSource, unsigned char* lum, int pixel) +{ + unsigned int buf[4]; + + // %3 = TEMP0 + // 8%3 = TEMPY + + __asm__ __volatile__ ( + "1:\n" + + // pack rgb + // was: "movq (%0), %%mm1\n" // load G2R2B1G1R1B0G0R0 + // ------------------------------ + // (uses: mm0, mm1) + "movd 8(%0), %%mm0\n" + "psllq $24, %%mm0\n" + "movd 4(%0), %%mm1\n" + "por %%mm1, %%mm0\n" + "psllq $24, %%mm0\n" + "movd (%0), %%mm1\n" + "por %%mm0, %%mm1\n" + // ------------------------------ + + "pxor %%mm6, %%mm6\n" // 0 -> mm6 + "movq %%mm1, %%mm0\n" // G2R2B1G1R1B0G0R0 -> mm0 + "psrlq $16, %%mm1\n" // 00G2R2B1G1R1B0 -> mm1 + "punpcklbw ZEROSX, %%mm0\n" // R1B0G0R0 -> mm0 + "movq %%mm1, %%mm7\n" // 00G2R2B1G1R1B0 -> mm7 + "punpcklbw ZEROSX, %%mm1\n" // B1G1R1B0 -> mm1 + "movq %%mm0, %%mm2\n" // R1B0G0R0 -> mm2 + "pmaddwd YR0GRX, %%mm0\n" // yrR1,ygG0+yrR0 -> mm0 + "movq %%mm1, %%mm3\n" // B1G1R1B0 -> mm3 + "pmaddwd YBG0BX, %%mm1\n" // ybB1+ygG1,ybB0 -> mm1 + "movq %%mm2, %%mm4\n" // R1B0G0R0 -> mm4 + "movq %%mm3, %%mm5\n" // B1G1R1B0 -> mm5 + "punpckhbw %%mm6, %%mm7\n" // 00G2R2 -> mm7 + "paddd %%mm1, %%mm0\n" // Y1Y0 -> mm0 + + // pack rgb + // was: "movq 8(%0),%%mm1\n" // R5B4G4R4B3G3R3B2 -> mm1 + // ------------------------------ + // (uses: mm1, mm6) + "movd 20(%0), %%mm1\n" + "psllq $24, %%mm1\n" + "movd 16(%0), %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $24, %%mm1\n" + "movd 12(%0), %%mm6\n" + "por %%mm6, %%mm1\n" + "psllq $8, %%mm1\n" + "movd 8(%0), %%mm6\n" + "psrlq $16, %%mm6\n" + "por %%mm6, %%mm1\n" + // ------------------------------ + + "movq %%mm1, %%mm6\n" // R5B4G4R4B3G3R3B2 -> mm6 + "punpcklbw ZEROSX, %%mm1\n" // B3G3R3B2 -> mm1 + + //---------------------------------------------------------------------- + + "movq %%mm1, %%mm5\n" // B3G3R3B2 -> mm5 + "psllq $32, %%mm1\n" // R3B200 -> mm1 + + "paddd %%mm7, %%mm1\n" // R3B200+00G2R2=R3B2G2R2->mm1 + + "punpckhbw ZEROSX, %%mm6\n" // R5B4G4R3 -> mm6 + "movq %%mm1, %%mm3\n" // R3B2G2R2 -> mm3 + + "pmaddwd YR0GRX, %%mm1\n" // yrR3,ygG2+yrR2 -> mm1 + "movq %%mm5, %%mm7\n" // B3G3R3B2 -> mm7 + + "pmaddwd YBG0BX, %%mm5\n" // ybB3+ygG3,ybB2 -> mm5 + "psrad $15, %%mm0\n" // 32-bit scaled Y1Y0 -> mm0 + + "movq %%mm6, %3\n" // R5B4G4R4 -> TEMP0 + "movq %%mm3, %%mm6\n" // R3B2G2R2 -> mm6 + + "paddd %%mm5, %%mm1\n" // Y3Y2 -> mm1 + "movq %%mm7, %%mm5\n" // B3G3R3B2 -> mm5 + "psrad $15, %%mm1\n" // 32-bit scaled Y3Y2 -> mm1 + + "packssdw %%mm1, %%mm0\n" // Y3Y2Y1Y0 -> mm0 + + //---------------------------------------------------------------------- + + // pack rgb + // was: "movq 16(%0), %%mm1\n" // B7G7R7B6G6R6B5G5 -> mm1 + // ------------------------------ + // (uses: mm1, mm7) + "movd 28(%0), %%mm1\n" + "psllq $24, %%mm1\n" + "movd 24(%0), %%mm7\n" + "por %%mm7, %%mm1\n" + "psllq $16, %%mm1\n" + "movd 20(%0), %%mm7\n" + "psrlq $8, %%mm7\n" + "por %%mm7, %%mm1\n" + // ------------------------------ + + "movq %%mm1, %%mm7\n" // B7G7R7B6G6R6B5G5 -> mm1 + + "psllq $16, %%mm7\n" // R7B6G6R6B5G500 -> mm7 + + "movq %%mm7, %%mm5\n" // R7B6G6R6B5G500 -> mm5 + + "movq %%mm0, 8%3\n" // 32-bit scaled Y3Y2Y1Y0 -> TEMPY + + "movq %3, %%mm0\n" // R5B4G4R4 -> mm0 + + "punpcklbw ZEROSX, %%mm7\n" // B5G500 -> mm7 + "movq %%mm0, %%mm6\n" // R5B4G4R4 -> mm6 + + "psrlq $32, %%mm0\n" // 00R5B4 -> mm0 + + "paddw %%mm0, %%mm7\n" // B5G5R5B4 -> mm7 + "movq %%mm6, %%mm2\n" // B5B4G4R4 -> mm2 + + "pmaddwd YR0GRX, %%mm2\n" // yrR5,ygG4+yrR4 -> mm2 + + "pmaddwd YBG0BX, %%mm7\n" // ybB5+ygG5,ybB4 -> mm7 + + //---------------------------------------------------------------------- + "paddd %%mm7, %%mm2\n" // Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "pxor %%mm7, %%mm7\n" // 0 -> mm7 + + "punpckhbw %%mm7, %%mm1\n" // B7G7R7B6 -> mm1 + + "movq %%mm1, %%mm6\n" // B7G7R7B6 -> mm6 + + "pmaddwd YBG0BX, %%mm6\n" // ybB7+ygG7,ybB6 -> mm6 + "punpckhbw %%mm7, %%mm5\n" // R7B6G6R6 -> mm5 + + "pmaddwd YR0GRX, %%mm5\n" // yrR7,ygG6+yrR6 -> mm5 + + //---------------------------------------------------------------------- + + "psrad $15, %%mm2\n" // 32-bit scaled Y5Y4 -> mm2 + + "paddd %%mm5, %%mm6\n" // Y7Y6 -> mm6 + "psrad $15, %%mm6\n" // 32-bit scaled Y7Y6 -> mm6 + + "packssdw %%mm6, %%mm2\n" // Y7Y6Y5Y4 -> mm2 + + //---------------------------------------------------------------------- + + "movq 8%3, %%mm6\n" // 32-bit scaled Y3Y2Y1Y0 -> mm6 + "packuswb %%mm2, %%mm6\n" // all 8 Y values -> mm6 + + //---------------------------------------------------------------------- + + "movq %%mm6, (%1)\n" // store Y + + "add $32, %0\n" + "add $8, %1\n" + + "sub $8, %2\n" + "jnz 1b\n" + "emms\n" + + : + : "r" (rgbSource), "r" (lum), "r" (pixel), "m" (buf[0]) + + ); +} + +#endif +// INTEL + diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h new file mode 100644 index 00000000..75fea27f --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuv32.h @@ -0,0 +1,93 @@ +/*************************************************************************** + rgb2yuv32.h - description + ------------------- + begin : Tue Nov 2 2000 + copyright : (C) 2000 by Christian Gerlach + email : cgerlach@rhrk.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _RGB2YUV32_H_ +#define _RGB2YUV32_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../yuvPicture.h" +#include "rgb2yuvdefs.h" + +void rgb2yuv32(unsigned char* rgb, unsigned char* dest); + +// slow C rountines +void rgb2yuv24bit(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + +void rgb2yuv32bit(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + + + + +#ifndef INTEL +void rgb2yuv24bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + +void rgb2yuv32bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); +#endif + + +#ifdef INTEL + +void rgb2yuv24bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + +void rgb2yuv32bit_mmx(unsigned char* rgbSource, + unsigned char* lum, + unsigned char* cr, + unsigned char* cb,int height, int width); + + +void rgb2yuv24bit_mmx444_row(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel); + + +void rgb2yuv24bit_mmx422_row(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel); + +void rgb2yuv32bit_mmx422_row(unsigned char* rgb, + unsigned char* lum, unsigned char* cr, + unsigned char* cb, int pixel); + +void rgb2y24bit_mmx_row(unsigned char* rgbSource, + unsigned char* lum, int pixel); + +void rgb2y32bit_mmx_row(unsigned char* rgbSource, + unsigned char* lum, int pixel); + +#endif +//INTEL + + +#endif diff --git a/mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h b/mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h new file mode 100644 index 00000000..5c7ae574 --- /dev/null +++ b/mpeglib/lib/util/render/dither2YUV/rgb2yuvdefs.h @@ -0,0 +1,74 @@ +/*************************************************************************** + rgb2yuvdefs.h - description + ------------------- + begin : Tue Nov 2 2000 + copyright : (C) 2000 by Christian Gerlach + email : cgerlach@rhrk.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __RGB2YUVDEFS_H +#define __RGB2YUVDEFS_H + +/* gcc 3.3.1 and later optimise the "not used" (only in asm code) + symbols away. So we need to mark them as used. */ +#if defined(__GNUC_PREREQ__) && !defined(__GNUC_PREREQ) +#define __GNUC_PREREQ __GNUC_PREREQ__ +#endif +#ifdef __GNUC_PREREQ +#if __GNUC_PREREQ (3,1) +# define __attribute_used__ __attribute__ ((__used__)) +#else +# define __attribute_used__ +#endif +#else +# define __attribute_used__ +#endif + +// hicolor mode (16 bit) with r(5) g(6) b(5) bits (reverse order b, g, r) +#define RED(rgb) (unsigned char) ((rgb) << 3) +#define GREEN(rgb) (((rgb) & 0x7e0) >> 3) +#define BLUE(rgb) (((rgb) & 0xf800) >> 8) + +#define YUV_SHIFT 15 +#define YUV_HALF (1<<(YUV_SHIFT-1)) +#define YUV_ONE (1<<YUV_SHIFT) +#define Y_R ((int)( 0.299 * YUV_ONE )) +#define Y_G ((int)( 0.587 * YUV_ONE )) +#define Y_B ((int)( 0.114 * YUV_ONE )) +#define U_R ((int)(-0.146 * YUV_ONE )) +#define U_G ((int)(-0.288 * YUV_ONE )) +#define U_B ((int)( 0.434 * YUV_ONE )) +#define V_R ((int)( 0.617 * YUV_ONE )) +#define V_G ((int)(-0.517 * YUV_ONE )) +#define V_B ((int)(-0.100 * YUV_ONE )) + +#define Y_RGB(R,G,B) (( Y_R * (R) + Y_G * (G) + Y_B * (B)) >> YUV_SHIFT) +#define U_RGB(R,G,B) ((( U_R * (R) + U_G * (G) + U_B * (B)) >> YUV_SHIFT) + 128) +#define V_RGB(R,G,B) ((( V_R * (R) + V_G * (G) + V_B * (B)) >> YUV_SHIFT) + 128) + +static unsigned char __attribute_used__ CLEARX[8] = { 255, 0, 255, 0, 255, 0, 255, 0 }; +static short __attribute_used__ ZEROSX[4] = { 0, 0, 0, 0 }; + +static short __attribute_used__ OFFSETDX[4] = { 0, 64, 0, 64 }; +static short __attribute_used__ OFFSETWX[4] = { 128, 0, 128, 0 }; +static short __attribute_used__ OFFSETBX[4] = { 128, 128, 128, 128 }; + +static short __attribute_used__ YR0GRX[4] = { Y_R, Y_G, 0, Y_R }; +static short __attribute_used__ YBG0BX[4] = { Y_B, 0, Y_G, Y_B }; + +static short __attribute_used__ UR0GRX[4] = { U_R, U_G, 0, U_R }; +static short __attribute_used__ UBG0BX[4] = { U_B, 0, U_G, U_B }; + +static short __attribute_used__ VR0GRX[4] = { V_R, V_G, 0, V_R }; +static short __attribute_used__ VBG0BX[4] = { V_B, 0, V_G, V_B }; + +#endif diff --git a/mpeglib/lib/util/render/imageBase.cpp b/mpeglib/lib/util/render/imageBase.cpp new file mode 100644 index 00000000..040486ea --- /dev/null +++ b/mpeglib/lib/util/render/imageBase.cpp @@ -0,0 +1,76 @@ +/* + base clase for X11 images (stores important parameters and dither pic) + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "imageBase.h" + +#include <iostream> + +using namespace std; + +ImageBase::ImageBase() { + identifier = NULL; +} + + +ImageBase::~ImageBase() { + if (identifier != NULL) + delete [] identifier; +} + +void ImageBase::init(XWindow* xWindow, YUVPicture*) +{ + cout << "direct virtual call: ImageBase::init "<<endl; +} + +int ImageBase::support() { + cout << "direct virtual call: ImageBase::support "<<endl; + return false; +} + +int ImageBase::openImage(int) { + cout << "direct virtual call: ImageBase::openImage "<<endl; + return false; +} + + +int ImageBase::closeImage(){ + cout << "direct virtual call: ImageBase::closeImage "<<endl; + return false; +} + +void ImageBase::ditherImage(YUVPicture*) { + cout << "direct virtual call: ImageBase::ditherImage "<<endl; +} + + +void ImageBase::putImage() { + cout << "direct virtual call: ImageBase::putImage "<<endl; +} + +void ImageBase::putImage(int ,int ) { + cout << "direct virtual call: ImageBase::putImage(w,h) "<<endl; +} + +void ImageBase::setIdentifier(const char *id) +{ + if (identifier != NULL) + delete [] identifier; + + identifier = new char [strlen(id) + 1]; + strcpy(identifier, id); +} + +char *ImageBase::getIdentifier() +{ + return identifier; +} diff --git a/mpeglib/lib/util/render/imageBase.h b/mpeglib/lib/util/render/imageBase.h new file mode 100644 index 00000000..e1f7ae8c --- /dev/null +++ b/mpeglib/lib/util/render/imageBase.h @@ -0,0 +1,140 @@ +/* + base clase for X11 images (stores important parameters and dither pic) + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __IMAGEBASE_H +#define __IMAGEBASE_H + + +#include <stdio.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "yuvPicture.h" +#include "dither/ditherWrapper.h" + + + +#define _IMAGE_NONE 0 +#define _IMAGE_DESK 1 +#define _IMAGE_FULL 2 +#define _IMAGE_DOUBLE 4 +#define _IMAGE_RESIZE 8 +#define _IMAGE_DISABLED 16 + + +#define HAS_DESK(image) ((((image)->supportedModes) & _IMAGE_DESK) > 0) +#define HAS_FULL(image) ((((image)->supportedModes) & _IMAGE_FULL) > 0) +#define HAS_DOUBLE(image) ((((image)->supportedModes) & _IMAGE_DOUBLE) > 0) +#define HAS_RESIZE(image) ((((image)->supportedModes) & _IMAGE_RESIZE) > 0) +#define IS_DISABLED(image) ((((image)->supportedModes) & _IMAGE_DISABLED) > 0) + +#define IS_DESK(mode) (((mode) & _IMAGE_DESK) > 0) +#define IS_FULL(mode) (((mode) & _IMAGE_FULL) > 0) +#define IS_DOUBLE(mode) (((mode) & _IMAGE_DOUBLE) > 0) +#define IS_RESIZEABLE(mode) (((mode) & _IMAGE_RESIZE) > 0) + + +/** + This class creates from a given X11 Window a special image to + display. + An image has some characteristics, like startadress, width height, + if each row has a terminating modifier etc... + + The image is resposible for the conversion from the yuv + format to the destination. + + It is initialized with the constructed x11Window. + During a mode-switch (which is handled by x11window) the following + sequence is called: + + support() ->true/false if this image type is supported + (switching to it is allowed) + + openImage() called once when we switch to this + image type + + ditherImage(..) for the conversion from yuv->rgb + obviously called for every image + putImage(..) time for display it + + closeImage() called once, when we leave this image type + + + This sequence is necessary, because the user likey to switch + form desktop display to dga fullscreen. + + The following image classes seems to be useful: + + imageDeskX11 : standard ximage, maybe with shared mem support + full software rendering + imageDeskXV : image with hardware yuv->rgb rendering + + imageDGAFull : dga 2.0 full software rendering (needs root) + imageXVFull : fullscreen hardware yuv->rgb rendering + + The hierarchy is as follows: + + (desk mode) + imageStdX11 : fallback, should work everywhere + imageStdXV : if supported imageStdX11 is disabled + + (fullscreen mode) + imageDGAFull : + imageXVFull : + + The supported switches between the modes are + + + desktop <-> fullscreen mode. + + +*/ + + +class XWindow; + +class ImageBase { + private: + char *identifier; + + public: + unsigned int supportedModes; + + public: + ImageBase(); + virtual ~ImageBase(); + + virtual void init(XWindow* xWindow, YUVPicture* pic = NULL); + + virtual int support(); + + virtual int openImage(int imageMode); + virtual int closeImage(); + + virtual void ditherImage(YUVPicture* pic); + virtual void putImage(); + virtual void putImage(int w,int h); + + virtual int active() { return true; } + + void setIdentifier(const char *id); + char *getIdentifier(); + +}; + +#endif + diff --git a/mpeglib/lib/util/render/pictureArray.cpp b/mpeglib/lib/util/render/pictureArray.cpp new file mode 100644 index 00000000..71381ea0 --- /dev/null +++ b/mpeglib/lib/util/render/pictureArray.cpp @@ -0,0 +1,101 @@ +/* + nice try of an X11 output plugin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "pictureArray.h" + + + +PictureArray::PictureArray(int width, int height) { + int i; + pictureCallback=NULL; + imageType=PICTURE_NO_TYPE; + + for (i=0;i<_PICTURE_ARRAY_SIZE;i++) { + pictureArray[i]=new YUVPicture(width,height); + imageType=pictureArray[i]->getImageType(); + } + + /* Find a pict image structure in ring buffer not currently locked. */ + /* Set current pict image structure to the one just found in ring. */ + + current=pictureArray[0]; + past=pictureArray[1]; + future=pictureArray[2]; + + picPerSec=0.0; + this->width=width; + this->height=height; + +} + + +PictureArray::~PictureArray() { + int i; + for (i=0;i<_PICTURE_ARRAY_SIZE;i++) { + if (pictureArray[i] != NULL) { + delete pictureArray[i]; + pictureArray[i]=NULL; + } + + } +} + + + + + +void PictureArray::setPicturePerSecond(double val) { + picPerSec=val; +} + + +double PictureArray::getPicturePerSecond() { + return picPerSec; +} + + + + +void PictureArray::forward() { + /* Update past and future references if needed. */ + + YUVPicture* tmp=past; + + past = future; + future = current; + current = tmp; + + +} + + + + +YUVPicture* PictureArray::getYUVPictureCallback() { + return pictureCallback; +} + + +void PictureArray::setYUVPictureCallback(YUVPicture* pic) { + this->pictureCallback=pic; +} + + +void PictureArray::setImageType(int imageType) { + int i; + this->imageType=imageType; + for (i=0;i<_PICTURE_ARRAY_SIZE;i++) { + pictureArray[i]->setImageType(imageType); + } +} + diff --git a/mpeglib/lib/util/render/pictureArray.h b/mpeglib/lib/util/render/pictureArray.h new file mode 100644 index 00000000..6a7e731c --- /dev/null +++ b/mpeglib/lib/util/render/pictureArray.h @@ -0,0 +1,76 @@ +/* + nice try of an X11 output plugin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __VIDEOOUTPUTX11_H +#define __VIDEOOUTPUTX11_H + + +#include "yuvPicture.h" +#include <stdlib.h> + +#define _PICTURE_ARRAY_SIZE 5 + +class PictureArray { + + class YUVPicture* pictureArray[_PICTURE_ARRAY_SIZE]; + + class YUVPicture* past; /* Past predictive frame. */ + class YUVPicture* future; /* Future predictive frame. */ + class YUVPicture* current; /* Current frame. */ + + double picPerSec; + int width; + int height; + + int imageType; + + public: + PictureArray(int width, int height); + ~PictureArray(); + + inline YUVPicture* getPast() {return past;} + inline YUVPicture* getFuture() {return future;} + inline YUVPicture* getCurrent() {return current;} + + + inline void setPast(YUVPicture* pic) {past=pic;} + inline void setFuture(YUVPicture* pic) {future=pic;} + inline void setCurrent(YUVPicture* pic) {current=pic;} + inline int getWidth() { return width; } + inline int getWidth_Half() { return width/2; } + + // attention with these! + // these are shares pointer + // only call after mpegVidRsrc and then set them back to NULL + YUVPicture* getYUVPictureCallback(); + void setYUVPictureCallback(YUVPicture* pic); + + + void forward(); + + void setPicturePerSecond(double val); + double getPicturePerSecond(); + + // use these to swap the yuv Mode + inline int getImageType() { return imageType; } + void setImageType(int mode); + + + private: + YUVPicture* pictureCallback; + + +}; +#endif + diff --git a/mpeglib/lib/util/render/renderMachine.cpp b/mpeglib/lib/util/render/renderMachine.cpp new file mode 100644 index 00000000..c6327930 --- /dev/null +++ b/mpeglib/lib/util/render/renderMachine.cpp @@ -0,0 +1,205 @@ + /* + puts the yuv images onto a surface + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "renderMachine.h" + +#include <iostream> + +using namespace std; + + +RenderMachine::RenderMachine() { + +#ifndef SDL_WRAPPER + surface=new X11Surface(); +#endif +#ifdef SDL_WRAPPER + surface=new SDLSurface(); +#endif + + + pictureArray=NULL; + + startTime=new TimeStamp(); + endTime=new TimeStamp(); + + initialMode = _IMAGE_DESK; +} + + +RenderMachine::~RenderMachine() { + + + closeWindow(); + delete surface; + + delete startTime; + delete endTime; + +} + + + + + + +void RenderMachine::waitRestTime() { + endTime->gettimeofday(); + startTime->minus(endTime,endTime); + endTime->waitForIt(); + +} + +int RenderMachine::x11WindowId() +{ + return surface->x11WindowId(); +} + + +int RenderMachine::openWindow(int width, + int height,const char *title) { +if (surface->open(width,height,title)) { + pictureArray=new PictureArray(width, height); + + return switchToMode(initialMode); + } + return false; +} + + +void RenderMachine::closeWindow() { + + if (surface->isOpen()==false) { + return; + } + if (pictureArray != NULL) { + delete pictureArray; + pictureArray=NULL; + } + surface->close(); +} + +/** + important method. This is our only way to switch from + fullscreen back to the desktop screen. + This method is called if the video end (normal or by user request) + We dont have a callback, thus after the image stops, we would + never get events. +*/ +void RenderMachine::flushWindow() { + + // we always switch back to desk mode. + if (IS_FULL(surface->getImageMode())) { + switchToMode(surface->getImageMode() ^ _IMAGE_DESK ^ _IMAGE_FULL); + } + + +} + + + + +void RenderMachine::putImage(YUVPicture* pic, + TimeStamp* waitTime, + TimeStamp* ) { + if (pic == NULL) { + cout << "pic is null"<<endl; + return; + } + startTime->gettimeofday(); + startTime->addOffset(waitTime); + + // need dither? + surface->dither(pic); + + int nextMode; + if (surface->checkEvent(&nextMode) == true) { + switchToMode(nextMode); + } + surface->putImage(pic); + waitRestTime(); +} + + +int RenderMachine::switchToMode(int mode) { + if (surface->getImageMode() != mode) { + surface->closeImage(); + if (mode != _IMAGE_NONE) { + surface->openImage(mode); + } + + else { + cout << "no imageMode, no open, that's life"<<endl; + return false; + } + } + return true; +} + + + +PictureArray* RenderMachine::lockPictureArray() { + return pictureArray; +} + + +void RenderMachine::unlockPictureArray(PictureArray* pictureArray) { + + // chance to switch mode + + + // put picture out + if (surface->getImageMode() != _IMAGE_NONE) { + YUVPicture* pic=pictureArray->getYUVPictureCallback(); + if (pic != NULL) { + TimeStamp* waitTime=pic->getWaitTime(); + TimeStamp* earlyTime=pic->getEarlyTime(); + putImage(pic,waitTime,earlyTime); + } + } else { + cout << "no mode selected"<<endl; + } +} + + +void RenderMachine::config(const char* key, + const char* value,void* user_data) { + if (strcmp(key,"getDepth")==0) { + int* val=(int*)user_data; + *val=surface->getDepth(); + } + if (surface != NULL) { + int mode = surface->getImageMode(); + if (strcmp(key,"toggleFullscreen")==0) { + if (surface->findImage(mode ^ _IMAGE_FULL) != NULL) { + if (surface->isOpen()) + switchToMode(mode ^ _IMAGE_FULL); + else + initialMode = _IMAGE_FULL; + } + } + if (strcmp(key,"toggleDouble")==0) { + if (surface->findImage(mode ^ _IMAGE_DOUBLE) != NULL) { + if (surface->isOpen()) + switchToMode(mode ^ _IMAGE_DOUBLE); + else + initialMode = _IMAGE_DOUBLE; + } + } + } + + surface->config(key,value,user_data); +} + + + diff --git a/mpeglib/lib/util/render/renderMachine.h b/mpeglib/lib/util/render/renderMachine.h new file mode 100644 index 00000000..728a6740 --- /dev/null +++ b/mpeglib/lib/util/render/renderMachine.h @@ -0,0 +1,90 @@ +/* + puts the yuv images onto a surface + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __RENDERMACHINE_H +#define __RENDERMACHINE_H + + + + +/** + RenderMachine. We still have the problem, because of performance, + that we cannot have a yuv picture format in the decoder + and one in the output to x11. they must be shared. + XV support then directly works on them and SDL images + can be exported to the decoder as well. + + Another point is : mode switch. User want desktop->fullscreen switch. + Due to the threaded nature, we must have a single synchronization + point, when we know that the decoder currently does _not_ decode + so that we can switch the imaged and free the memory. + + Some points are currently unclear, for example how to handle + applications, which want to redirect the image into their own + buffers, but hey, there are that many classes and layers + I really think it should be doable somehow + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef SDL_WRAPPER +#include "x11/x11Surface.h" +#endif + +#ifdef SDL_WRAPPER +#include "sdl/sdlSurface.h" +#endif + +#include "pictureArray.h" +#include "../abstract/abs_thread.h" + +class RenderMachine { + + + Surface* surface; + PictureArray* pictureArray; + + + TimeStamp* startTime; + TimeStamp* endTime; + + int initialMode; + + public: + RenderMachine(); + ~RenderMachine(); + + int openWindow(int width, int height,const char *title); + int x11WindowId(); + void closeWindow(); + void flushWindow(); + + + PictureArray* lockPictureArray(); + void unlockPictureArray(PictureArray* pictureArray); + + void config(const char* key, const char* value,void* user_data); + + private: + void waitRestTime(); + void putImage(YUVPicture* pic,TimeStamp* waitTime,TimeStamp* earlyTime); + + int switchToMode(int mode); + +}; +#endif diff --git a/mpeglib/lib/util/render/sdl/Makefile.am b/mpeglib/lib/util/render/sdl/Makefile.am new file mode 100644 index 00000000..1a4b85eb --- /dev/null +++ b/mpeglib/lib/util/render/sdl/Makefile.am @@ -0,0 +1,43 @@ +# player - Makefile.am + +INCLUDES = $(all_includes) + + +noinst_LTLIBRARIES = libutilsdl.la + +noinst_HEADERS = imageDeskSDL.h sdlSurface.h + +libutilsdl_la_SOURCES = imageDeskSDL.cpp sdlSurface.cpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mpeglib/lib/util/render/sdl/imageDeskSDL.cpp b/mpeglib/lib/util/render/sdl/imageDeskSDL.cpp new file mode 100644 index 00000000..b1ff9a7c --- /dev/null +++ b/mpeglib/lib/util/render/sdl/imageDeskSDL.cpp @@ -0,0 +1,110 @@ +/* + SDL surface output + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "imageDeskSDL.h" + +#ifdef SDL_WRAPPER + + +ImageDeskSDL::ImageDeskSDL() { + + this->surface=NULL; + this->rect=NULL; + imageMode=_IMAGE_NONE; + lSupport=true; + image=NULL; +} + + +ImageDeskSDL::~ImageDeskSDL() { + closeImage(); + cout << "SDL destry needed"<<endl; +} + + + +int ImageDeskSDL::support() { + return lSupport; +} + + +void ImageDeskSDL::init(XWindow* xWindow, YUVPicture* pic) { + cout << "ImageDeskSDL::init"<<endl; + this->surface=(SDL_Surface*)xWindow; + this->rect=(SDL_Rect*)pic; +} + +int ImageDeskSDL::openImage(int imageMode) { + int w=rect->w; + int h=rect->h; + this->imageMode=imageMode; + /* Create a YV12 image (Y + V + U) */ + cout << "CreateYUVOverlay -s"<<imageMode<<" w:"<<w<<" h:"<<h<<endl; + image = SDL_CreateYUVOverlay(w,h, + SDL_YV12_OVERLAY, + surface); + if (image == NULL) { + cout << "error creating image"<<endl; + exit(0); + } + cout << "CreateYUVOverlay -e"<<endl; + return true; +} + + +int ImageDeskSDL::closeImage() { + if (image != NULL) { + cout << "FreeYUVOverlay -s"<<endl; + SDL_FreeYUVOverlay(image); + // otherwise test of NULL will fail + image = NULL; + cout << "FreeYUVOverlay -e"<<endl; + } + return true; +} + + + +void ImageDeskSDL::ditherImage(YUVPicture* pic) { + + int w=pic->getWidth(); + int h=pic->getHeight(); + int size=w*h+(w*h)/2; + SDL_LockYUVOverlay(image); + memcpy(*((char**)image->pixels),pic->getLuminancePtr(),size); + SDL_UnlockYUVOverlay(image); + +} + + +void ImageDeskSDL::putImage(int w, int h) { + SDL_Rect dest; + dest.x=0; + dest.y=0; + dest.w=rect->w; + dest.h=rect->h; + if (imageMode & _IMAGE_RESIZE) { + dest.w = w; + dest.h = h; + } + + if (imageMode & _IMAGE_DOUBLE) { + dest.w*=2; + dest.h*=2; + } + SDL_DisplayYUVOverlay(image,&dest); + +} + +#endif + diff --git a/mpeglib/lib/util/render/sdl/imageDeskSDL.h b/mpeglib/lib/util/render/sdl/imageDeskSDL.h new file mode 100644 index 00000000..1bccb94a --- /dev/null +++ b/mpeglib/lib/util/render/sdl/imageDeskSDL.h @@ -0,0 +1,65 @@ +/* + SDL surface output + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __IMAGEDESKSDL_H +#define __IMAGEDESKSDL_H + +#include "../imageBase.h" + + + +#ifndef SDL_WRAPPER + class ImageDeskSDL : public ImageBase { + }; +#endif + +#ifdef SDL_WRAPPER + +#if defined WIN32 +#include <SDL.h> +#include <SDL_video.h> +#else +#include <SDL/SDL.h> +#include <SDL/SDL_video.h> +#endif + +class ImageDeskSDL : public ImageBase { + + int lSupport; + SDL_Overlay *image; + + SDL_Surface* surface; + SDL_Rect* rect; + int imageMode; + + public: + ImageDeskSDL(); + ~ImageDeskSDL(); + + int support(); + void init(XWindow* xWindow, YUVPicture* pic=NULL); + + + int openImage(int imageMode); + int closeImage(); + + void ditherImage(YUVPicture* pic); + + void putImage(int w, int h); + + + +}; +#endif + +#endif diff --git a/mpeglib/lib/util/render/sdl/sdlSurface.cpp b/mpeglib/lib/util/render/sdl/sdlSurface.cpp new file mode 100644 index 00000000..86ef41bb --- /dev/null +++ b/mpeglib/lib/util/render/sdl/sdlSurface.cpp @@ -0,0 +1,219 @@ +/* + surface wrapper for SDL + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "sdlSurface.h" + + +#ifdef SDL_WRAPPER + + +SDLSurface::SDLSurface() { + surface=NULL; + lOpen=false; + imageMode=_IMAGE_NONE; + lSDLInit=false; + imageDeskSDL=new ImageDeskSDL(); +} + + +SDLSurface::~SDLSurface() { + close(); + if (imageCurrent != NULL) { + imageCurrent->closeImage(); + delete imageCurrent; + // otherwise test of NULL will fail + imageCurrent = NULL; + } +} + + +int SDLSurface::isOpen() { + return lOpen; +} + +int SDLSurface::getImageMode() { + return imageMode; +} + +int SDLSurface::open(int width, int height,const char *title,bool border) { + cout << "SDL openImage:"<<title<<endl; + + sdlinit(); + + rect.x = 0; + rect.y = 0; + rect.w = width; + rect.h = height; + + return true; +} + + +int SDLSurface::close() { + if (isOpen()==false) { + cout << "WindowOut::closeWindow already closed"<<endl; + return true; + } + if(surface) { + SDL_FreeSurface(surface); + surface = NULL; + } + + lOpen=false; + return true; +} + + +int SDLSurface::getHeight() { + return rect.h; +} + + +int SDLSurface::getWidth() { + return rect.w; +} + + +int SDLSurface::getDepth() { + return video_bpp; +} + +int SDLSurface::putImage(YUVPicture* ) { + return true; +} + + +int SDLSurface::openImage(int imageMode, YUVPicture* pic) { + if (this->imageMode != _IMAGE_NONE) { + cout << "bad open error X11Surface::openImage"<<endl; + exit(0); + } + cout << "************* openImage SDL"<<imageMode<<endl; + this->imageMode=imageMode; + imageCurrent=NULL; + int w=getWidth(); + int h=getHeight(); + if(imageMode & _IMAGE_RESIZE) { + w=resize_rect.w; + h=resize_rect.h; + } + + if (imageMode & _IMAGE_DOUBLE) { + w=rect.w*2; + h=rect.h*2; + } + + if (imageMode & _IMAGE_DESK) { + if (imageDeskSDL->support()) { + imageCurrent=imageDeskSDL; + int video_flags = SDL_SWSURFACE; + video_flags |= SDL_ASYNCBLIT; + video_flags |= SDL_RESIZABLE; + if(surface) + SDL_FreeSurface(surface); + surface = SDL_SetVideoMode(w, h, video_bpp, video_flags); + + } + } + if (imageMode & _IMAGE_FULL) { + if (imageDeskSDL->support()) { + imageCurrent=imageDeskSDL; + int video_flags = SDL_FULLSCREEN; + video_flags |= SDL_ASYNCBLIT; + video_flags |= SDL_HWSURFACE; + if(surface) + SDL_FreeSurface(surface); + surface = SDL_SetVideoMode(w, h, video_bpp, video_flags); + } + } + if (imageCurrent != NULL) { + cout << "surface:"<<surface<<endl; + imageCurrent->init((XWindow*)surface,(YUVPicture*)&rect); + imageCurrent->openImage(imageMode); + } + return (imageCurrent != NULL); +} + + +int SDLSurface::closeImage() { + this->imageMode = _IMAGE_NONE; + if (imageCurrent != NULL) { + imageCurrent->closeImage(); + } + imageCurrent=NULL; + return true; +} + +int SDLSurface::checkEvent(int* newMode) { + int back=false; + SDL_Event event; + SDL_PollEvent(&event); + switch (event.type) { + case SDL_MOUSEBUTTONDOWN: { + int button=event.button.button; + if (button == 1) { + *newMode = imageMode ^ _IMAGE_DOUBLE; + back=true; + } + if (button == 3) { + *newMode = imageMode ^ _IMAGE_DESK ^ _IMAGE_FULL; + back=true; + } + break; + } + case SDL_VIDEORESIZE : { + resize_rect.w = event.resize.w; + resize_rect.h = event.resize.h; + *newMode = imageMode | _IMAGE_RESIZE; + back = true; + break; + } + + } + return back; +} + +int SDLSurface::dither(YUVPicture* pic) { + if (imageCurrent != NULL) { + imageCurrent->ditherImage(pic); + if(imageMode & _IMAGE_RESIZE) { + imageCurrent->putImage(resize_rect.w, resize_rect.h); + } else { + imageCurrent->putImage(rect.w, rect.h); + } + } + return true; +} + +void SDLSurface::sdlinit() { + if (lSDLInit == false) { + if (SDL_Init(SDL_INIT_VIDEO) < 0 ) { + fprintf(stderr, "Warning: Couldn't init SDL video: %s\n", + SDL_GetError()); + fprintf(stderr, "Will ignore video stream\n"); + exit(0); + } + atexit(SDL_Quit); + cout << "****************** SDL VIDEO System **********"<<endl; + /* Get the "native" video mode */ + video_info=SDL_GetVideoInfo(); + video_bpp=video_info->vfmt->BitsPerPixel; + imageMode=_IMAGE_NONE; + + imageCurrent=NULL; + } + lSDLInit=true; +} + +#endif diff --git a/mpeglib/lib/util/render/sdl/sdlSurface.h b/mpeglib/lib/util/render/sdl/sdlSurface.h new file mode 100644 index 00000000..aca5f293 --- /dev/null +++ b/mpeglib/lib/util/render/sdl/sdlSurface.h @@ -0,0 +1,78 @@ +/* + surface wrapper for SDL + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __SDLSURFACE_H +#define __SDLSURFACE_H + + +#include "../surface.h" +#include "imageDeskSDL.h" + + + +#ifndef SDL_WRAPPER + class SDLSurface : public Surface { + }; +#endif + +#ifdef SDL_WRAPPER +#if defined WIN32 +#include <SDL.h> +#include <SDL_video.h> +#else +#include <SDL/SDL.h> +#include <SDL/SDL_video.h> +#endif + + +class SDLSurface : public Surface { + + int lOpen; + int imageMode; + int lSDLInit; + int video_bpp; + SDL_Surface* surface; + SDL_Rect rect; + SDL_Rect resize_rect; + const SDL_VideoInfo *video_info; + + ImageBase* imageCurrent; + + ImageDeskSDL* imageDeskSDL; + + public: + SDLSurface(); + ~SDLSurface(); + + int isOpen(); + int open(int width, int height,const char *title, bool border=false); + int close(); + int getHeight(); + int getWidth(); + int getDepth(); + int getImageMode(); + int checkEvent(int* mode); + + int openImage(int imageMode, YUVPicture* pic = NULL); + int closeImage(); + int dither(YUVPicture* pic); + int putImage(YUVPicture* pic); + + + private: + void sdlinit(); +}; +#endif + +#endif diff --git a/mpeglib/lib/util/render/surface.cpp b/mpeglib/lib/util/render/surface.cpp new file mode 100644 index 00000000..12a15410 --- /dev/null +++ b/mpeglib/lib/util/render/surface.cpp @@ -0,0 +1,117 @@ +/* + surface base class + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "surface.h" + +#include <iostream> + +using namespace std; + +Surface::Surface() { +} + + +Surface::~Surface() { +} + + +int Surface::isOpen() { + cout << "direct virtual call Surface::isOpen "<<endl; + return false; +} + + +int Surface::open(int width, int height,const char *title, bool border) { + cout << "direct virtual call Surface::open "<<endl; + cout << "width:"<<width<<" height:"<<height + << " title:"<<title<<endl; + return false; +} + + +int Surface::close() { + cout << "direct virtual call Surface::close "<<endl; + return true; +} + + +int Surface::getHeight() { + cout << "direct virtual call Surface::getHeight "<<endl; + return 0; +} + + +int Surface::getWidth() { + cout << "direct virtual call Surface::getWidth "<<endl; + return 0; +} + + +int Surface::getDepth() { + cout << "direct virtual call Surface::getDepth "<<endl; + return 0; +} + +int Surface::getImageMode() { + cout << "direct virtual call Surface::getImageMode "<<endl; + return 0; +} + +int Surface::x11WindowId() { + cout << "direct virtual call Surface::x11WindowId " << endl; + return -1; +} + +ImageBase *Surface::findImage(int) +{ + cout << "direct virtual call: Surface::findImage "<<endl; + return NULL; +} + +int Surface::openImage(int mode, YUVPicture*) { + cout << "direct virtual call Surface::openImage "<<endl; + cout << "imageMode:"<<mode<<endl; + return false; +} + + +int Surface::closeImage() { + cout << "direct virtual call Surface::closeImage "<<endl; + return true; +} + + +int Surface::dither(YUVPicture* pic) { + cout << "direct virtual call Surface::dither "<<endl; + pic->print("Surface::dither"); + return false; +} + + +int Surface::putImage(YUVPicture* pic) { + cout << "direct virtual call Surface::putImage "<<endl; + pic->print("Surface::putImage"); + return false; +} + +int Surface::checkEvent(int*) { + cout << "direct virtual call Surface::checkEvent "<<endl; + return false; +} + +void Surface::config(const char* , + const char* ,void* ) { + cout << "direct virtual call Surface::config"<<endl; +} + diff --git a/mpeglib/lib/util/render/surface.h b/mpeglib/lib/util/render/surface.h new file mode 100644 index 00000000..84de996a --- /dev/null +++ b/mpeglib/lib/util/render/surface.h @@ -0,0 +1,55 @@ +/* + surface base class + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __SURFACE_H +#define __SURFACE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "yuvPicture.h" + +class ImageBase; + +class Surface { + + public: + Surface(); + virtual ~Surface(); + + virtual int isOpen(); + virtual int open(int width, int height,const char *title, bool border=false); + virtual int close(); + virtual int getHeight(); + virtual int getWidth(); + virtual int getDepth(); + virtual int getImageMode(); + virtual int x11WindowId(); + + virtual ImageBase *findImage(int imageMode); + + virtual int openImage(int mode, YUVPicture* pic = NULL); + virtual int closeImage(); + virtual int dither(YUVPicture* pic); + virtual int putImage(YUVPicture* pic); + + virtual int checkEvent(int* mode); + + // config surface + virtual void config(const char* key, + const char* value,void* user_data); + + +}; +#endif diff --git a/mpeglib/lib/util/render/x11/Makefile.am b/mpeglib/lib/util/render/x11/Makefile.am new file mode 100644 index 00000000..97ab0d67 --- /dev/null +++ b/mpeglib/lib/util/render/x11/Makefile.am @@ -0,0 +1,48 @@ +# player - Makefile.am + +INCLUDES = $(all_includes) + + +noinst_LTLIBRARIES = libutilx11.la + + +noinst_HEADERS = initDisplay.h \ + imageDeskX11.h imageDGAFull.h \ + imageXVDesk.h x11Surface.h xinit.h + +libutilx11_la_SOURCES = initDisplay.cpp \ + imageDeskX11.cpp \ + imageDGAFull.cpp imageXVDesk.cpp \ + x11Surface.cpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mpeglib/lib/util/render/x11/imageDGAFull.cpp b/mpeglib/lib/util/render/x11/imageDGAFull.cpp new file mode 100644 index 00000000..6e07b658 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageDGAFull.cpp @@ -0,0 +1,289 @@ +/* + xfree 4.0 dga fullscreen mode + Copyright (C) 2000 Martin Vogt, Christian Gerlach + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "imageDGAFull.h" + +#include <iostream> + +using namespace std; + +ImageDGAFull::ImageDGAFull() { + + m_iMode = -1; + m_bIsActive = false; + lSupport=false; + m_pxWindow = NULL; + m_iImageMode = _IMAGE_NONE; + ditherWrapper=NULL; + supportedModes = _IMAGE_NONE; + setIdentifier("DGA"); +} + + +ImageDGAFull::~ImageDGAFull() { + if (ditherWrapper != NULL) { + delete ditherWrapper; + } +} + +void ImageDGAFull::init(XWindow *xWindow, YUVPicture*) +{ + int uid; + + m_pxWindow = xWindow; + if (ditherWrapper == NULL) { + ditherWrapper=new DitherWrapper(xWindow->depth, + xWindow->redMask, + xWindow->greenMask, + xWindow->blueMask, + xWindow->pixel); + } + +#ifndef X11_DGA2 + return; +#endif + +#ifdef X11_DGA2 + m_pDGAModes=NULL; + m_iNumberModes = 0; + + m_iVideoWidth = xWindow->width; + m_iVideoHeight = xWindow->height; + uid=getuid(); + if (uid != 0) { + //cout << "you are :"<<uid<<" and not root(0). DGA 2.0 needs root"<<endl; + return; + } + + if ((m_pDisplay =xWindow->display)==NULL ) { + fprintf( stderr, " cannot connect to X server %s\n", XDisplayName(NULL)); + return; + } + + m_iScreen = DefaultScreen(xWindow->display); + + + if (!XF86DGAQueryVersion(xWindow->display, + &m_iMajorVersion, &m_iMinorVersion)) { + fprintf(stderr, "Unable to query video extension version\n"); + return ; + } + printf("DGA version %d.%d detected!\n", m_iMajorVersion, m_iMinorVersion); + + // Fail if the extension version in the server is too old + if (m_iMajorVersion < DGA_MINMAJOR || + (m_iMajorVersion == DGA_MINMAJOR && m_iMinorVersion < DGA_MINMINOR)) { + fprintf(stderr, "Xserver is running an old XFree86-DGA version" + " (%d.%d)\n", m_iMajorVersion, m_iMinorVersion); + fprintf(stderr, "Minimum required version is %d.%d\n", + DGA_MINMAJOR, DGA_MINMINOR); + return ; + } + + if (!XF86DGAQueryExtension(m_pDisplay, &m_iEventBase, &m_iErrorBase)) { + fprintf(stderr, "Unable to query video extension information\n"); + return ; + } + printf("Event base %d\n", m_iEventBase); + printf("Error base %d\n", m_iErrorBase); + + lSupport=true; + supportedModes = _IMAGE_FULL; +#endif +} + +int ImageDGAFull::support() { + return lSupport; +} + + +int ImageDGAFull::openImage(int mode) { +#ifdef X11_DGA2 + int width, bank, ram; + m_bAllowZoom = IS_DOUBLE(mode); + m_iImageMode = mode; + + /* Open access to the framebuffer */ + if ( ! XDGAOpenFramebuffer(m_pDisplay,m_iScreen) ) { + return(false); + } + + findMode(m_pxWindow->width, m_pxWindow->height, m_pxWindow->depth); + m_pDevice = XDGASetMode(m_pDisplay, m_iScreen, m_pDGAModes[m_iMode].num); + + + XDGASelectInput(m_pDisplay, m_iScreen, + KeyPressMask | ButtonPressMask | PointerMotionMask); + + XF86DGAGetVideo(m_pDisplay,m_iScreen,&m_pAddr,&width,&bank,&ram); + + + if(bank < (ram * 1024)) { + XF86DGASetVidPage(m_pxWindow->display, + DefaultScreen(m_pxWindow->display), 0); + } + + XF86DGASetViewPort(m_pxWindow->display, + DefaultScreen(m_pxWindow->display),0,0); + + + printf("Offset:%8x\n",m_iOffsetScreen); + m_pStartAddr = m_pAddr + m_iOffsetScreen; + m_iOffsetLine = (m_iBytesPerLine - m_iBytesPerRow) / m_iBytesPerPixel; + cout << "LineOffset: " << m_iOffsetLine << endl; + + // Clear the screen + memset(m_pAddr, 0, m_iBytesPerLine * m_iScreenHeight); + /* char *pos = m_pStartAddr; + int end = (m_bZoom) ? 2*m_iVideoHeight : m_iVideoHeight; + for (int line=0 ; line<end ; line++) { + memset(pos, 80, m_iBytesPerRow); + pos += m_iBytesPerRow + m_iOffsetLine * m_iBytesPerPixel; + } + sleep(2);*/ + + m_bIsActive = true; +#endif + return true; +} + + +int ImageDGAFull::closeImage() { +#ifdef X11_DGA2 + m_bIsActive = false; + stop(); + + // delete resources + if (m_pDGAModes != NULL) { + delete m_pDGAModes; + m_pDGAModes=NULL; + } +#endif + return true; +} + + +unsigned char* ImageDGAFull::address() { + return (unsigned char*) m_pStartAddr; +} + + +int ImageDGAFull::offset() { + return m_iOffsetLine; +} + + +void ImageDGAFull::ditherImage(YUVPicture* pic) { + + int useMode = (m_bZoom) ? m_iImageMode : m_iImageMode & (!_IMAGE_DOUBLE); + + ditherWrapper->doDither(pic,m_pxWindow->depth,useMode, + address(),offset()); +} + + +void ImageDGAFull::putImage() { + + if (event()) + closeImage(); +} + + +int ImageDGAFull::findMode(int width, int height, int bpp) { +#ifdef X11_DGA2 + int minBorder = INT_MAX; + int yBorder=0; + int border; + + // TODO: also check the y-axis + + m_iMode = -1; + m_iNumberModes = 0; + m_pDGAModes = XDGAQueryModes(m_pDisplay, m_iScreen, &m_iNumberModes); + printf("Number modes: %d\n", m_iNumberModes); + + for (int count=0 ; count<m_iNumberModes ; count++) { + + + if (m_pDGAModes[count].depth != bpp) + continue; + + printf("Mode: %d %dx%d \t bpp %d\n", + count, + m_pDGAModes[count].viewportWidth, + m_pDGAModes[count].viewportHeight, + m_pDGAModes[count].bitsPerPixel); + + // test normal video + border = m_pDGAModes[count].viewportWidth - width; + if ((border >= 0) && (border < minBorder)) { + minBorder = border; + m_iMode = count; + m_bZoom = false; + yBorder = m_pDGAModes[count].viewportHeight - height; + } + + // test zoomed video + if (m_bAllowZoom) { + border = m_pDGAModes[count].viewportWidth - 2 * width; + if ((border >= 0) && (border < minBorder)) { + minBorder = border; + m_iMode = count; + m_bZoom = true; + yBorder = m_pDGAModes[count].viewportHeight-2*height; + } + } + } + + if (m_iMode != -1) { + m_iScreenWidth = m_pDGAModes[m_iMode].viewportWidth; + m_iScreenHeight = m_pDGAModes[m_iMode].viewportHeight; + + m_iBytesPerPixel = m_pDGAModes[m_iMode].bitsPerPixel / 8; + m_iBytesPerLine = m_pDGAModes[m_iMode].bytesPerScanline; + m_iBytesPerRow = width * m_iBytesPerPixel; + if (m_bZoom) { + m_iBytesPerRow += m_iBytesPerRow; + } + + m_iOffsetScreen = minBorder * (m_iBytesPerPixel / 2) + + (yBorder / 2) * m_iBytesPerLine; + } + + cout << "Best Mode: " << m_iMode << endl; + cout << "Border Size: " << minBorder / 2 << endl; + cout << "Zoom: " << m_bZoom << endl; + cout << "Bytes per Line: " << m_iBytesPerLine << endl; + cout << "Bytes per Row: " << m_iBytesPerRow << endl; + cout << "Bytes per Pixel:" << m_iBytesPerPixel << endl; + cout << "Total offset: " << m_iOffsetScreen << endl; +#endif + return (m_iMode != -1); +} + + + +int ImageDGAFull::event() { + XEvent event; + return XCheckTypedEvent(m_pDisplay, ButtonPress + m_iEventBase, &event); +} + +void ImageDGAFull::stop() { +#ifdef X11_DGA2 + m_bIsActive = false; + XF86DGADirectVideo(m_pDisplay, m_iScreen, 0); + + XUngrabPointer(m_pDisplay, CurrentTime); + XUngrabKeyboard(m_pDisplay, CurrentTime); +#endif +} diff --git a/mpeglib/lib/util/render/x11/imageDGAFull.h b/mpeglib/lib/util/render/x11/imageDGAFull.h new file mode 100644 index 00000000..ddb8f493 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageDGAFull.h @@ -0,0 +1,131 @@ +/* + xfree 4.0 dga fullscreen mode + Copyright (C) 2000 Martin Vogt, Christian Gerlach + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __IMAGEDGAFULL_H +#define __IMAGEDGAFULL_H +#include "xinit.h" + +#include "../imageBase.h" + + + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <sys/types.h> + + + + +#define DGA_MINMAJOR 2 +#define DGA_MINMINOR 0 + + + + +/** + + Displays and renders X11 images in software with the help + of the ditherWrapper class. It switches to xfree 4.0 dga 2.0 + and needs root priviliges for that + +*/ + + +class ImageDGAFull : public ImageBase { + + + XWindow* m_pxWindow; + + // DGA status + int m_iMajorVersion; + int m_iMinorVersion; + int m_iEventBase; + int m_iErrorBase; + + int m_iScreen; + + Display *m_pDisplay; + + int m_iNumberModes; + +#ifdef X11_DGA2 + XDGAMode *m_pDGAModes; + XDGADevice *m_pDevice; +#endif + + int m_iScreenWidth; + int m_iScreenHeight; + + char *m_pAddr; // Base address of the screen + + // DGA parameter + int m_iVideoWidth; + int m_iVideoHeight; + + int m_iBytesPerLine; + int m_iBytesPerRow; // Size of one image line + int m_iBytesPerPixel; + int m_iOffsetScreen; + int m_iOffsetLine; + char *m_pStartAddr; // Start address for a centered image + + int m_iImageMode; + int m_iMode; + bool m_bZoom; + bool m_bAllowZoom; + + bool m_bIsActive; + + int lSupport; + DitherWrapper* ditherWrapper; + + + public: + ImageDGAFull(); + ~ImageDGAFull(); + + void init(XWindow *xWindow, YUVPicture* pic = NULL); + + int support(); + + int openImage(int mode); + int closeImage(); + + void ditherImage(YUVPicture* pic); + void putImage(); + + int active() { return m_bIsActive; } + + private: + + // Tries to find a fullscreen-mode which matches the resolution best + int findMode(int width, int height, int bpp); + + // Returns TRUE if an event is waiting + int event(); + + // Returns the start address of the upper left corner of the video frame + unsigned char *address(); + + // Number of bytes from the end of a row to the beginning of next one + int offset(); + + // Disables DGA-View (performs a mode-switch if neccesary) + void stop(); + + + +}; + +#endif diff --git a/mpeglib/lib/util/render/x11/imageDeskX11.cpp b/mpeglib/lib/util/render/x11/imageDeskX11.cpp new file mode 100644 index 00000000..9607d749 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageDeskX11.cpp @@ -0,0 +1,439 @@ +/* + standard and shared mem X11 images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "imageDeskX11.h" + +#include <iostream> + +using namespace std; + +static int lXerror; + +static int dummy(Display* , XErrorEvent*) { + lXerror=true; + return true; +} + + + +ImageDeskX11::ImageDeskX11() { + lSupport=true; + supportedModes = _IMAGE_DESK | _IMAGE_DOUBLE | _IMAGE_FULL; + setIdentifier("Standard X11"); + xWindow = NULL; + ditherWrapper=NULL; +#ifdef X11_XVIDMODE + iOldMode = -1; + vm_modelines = NULL; +#endif +} + + +ImageDeskX11::~ImageDeskX11() { + destroyImage(); + if (ditherWrapper != NULL) { + delete ditherWrapper; + } +} + + +void ImageDeskX11::init(XWindow* xWindow, YUVPicture*) +{ + videoaccesstype=VIDEO_XI_NONE; + this->xWindow=xWindow; + virtualscreen=NULL; + ximage=NULL; + imageMode=_IMAGE_NONE; + if (ditherWrapper == NULL) { + ditherWrapper=new DitherWrapper(xWindow->depth, + xWindow->redMask, + xWindow->greenMask, + xWindow->blueMask, + xWindow->pixel); + } + +#ifdef X11_SHARED_MEM + shmseginfo=NULL; +#endif +} + +int ImageDeskX11::support() { + return lSupport; +} + + +int ImageDeskX11::openImage(int mode) { + + if (xWindow == NULL) { + cout << "ImageDeskX11::openImage - call init before open!" << endl; + return false; + } + + closeImage(); + imageMode = mode; + int err; + + if ((err=createImage(VIDEO_XI_SHMSTD,imageMode)) != ERR_XI_OK) { + printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[err]); + printf("check ipcs and delete resources with ipcrm\n"); + if ((err=createImage(VIDEO_XI_STANDARD,imageMode)) != ERR_XI_OK) { + printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[err]); + videoaccesstype=VIDEO_XI_NONE; + } else { + lSupport=true; + } + } else { + lSupport=true; + } + switch(videoaccesstype) { + case VIDEO_XI_STANDARD: + //printf(" # using conventional Xlib calls.\n\n"); + break; + case VIDEO_XI_SHMSTD: + //printf(" # Using Xlib shared memory extension %d.%d\n\n", + //XShmMajor,XShmMinor); + break; + default: + cout << "could not create image->no video output possible"<<endl; + + } + + iOffsetX = iOffsetY = 0; + int w = xWindow->width; + int h = xWindow->height; + if (IS_FULL(imageMode)) { + switchMode(xWindow->width, xWindow->height, IS_DOUBLE(imageMode)); + iOffsetX = (iWidth - w) / 2; + iOffsetY = (iHeight - h) / 2; + if (bZoom) { + iOffsetX -= w / 2; + iOffsetY -= h / 2; + } + XResizeWindow(xWindow->display, xWindow->window, iWidth, iHeight); + } else if (IS_DOUBLE(imageMode)) { + XResizeWindow(xWindow->display, xWindow->window, + xWindow->width * 2, xWindow->height * 2); + } + + if (lSupport==true) { + return true; + } + return false; +} + + +int ImageDeskX11::closeImage() { + destroyImage(); + +#ifdef X11_XVIDMODE + if (iOldMode != -1) { + cout << "switch back to original videomode" << endl; + XF86VidModeSwitchToMode(xWindow->display,XDefaultScreen(xWindow->display), + vm_modelines[iOldMode]); + XFlush(xWindow->display); + iOldMode=-1; + } +#endif + + return true; +} + + +void ImageDeskX11::ditherImage(YUVPicture* pic) { + if (xWindow == NULL) { + cout << "ImageDeskX11::ditherImage - you have to call init first!" << endl; + return; + } + + ditherWrapper->doDither(pic,xWindow->depth,imageMode, + virtualscreen,0); +} + + +void ImageDeskX11::putImage(){ + if (xWindow == NULL) { + cout << "ImageDeskX11::putImage - you have to call init first!" << endl; + return; + } + + + int height=xWindow->height; + int width=xWindow->width; + + if (imageMode & _IMAGE_DOUBLE) { + height=2*height; + width=2*width; + } + +#ifdef X11_SHARED_MEM + switch(videoaccesstype) { + case VIDEO_XI_SHMSTD: + XShmPutImage(xWindow->display,xWindow->window, + xWindow->gc,ximage, + 0, 0, iOffsetX, iOffsetY, width, height, False); + XSync(xWindow->display,false); /* true not needed, done by XPending */ + break; + + + case VIDEO_XI_STANDARD: +#endif + XPutImage(xWindow->display,xWindow->window, + xWindow->gc, ximage, + 0, 0, iOffsetX, iOffsetY, width, height); + XSync(xWindow->display,false); /* true not needed, done by XPending */ +#ifdef X11_SHARED_MEM + break; + } +#endif +} + + + +int ImageDeskX11::createImage(int createType,int mode) { + + if (xWindow == NULL) { + cout << "ImageDeskX11::createImage - you have to call init first!" << endl; + return false; + } + + videoaccesstype=VIDEO_XI_NONE; + +#ifdef X11_SHARED_MEM + if(XShmQueryVersion(xWindow->display,&XShmMajor,&XShmMinor,&XShmPixmaps)) { + if (XShmPixmaps==True) { + if (createType & VIDEO_XI_SHMSTD) { + videoaccesstype=VIDEO_XI_SHMSTD; + } + } + } else { + if (createType & VIDEO_XI_SHMSTD) { + return ERR_XI_NOSHAREDMEMORY; + } + } +#endif + if (videoaccesstype == VIDEO_XI_NONE) { + videoaccesstype=createType; + } + + switch(videoaccesstype) + { +#ifdef X11_SHARED_MEM + + + case VIDEO_XI_SHMSTD: + + lXerror=false; + XSetErrorHandler(dummy); + + shmseginfo=(XShmSegmentInfo *)malloc(sizeof(XShmSegmentInfo)); + if(!shmseginfo) + return ERR_XI_SHMALLOC; + + memset(shmseginfo,0, sizeof(XShmSegmentInfo)); + + if (imageMode & _IMAGE_DOUBLE) { + ximage=XShmCreateImage(xWindow->display,xWindow->visual, + xWindow->depth, + ZPixmap,NULL,shmseginfo,2*xWindow->width, + 2*xWindow->height); + } else { + ximage=XShmCreateImage(xWindow->display,xWindow->visual, + xWindow->depth, + ZPixmap,NULL,shmseginfo,xWindow->width, + xWindow->height); + } + + if(!ximage) + return ERR_XI_SHMXIMAGE; + + shmseginfo->shmid=shmget(IPC_PRIVATE, + ximage->bytes_per_line* + ximage->height,IPC_CREAT|0777); + + if(shmseginfo->shmid<0) + return ERR_XI_SHMSEGINFO; + + shmseginfo->shmaddr=(char*)shmat(shmseginfo->shmid,NULL,0); + ximage->data=shmseginfo->shmaddr; + virtualscreen=(unsigned char *)ximage->data; + + if(!virtualscreen) + return ERR_XI_SHMVIRTALLOC; + + shmseginfo->readOnly=False; + + XShmAttach(xWindow->display,shmseginfo); + XSync(xWindow->display, False); + XSetErrorHandler(NULL); + XFlush(xWindow->display); + if (lXerror) { + cout << "ERR_XI_SHMATTACH -2"<<endl; + return ERR_XI_SHMATTACH; + } + + break; +#endif + + case VIDEO_XI_STANDARD: + if (mode & _IMAGE_DOUBLE) { + virtualscreen=(unsigned char *) + malloc(xWindow->screensize*sizeof(char)*4); + + if(virtualscreen==NULL) + return ERR_XI_VIRTALLOC; + + ximage=XCreateImage(xWindow->display,xWindow->visual, + xWindow->depth,ZPixmap, + 0,(char*)virtualscreen, + 2*xWindow->width,2*xWindow->height, + 32,2*xWindow->width*xWindow->pixelsize); + } else { + virtualscreen=(unsigned char *) + malloc(xWindow->screensize*sizeof(char)); + + if(virtualscreen==NULL) + return ERR_XI_VIRTALLOC; + + ximage=XCreateImage(xWindow->display,xWindow->visual, + xWindow->depth,ZPixmap, + 0,(char*)virtualscreen, + xWindow->width,xWindow->height, + 32,xWindow->width*xWindow->pixelsize); + } + + if(!ximage) + return ERR_XI_XIMAGE; + break; + + default: + return ERR_XI_FAILURE; + + } + + if ( (videoaccesstype == VIDEO_XI_STANDARD) || + (videoaccesstype == VIDEO_XI_SHMSTD) ) { +#ifndef WORDS_BIGENDIAN + ximage->byte_order = LSBFirst; + ximage->bitmap_bit_order = LSBFirst; +#else + ximage->byte_order = MSBFirst; + ximage->bitmap_bit_order = MSBFirst; +#endif + + } + return ERR_XI_OK; +} + + + +int ImageDeskX11::destroyImage() { + if(xWindow && xWindow->display && xWindow->window) { + switch(videoaccesstype) { +#ifdef X11_SHARED_MEM + case VIDEO_XI_SHMSTD: + if (shmseginfo) { + XShmDetach(xWindow->display,shmseginfo); + if(ximage) { + XDestroyImage(ximage); + ximage=NULL; + } + if(shmseginfo->shmaddr) { + shmdt(shmseginfo->shmaddr); + shmseginfo->shmaddr=NULL; + } + if(shmseginfo->shmid>=0) + shmctl(shmseginfo->shmid,IPC_RMID,NULL); + + free(shmseginfo); + } + shmseginfo=NULL; + break; + +#endif + case VIDEO_XI_STANDARD: + if(ximage) { + XDestroyImage(ximage); + ximage=NULL; + /* + XDestroyImage function calls frees both the image structure + and the data pointed to by the image structure. + */ + virtualscreen=NULL; + } + break; + + default: + // cout << "no open window to close"<<endl; + break; + } + } + videoaccesstype=VIDEO_XI_NONE; + imageMode=_IMAGE_NONE; + return true; +} + + +bool ImageDeskX11::switchMode(int width, int , bool zoom) +{ + iWidth = xWindow->screenptr->width; + iHeight = xWindow->screenptr->height; + +#ifdef X11_XVIDMODE + iOldMode = -1; + int vm_count,i; + + cout << "Find best matching videomode ..." << endl; + + if (!XF86VidModeGetAllModeLines(xWindow->display,XDefaultScreen(xWindow->display), + &vm_count,&vm_modelines)) { + return false; + } + + int bestMode = -1; + int border, minBorder = INT_MAX; + + for (i = 0; i < vm_count; i++) { + printf("mode %d: %dx%d\n",i, vm_modelines[i]->hdisplay,vm_modelines[i]->vdisplay); + + if (xWindow->screenptr->width == vm_modelines[i]->hdisplay) + iOldMode = i; + + border = vm_modelines[i]->hdisplay - width; + if ((border > 0) && (border < minBorder)) { + bestMode = i; + minBorder = border; + bZoom = false; + } + if (zoom) { + border = vm_modelines[i]->hdisplay - 2 * width; + if ((border > 0) && (border < minBorder)) { + bestMode = i; + minBorder = border; + bZoom = true; + } + } + } + cout << "best mode: " << bestMode << endl; + + iWidth = vm_modelines[bestMode]->hdisplay; + iHeight = vm_modelines[bestMode]->vdisplay; + + if (XF86VidModeSwitchToMode(xWindow->display,XDefaultScreen(xWindow->display), + vm_modelines[bestMode])) { + XF86VidModeSetViewPort(xWindow->display,XDefaultScreen(xWindow->display), 0, 0); + XFlush(xWindow->display); + return true; + } +#endif + return false; +} diff --git a/mpeglib/lib/util/render/x11/imageDeskX11.h b/mpeglib/lib/util/render/x11/imageDeskX11.h new file mode 100644 index 00000000..efbd4e90 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageDeskX11.h @@ -0,0 +1,85 @@ +/* + standard and shared mem X11 images + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __IMAGEDESKX11_H +#define __IMAGEDESKX11_H +#include <limits.h> +#include "xinit.h" + +#include "../imageBase.h" + +#define VIDEO_XI_NONE 0x00 /* No access defined */ +#define VIDEO_XI_STANDARD 0x01 /* Use standard Xlib calls */ +#define VIDEO_XI_SHMSTD 0X02 /* Use Xlib shared memory extension */ + +/** + + Displays and renders X11 images in software with the help + of the ditherWrapper class. +*/ + + +class ImageDeskX11 : public ImageBase { + +#ifdef X11_SHARED_MEM + XShmSegmentInfo *shmseginfo; +#endif + + unsigned char *virtualscreen; + int videoaccesstype; + XImage *ximage; + int lSupport; + + int XShmMajor,XShmMinor; + Bool XShmPixmaps; + + XWindow* xWindow; + int imageMode; + DitherWrapper* ditherWrapper; + + int iOffsetX; + int iOffsetY; + int iWidth; + int iHeight; + +#ifdef X11_XVIDMODE + XF86VidModeModeInfo **vm_modelines; + + int iOldMode; +#endif + + bool bZoom; + + public: + ImageDeskX11(); + ~ImageDeskX11(); + + void init(XWindow* xWindow, YUVPicture* pic = NULL); + + int support(); + + int openImage(int ditherSize); + int closeImage(); + + void ditherImage(YUVPicture* pic); + void putImage(); + + private: + int createImage(int createType,int size); + int destroyImage(); + + bool switchMode(int width, int height, bool zoom); + +}; + +#endif diff --git a/mpeglib/lib/util/render/x11/imageXVDesk.cpp b/mpeglib/lib/util/render/x11/imageXVDesk.cpp new file mode 100644 index 00000000..e087ba40 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageXVDesk.cpp @@ -0,0 +1,405 @@ +/* + xfree 4.0 XV extension desk mode + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include "imageXVDesk.h" + +#include <iostream> + +using namespace std; + +ImageXVDesk::ImageXVDesk() { + + lSupport=false; + + ditherWrapper=NULL; + supportedModes = _IMAGE_NONE; + setIdentifier("XV"); + + xWindow = NULL; + +#ifdef X11_XV + keepRatio = false; + +#endif +} + + +ImageXVDesk::~ImageXVDesk() { + if (ditherWrapper != NULL) { + delete ditherWrapper; + } + freeImage(); +} + +void ImageXVDesk::init(XWindow* xWindow, YUVPicture*) +{ +#ifdef X11_XV + this->xWindow=xWindow; + + xv_port=-1; + shmem_flag = 0; + yuv_image=NULL; + yuv_shminfo.shmaddr=NULL; + yuv_shminfo.shmid=-1; + + if (XShmQueryExtension(xWindow->display)) shmem_flag = 1; + if (!shmem_flag) { + printf("no shmem available.\n"); + return; + } + + + if (haveXVSupport(xWindow)==true) { + supportedModes = _IMAGE_DESK | _IMAGE_DOUBLE | _IMAGE_FULL | _IMAGE_RESIZE; + lSupport=true; + } else { + return; + } + + if (ditherWrapper == NULL) { + ditherWrapper=new Dither2YUV(); + } + imageID = -1; +#endif +} + +int ImageXVDesk::support() { + return lSupport; +} + +int ImageXVDesk::openImage(int imageMode) { + + + if (imageMode & _IMAGE_FULL) { + XResizeWindow(xWindow->display, xWindow->window, + xWindow->screenptr->width, xWindow->screenptr->height); + setKeepRatio(true); + } else if (imageMode & _IMAGE_DOUBLE) { + XResizeWindow(xWindow->display, xWindow->window, + xWindow->width * 2, xWindow->height * 2); + setKeepRatio(false); + } else { + setKeepRatio(false); + } + + return true; +} + + +int ImageXVDesk::closeImage() { + freeImage(); + return true; +} + +void ImageXVDesk::ditherImage(YUVPicture* pic) { + +#ifdef X11_XV + int x_return; + int y_return; + int height, dy; + unsigned int border_width_return; + unsigned int depth_return; + unsigned int _w; + unsigned int _h; + Window _dw; + + if (xWindow == NULL) { + cout << "ImageXVDesk::ditherImage - you have to call before dithering an image!" << endl; + return; + } + + // check for not supported formats and if possible convert them + int inputType=pic->getImageType(); + if (inputType == PICTURE_RGB_FLIPPED) { + cout << "xv for flipped rgb not implemented"<<endl; + return; + } + + // create xv image + int id; + if (imageID != pic->getImageType()) { + imageID = pic->getImageType(); + switch (imageID) { + case PICTURE_YUVMODE_CR_CB: + case PICTURE_YUVMODE_CB_CR: + case PICTURE_RGB: + id = GUID_YUV12_PLANAR; + break; + case PICTURE_YUVMODE_YUY2: + id = GUID_YUY2_PACKED; + break; + case PICTURE_YUVMODE_UYVY: + id = GUID_UYVY_PACKED; + break; + default: + cout << "unknown type for yuv image!" << endl; + return; + } + freeImage(); + + createImage(id); + } + + XGetGeometry(xWindow->display,(Drawable)xWindow->window, + &_dw, &x_return, &y_return, &_w, &_h, + &border_width_return, &depth_return); + + // now dither the image + + // we (currently) cannot create yuvPicture _in_ + // the shared segment here we copy it + + unsigned char* image=pic->getImagePtr(); + if (inputType == PICTURE_RGB) { + ditherWrapper->doDither(pic, + DefaultDepth(xWindow->display,xWindow->screennum), + _SIZE_NORMAL, (unsigned char*) yuv_image->data, 0); + } else { + memcpy(yuv_image->data,image,pic->getImageSize()); + } + + if (keepRatio) { + height = (_w * yuv_image->height) / yuv_image->width; + dy = (((int) _h) - height + 1) / 2; + XvShmPutImage(xWindow->display, xv_port,xWindow->window, + xWindow->gc, yuv_image, + 0, 0, yuv_image->width, yuv_image->height, + 0, dy, _w, height, False); + if (dy > 0) { + XFillRectangle(xWindow->display, xWindow->window,xWindow->gc, + 0, 0, _w, dy); + XFillRectangle(xWindow->display, xWindow->window,xWindow->gc, + 0, height+dy-1, _w, dy+1); + } + } else { + XvShmPutImage(xWindow->display, xv_port,xWindow->window, + xWindow->gc, yuv_image, + 0, 0, yuv_image->width, yuv_image->height, + 0, 0, _w, _h, False); + } +#endif +} + + +void ImageXVDesk::putImage() { + + //XFlush(xWindow->display); + XSync(xWindow->display, false); +} + +void ImageXVDesk::setKeepRatio(bool enable) +{ +#ifdef X11_XV + keepRatio = enable; +#endif +} + + +int ImageXVDesk::haveXVSupport(XWindow* xWindow) { +#ifdef X11_XV + int ret; + unsigned int p_version=0; + unsigned int p_release=0; + unsigned int p_request_base=0; + unsigned int p_event_base=0; + unsigned int p_error_base=0; + + unsigned int p_num_adaptors=0; + + /**------------------------------- XV ------------------------------------*/ + + /** query and print Xvideo properties */ + + ret = XvQueryExtension(xWindow->display, + &p_version, &p_release, &p_request_base, + &p_event_base, &p_error_base); + if (ret != Success) { + if (ret == XvBadExtension) { + printf("XvBadExtension returned at XvQueryExtension.\n"); + } else if (ret == XvBadAlloc) { + printf("XvBadAlloc returned at XvQueryExtension.\n"); + } else { + printf("other error happened at XvQueryExtension.\n"); + } + return false; + } + /* + printf("========================================\n"); + printf("XvQueryExtension returned the following:\n"); + printf("p_version : %u\n", p_version); + printf("p_release : %u\n", p_release); + printf("p_request_base : %u\n", p_request_base); + printf("p_event_base : %u\n", p_event_base); + printf("p_error_base : %u\n", p_error_base); + printf("========================================\n"); + */ + + ret = XvQueryAdaptors(xWindow->display, DefaultRootWindow(xWindow->display), + &p_num_adaptors, &ai); + + if (ret != Success) { + if (ret == XvBadExtension) { + printf("XvBadExtension returned at XvQueryExtension.\n"); + } else if (ret == XvBadAlloc) { + printf("XvBadAlloc returned at XvQueryExtension.\n"); + } else { + printf("other error happaned at XvQueryAdaptors.\n"); + } + return false; + } + /* + printf("=======================================\n"); + printf("XvQueryAdaptors returned the following:\n"); + printf("%d adaptors available.\n", p_num_adaptors); + */ + if (p_num_adaptors == 0) { + //cout << "no adaptors found. XV not possible"<<endl; + return false; + } + + unsigned int i; + unsigned int j; + + for (i = 0; i < p_num_adaptors; i++) { + /* + printf(" name: %s\n" + " type: %s%s%s%s%s\n" + " ports: %ld\n" + " first port: %ld\n", + ai[i].name, + (ai[i].type & XvInputMask) ? "input | " : "", + (ai[i].type & XvOutputMask) ? "output | " : "", + (ai[i].type & XvVideoMask) ? "video | " : "", + (ai[i].type & XvStillMask) ? "still | " : "", + (ai[i].type & XvImageMask) ? "image | " : "", + ai[i].num_ports, + ai[i].base_id); + */ + xv_port = ai[i].base_id; + + //printf("adaptor %d ; format list:\n", i); + for (j = 0; j < ai[i].num_formats; j++) { + /* + printf(" depth=%d, visual=%ld\n", + ai[i].formats[j].depth, + ai[i].formats[j].visual_id); + */ + } + unsigned int p; + unsigned int encodings; + int attributes; + int formats; + + for (p = ai[i].base_id; p < ai[i].base_id+ai[i].num_ports; p++) { + + //printf(" encoding list for port %d\n", p); + if (XvQueryEncodings(xWindow->display, p, &encodings, &ei) != Success) { + //printf("XvQueryEncodings failed.\n"); + continue; + } + for (j = 0; j < encodings; j++) { + /* + printf(" id=%ld, name=%s, size=%ldx%ld, numerator=%d, denominator=%d\n", + ei[j].encoding_id, ei[j].name, ei[j].width, ei[j].height, + ei[j].rate.numerator, ei[j].rate.denominator); + */ + } + XvFreeEncodingInfo(ei); + int k; + //printf(" attribute list for port %d\n", p); + at = XvQueryPortAttributes(xWindow->display, p, &attributes); + for (k = 0; k < attributes; k++) { + /* + printf(" name: %s\n" + " flags: %s%s\n" + " min_color: %i\n" + " max_color: %i\n", + at[k].name, + (at[k].flags & XvGettable) ? " get" : "", + (at[k].flags & XvSettable) ? " set" : "", + at[k].min_value, at[k].max_value); + */ + } + if (at) + XFree(at); + + //printf(" image format list for port %d\n", p); + fo = XvListImageFormats(xWindow->display, p, &formats); + for (k = 0; k < formats; k++) { + /* + printf(" 0x%x (%4.4s) %s\n", + fo[k].id, + (char *)&fo[k].id, + (fo[k].format == XvPacked) ? "packed" : "planar"); + */ + } + if (fo) + XFree(fo); + } + printf("\n"); + } + if (p_num_adaptors > 0) + XvFreeAdaptorInfo(ai); + if (xv_port == -1) { + return false; + } +#endif + return true; + +} + + +void ImageXVDesk::freeImage() { +#ifdef X11_XV + if (xWindow == NULL) { + return; + } + if (yuv_shminfo.shmid >=0) { + XShmDetach(xWindow->display,&yuv_shminfo); + if(yuv_shminfo.shmaddr) { + shmdt(yuv_shminfo.shmaddr); + XFree(yuv_image); + yuv_shminfo.shmaddr=NULL; + } + XSync(xWindow->display, False); + yuv_shminfo.shmid=-1; + } +#endif +} + + +void ImageXVDesk::createImage(int id) { +#ifdef X11_XV + if (xWindow == NULL) { + cout << "ImageXVDesk::freeImage - you have to call init before creating an image!" << endl; + return; + } + + yuv_image = XvShmCreateImage(xWindow->display, xv_port, + id, 0, + xWindow->width, + xWindow->height, &yuv_shminfo); + + yuv_shminfo.shmid = shmget(IPC_PRIVATE, + yuv_image->data_size, IPC_CREAT | 0777); + yuv_shminfo.shmaddr = yuv_image->data = + (char*)shmat(yuv_shminfo.shmid, 0, 0); + yuv_shminfo.readOnly = False; + + if (!XShmAttach(xWindow->display, &yuv_shminfo)) { + printf("XShmAttach failed !\n"); + lSupport=false; + return; + } + shmctl(yuv_shminfo.shmid, IPC_RMID, 0); +#endif +} diff --git a/mpeglib/lib/util/render/x11/imageXVDesk.h b/mpeglib/lib/util/render/x11/imageXVDesk.h new file mode 100644 index 00000000..44124428 --- /dev/null +++ b/mpeglib/lib/util/render/x11/imageXVDesk.h @@ -0,0 +1,88 @@ +/* + xfree 4.0 XV extension desk mode + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __IMAGEXVDESK_H +#define __IMAGEXVDESK_H + +#include "xinit.h" + +#include "../imageBase.h" +#include "../dither2YUV/dither2YUV.h" + +#include <stdio.h> + +#if !defined(__NetBSD__) +#include <semaphore.h> +#endif + +//#undef X11_XV + +#define GUID_YUV12_PLANAR 0x32315659 +#define GUID_I420_PLANAR 0x30323449 +#define GUID_YUY2_PACKED 0x32595559 +#define GUID_UYVY_PACKED 0x59565955 + +/** + The XV extension dither yuv images in hardware and allows + scaling of images. + But its currently not supported by many drivers. + +*/ + + +class ImageXVDesk : public ImageBase { + +#ifdef X11_XV + XvAdaptorInfo *ai; + XvEncodingInfo *ei; + XvAttribute *at; + XvImageFormatValues *fo; + + XvImage *yuv_image; + bool keepRatio; + + int xv_port; + int imageID; + + int shmem_flag; + XShmSegmentInfo yuv_shminfo; +#endif + Dither2YUV* ditherWrapper; + + int lSupport; + XWindow* xWindow; + + public: + ImageXVDesk(); + ~ImageXVDesk(); + + void init(XWindow* xWindow, YUVPicture* pic = NULL); + + int support(); + + int openImage(int imageMode); + int closeImage(); + + void ditherImage(YUVPicture* pic); + void putImage(); + + void setKeepRatio(bool enable); + + private: + int haveXVSupport(XWindow* xWindow); + void freeImage(); + void createImage(int id); + +}; + +#endif diff --git a/mpeglib/lib/util/render/x11/initDisplay.cpp b/mpeglib/lib/util/render/x11/initDisplay.cpp new file mode 100644 index 00000000..d0029eb6 --- /dev/null +++ b/mpeglib/lib/util/render/x11/initDisplay.cpp @@ -0,0 +1,255 @@ +/* + here are the different initialisation routines for different displays + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "initDisplay.h" + +#include <iostream> + +using namespace std; + + + +static unsigned long wpixel[256]; + + + + +/* + *-------------------------------------------------------------- + * + * InitColorDisplay -- + * + * Initialized display for full color output. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void initColorDisplay(XWindow* xwindow) { + XWindowAttributes winattr; + + + XGetWindowAttributes(xwindow->display, xwindow->window, &winattr); + + xwindow->redMask = winattr.visual->red_mask; + xwindow->greenMask = winattr.visual->green_mask; + xwindow->blueMask = winattr.visual->blue_mask; +} + + + + + + + +/* + *-------------------------------------------------------------- + * + * FindFullColorVisual + * + * Returns a pointer to a full color bit visual on the display + * + * Results: + * See above. + * + * Side effects: + * Unknown. + * + *-------------------------------------------------------------- + */ +Visual* FindFullColorVisual (Display* dpy,int* depth) { + XVisualInfo vinfo; + XVisualInfo *vinfo_ret; + int numitems, maxdepth; + +#if defined(__cplusplus) || defined(c_plusplus) + vinfo.c_class = TrueColor; +#else + vinfo.class = TrueColor; +#endif + + vinfo_ret = XGetVisualInfo(dpy, VisualClassMask, &vinfo, &numitems); + + if (numitems == 0) return NULL; + + maxdepth = 0; + while(numitems > 0) { + if (vinfo_ret[numitems-1].depth > maxdepth) { + maxdepth = vinfo_ret[numitems-1 ].depth; + } + numitems--; + } + XFree((void *) vinfo_ret); + + if (maxdepth < 16) return NULL; + + if (XMatchVisualInfo(dpy, DefaultScreen(dpy), maxdepth, + TrueColor, &vinfo)) { + *depth = maxdepth; + return vinfo.visual; + } + + return NULL; +} + + +/* + *-------------------------------------------------------------- + * + * CreateFullColorWindow + * + * Creates a window capable of handling 32 bit color. + * + * Results: + * See above. + * + * Side effects: + * Unknown. + * + *-------------------------------------------------------------- + */ +void CreateFullColorWindow (XWindow* xwindow) { + int depth; + Visual *visual; + XSetWindowAttributes xswa; + unsigned long mask; + unsigned int c_class; + int screen; + Display *dpy=xwindow->display; + /* + int x = xinfo->hints.x, + y = xinfo->hints.y; + unsigned int w = xinfo->hints.width, + h = xinfo->hints.height; + */ + screen = XDefaultScreen(dpy); + c_class = InputOutput; /* Could be InputOnly */ + if (xwindow->visual == NULL) { + xwindow->visual = visual = FindFullColorVisual (dpy, &depth); + xwindow->depth = depth; + } else { + visual=xwindow->visual; + depth=xwindow->depth; + } + + if (visual == NULL) { + cout << "visual is null"<<endl; + return; + } + mask = CWBackPixel | CWColormap | CWBorderPixel; + if (xwindow->colormap==0) { + xswa.colormap = XCreateColormap(dpy, + XRootWindow(dpy, screen), + visual, AllocNone); + } else xswa.colormap = xwindow->colormap; + xswa.background_pixel = BlackPixel(dpy, DefaultScreen(dpy)); + xswa.border_pixel = WhitePixel(dpy, DefaultScreen(dpy)); + XSetWindowColormap(xwindow->display,xwindow->window,xwindow->colormap); + + + /* + xwindow->window = XCreateWindow(dpy, RootWindow(dpy, screen), x, y, w, h, + (unsigned int) 1, depth, c_class, + visual, mask, &xswa); + */ +} + + + + + + + +/* + *-------------------------------------------------------------- + * + * InitSimpleDisplay -- + * + * Initialized display, sets up colormap, etc. Use for 8 Bit color + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void initSimpleDisplay(XWindow* xwindow) { + int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE; + XColor xcolor; + int i, lum_num, cr_num, cb_num; + unsigned char r, g, b; + Colormap dcmap; + Display *display; + ColorTable8Bit colorTable8Bit; + + display = xwindow->display; + + + xwindow->colormap = XDefaultColormap(display, DefaultScreen(display)); + dcmap = xwindow->colormap; + + xcolor.flags = DoRed | DoGreen | DoBlue; + + + //if (xinfo->owncmFlag) goto create_map; + +retry_alloc_colors: + for (i=0; i<ncolors; i++) { + + lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE; + cr_num = (i / CB_RANGE)%CR_RANGE; + cb_num = i % CB_RANGE; + + colorTable8Bit.ConvertColor(lum_num, cr_num, cb_num, &r, &g, &b); + + xcolor.red = r * 256; + xcolor.green = g * 256; + xcolor.blue = b * 256; + + if ((XAllocColor(display,xwindow->colormap , &xcolor) == 0 + && xwindow->colormap == dcmap)) { + int j; + unsigned long tmp_pixel; + XWindowAttributes xwa; + + // Free colors. + for (j = 0; j < i; j ++) { + tmp_pixel = wpixel[j]; + XFreeColors(display,xwindow->colormap , &tmp_pixel, 1, 0); + } + + + //create_map: + XGetWindowAttributes(display, xwindow->window, &xwa); + xwindow->colormap = XCreateColormap(display, xwindow->window, + xwa.visual, AllocNone); + XSetWindowColormap(display, xwindow->window,xwindow->colormap ); + + goto retry_alloc_colors; + } + xwindow->pixel[i]=xcolor.pixel; + wpixel[i] = xcolor.pixel; + } + +} + + diff --git a/mpeglib/lib/util/render/x11/initDisplay.h b/mpeglib/lib/util/render/x11/initDisplay.h new file mode 100644 index 00000000..62841f19 --- /dev/null +++ b/mpeglib/lib/util/render/x11/initDisplay.h @@ -0,0 +1,34 @@ +/* + here are the different initialisation routines for different displays + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __INITDISPLAY_H +#define __INITDISPLAY_H + +#include "math.h" +#include "xinit.h" +#include "../dither/colorTable8Bit.h" + + + +extern void initColorDisplay(XWindow* xwindow); +extern void initSimpleDisplay(XWindow* xwindow); + +// helper functions +Visual *FindFullColorVisual (Display *dpy ,int *depth); +void CreateFullColorWindow (XWindow* xwindow); + + + +#endif diff --git a/mpeglib/lib/util/render/x11/x11Surface.cpp b/mpeglib/lib/util/render/x11/x11Surface.cpp new file mode 100644 index 00000000..d7b8f052 --- /dev/null +++ b/mpeglib/lib/util/render/x11/x11Surface.cpp @@ -0,0 +1,389 @@ +/* + surface wrapper for X11 Window + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "x11Surface.h" + +#include <iostream> + +using namespace std; + +const char *ERR_XI_STR[] = { + "X initialisation OK!", + "No Shared Memory available", + "cannot open Display", + "bad color depth", + "can't create Window", + "can't alloc memory for virtual screen", + "cannot create XImage", + "can't alloc memory for Shared memory segment info", + "cannot create Shared Memory XImage", + "Shared memory segment info error", + "Shared memory virtual screen allocation failed", + "cannot attach Shared Memory segment to display" +}; + + +#ifndef KDE_USE_FINAL +static int dummy(Display* , XErrorEvent*) { + cout << "received x11 error!"<<endl; + return true; +} +#endif + +X11Surface::X11Surface() { + xWindow=(XWindow *)malloc(sizeof(XWindow)); + xWindow->lOpen=false; + xWindow->x = xWindow->y = 0; + xWindow->window = 0; + m_windowIdAvailable = false; + + imageMode=_IMAGE_NONE; + + imageCurrent=NULL; + xWindow->lOpen=false; + + + xWindow->display=XOpenDisplay(NULL); + if (xWindow->display) + XFlush(xWindow->display); + xWindow->redMask=0; + xWindow->greenMask=0; + xWindow->blueMask=0; + lXVAllow=true; + + images=0; + imageList = new ImageBase* [4]; + imageList[images++] = new ImageXVDesk(); + imageList[images++] = new ImageDGAFull(); + imageList[images++] = new ImageDeskX11(); + imageList[images] = NULL; +} + + +X11Surface::~X11Surface() { + close(); + if (xWindow->display) + XCloseDisplay(xWindow->display); + free(xWindow); + + for (int count=0 ; count<images ; count++) { + if (imageList[count] != NULL) + delete imageList[count]; + } + delete [] imageList; +} + + +int X11Surface::getHeight() { + return xWindow->height; +} + + +int X11Surface::getWidth() { + return xWindow->width; +} + +int X11Surface::isOpen() { + return xWindow->lOpen; +} + +int X11Surface::x11WindowId() { + if(m_windowIdAvailable) + return xWindow->window; + else + return -1; +} + +int X11Surface::open(int width, int height,const char *title, bool border) { + + close(); + xWindow->width=width; + xWindow->height=height; + + if(!xWindow->display) { + printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[ERR_XI_DISPLAY]); + printf("check ipcs and delete resources with ipcrm\n"); + exit(0); + } + + xWindow->screennum=DefaultScreen(xWindow->display); + xWindow->screenptr=DefaultScreenOfDisplay(xWindow->display); + xWindow->visual=DefaultVisualOfScreen(xWindow->screenptr); + xWindow->depth=DefaultDepth(xWindow->display,xWindow->screennum); + + switch(xWindow->depth) { + case 8: + xWindow->pixelsize=1; + break; + case 16: + xWindow->pixelsize=2; + break; + case 24: + xWindow->pixelsize=4; + break; + case 32: + xWindow->pixelsize=4; + break; + default: + cout << "unknown pixelsize for depth:"<<xWindow->depth<<endl; + exit(0); + } + + XColor background, ignored; + XAllocNamedColor (xWindow->display, + DefaultColormap (xWindow->display, xWindow->screennum), + "black", &background, &ignored); + + XSetWindowAttributes attributes; + attributes.background_pixel=background.pixel; + attributes.backing_store=NotUseful; + attributes.override_redirect=True; + + xWindow->window=XCreateWindow(xWindow->display, + RootWindowOfScreen(xWindow->screenptr), + 0,0, + xWindow->width, + xWindow->height,0, + xWindow->depth, + InputOutput, xWindow->visual, + (border) ? CWBackingStore : CWBackPixel|CWOverrideRedirect, + &attributes); + + m_windowIdAvailable = true; + if(!xWindow->window) { + printf("\nX initialisation error:\n *** %s\n",ERR_XI_STR[ERR_XI_WINDOW]); + printf("check ipcs and delete resources with ipcrm\n"); + return false; + } + + WM_DELETE_WINDOW = XInternAtom(xWindow->display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(xWindow->display, xWindow->window, &WM_DELETE_WINDOW, 1); + + XSetErrorHandler(dummy); + + XStoreName(xWindow->display,xWindow->window,title); + XSelectInput(xWindow->display,xWindow->window, + ExposureMask|KeyPressMask|KeyReleaseMask|ButtonPressMask); + xWindow->gc=XCreateGC(xWindow->display,xWindow->window,0,NULL); + XMapRaised(xWindow->display,xWindow->window); + + if (xWindow->depth >= 16) { + initColorDisplay(xWindow); + + } else { + // depth is <= 8 + // allocate memory for dithertables + // gets the rgb masks + initColorDisplay(xWindow); + // create 8 bit dithertables + // create private colormap + initSimpleDisplay(xWindow); + + } + + xWindow->palette=NULL; + xWindow->screensize=xWindow->height*xWindow->width*xWindow->pixelsize; + xWindow->lOpen=true; + + for (int count=0 ; count<images ; count++) { + if (imageList[count] != NULL) + imageList[count]->init(xWindow); + } + + return true; +} + + +int X11Surface::close() { + if (isOpen()==false) { + return true; + } + closeImage(); + + XFreeGC(xWindow->display,xWindow->gc); + XDestroyWindow(xWindow->display,xWindow->window); + + xWindow->lOpen=false; + + + return true; +} + +ImageBase *X11Surface::findImage(int mode) { + for (int count=0 ; count<images ; count++) { + if ((imageList[count] == NULL) || (IS_DISABLED(imageList[count]))) + continue; + + if (imageList[count]->supportedModes & mode) + return imageList[count]; + } + return NULL; +} + +ImageBase **X11Surface::getModes() { + return imageList; +} + +void X11Surface::setModes(ImageBase **modes) { + imageList = modes; +} + +int X11Surface::openImage(int mode, YUVPicture*) { + if (imageMode != _IMAGE_NONE) { + cout << "bad open error X11Surface::openImage"<<endl; + return false; + } + if (mode == _IMAGE_NONE) { + cout << "X11Surface::openImage - no valid mode specified"<<endl; + return false; + } + + ImageBase *newImage=findImage(mode); + + if (newImage == NULL) { + cout << " X11Surface::openImage - no matching image found"<<endl; + imageMode=_IMAGE_NONE; + } else { + /* + printf("Best image found: %s\n", newImage->getIdentifier()); + printf("\tsupported modes: desk=%d, double=%d, full=%d, resize=%d\n", + HAS_DESK(newImage), + HAS_DOUBLE(newImage), + HAS_FULL(newImage), + HAS_RESIZE(newImage)); + */ + + open(xWindow->width, xWindow->height, "mpeglib", !(mode & _IMAGE_FULL)); + newImage->openImage(mode); + if (!IS_FULL(mode)) { + XMoveWindow(xWindow->display, xWindow->window, + xWindow->x, xWindow->y); + + XSizeHints hints; + hints.flags = PMaxSize; + if (HAS_RESIZE(newImage)) { + hints.max_width = INT_MAX; + hints.max_height = INT_MAX; + } else { + hints.max_width = xWindow->width; + hints.max_height = xWindow->height; + } + XSetWMNormalHints(xWindow->display, xWindow->window, &hints); + } + + imageMode=mode; + } + imageCurrent = newImage; + XSync(xWindow->display,true); + return (imageCurrent != NULL); +} + + +int X11Surface::closeImage() { + + if ((imageMode == _IMAGE_NONE) || (!xWindow->lOpen)) + return false; + + ImageBase *old = imageCurrent; + imageCurrent=NULL; + + XWindowAttributes attr; + Window junkwin; + + if (!IS_FULL(imageMode)) { + if (!XGetWindowAttributes(xWindow->display, xWindow->window, &attr)) + cout << "Can't get window attributes." << endl; + + XTranslateCoordinates (xWindow->display, xWindow->window, attr.root, + -attr.border_width, + -attr.border_width, + &xWindow->x, &xWindow->y, &junkwin); + } + + imageMode=_IMAGE_NONE; + old->closeImage(); + + return true; +} + + +int X11Surface::dither(YUVPicture* pic) { + if (imageCurrent != NULL) { + imageCurrent->ditherImage(pic); + } + return true; +} + + +int X11Surface::putImage(YUVPicture* ) { + if (imageCurrent != NULL) { + imageCurrent->putImage(); + } + return true; +} + + +int X11Surface::getDepth() { + return xWindow->depth; +} + +int X11Surface::getImageMode() { + return imageMode; +} + +int X11Surface::checkEvent(int* newMode) { + XEvent event; + + if (isOpen()==false) + return false; + + // check if we forward the call to the FULLSCREEN mode + if (!imageCurrent->active()) { + if (IS_FULL(imageMode)) { + *newMode=imageMode ^ _IMAGE_FULL; + return true; + } + } + + // normal X11 images use the X11 event queue + if (XCheckTypedWindowEvent(xWindow->display, + xWindow->window,ButtonPress,&event)) { + if (event.xbutton.button == Button1) { + if (findImage(_IMAGE_DOUBLE) != NULL) + *newMode = imageMode ^ _IMAGE_DOUBLE; + } else if (event.xbutton.button == Button3) { + if (findImage(_IMAGE_FULL) != NULL) + *newMode = imageMode ^ _IMAGE_DESK ^ _IMAGE_FULL; + } + return true; + } + // now check if there are unneeded events in the queue, + // then delete them + int eventCnt=XPending(xWindow->display); + if (eventCnt > 10) { + XSync(xWindow->display,true); + } + return false; + + +} + + + +void X11Surface::config(const char* key, + const char* value, void* ) { + if (strcmp(key,"xvAllow")==0) { + lXVAllow=atoi(value); + } +} + diff --git a/mpeglib/lib/util/render/x11/x11Surface.h b/mpeglib/lib/util/render/x11/x11Surface.h new file mode 100644 index 00000000..54a6582d --- /dev/null +++ b/mpeglib/lib/util/render/x11/x11Surface.h @@ -0,0 +1,79 @@ +/* + surface wrapper for X11 Window + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __X11SURFACE_H +#define __X11SURFACE_H + +#include <limits.h> +#include "xinit.h" +#include "../surface.h" +#include "initDisplay.h" +#include "../dither/ditherWrapper.h" +#include "imageDeskX11.h" +#include "imageDGAFull.h" +#include "imageXVDesk.h" + + + +class X11Surface : public Surface { + + int lOpen; + int imageMode; + + XWindow* xWindow; + + ImageBase** imageList; + int images; + + ImageBase* imageCurrent; + + Atom WM_DELETE_WINDOW; + Atom WM_RESIZE_WINDOW; + int lXVAllow; + + public: + X11Surface(); + ~X11Surface(); + + int isOpen(); + int open(int width, int height,const char *title, bool border = false); + int close(); + int getHeight(); + int getWidth(); + int getDepth(); + int getImageMode(); + int x11WindowId(); + + ImageBase *findImage(int mode); + + // these functions grant access to the supported images. be careful when changing + // entries, because these are no copies. they are the original values! + ImageBase **getModes(); + void setModes(ImageBase **modes); + + int openImage(int mode, YUVPicture* pic = NULL); + int closeImage(); + int dither(YUVPicture* pic); + int putImage(YUVPicture* pic); + + int checkEvent(int* mode); + + void config(const char* key, + const char* value,void* user_data); + + + private: + int initX11(); + bool m_windowIdAvailable; +}; +#endif diff --git a/mpeglib/lib/util/render/x11/xinit.h b/mpeglib/lib/util/render/x11/xinit.h new file mode 100644 index 00000000..c42c290f --- /dev/null +++ b/mpeglib/lib/util/render/x11/xinit.h @@ -0,0 +1,99 @@ + +#ifndef __XINIT_H__ +#define __XINIT_H__ + +#define __USE_X_SHAREDMEMORY__ + +#include <pthread.h> + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> + + + +#ifdef X11_SHARED_MEM +#include <X11/extensions/XShm.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#endif + + +#ifdef X11_XV +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XShm.h> +#endif + +#ifdef X11_XVIDMODE +#include <X11/extensions/xf86vmode.h> +#endif + +#ifdef X11_DGA2 +#include <X11/extensions/xf86dga.h> +#endif + +#define ERR_XI_FAILURE 0xFF +#define ERR_XI_OK 0x00 +#define ERR_XI_NOSHAREDMEMORY 0x01 +#define ERR_XI_DISPLAY 0x02 +#define ERR_XI_BADDEPTH 0x03 +#define ERR_XI_WINDOW 0x04 +#define ERR_XI_VIRTALLOC 0x05 +#define ERR_XI_XIMAGE 0x06 +#define ERR_XI_SHMALLOC 0x07 +#define ERR_XI_SHMXIMAGE 0x08 +#define ERR_XI_SHMSEGINFO 0x09 +#define ERR_XI_SHMVIRTALLOC 0x0A +#define ERR_XI_SHMATTACH 0x0B + + + + +#define PIXEL unsigned long + +extern const char *ERR_XI_STR[]; + +struct XWindow { + + Display *display; + Window window; + Screen *screenptr; + int screennum; + Visual *visual; + GC gc; + + Colormap colormap; + PIXEL *palette; + int colorcells; + + int x; + int y; + int width; + int height; + int depth; + int pixelsize; + int screensize; + int lOpen; + + // colorMask + unsigned int redMask; + unsigned int greenMask; + unsigned int blueMask; + + // colortable for 8 bit colormap + // (created with interference by the XServer) + unsigned char pixel[256]; + +}; + + +#endif /* __XINIT_H__ */ diff --git a/mpeglib/lib/util/render/yuvPicture.cpp b/mpeglib/lib/util/render/yuvPicture.cpp new file mode 100644 index 00000000..e79d3bde --- /dev/null +++ b/mpeglib/lib/util/render/yuvPicture.cpp @@ -0,0 +1,253 @@ +/* + describes a picture in yuv format + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "yuvPicture.h" + +#include <iostream> + +using namespace std; + +static int instanceCnt=0; + +YUVPicture::YUVPicture(int width,int height) { + this->width=width; + this->height=height; + + instance=instanceCnt; + instanceCnt++; + imagePtr=NULL; + + setImageType(PICTURE_YUVMODE_CR_CB); + + + startTimeStamp=new TimeStamp(); + waitTime=new TimeStamp(); + earlyTime=new TimeStamp(); + mpegType=-1; + +} + + +YUVPicture::~YUVPicture() { + delete imagePtr; + delete earlyTime; + delete startTimeStamp; + delete waitTime; +} + + + +int YUVPicture::getHeight() { + return height; +} + + +int YUVPicture::getWidth() { + return width; +} + + + +int YUVPicture::getLumLength() { + return lumLength; +} + + +int YUVPicture::getColorLength() { + return colorLength; +} + +int YUVPicture::getImageSize() { + return imageSize; +} + + + + + + + +void YUVPicture::print(const char* title) { + cout << title <<":"; + printf(" instance:%d ",instance); + printf(" width:%d ",width); + printf(" height:%d ",height); + cout <<" picPerSec:"<<picPerSec; + switch(mpegType) { + case 1: + printf("I_FRAME "); + break; + case 2: + printf("P_FRAME "); + break; + case 3: + printf("B_FRAME "); + break; + case 4: + printf("D_FRAME "); + break; + default: + printf("<unknown> "); + } + printf("\n"); + + +} + + +void YUVPicture::setPicturePerSecond(float val) { + this->picPerSec=val; +} + + +float YUVPicture::getPicturePerSecond() { + return picPerSec; +} + + +void YUVPicture::setStartTimeStamp(TimeStamp* aStamp) { + aStamp->copyTo(startTimeStamp); +} + + +TimeStamp* YUVPicture::getStartTimeStamp() { + return startTimeStamp; +} + +void YUVPicture::setWaitTime(TimeStamp* aStamp) { + aStamp->copyTo(waitTime); +} + + +TimeStamp* YUVPicture::getWaitTime() { + return waitTime; +} + +void YUVPicture::setEarlyTime(TimeStamp* earlyTime) { + this->earlyTime=earlyTime; +} + + +TimeStamp* YUVPicture::getEarlyTime() { + return earlyTime; +} + + + +void YUVPicture::setMpegPictureType(int type) { + this->mpegType=type; +} + + +int YUVPicture::getMpegPictureType() { + return mpegType; +} + + +void YUVPicture::setImageType(int imageType) { + + + // + // Reset everything + // + + if (imagePtr != NULL) { + delete [] imagePtr; + imagePtr=NULL; + } + this->imageType=imageType; + + lumLength=0; + colorLength=0; + Cr_mode=NULL; + Cb_mode=NULL; + luminance_mode=NULL; + + + // + // YUV Images + // + if ( (imageType == PICTURE_YUVMODE_CR_CB) || + (imageType == PICTURE_YUVMODE_CB_CR) ) { + + + lumLength=width * height; + colorLength=width * height / 4; + imageSize=lumLength+colorLength+colorLength; + + // the 64 is some "security" space + imagePtr=new unsigned char[imageSize+64]; + + if (imagePtr == NULL) { + cout << "cannot create image"<<endl; + exit(0); + } + + // now caculate pointers to start addresses of lum/Cr/Cb blocks + // we need the yuvPtr for direct dither in hardware + // this should save a memcpy + + luminance = imagePtr; + Cr = imagePtr+lumLength; + Cb = imagePtr+lumLength+colorLength; + + + if ( (luminance == NULL) || + (Cr == NULL) || + (Cb == NULL) ) { + cout << "allocation luminance/Cr/Cb error"<<endl; + exit(0); + } + + switch(imageType) { + case PICTURE_YUVMODE_CR_CB: + Cr_mode=Cr; + Cb_mode=Cb; + luminance_mode=imagePtr; + break; + case PICTURE_YUVMODE_CB_CR: + Cr_mode=Cb; + Cb_mode=Cr; + luminance_mode=imagePtr; + break; + default: + cout << "unknown yuv mode:"<<imageType<<endl; + } + } + else if ( (imageType == PICTURE_YUVMODE_YUY2) || + (imageType == PICTURE_YUVMODE_UYVY) ) { + // these yuv-modes are packed + + imageSize=width * height * 2; + + // the 64 is some "security" space + imagePtr=new unsigned char[imageSize+64]; + + if (imagePtr == NULL) { + cout << "cannot create image"<<endl; + exit(0); + } + } + + // + // RGB Imcdages + // + + if ( (imageType == PICTURE_RGB) || + (imageType == PICTURE_RGB_FLIPPED) ){ + imageSize=width*height*4; + imagePtr=new unsigned char[imageSize]; + } + memset(imagePtr,0,imageSize); +} diff --git a/mpeglib/lib/util/render/yuvPicture.h b/mpeglib/lib/util/render/yuvPicture.h new file mode 100644 index 00000000..1995b473 --- /dev/null +++ b/mpeglib/lib/util/render/yuvPicture.h @@ -0,0 +1,110 @@ +/* + describes a picture in yuv format + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __YUVPICTURE_H +#define __YUVPICTURE_H + + +extern "C" { +#include <stdio.h> +#include <string.h> +} + +#include "../timeStamp.h" + +#define PICTURE_NO_TYPE -1 + +#define PICTURE_YUVMODE_CR_CB 1 +#define PICTURE_YUVMODE_CB_CR 2 +#define PICTURE_RGB 3 +#define PICTURE_RGB_FLIPPED 4 +#define PICTURE_YUVMODE_YUY2 5 +#define PICTURE_YUVMODE_UYVY 6 + +class YUVPicture { + + unsigned char* imagePtr; /* Pointer to complete yuv image */ + + unsigned char* luminance; /* Luminance plane. */ + unsigned char* Cr; /* Cr plane. */ + unsigned char* Cb; /* Cb plane. */ + + + int width; + int height; + + float picPerSec; + int lumLength; + int colorLength; + int imageSize; + + TimeStamp* startTimeStamp; + TimeStamp* waitTime; + TimeStamp* earlyTime; + + int mpegType; + int instance; + int imageType; + + unsigned char* image_mode; /* start Pointer to complete image */ + unsigned char* luminance_mode; /* Luminace plane. */ + unsigned char* Cr_mode; /* Cr plane. */ + unsigned char* Cb_mode; /* Cb plane. */ + + public: + YUVPicture(int width,int height); + ~YUVPicture(); + + // + // For YUV Images + // + inline unsigned char* getLuminancePtr() {return luminance_mode;} + inline unsigned char* getCrPtr() {return Cr_mode;} + inline unsigned char* getCbPtr() {return Cb_mode;} + + // general + inline unsigned char* getImagePtr() {return imagePtr;} + + // use these to swap the image Types + inline int getImageType() { return imageType; } + void setImageType(int mode); + + + int getHeight(); + int getWidth(); + + int getLumLength(); + int getColorLength(); + int getImageSize(); + + void setPicturePerSecond(float val); + float getPicturePerSecond(); + + + void setStartTimeStamp(TimeStamp* timeStamp); + TimeStamp* getStartTimeStamp(); + + void setWaitTime(TimeStamp* waitTime); + TimeStamp* getWaitTime(); + + void setEarlyTime(TimeStamp* earlyTime); + TimeStamp* getEarlyTime(); + + void setMpegPictureType(int type); + int getMpegPictureType(); + + + void print(const char* title); +}; +#endif |