[MPlayer-dev-eng] [PATCH] add AIC and ProRes422 binary codec support

Andrew Wason rectalogic at rectalogic.com
Fri Jul 31 15:49:21 CEST 2009


This patch adds support for the QuickTime binary codecs for AIC (Apple
Intermediate Codec) and ProRes422, currently only on Mac though.

It requires the use of "-demuxer mov" since the lavf mov demuxer does
not fill in the ImageDescription.

I've only tested this on Mac, and in fact AIC will only work on Mac
since Apple doesn't even support AIC on any other platform.  I think
more work will be needed in the binary codecs loader before ProRes
will work on Linux.

I had to change vd_qtvideo.c to use the QT decompression sequence APIs
(DecompressSequenceFrameS) instead of ImageCodecBandDecompress.
ImageCodecBandDecompress fails for both these codecs and Apple says it
is not intended to be called directly by applications. They recommend
using the decompression session APIs
(ICMDecompressionSessionDecodeFrame) or the older decompression
sequence APIs (DecompressSequenceFrameS).

I think changes will be needed in loader/qtx to support these QT
decompression APIs on Linux.  So this patch is not ready for
primetime, but might be useful as a starting point.

Andrew
-------------- next part --------------
Index: libmpcodecs/vd_qtvideo.c
===================================================================
--- libmpcodecs/vd_qtvideo.c	(revision 29461)
+++ libmpcodecs/vd_qtvideo.c	(working copy)
@@ -27,17 +27,15 @@
 LIBVD_EXTERN(qtvideo)
 
 //static ComponentDescription desc; // for FindNextComponent()
-static ComponentInstance ci=NULL; // codec handle
 //static CodecInfo cinfo;	// for ImageCodecGetCodecInfo()
 //Component prev=NULL;
 //ComponentResult cres; //
-static CodecCapabilities codeccap; // for decpar
-static CodecDecompressParams decpar; // for ImageCodecPreDecompress()
 //static ImageSubCodecDecompressCapabilities icap; // for ImageCodecInitialize()
 static Rect OutBufferRect;              //the dimensions of our GWorld
 
 static GWorldPtr OutBufferGWorld = NULL;//a GWorld is some kind of description for a drawing environment
 static ImageDescriptionHandle framedescHandle;
+static ImageSequence imageSeq;
 
 #ifndef CONFIG_QUICKTIME
 HMODULE   WINAPI LoadLibraryA(LPCSTR);
@@ -45,24 +43,25 @@
 int       WINAPI FreeLibrary(HMODULE);
 static    HINSTANCE qtime_qts; // handle to the preloaded quicktime.qts
 static    HMODULE handler;
-static    Component (*FindNextComponent)(Component prev,ComponentDescription* desc);
-static    OSErr (*GetComponentInfo)(Component prev,ComponentDescription* desc,Handle h1,Handle h2,Handle h3);
-static    long (*CountComponents)(ComponentDescription* desc);
 static    OSErr (*InitializeQTML)(long flags);
 static    OSErr (*EnterMovies)(void);
