This source file includes following definitions.
- init
 
- display
 
- display420
 
- display400
 
- display422
 
- display444as422
 
- display444as420
 
- doQuit
 
- close
 
#include "sdl.hh"
#include <assert.h>
bool SDL_YUV_Display::init(int frame_width, int frame_height, enum SDL_Chroma chroma)
{
  
  frame_width  &= ~7;
  frame_height &= ~7;
  mChroma = chroma;
  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0 ) {
    printf("SDL_Init() failed: %s\n", SDL_GetError( ) );
    SDL_Quit();
    return false;
  }
  const SDL_VideoInfo* info = SDL_GetVideoInfo();
  if( !info ) {
    printf("SDL_GetVideoInfo() failed: %s\n", SDL_GetError() );
    SDL_Quit();
    return false;
  }
  Uint8 bpp = info->vfmt->BitsPerPixel;
  Uint32 vflags;
  if (info->hw_available)
    vflags = SDL_HWSURFACE;
  else
    vflags = SDL_SWSURFACE;
  
  const char *window_title = "SDL YUV display";
  SDL_WM_SetCaption(window_title, NULL);
  mScreen = SDL_SetVideoMode(frame_width, frame_height, bpp, vflags);
  if (mScreen == NULL) {
    printf("SDL: Couldn't set video mode to %dx%d,%d bpp: %s",
           frame_width, frame_height, bpp, SDL_GetError());
    SDL_Quit();
    return false;
  }
  uint32_t pixelFormat;
  switch (mChroma) {
  case SDL_CHROMA_MONO: pixelFormat = SDL_YV12_OVERLAY; break;
  case SDL_CHROMA_420:  pixelFormat = SDL_YV12_OVERLAY; break;
  case SDL_CHROMA_422:  pixelFormat = SDL_YUY2_OVERLAY; break;
    case SDL_CHROMA_444:  pixelFormat = SDL_YV12_OVERLAY; break;
      
  }
  mYUVOverlay = SDL_CreateYUVOverlay(frame_width, frame_height, pixelFormat, mScreen);
  if (mYUVOverlay == NULL ) {
    printf("SDL: Couldn't create SDL YUV overlay: %s",SDL_GetError());
    SDL_Quit();
    return false;
  }
  rect.x = 0;
  rect.y = 0;
  rect.w = frame_width;
  rect.h = frame_height;
  mWindowOpen=true;
  return true;
}
void SDL_YUV_Display::display(const unsigned char *Y,
                              const unsigned char *U,
                              const unsigned char *V,
                              int stride, int chroma_stride)
{
  if (!mWindowOpen) return;
  if (SDL_LockYUVOverlay(mYUVOverlay) < 0) return;
  if (mChroma == SDL_CHROMA_420) {
    display420(Y,U,V,stride,chroma_stride);
  }
  else if (mChroma == SDL_CHROMA_422) {
    display422(Y,U,V,stride,chroma_stride);
  }
  else if (mChroma == SDL_CHROMA_444) {
    display444as420(Y,U,V,stride,chroma_stride);
    
  }
  else if (mChroma == SDL_CHROMA_MONO) {
    display400(Y,stride);
  }
  SDL_UnlockYUVOverlay(mYUVOverlay);
  SDL_DisplayYUVOverlay(mYUVOverlay, &rect);
}
void SDL_YUV_Display::display420(const unsigned char *Y,
                                 const unsigned char *U,
                                 const unsigned char *V,
                                 int stride, int chroma_stride)
{
  if (stride == rect.w && chroma_stride == rect.w/2) {
    
    memcpy(mYUVOverlay->pixels[0], Y, rect.w * rect.h);
    memcpy(mYUVOverlay->pixels[1], V, rect.w * rect.h / 4);
    memcpy(mYUVOverlay->pixels[2], U, rect.w * rect.h / 4);
  }
  else {
    
    for (int y=0;y<rect.h;y++)
      {
        memcpy(mYUVOverlay->pixels[0]+y*rect.w, Y+stride*y, rect.w);
      }
    for (int y=0;y<rect.h/2;y++)
      {
        memcpy(mYUVOverlay->pixels[2]+y*rect.w/2, U+chroma_stride*y, rect.w/2);
        memcpy(mYUVOverlay->pixels[1]+y*rect.w/2, V+chroma_stride*y, rect.w/2);
      }
  }
}
void SDL_YUV_Display::display400(const unsigned char *Y, int stride)
{
  if (stride == rect.w) {
    
    memcpy(mYUVOverlay->pixels[0], Y, rect.w * rect.h);
  }
  else {
    
    for (int y=0;y<rect.h;y++)
      {
        memcpy(mYUVOverlay->pixels[0]+y*rect.w, Y+stride*y, rect.w);
      }
  }
  
  memset(mYUVOverlay->pixels[1], 0x80, rect.w * rect.h / 4);
  memset(mYUVOverlay->pixels[2], 0x80, rect.w * rect.h / 4);
}
void SDL_YUV_Display::display422(const unsigned char *Y,
                                 const unsigned char *U,
                                 const unsigned char *V,
                                 int stride, int chroma_stride)
{
  for (int y=0;y<rect.h;y++)
    {
      unsigned char* p = mYUVOverlay->pixels[0] + y*rect.w *2;
      const unsigned char* Yp = Y + y*stride;
      const unsigned char* Up = U + y*chroma_stride;
      const unsigned char* Vp = V + y*chroma_stride;
      for (int x=0;x<rect.w;x+=2) {
        *p++ = Yp[x];
        *p++ = Up[x/2];
        *p++ = Yp[x+1];
        *p++ = Vp[x/2];
      }
    }
}
void SDL_YUV_Display::display444as422(const unsigned char *Y,
                                      const unsigned char *U,
                                      const unsigned char *V,
                                      int stride, int chroma_stride)
{
  for (int y=0;y<rect.h;y++)
    {
      unsigned char* p = mYUVOverlay->pixels[0] + y*rect.w *2;
      const unsigned char* Yp = Y + y*stride;
      const unsigned char* Up = U + y*chroma_stride;
      const unsigned char* Vp = V + y*chroma_stride;
      for (int x=0;x<rect.w;x+=2) {
        *p++ = Yp[x];
        *p++ = Up[x];
        *p++ = Yp[x+1];
        *p++ = Vp[x];
      }
    }
}
void SDL_YUV_Display::display444as420(const unsigned char *Y,
                                      const unsigned char *U,
                                      const unsigned char *V,
                                      int stride, int chroma_stride)
{
  for (int y=0;y<rect.h;y++)
    {
      unsigned char* p = mYUVOverlay->pixels[0] + y*rect.w;
      memcpy(p, Y+y*stride, rect.w);
    }
  for (int y=0;y<rect.h;y+=2)
    {
      unsigned char* u = mYUVOverlay->pixels[2] + y/2*rect.w/2;
      unsigned char* v = mYUVOverlay->pixels[1] + y/2*rect.w/2;
      for (int x=0;x<rect.w;x+=2) {
        u[x/2] = (U[ y   *chroma_stride + x] + U[ y   *chroma_stride + x +1] +
                  U[(y+1)*chroma_stride + x] + U[(y+1)*chroma_stride + x +1])/4;
        v[x/2] = (V[ y   *chroma_stride + x] + V[ y   *chroma_stride + x +1] +
                  V[(y+1)*chroma_stride + x] + V[(y+1)*chroma_stride + x +1])/4;
        
        
      }
    }
}
bool SDL_YUV_Display::doQuit() const
{
  SDL_Event event;
  while (SDL_PollEvent(&event)) {
    if (event.type == SDL_QUIT) {
      return true;
    }
  }
  return false;
}
void SDL_YUV_Display::close()
{
  SDL_FreeYUVOverlay(mYUVOverlay);
  SDL_Quit();
  mWindowOpen=false;
}