[MPlayer-dev-eng] [PATCH] [RFC] image API

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Sun Jul 17 02:19:44 CEST 2005


Hi,
attached is my first attempt for an image en/decoding API in MPlayer.
Currently only for decoding though *g*.
It think it is a piece of crap right now (and the Gui example is missing
lots of checks), but I'm eager to hear any good suggestions from you.
I think we will at least need an "autodetection" function, that tells
you what type a file is.
For encoding I have the problem of how to set all those possible
options... Especially since I wanted to make it not
libavcodec-specific...

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: Gui/bitmap.c
===================================================================
RCS file: /cvsroot/mplayer/main/Gui/bitmap.c,v
retrieving revision 1.13
diff -u -r1.13 bitmap.c
--- Gui/bitmap.c	15 Dec 2004 01:22:23 -0000	1.13
+++ Gui/bitmap.c	17 Jul 2005 00:18:49 -0000
@@ -2,22 +2,18 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <png.h>
-
 #include "../mp_msg.h"
 #include "../help_mp.h"
 #include "bitmap.h"
+#include "libmpcodecs/imgapi.h"
+#include "libmpcodecs/img_format.h"
 
 int pngRead( unsigned char * fname,txSample * bf )
 {
- unsigned char   header[8];
- png_structp     png;
- png_infop       info;
- png_infop       endinfo;
- png_bytep     * row_p;
- png_bytep       palette = NULL;
- int             color;
- png_uint_32     i;
+ img_decoder_t* dec;
+ int fsize;
+ int i, linesize;
+ char *buf;
  
  FILE *fp=fopen( fname,"rb" );
  if ( !fp ) 
@@ -26,64 +22,29 @@
    return 1;
   }
 