-static    ComponentInstance (*OpenComponent)(Component c);
-static    ComponentResult (*ImageCodecInitialize)(ComponentInstance ci,
-                                 ImageSubCodecDecompressCapabilities * cap);
-static    ComponentResult (*ImageCodecBeginBand)(ComponentInstance      ci,
-                                 CodecDecompressParams * params,
-                                 ImageSubCodecDecompressRecord * drp,
-                                 long                   flags);
-static    ComponentResult (*ImageCodecGetCodecInfo)(ComponentInstance      ci,
-                                 CodecInfo *            info);
-static    ComponentResult (*ImageCodecPreDecompress)(ComponentInstance      ci,
-                                 CodecDecompressParams * params);
-static    ComponentResult (*ImageCodecBandDecompress)(ComponentInstance      ci,
-                                 CodecDecompressParams * params);
+static    OSErr (*DecompressSequenceBegin)(ImageSequence *seqID,
+                                           ImageDescriptionHandle desc,
+                                           CGrafPtr port,
+                                           /*GDHandle*/void* gdh,
+                                           const Rect *srcRect,
+                                           MatrixRecordPtr matrix,
+                                           short mode,
+                                           RgnHandle mask,
+                                           CodecFlags flags,
+                                           CodecQ accuracy,
+                                           DecompressorComponent codec);
+static   OSErr (*DecompressSequenceFrameS)(ImageSequence seqID,
+                                           Ptr data,
+                                           long dataSize,
+                                           CodecFlags inFlags,
+                                           CodecFlags *outFlags,
+                                           ICMCompletionProcRecordPtr asyncCompletionProc);
 static    PixMapHandle    (*GetGWorldPixMap)(GWorldPtr offscreenGWorld);
 static    OSErr           (*QTNewGWorldFromPtr)(GWorldPtr *gw,
 			       OSType pixelFormat,
@@ -73,6 +72,9 @@
                                void *baseAddr,
                                long rowBytes);
 static    OSErr           (*NewHandleClear)(Size byteCount);
+static    void            (*DisposeHandle)(Handle h);
+static    void            (*DisposeGWorld)(GWorldPtr offscreenGWorld);
+static    OSErr           (*CDSequenceEnd)(ImageSequence seqID);
 #endif /* #ifndef CONFIG_QUICKTIME */
 
 // to set/get/query special features/parameters
@@ -87,12 +89,6 @@
 #ifndef CONFIG_QUICKTIME
     long result = 1;
 #endif
-    ComponentResult cres;
-    ComponentDescription desc;
-    Component prev=NULL;
-    CodecInfo cinfo;	// for ImageCodecGetCodecInfo()
-    ImageSubCodecDecompressCapabilities icap; // for ImageCodecInitialize()
-
     codec_initialized = 0;
 #ifdef CONFIG_QUICKTIME
     EnterMovies();
@@ -117,21 +113,17 @@
 
     InitializeQTML = (OSErr (*)(long))GetProcAddress(handler, "InitializeQTML");
     EnterMovies = (OSErr (*)(void))GetProcAddress(handler, "EnterMovies");
-    FindNextComponent = (Component (*)(Component,ComponentDescription*))GetProcAddress(handler, "FindNextComponent");
-    CountComponents = (long (*)(ComponentDescription*))GetProcAddress(handler, "CountComponents");
-    GetComponentInfo = (OSErr (*)(Component,ComponentDescription*,Handle,Handle,Handle))GetProcAddress(handler, "GetComponentInfo");
-    OpenComponent = (ComponentInstance (*)(Component))GetProcAddress(handler, "OpenComponent");
-    ImageCodecInitialize = (ComponentResult (*)(ComponentInstance,ImageSubCodecDecompressCapabilities *))GetProcAddress(handler, "ImageCodecInitialize");
-    ImageCodecGetCodecInfo = (ComponentResult (*)(ComponentInstance,CodecInfo *))GetProcAddress(handler, "ImageCodecGetCodecInfo");
-    ImageCodecBeginBand = (ComponentResult (*)(ComponentInstance,CodecDecompressParams *,ImageSubCodecDecompressRecord *,long))GetProcAddress(handler, "ImageCodecBeginBand");
-    ImageCodecPreDecompress = (ComponentResult (*)(ComponentInstance,CodecDecompressParams *))GetProcAddress(handler, "ImageCodecPreDecompress");
-    ImageCodecBandDecompress = (ComponentResult (*)(ComponentInstance,CodecDecompressParams *))GetProcAddress(handler, "ImageCodecBandDecompress");
+    DecompressSequenceBegin = (OSErr (*)(ImageSequence*,ImageDescriptionHandle,CGrafPtr,void *,const Rect *,MatrixRecordPtr,short,RgnHandle,CodecFlags,CodecQ,DecompressorComponent))GetProcAddress(handler, "DecompressSequenceBegin");
+    DecompressSequenceFrameS = (OSErr (*)(ImageSequence,Ptr,long,CodecFlags,CodecFlags*,ICMCompletionProcRecordPtr))GetProcAddress(handler, "DecompressSequenceFrameS");
     GetGWorldPixMap = (PixMapHandle (*)(GWorldPtr))GetProcAddress(handler, "GetGWorldPixMap");
