changeset 30606:caaa73737ef1

DirectShow requires stride to be a multiple of 4 for RGB24/BGR24, add a special case to the DMO decoder to handle this.
author reimar
date Thu, 18 Feb 2010 23:11:27 +0000
parents a9c86e91de71
children c6356454b724
files libmpcodecs/vd_dmo.c
diffstat 1 files changed, 39 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/vd_dmo.c	Thu Feb 18 22:37:08 2010 +0000
+++ b/libmpcodecs/vd_dmo.c	Thu Feb 18 23:11:27 2010 +0000
@@ -39,6 +39,12 @@
 
 LIBVD_EXTERN(dmo)
 
+struct context {
+    void *decoder;
+    uint8_t *buffer;
+    int stride;
+};
+
 // to set/get/query special features/parameters
 static int control(sh_video_t *sh,int cmd,void* arg,...){
     return CONTROL_UNKNOWN;
@@ -47,57 +53,80 @@
 // init driver
 static int init(sh_video_t *sh){
     unsigned int out_fmt=sh->codec->outfmt[sh->outfmtidx];
-    if(!(sh->context=DMO_VideoDecoder_Open(sh->codec->dll,&sh->codec->guid, sh->bih, 0, 0))){
+    struct context *ctx;
+    void *decoder;
+    if(!(decoder=DMO_VideoDecoder_Open(sh->codec->dll,&sh->codec->guid, sh->bih, 0, 0))){
         mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_MissingDLLcodec,sh->codec->dll);
         mp_msg(MSGT_DECVIDEO,MSGL_HINT,MSGTR_DownloadCodecPackage);
 	return 0;
     }
     if(!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,out_fmt)) return 0;
+    sh->context = ctx = calloc(1, sizeof(*ctx));
+    ctx->decoder = decoder;
     switch(out_fmt){
     case IMGFMT_YUY2:
     case IMGFMT_UYVY:
-	DMO_VideoDecoder_SetDestFmt(sh->context,16,out_fmt);break; // packed YUV
+	DMO_VideoDecoder_SetDestFmt(ctx->decoder,16,out_fmt);break; // packed YUV
     case IMGFMT_YV12:
     case IMGFMT_I420:
     case IMGFMT_IYUV:
-	DMO_VideoDecoder_SetDestFmt(sh->context,12,out_fmt);break; // planar YUV
+	DMO_VideoDecoder_SetDestFmt(ctx->decoder,12,out_fmt);break; // planar YUV
     case IMGFMT_YVU9:
-        DMO_VideoDecoder_SetDestFmt(sh->context,9,out_fmt);break;
+        DMO_VideoDecoder_SetDestFmt(ctx->decoder,9,out_fmt);break;
+    case IMGFMT_RGB24:
+    case IMGFMT_BGR24:
+        if (sh->disp_w & 3)
+        {
+            ctx->stride = ((sh->disp_w * 3) + 3) & ~3;
+            ctx->buffer = memalign(64, ctx->stride * sh->disp_h);
+        }
     default:
-	DMO_VideoDecoder_SetDestFmt(sh->context,out_fmt&255,0);    // RGB/BGR
+	DMO_VideoDecoder_SetDestFmt(ctx->decoder,out_fmt&255,0);    // RGB/BGR
     }
-    DMO_VideoDecoder_StartInternal(sh->context);
+    DMO_VideoDecoder_StartInternal(ctx->decoder);
     mp_msg(MSGT_DECVIDEO,MSGL_V,MSGTR_DMOInitOK);
     return 1;
 }
 
 // uninit driver
 static void uninit(sh_video_t *sh){
-    DMO_VideoDecoder_Destroy(sh->context);
+    struct context *ctx = sh->context;
+    DMO_VideoDecoder_Destroy(ctx->decoder);
+    free(ctx);
+    sh->context = NULL;
 }
 
 //mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h);
 
 // decode a frame
 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
+    struct context *ctx = sh->context;
+    uint8_t *buffer = ctx->buffer;
+    int type = ctx->buffer ? MP_IMGTYPE_EXPORT : MP_IMGTYPE_TEMP;
     mp_image_t* mpi;
     if(len<=0) return NULL; // skipped frame
 
     if(flags&3){
 	// framedrop:
-        DMO_VideoDecoder_DecodeInternal(sh->context, data, len, 0, 0);
+        DMO_VideoDecoder_DecodeInternal(ctx->decoder, data, len, 0, 0);
 	return NULL;
     }
 
-    mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_COMMON_PLANE,
+    mpi=mpcodecs_get_image(sh, type, MP_IMGFLAG_COMMON_PLANE,
 	sh->disp_w, sh->disp_h);
+    if (buffer) {
+        mpi->planes[0] = buffer;
+        mpi->stride[0] = ctx->stride;
+    } else {
+        buffer = mpi->planes[0];
+    }
 
     if(!mpi){	// temporary!
 	mp_msg(MSGT_DECVIDEO,MSGL_WARN,MSGTR_MPCODECS_CouldntAllocateImageForCinepakCodec);
 	return NULL;
     }
 
-    DMO_VideoDecoder_DecodeInternal(sh->context, data, len, 1, mpi->planes[0]);
+    DMO_VideoDecoder_DecodeInternal(ctx->decoder, data, len, 1, buffer);
 
     return mpi;
 }