core/vidl/vidl_ffmpeg_convert.cxx
Go to the documentation of this file.
00001 // This is core/vidl/vidl_ffmpeg_convert.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Matt Leotta
00008 // \date   19 Jan 2006
00009 //
00010 //-----------------------------------------------------------------------------
00011 
00012 #include "vidl_ffmpeg_convert.h"
00013 #include "vidl_frame.h"
00014 #include <vcl_cstring.h>
00015 
00016 
00017 #ifdef LIBAVFORMAT_BUILD
00018 #if LIBAVFORMAT_BUILD <= 4623
00019 // PIX_FMT_NONE is undefined in old versions of FFMPEG
00020 #define PIX_FMT_NONE PixelFormat(-1)
00021 #endif
00022 #endif
00023 
00024 #if LIBAVCODEC_BUILD >= ((52<<16)+(10<<8)+0)  // after ver 52.10.0
00025 extern "C" {
00026 #include <libswscale/swscale.h>
00027 }
00028 #endif
00029 
00030 
00031 //--------------------------------------------------------------------------------
00032 
00033 //: Convert the pixel format of a frame using FFMPEG
00034 //
00035 // The \p in_frame->data() is converted from \p in_frame->pixel_format()
00036 // to \p out_frame->pixel_format() and stored in \p out_frame->data()
00037 // If the output frame data is not the correct size new memory
00038 // will be allocated
00039 bool vidl_ffmpeg_convert(const vidl_frame_sptr& in_frame,
00040                                vidl_frame_sptr& out_frame)
00041 {
00042   if (!in_frame || !out_frame)
00043     return false;
00044 
00045   PixelFormat in_fmt =
00046       vidl_pixel_format_to_ffmpeg(in_frame->pixel_format());
00047 
00048   PixelFormat out_fmt =
00049       vidl_pixel_format_to_ffmpeg(out_frame->pixel_format());
00050 
00051   if (in_fmt == PIX_FMT_NONE || out_fmt == PIX_FMT_NONE)
00052     return false;
00053 
00054   unsigned ni = in_frame->ni();
00055   unsigned nj = in_frame->nj();
00056   unsigned out_size = (unsigned) avpicture_get_size( out_fmt, ni, nj );
00057 
00058   if (out_frame->size() != out_size ||
00059       out_frame->ni() != ni ||
00060       out_frame->nj() != nj ||
00061       !out_frame->data() )
00062     out_frame = new vidl_memory_chunk_frame(ni, nj, out_frame->pixel_format(),
00063                                             new vil_memory_chunk(out_size, VIL_PIXEL_FORMAT_BYTE));
00064 
00065   AVPicture in_pic;
00066   vcl_memset( &in_pic, 0, sizeof(in_pic) );
00067   avpicture_fill(&in_pic, (uint8_t*) in_frame->data(), in_fmt, ni, nj);
00068 
00069   AVPicture out_pic;
00070   vcl_memset( &out_pic, 0, sizeof(out_pic) );
00071   avpicture_fill(&out_pic, (uint8_t*) out_frame->data(), out_fmt, ni, nj);
00072 
00073 #if LIBAVCODEC_BUILD < ((52<<16)+(10<<8)+0)  // before ver 52.10.0
00074   if ( img_convert( &out_pic, out_fmt, &in_pic, in_fmt, ni, nj ) < 0 )
00075     return false;
00076 #else
00077   SwsContext* ctx = sws_getContext( ni, nj, in_fmt,
00078                                     ni, nj, out_fmt,
00079                                     SWS_BILINEAR,
00080                                     NULL, NULL, NULL );
00081   sws_scale( ctx,
00082              in_pic.data, in_pic.linesize,
00083              0, nj,
00084              out_pic.data, out_pic.linesize );
00085   sws_freeContext( ctx );
00086 #endif
00087 
00088   return true;
00089 }
00090 
00091 
00092 //: Find the vidl pixel format that matches a FFMPEG one
00093 vidl_pixel_format
00094 vidl_pixel_format_from_ffmpeg(PixelFormat ffmpeg_pix_fmt)
00095 {
00096   switch (ffmpeg_pix_fmt)
00097   {
00098     case PIX_FMT_YUV420P:   return VIDL_PIXEL_FORMAT_YUV_420P;
00099     case PIX_FMT_YUYV422:   return VIDL_PIXEL_FORMAT_YUYV_422;
00100     case PIX_FMT_RGB24:     return VIDL_PIXEL_FORMAT_RGB_24;
00101     case PIX_FMT_BGR24:     return VIDL_PIXEL_FORMAT_BGR_24;
00102     case PIX_FMT_YUV422P:   return VIDL_PIXEL_FORMAT_YUV_422P;
00103     case PIX_FMT_YUV444P:   return VIDL_PIXEL_FORMAT_YUV_444P;
00104 #ifdef PIX_FMT_RGBA
00105     case PIX_FMT_RGBA:      return VIDL_PIXEL_FORMAT_RGBA_32;
00106 #endif
00107     case PIX_FMT_YUV410P:   return VIDL_PIXEL_FORMAT_YUV_410P;
00108     case PIX_FMT_YUV411P:   return VIDL_PIXEL_FORMAT_YUV_411P;
00109     case PIX_FMT_RGB565:    return VIDL_PIXEL_FORMAT_RGB_565;
00110     case PIX_FMT_RGB555:    return VIDL_PIXEL_FORMAT_RGB_555;
00111     case PIX_FMT_GRAY8:     return VIDL_PIXEL_FORMAT_MONO_8;
00112     case PIX_FMT_PAL8:      return VIDL_PIXEL_FORMAT_MONO_8;   //HACK: Treating 8-bit palette as greyscale image
00113     case PIX_FMT_MONOWHITE: return VIDL_PIXEL_FORMAT_MONO_1;
00114     case PIX_FMT_MONOBLACK: return VIDL_PIXEL_FORMAT_MONO_1;
00115     case PIX_FMT_UYVY422:   return VIDL_PIXEL_FORMAT_UYVY_422;
00116     case PIX_FMT_UYYVYY411: return VIDL_PIXEL_FORMAT_UYVY_411;
00117     default: break;
00118   }
00119   return VIDL_PIXEL_FORMAT_UNKNOWN;
00120 }
00121 
00122 
00123 //: Find the FFMPEG pixel format that matches a vidl one
00124 PixelFormat
00125 vidl_pixel_format_to_ffmpeg(vidl_pixel_format vidl_pix_fmt)
00126 {
00127   switch (vidl_pix_fmt)
00128   {
00129     case VIDL_PIXEL_FORMAT_RGB_24:   return PIX_FMT_RGB24;
00130     case VIDL_PIXEL_FORMAT_BGR_24:   return PIX_FMT_BGR24;
00131 #ifdef PIX_FMT_RGBA
00132     case VIDL_PIXEL_FORMAT_RGBA_32:  return PIX_FMT_RGBA;
00133 #endif
00134     case VIDL_PIXEL_FORMAT_RGB_565:  return PIX_FMT_RGB565;
00135     case VIDL_PIXEL_FORMAT_RGB_555:  return PIX_FMT_RGB555;
00136     case VIDL_PIXEL_FORMAT_YUV_444P: return PIX_FMT_YUV444P;
00137     case VIDL_PIXEL_FORMAT_YUYV_422: return PIX_FMT_YUYV422;
00138     case VIDL_PIXEL_FORMAT_YUV_422P: return PIX_FMT_YUV422P;
00139     case VIDL_PIXEL_FORMAT_YUV_420P: return PIX_FMT_YUV420P;
00140     case VIDL_PIXEL_FORMAT_YUV_411P: return PIX_FMT_YUV411P;
00141     case VIDL_PIXEL_FORMAT_YUV_410P: return PIX_FMT_YUV410P;
00142     case VIDL_PIXEL_FORMAT_UYVY_422: return PIX_FMT_UYVY422;
00143     case VIDL_PIXEL_FORMAT_UYVY_411: return PIX_FMT_UYYVYY411;
00144     case VIDL_PIXEL_FORMAT_MONO_1:   return PIX_FMT_MONOBLACK;
00145     case VIDL_PIXEL_FORMAT_MONO_8:   return PIX_FMT_GRAY8;
00146     default: break;
00147   }
00148   return PIX_FMT_NONE;
00149 }