-    QTNewGWorldFromPtr = (OSErr(*)(GWorldPtr *,OSType,const Rect *,CTabHandle,void*,GWorldFlags,void *,long))GetProcAddress(handler, "QTNewGWorldFromPtr");
-    NewHandleClear = (OSErr(*)(Size))GetProcAddress(handler, "NewHandleClear");
+    QTNewGWorldFromPtr = (OSErr (*)(GWorldPtr *,OSType,const Rect *,CTabHandle,void*,GWorldFlags,void *,long))GetProcAddress(handler, "QTNewGWorldFromPtr");
+    NewHandleClear = (OSErr (*)(Size))GetProcAddress(handler, "NewHandleClear");
     //     = GetProcAddress(handler, "");
+    DisposeHandle = (void (*)(Handle))GetProcAddress(handler, "DisposeHandle");
+    DisposeGWorld = (void (*)(GWorldPtr))GetProcAddress(handler, "DisposeGWorld");
+    CDSequenceEnd = (OSErr (*)(ImageSequence))GetProcAddress(handler, "CDSequenceEnd");
 
-    if(!InitializeQTML || !EnterMovies || !FindNextComponent || !ImageCodecBandDecompress){
+    if(!InitializeQTML || !EnterMovies || !DecompressSequenceBegin || !DecompressSequenceFrameS){
 	mp_msg(MSGT_DECVIDEO,MSGL_ERR,"invalid qtmlClient.dll!\n");
 	return 0;
     }
@@ -143,64 +135,6 @@
 //    printf("EnterMovies->%d\n",result);
 #endif /* CONFIG_QUICKTIME */
 
-#if 0
-    memset(&desc,0,sizeof(desc));
-    while((prev=FindNextComponent(prev,&desc))){
-	ComponentDescription desc2;
-	unsigned char* c1=&desc2.componentType;
-	unsigned char* c2=&desc2.componentSubType;
-	memset(&desc2,0,sizeof(desc2));
-//	printf("juhee %p (%p)\n",prev,&desc);
-	GetComponentInfo(prev,&desc2,NULL,NULL,NULL);
-	mp_msg(MSGT_DECVIDEO,MSGL_DGB2,"DESC: %c%c%c%c/%c%c%c%c [0x%X/0x%X] 0x%X\n",
-	    c1[3],c1[2],c1[1],c1[0],
-	    c2[3],c2[2],c2[1],c2[0],
-	    desc2.componentType,desc2.componentSubType,
-	    desc2.componentFlags);
-    }
-#endif
-
-
-    memset(&desc,0,sizeof(desc));
-    desc.componentType= (((unsigned char)'i')<<24)|
-			(((unsigned char)'m')<<16)|
-			(((unsigned char)'d')<<8)|
-			(((unsigned char)'c'));
-#if 0
-    desc.componentSubType=
-		    (((unsigned char)'S'<<24))|
-			(((unsigned char)'V')<<16)|
-			(((unsigned char)'Q')<<8)|
-			(((unsigned char)'3'));
-#else
-    desc.componentSubType = bswap_32(sh->format);
-#endif
-    desc.componentManufacturer=0;
-    desc.componentFlags=0;
-    desc.componentFlagsMask=0;
-
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"Count = %ld\n",CountComponents(&desc));
-    prev=FindNextComponent(NULL,&desc);
-    if(!prev){
-	mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Cannot find requested component\n");
-	return 0;
-    }
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"Found it! ID = %p\n",prev);
-
-    ci=OpenComponent(prev);
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ci=%p\n",ci);
-
-    memset(&icap,0,sizeof(icap));
-    cres=ImageCodecInitialize(ci,&icap);
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageCodecInitialize->%#x  size=%d (%d)\n",cres,icap.recordSize,icap.decompressRecordSize);
-
-    memset(&cinfo,0,sizeof(cinfo));
-    cres=ImageCodecGetCodecInfo(ci,&cinfo);
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"Flags: compr: 0x%X  decomp: 0x%X format: 0x%X\n",
-	cinfo.compressFlags, cinfo.decompressFlags, cinfo.formatFlags);
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"Codec name: %.*s\n",((unsigned char*)&cinfo.typeName)[0],
-	((unsigned char*)&cinfo.typeName)+1);
-
     //make a yuy2 gworld
     OutBufferRect.top=0;
     OutBufferRect.left=0;