- fread( header,1,8,fp );
- if ( !png_check_sig( header,8 ) ) return 1;
-
- png=png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL );
- info=png_create_info_struct( png );
- endinfo=png_create_info_struct( png );
-
- png_init_io( png,fp );
- png_set_sig_bytes( png,8 );
- png_read_info( png,info );
- png_get_IHDR( png,info,&bf->Width,&bf->Height,&bf->BPP,&color,NULL,NULL,NULL );
-
- row_p=(png_bytep *)malloc( sizeof( png_bytep ) * bf->Height );
- if ( !row_p )
-  {
-   mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[png]  not enough memory for row buffer\n" );
-   return 2;
-  }
- bf->Image=(png_bytep)malloc( png_get_rowbytes( png,info ) * bf->Height );
- if ( !bf->Image )
-  {
-   mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[png]  not enough memory for image buffer\n" );
-   return 2;
-  }
- for ( i=0; i < bf->Height; i++ ) row_p[i]=&bf->Image[png_get_rowbytes( png,info ) * i];
-
- png_read_image( png,row_p );
- free( row_p );
-
-#if 0
- if ( color == PNG_COLOR_TYPE_PALETTE )
-  {
-   int cols;
-   png_get_PLTE( png,info,(png_colorp *)&palette,&cols );
+  fseek(fp, 0, SEEK_END);
+  fsize = ftell(fp);
+  rewind(fp);
+  buf = malloc(fsize);
+  fread(buf, fsize, 1, fp);
+  dec = img_dec_init(IMG_TYPE_PNG);
+  img_dec_decode(dec, buf, fsize);
+  bf->Width = dec->width;
+  bf->Height = dec->height;
+  bf->BPP = IMGFMT_RGB_DEPTH(dec->img_fmt);
+  linesize = bf->Width * (bf->BPP / 8);
+  bf->ImageSize = bf->Height * linesize;
+  bf->Image = malloc(bf->ImageSize);
+  for (i = 0; i < bf->Height; i++) {
+    memcpy(&bf->Image[i * linesize], &dec->data[0][i * dec->stride[0]], linesize);
   }
-#endif
-
- if ( color&PNG_COLOR_MASK_ALPHA )
-  {
-   if ( color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA ) bf->BPP*=2;
-     else bf->BPP*=4;
-  }
-  else
-   {
-    if ( color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY ) bf->BPP*=1;
-      else bf->BPP*=3;
-   }
-
- png_read_end( png,endinfo );
- png_destroy_read_struct( &png,&info,&endinfo );
+  img_dec_close(dec);
 
  if ( fclose( fp ) != 0 )
   {
    free( bf->Image );
-   free( palette );
    return 1;
   }
- bf->ImageSize=bf->Width * bf->Height * ( bf->BPP / 8 );
 
  mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[png] filename: %s.\n",fname );
  mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[png]  size: %dx%d bits: %d\n",bf->Width,bf->Height,bf->BPP );
Index: libmpcodecs/imgapi.h
===================================================================
RCS file: libmpcodecs/imgapi.h
diff -N libmpcodecs/imgapi.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libmpcodecs/imgapi.h	17 Jul 2005 00:18:49 -0000
@@ -0,0 +1,27 @@
+#define IMG_TYPE_PGM 1
+#define IMG_TYPE_PGMYUV 2
+#define IMG_TYPE_PPM 3
+#define IMG_TYPE_PBM 4
+#define IMG_TYPE_PAM 5
+#define IMG_TYPE_JPEG 6
+#define IMG_TYPE_PNG 7
+
+#ifndef IMGAPI_INTERNAL
+#define AVCodecContext void
+#define AVFrame void
+#endif
+
+typedef struct {
+  AVCodecContext *avctx;
+  AVFrame *pic;
+  int img_fmt;
+  char *data[3];
+  int stride[3];
+  int width;
+  int height;
+} img_decoder_t;
+
+img_decoder_t *img_dec_init(int type);
+void img_dec_close(img_decoder_t *dec);
+int img_dec_decode(img_decoder_t *dec, char *data, int len);
+
Index: libmpcodecs/imgapi.c
===================================================================
RCS file: libmpcodecs/imgapi.c
diff -N libmpcodecs/imgapi.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libmpcodecs/imgapi.c	17 Jul 2005 00:18:49 -0000
@@ -0,0 +1,133 @@
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef USE_LIBAVCODEC_SO
+#include <ffmpeg/avcodec.h>
+#else
+#include "libavcodec/avcodec.h"
+#endif
+#if LIBAVCODEC_BUILD < 4641
+#error we do not support libavcodec prior to build 4641, get the latest libavcodec CVS
+#endif
+#define IMGAPI_INTERNAL 1
+#include "imgapi.h"
+#include "img_format.h"
+
+extern int avcodec_inited;
+
+img_decoder_t *img_dec_init(int type) {
+  img_decoder_t *dec = (img_decoder_t *)calloc(1, sizeof(img_decoder_t));
+  AVCodec *lavc_codec;
+  if (!avcodec_inited) {
+    avcodec_init();
+    avcodec_register_all();
+    avcodec_inited = 1;
+  }
+  switch (type) {
+    case IMG_TYPE_PGM:
+      type = CODEC_ID_PGM;
+      break;
+    case IMG_TYPE_PGMYUV:
+      type = CODEC_ID_PGMYUV;
+      break;
+    case IMG_TYPE_PPM:
+      type = CODEC_ID_PPM;
+      break;
+    case IMG_TYPE_PBM:
+      type = CODEC_ID_PBM;
+      break;
+    case IMG_TYPE_PAM:
+      type = CODEC_ID_PAM;
+      break;
+    case IMG_TYPE_JPEG:
+      type = CODEC_ID_MJPEG;
+      break;
+    case IMG_TYPE_PNG:
+      type = CODEC_ID_PNG;
+      break;
+    default:
+      goto fail;
+  }
+  lavc_codec = avcodec_find_decoder(type);
+  if (!lavc_codec)
+    goto fail;
+  dec->avctx = avcodec_alloc_context();
+#if LIBAVCODEC_BUILD >= 4645
+  dec->pic = avcodec_alloc_frame();
+#else
+  dec->pic = avcodec_alloc_picture();
+#endif
+  if (avcodec_open(dec->avctx, lavc_codec) < 0)
+    goto fail;
+  return dec;
+fail:
+  av_freep(&dec->avctx);
+  av_freep(&dec->pic);
+  free(dec);
+  return NULL;
+}
+
+void img_dec_close(img_decoder_t *dec) {
+  avcodec_close(dec->avctx);
+  av_freep(&dec->avctx);
+  av_freep(&dec->pic);
+  free(dec);
+}
+
+int img_dec_decode(img_decoder_t *dec, char *data, int len) {
+  int got_picture = 0;
+  int res = avcodec_decode_video(dec->avctx, dec->pic, &got_picture, data, len);
+  switch (dec->avctx->pix_fmt) {
+    case PIX_FMT_YUV410P:
+      dec->img_fmt = IMGFMT_YVU9;
+      break;
+    case PIX_FMT_YUVJ420P:
+    case PIX_FMT_YUV420P:
+      dec->img_fmt = IMGFMT_YV12;
+      break;
+    case PIX_FMT_YUVJ422P:
+    case PIX_FMT_YUV422P:
+      dec->img_fmt = IMGFMT_422P;
+      break;
+    case PIX_FMT_YUVJ444P:
+    case PIX_FMT_YUV444P:
+      dec->img_fmt = IMGFMT_444P;
+      break;
+    case PIX_FMT_YUV411P:
+      dec->img_fmt = IMGFMT_411P;
+      break;
+    case PIX_FMT_YUV422:
+      dec->img_fmt = IMGFMT_YUY2;
+      break;
+    case PIX_FMT_RGB24:
+      dec->img_fmt = IMGFMT_RGB24;
+      break;
+    case PIX_FMT_RGBA32:
+      dec->img_fmt = IMGFMT_BGR32;
+      break;
+    case PIX_FMT_BGR24:
+      dec->img_fmt = IMGFMT_BGR24;
+      break;
+    case PIX_FMT_RGB555:
+      dec->img_fmt = IMGFMT_BGR15;
+      break;
+    case PIX_FMT_RGB565:
+      dec->img_fmt = IMGFMT_BGR16;
+      break;
+    case PIX_FMT_PAL8:
+      dec->img_fmt = IMGFMT_BGR8;
+      break;
+    default:
+      return 0;
+  }
+  dec->data[0] = dec->pic->data[0];
+  dec->data[1] = dec->pic->data[1];
+  dec->data[2] = dec->pic->data[2];
+  dec->stride[0] = dec->pic->linesize[0];
+  dec->stride[1] = dec->pic->linesize[1];
+  dec->stride[2] = dec->pic->linesize[2];
+  dec->width = dec->avctx->width;
+  dec->height = dec->avctx->height;
+  return (res >= 0) && got_picture;
+}
+


More information about the MPlayer-dev-eng mailing list