@@ -219,7 +153,7 @@
 }
 #else
     if(!sh->ImageDesc) sh->ImageDesc=(sh->bih+1); // hack for SVQ3-in-AVI
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageDescription size: %d\n",((ImageDescription*)(sh->ImageDesc))->idSize);
+    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageDescription size: %ld\n",((ImageDescription*)(sh->ImageDesc))->idSize);
     framedescHandle=(ImageDescriptionHandle)NewHandleClear(((ImageDescription*)(sh->ImageDesc))->idSize);
     memcpy(*framedescHandle,sh->ImageDesc,((ImageDescription*)(sh->ImageDesc))->idSize);
     dump_ImageDescription(*framedescHandle);
@@ -228,6 +162,7 @@
 //    result = FindCodec ('SVQ1',anyCodec,&compressor,&decompressor );
 //    printf("FindCodec SVQ1 returned:%i compressor: 0x%X decompressor: 0x%X\n",result,compressor,decompressor);
 
+    (**framedescHandle).cType = bswap_32(sh->format);
     sh->context = (void *)kYUVSPixelFormat;
 #if 1
     {
@@ -245,7 +180,7 @@
 	    qt_imgfmt = 0x79343230;
 	    break;
 	case IMGFMT_UYVY:
-	    qt_imgfmt = kUYVY422PixelFormat;
+	    qt_imgfmt = k2vuyPixelFormat;
 	    break;
 	case IMGFMT_YVYU:
 	    qt_imgfmt = kYVYU422PixelFormat;
@@ -280,6 +215,18 @@
 
 // uninit driver
 static void uninit(sh_video_t *sh){
+    if(OutBufferGWorld) {
+        DisposeGWorld(OutBufferGWorld);
+        OutBufferGWorld = NULL;
+    }
+    if(framedescHandle) {
+        DisposeHandle((Handle)framedescHandle);
+        framedescHandle = NULL;
+    }
+    if(imageSeq) {
+        CDSequenceEnd(imageSeq);
+        imageSeq = 0;
+    }
 #ifdef CONFIG_QUICKTIME
     ExitMovies();
 #endif
@@ -290,7 +237,7 @@
     long result = 1;
     int i;
     mp_image_t* mpi;
-    ComponentResult cres;
+    CodecFlags ignore;
 
     if(len<=0) return NULL; // skipped frame
 
@@ -298,10 +245,6 @@
 	sh->disp_w, sh->disp_h);
     if(!mpi) return NULL;
 
-    decpar.data = (char*)data;
-    decpar.bufferSize = len;
-    (**framedescHandle).dataSize=len;
-
 if(!codec_initialized){
     result = QTNewGWorldFromPtr(
         &OutBufferGWorld,
@@ -319,56 +262,14 @@
 
 //    printf("IDesc=%d\n",sizeof(ImageDescription));
 
-    decpar.imageDescription = framedescHandle;
-    decpar.startLine=0;
-    decpar.stopLine=(**framedescHandle).height;
-    decpar.frameNumber = 1; //1
-//    decpar.conditionFlags=0xFFD; // first
-//    decpar.callerFlags=0x2001; // first
-    decpar.matrixFlags = 0;
-    decpar.matrixType = 0;
-    decpar.matrix = 0;
-    decpar.capabilities=&codeccap;
-//    decpar.accuracy = 0x1680000; //codecNormalQuality;
-    decpar.accuracy = codecNormalQuality;
-//    decpar.port = OutBufferGWorld;
-//    decpar.preferredOffscreenPixelSize=17207;
-
-//    decpar.sequenceID=malloc(1000);
-//    memset(decpar.sequenceID,0,1000);
-
-//    SrcRect.top=17207;
-//    SrcRect.left=0;
-//    SrcRect.right=0;//image_width;
-//    SrcRect.bottom=0;//image_height;
-
-//    decpar.srcRect = SrcRect;
-    decpar.srcRect = OutBufferRect;
-
-    decpar.transferMode = srcCopy;
-    decpar.dstPixMap = **GetGWorldPixMap( OutBufferGWorld);//destPixmap;
-
-    cres=ImageCodecPreDecompress(ci,&decpar);
-    mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageCodecPreDecompress cres=0x%X\n",cres);
-
-    if(decpar.wantedDestinationPixelTypes)
-    { OSType *p=*(decpar.wantedDestinationPixelTypes);
-      if(p) while(*p){
-          mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"supported csp: 0x%08X %.4s\n",*p,(char *)p);
-	  ++p;
-      }
+    result = DecompressSequenceBegin(&imageSeq, framedescHandle, OutBufferGWorld,
+                                     NULL, NULL, NULL, srcCopy,  NULL, 0,
+                                     codecNormalQuality, 0);
+    if(result) {
+	mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"DecompressSequenceBegin result=%ld\n",65536-(result&0xffff));
+	return NULL;
     }
 
-
-//    decpar.conditionFlags=0x10FFF; // first
-//    decpar.preferredOffscreenPixelSize=17207;
-
-//    decpar.conditionFlags=0x10FFD; // first
-
-//	cres=ImageCodecPreDecompress(ci,&decpar);
-//    printf("ImageCodecPreDecompress cres=0x%X\n",cres);
-
-
     codec_initialized=1;
 }
 
@@ -380,12 +281,9 @@
     }
 #endif
 
-    cres=ImageCodecBandDecompress(ci,&decpar);
-
-    ++decpar.frameNumber;
-
-    if(cres&0xFFFF){
-	mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageCodecBandDecompress cres=0x%X (-0x%X) %d\n",cres,-cres,cres);
+    result = DecompressSequenceFrameS(imageSeq, data, len, 0, &ignore, NULL);
+    if(result) {
+	mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"DecompressSequenceFrameS result=%ld\n",65536-(result&0xffff));
 	return NULL;
     }
 
@@ -394,7 +292,8 @@
 
 if((int)sh->context==0x73797639){	// Sorenson 16-bit YUV -> std YVU9
 
-    short *src0=(short *)((char*)decpar.dstPixMap.baseAddr+0x20);
+    PixMap dstPixMap = **GetGWorldPixMap(OutBufferGWorld);
+    short *src0=(short *)((char*)dstPixMap.baseAddr+0x20);
 
     for(i=0;i<mpi->h;i++){
 	int x;
Index: etc/codecs.conf
===================================================================
--- etc/codecs.conf	(revision 29461)
+++ etc/codecs.conf	(working copy)
@@ -2495,6 +2495,24 @@
   out BGR32,BGR24,BGR8,Y800,RGB32,RGB24,RGB8
   out YV12,YUY2
 
+videocodec qtaic
+  info "QuickTime AIC video decoder"
+  status untested
+  fourcc icod
+  driver qtvideo
+  dll "QuickTime.qts"
+  out UYVY
+
+videocodec qtprores
+  info "QuickTime ProRes 422 video decoder"
+  status untested
+  fourcc apcn
+  fourcc apch
+  fourcc apcs
+  driver qtvideo
+  dll "AppleProResDecoder.qtx"
+  out UYVY
+
 ; VSS codecs (http://vsofts.com/solutions.html):
 
 videocodec vsslight


More information about the MPlayer-dev-eng mailing list