#define __MACTYPES__ // my dodgy prefix requires this typedef ConstStr63Param ConstStrFileNameParam; #include #include #include pascal ComponentResult entrypoint(ComponentParameters *params,char **storage); RoutineDescriptor EntryPointRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char**))), entrypoint ); /* Version information */ #define MY_CODEC_REV 1 #define codecInterfaceVersion 1 /* high word returned in component GetVersion */ /* Some useful macros and constants */ #define R_W 0x4ccd #define G_W 0x970a #define B_W 0x1c29 #define PIN(_n) ((_n) < 0 ? 0 : (_n) > 255 ? 255 : (_n)) extern void avcodec_init(); struct AVCodecContextPlus; extern AVCodecContextPlus * make_my_av_ctx( int width, int height ); extern void free_my_av_ctx( AVCodecContextPlus * avctx ); extern long process_my_av_ctx( AVCodecContextPlus * avctx, unsigned char * inData, int inSize, unsigned char * outData, long outRowBytes ); /* Our data structure declarations */ /* This is the structure we use to hold data used by all instances of this compressor and decompressor */ typedef struct { CodecInfo **info; /* our cached codec info structure */ //OSType ** myPixelTypes; } SharedGlobals; /* This is the structure we use to store our global data for each instance */ typedef struct { SharedGlobals *sharedGlob; /* pointer to instance-shared globals */ AVCodecContextPlus *avctx; } Globals; pascal ComponentResult OpenCodec(ComponentInstance self); RoutineDescriptor OpenCodecRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *))), OpenCodec ); pascal ComponentResult CloseCodec(Handle storage,ComponentInstance self); RoutineDescriptor CloseCodecRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentParameters *))), CloseCodec ); pascal ComponentResult CanDoSelector(short selector); RoutineDescriptor CanDoSelectorRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))), CanDoSelector ); pascal ComponentResult GetVersion(); RoutineDescriptor GetVersionRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))), GetVersion ); ComponentResult InitSharedTables(Globals **glob,ComponentInstance self); pascal long CDPreCompress(Handle storage,register CodecCompressParams *p); RoutineDescriptor CDPreCompressRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CodecCompressParams *))), CDPreCompress ); pascal long CDBandCompress(Handle storage,register CodecCompressParams *p); RoutineDescriptor CDBandCompressRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CodecCompressParams *))), CDBandCompress ); pascal long CDPreDecompress(Handle storage,register CodecDecompressParams *p); RoutineDescriptor CDPreDecompressRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CodecDecompressParams *))), CDPreDecompress ); pascal long CDBandDecompress(Handle storage,register CodecDecompressParams *p); RoutineDescriptor CDBandDecompressRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CodecDecompressParams *))), CDBandDecompress ); pascal ComponentResult CDGetCodecInfo(Handle storage,CodecInfo *info); RoutineDescriptor CDGetCodecInfoRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CodecInfo *))), CDGetCodecInfo ); pascal ComponentResult CDGetCompressedImageSize(Handle storage,ImageDescriptionHandle desc,Ptr data,long dataSize, ICMDataProcRecordPtr dataProc,long *size); RoutineDescriptor CDGetCompressedImageSizeRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ImageDescriptionHandle))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Ptr))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(ICMDataProcRecordPtr))) | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(long))), CDGetCompressedImageSize ); pascal ComponentResult CDGetMaxCompressionSize(Handle storage,PixMapHandle src,const Rect *srcRect,short depth, CodecQ quality,long *size); RoutineDescriptor CDGetMaxCompressionSizeRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(PixMapHandle))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const Rect *))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(short))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(CodecQ))) | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(long *))), CDGetMaxCompressionSize ); pascal ComponentResult CDGetCompressionTime(Handle storage,PixMapHandle src,const Rect *srcRect,short depth, CodecQ *spatialQuality,CodecQ *temporalQuality,unsigned long *time); RoutineDescriptor CDGetCompressionTimeRD = BUILD_ROUTINE_DESCRIPTOR( kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(PixMapHandle))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const Rect *))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(short))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(CodecQ*))) | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(CodecQ*))) | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(unsigned long *))), CDGetCompressionTime ); /** * The entry point into our codec */ pascal ComponentResult entrypoint(ComponentParameters *params,char **storage) { if ( params->what < 0 ) { switch ( params->what ) { case kComponentOpenSelect: return CallComponentFunction(params, (ComponentFunctionUPP)&OpenCodecRD ); case kComponentCloseSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CloseCodecRD ); case kComponentCanDoSelect: return CallComponentFunction(params, (ComponentFunctionUPP)&CanDoSelectorRD ); case kComponentVersionSelect : return CallComponentFunction(params, (ComponentFunctionUPP)&GetVersionRD ); default : return (paramErr); } } switch ( params->what ) { case kImageCodecPreCompressSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDPreCompressRD); case kImageCodecBandCompressSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDBandCompressRD); case kImageCodecPreDecompressSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDPreDecompressRD); case kImageCodecBandDecompressSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDBandDecompressRD); case kImageCodecBusySelect: return 0; // our codec is never asynchronously busy case kImageCodecGetCodecInfoSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDGetCodecInfoRD); case kImageCodecGetCompressedImageSizeSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDGetCompressedImageSizeRD); case kImageCodecGetMaxCompressionSizeSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDGetMaxCompressionSizeRD); case kImageCodecGetCompressionTimeSelect: return CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)&CDGetCompressionTimeRD); default: return(paramErr); } } /************************************************************************************ * This gets called when the thing instance is opened. We allocate our storage at this * point. If we have shared globals, we check if they exist, and put a pointer to them * in our instance globals so that other calls can get to them. */ pascal ComponentResult OpenCodec(ComponentInstance self) { ComponentResult result; Globals **glob; /* First we allocate shared storage. This should be a handle to any kind of data used by the thing instance. They should be allocated in the current heap. */ if ( (glob = (Globals **)NewHandleClear(sizeof(Globals))) == nil ) { return(MemError()); } SetComponentInstanceStorage(self,(Handle)glob); /* Check and initialize our shared globals */ result = InitSharedTables(glob,self); // Perform generic static initialisations here too. avcodec_init(); // We get a new TOC (or so it seems) for every instance. // Well, we get moved around without our refcon disappearing // but with our globals getting cleared anyway. return result; } /************************************************************************************ * This gets called when the thing instance is opened. We allocate our shared storage at this * point. * If we have shared globals, we check if they exist, otherwise we allocate * them and set the ComponentRefCon so that other instances can use them. * * The shared globals hold our CodecInfo struct, which we read from our resource file, * and some tables that we use for speed. If we cant get the tables we can work without * them. All items in the shared globals are made purgeable when the last of our * instances is closed. If our component was loaded in the application heap ( because * there was no room in the system heap) then we keep our shared storage in the app heap. * * We keep a pointer to the shared globals in our instance globals so that other calls can get to them. */ ComponentResult InitSharedTables(Globals **glob,ComponentInstance self) { SharedGlobals *sGlob; long i,j,*lp; char *cp; short resFile; THz saveZone; Boolean inAppHeap; OSErr result = noErr; saveZone = GetZone(); inAppHeap = ( GetComponentInstanceA5(self) != 0 ); if ( !inAppHeap ) SetZone(SystemZone()); if ( (sGlob=(SharedGlobals*)GetComponentRefcon((Component)self)) == nil ) { if ( (sGlob = (SharedGlobals*)NewPtrClear(sizeof(SharedGlobals))) == nil ) { result = MemError(); goto obail; } SetComponentRefcon((Component)self,(long)sGlob); } (*glob)->sharedGlob = sGlob; // keep this around where it's easy to get at if ( sGlob->info == nil || *(Handle)sGlob->info == nil ) { if ( sGlob->info ) DisposeHandle((Handle)sGlob->info); /* Get the CodecInfo struct which we keep in our resource fork */ resFile = OpenComponentResFile((Component)self); if (resFile == -1) { result = memFullErr; goto obail; } sGlob->info = (CodecInfo **) Get1Resource(codecInfoResourceType,128); if ( sGlob->info == nil ) { CloseComponentResFile(resFile); result = ResError(); goto obail; } LoadResource((Handle)sGlob->info); if ( ResError() ) { CloseComponentResFile(resFile); result = ResError(); goto obail; } DetachResource((Handle)sGlob->info); CloseComponentResFile(resFile); } HNoPurge((Handle)sGlob->info); /* if (!sGlob->myPixelTypes) { sGlob->myPixelTypes = (OSType**)NewHandleSys(8); (*sGlob->myPixelTypes)[0] = kYUVSPixelFormat; (*sGlob->myPixelTypes)[1] = 0; HNoPurge( (Handle)sGlob->myPixelTypes ); } */ obail: SetZone(saveZone); if ( result != noErr && sGlob != nil ) { DisposePtr((Ptr)sGlob); SetComponentRefcon((Component)self,(long)nil); } return(result); } /************************************************************************************ * This gets called when the thing instance is closed. We need to get rid of any * instance storage here. */ pascal ComponentResult CloseCodec(Handle storage,ComponentInstance self) { SharedGlobals *sGlob; Globals **glob = (Globals **)storage; // Clean up anything left over if (glob) { if ((*glob)->avctx) { free_my_av_ctx( (*glob)->avctx ); (*glob)->avctx = NULL; } } /* If we are closing our last instance then we make the shared global items purgeable to speed things up next instance. */ if ( CountComponentInstances((Component)self) == 1) { if ( (sGlob=(SharedGlobals*)(*glob)->sharedGlob) != nil ) { if ( sGlob->info ) HPurge((Handle)sGlob->info); /* if (sGlob->myPixelTypes) { DisposeHandle( (Handle)sGlob->myPixelTypes ); } */ } } if ( glob ) DisposeHandle((Handle)glob); return(noErr); } /************************************************************************************ * Return true if we can handle the selector, otherwise false. */ pascal ComponentResult CanDoSelector(short selector) { switch(selector) { case kComponentOpenSelect: case kComponentCloseSelect: case kComponentCanDoSelect: case kComponentVersionSelect : case kImageCodecPreCompressSelect: case kImageCodecBandCompressSelect: case kImageCodecPreDecompressSelect: case kImageCodecBandDecompressSelect: case kImageCodecBusySelect: case kImageCodecGetCodecInfoSelect: case kImageCodecGetCompressedImageSizeSelect: case kImageCodecGetMaxCompressionSizeSelect: case kImageCodecGetCompressionTimeSelect: return(true); default: return (false); } } /************************************************************************************ * Return the version of this component ( defines interface ) and revision level * of the code. */ pascal ComponentResult GetVersion() { return 0x00010001; } /************************************************************************************ * CDPreCompress gets called before an image is compressed, or whenever the source pixmap * pixel size changes when compressing a sequence. We return information about * how we can compress the image to the codec manager, so that it can fit the source data * to our requirements. The ImageDescriptor is already filled in, so we can use it for * reference (or even add to it ). PixelSize is the pixel depth of the source pixmap, we * use this as a reference for deciding what we can do. The other parameters return information * to the CodecManager about what we can do. We can also do setup here if we want to. */ pascal long CDPreCompress(Handle storage,register CodecCompressParams *p) { #pragma unused(storage) CodecCapabilities *capabilities = p->capabilities; ImageDescription *desc = *p->imageDescription; /* * First we return which depth input pixels we can deal with - based on what the * app has available - we can only work with 32 bit input pixels. */ /* switch ( desc->depth ) { case 16: capabilities->wantedPixelSize = 32; break; default: return(codecConditionErr); break; } */ /* if the buffer gets banded, return the smallest one we can deal with */ capabilities->bandMin = desc->height; /* if the buffer gets banded, return the increment it be should grown */ capabilities->bandInc = 0; /* * If a codec needs the dimensions of the source pixmap to be of certain multiples * it can ask for the image to be extended out (via pixel replication) vertically * and/or horizontally. * * In our case, we're dealing with 2 by 2 blocks and therefore we want the image * height and width to both be multiples of 2. If either dimension is odd, we * ask it have it extended by one pixel. */ capabilities->extendWidth = 0; capabilities->extendHeight = 0; return(noErr); } /************************************************************************************ * CDBandCompress gets called when the codec manager wants us to compress an image, or a horizontal * band of an image. The pixel data at sBaseAddr is guaranteed to conform to the criteria we * demanded in BeginCompress. */ pascal long CDBandCompress(Handle storage,register CodecCompressParams *p) { short width,height; Ptr cDataPtr,dataStart; short depth; Rect sRect; long offsetH,offsetV; Globals **glob = (Globals **)storage; register char *baseAddr; long numLines,numStrips; short rowBytes; long stripBytes; char mmuMode = 1; register short y; ImageDescription **desc = p->imageDescription; OSErr result = noErr; /* If there is a progress proc, give it an open call at the start of this band. */ if (p->progressProcRecord.progressProc) CallICMDataProc(p->progressProcRecord.progressProc,codecProgressOpen,0, p->progressProcRecord.progressRefCon); width = (*desc)->width; height = (*desc)->height; depth = (*desc)->depth; dataStart = cDataPtr = p->data; /* figure out offset to first pixel in baseAddr from the pixelsize and bounds */ rowBytes = p->srcPixMap.rowBytes & 0x3fff; sRect = p->srcPixMap.bounds; numLines = p->stopLine - p->startLine; /* number of scanlines in this band */ numStrips = (numLines+1)>>1; /* number of strips in this band */ stripBytes = ((width+1)>>1) * 5; /* adjust the source baseAddress to be at the beginning of the desired rect */ switch ( p->srcPixMap.pixelSize ) { case 32: offsetH = sRect.left<<2; break; case 16: offsetH = sRect.left<<1; break; case 8: offsetH = sRect.left; break; default: result = codecErr; goto bail; } offsetV = sRect.top * rowBytes; baseAddr = p->srcPixMap.baseAddr + offsetH + offsetV; /* if there is not a flush proc, adjust the pointer to the next band */ if ( p->flushProcRecord.flushProc == nil ) cDataPtr += (p->startLine>>1) * stripBytes; else { if ( p->bufferSize < stripBytes ) { result = codecSpoolErr; goto bail; } } /* do the slower flush/progress case if we have too */ if ( p->flushProcRecord.flushProc || p->progressProcRecord.progressProc ) { SharedGlobals *sg = (*glob)->sharedGlob; /* for ( y=0; y < numStrips; y++) { SwapMMUMode(&mmuMode); CompressStrip(cDataPtr,baseAddr,rowBytes,width,sg); SwapMMUMode(&mmuMode); baseAddr += rowBytes<<1; if ( p->flushProcRecord.flushProc ) { if (( result=CallICMFlushProc(p->flushProcRecord.flushProc,cDataPtr,stripBytes, p->flushProcRecord.flushRefCon)) != noErr) { result = codecSpoolErr; goto bail; } } else { cDataPtr += stripBytes; } if (p->progressProcRecord.progressProc) { if(( result=CallICMProgressProc(p->progressProcRecord.progressProc,codecProgressUpdatePercent, FixDiv(y,numStrips),p->progressProcRecord.progressRefCon)) != noErr ) { result = codecAbortErr; goto bail; } } } */ } else { SharedGlobals *sg = (*glob)->sharedGlob; short tRowBytes = rowBytes<<1; /* SwapMMUMode(&mmuMode); for ( y=numStrips; y--; ) { CompressStrip(cDataPtr,baseAddr,rowBytes,width,sg); cDataPtr += stripBytes; baseAddr += tRowBytes; } SwapMMUMode(&mmuMode); */ } /* return size and similarity on the last band */ if ( p->conditionFlags & codecConditionLastBand ) { (*p->imageDescription)->dataSize = stripBytes * ((height+1)>>1); /* return the actual size of the compressed data */ p->similarity = 0; /* we don't do frame differencing */ } bail: /* If there is a progress proc, give it a close call at the end of this band. */ if (p->progressProcRecord.progressProc) CallICMProgressProc(p->progressProcRecord.progressProc,codecProgressClose,0, p->progressProcRecord.progressRefCon); return(result); } /************************************************************************************ * CDPreDecompress gets called before an image is decompressed. We return information about * how we can decompress the image to the codec manager, so that it can fit the destination data * to our requirements. */ pascal long CDPreDecompress(Handle storage,register CodecDecompressParams *p) { Globals **glob = (Globals **)storage; register CodecCapabilities *capabilities = p->capabilities; Rect dRect = p->srcRect; /* Check if the matrix is okay for us. We don't do anything fancy. */ if ( !TransformRect(p->matrix,&dRect,nil) ) return(codecConditionErr); capabilities->wantedPixelSize = 32; //p->wantedDestinationPixelTypes = (*glob)->sharedGlob->myPixelTypes; //DebugStr( "\pSetting pixel format" ); //(*(*glob)->sharedGlob->myPixelTypes)[0] = kYUVUPixelFormat; //(*(*glob)->sharedGlob->myPixelTypes)[1] = 0; capabilities->bandMin = (*p->imageDescription)->height; capabilities->bandInc = 0; /* If we needed our pixels to be aligned on some integer multiple we would set these to * the number of pixels we need the dest extended by. If we dont care, or we take care of * it ourselves we set them to zero. */ capabilities->extendWidth = 0; capabilities->extendHeight = 0; return(noErr); } /************************************************************************************ * CDBandDecompress gets called when the codec manager wants us to decompress an image or a horizontal * band of an image. The pixel data at baseAddr is guaranteed to conform to the criteria we * demanded in BeginDecompress. If maskIn is true, then the mask data at mBaseAddr is valid, and * we need to clear bits in it that correspond to any pixels in the destination we do not want to * change. ( We always write all pixels, so we dont care. This mode is important only for those * codecs that have frame differencing and don't always write all the pixels. ) */ pascal long CDBandDecompress(Handle storage,register CodecDecompressParams *p) { Rect dRect; long offsetH,offsetV; Globals **glob = (Globals **)storage; long numLines,numStrips; short rowBytes; long stripBytes; short width, height; register short y; register char *baseAddr; char *cDataPtr; char mmuMode = 1; OSErr result = noErr; /* Calculate the real base address based on the bounds rect. If it's not a linear transformation, we dont do it. */ dRect = p->srcRect; if ( !TransformRect(p->matrix,&dRect,nil) ) return(paramErr); /* If there is a progress proc, give it an open call at the start of this band. */ if (p->progressProcRecord.progressProc) CallICMProgressProc(p->progressProcRecord.progressProc,codecProgressOpen,0, p->progressProcRecord.progressRefCon); /* initialize some local variables */ width = (*p->imageDescription)->width; height = (*p->imageDescription)->height; rowBytes = p->dstPixMap.rowBytes; numLines = p->stopLine - p->startLine; /* number of scanlines in this band */ cDataPtr = p->data; /* adjust the destination baseaddress to be at the beginning of the desired rect */ offsetH = (dRect.left - p->dstPixMap.bounds.left); switch ( p->dstPixMap.pixelSize ) { case 32: offsetH <<=2; /* 1 pixel = 4 bytes */ break; case 24: offsetH += offsetH<<1; /* 1 pixel = 3 bytes */ break; case 16: offsetH <<=1; /* 1 pixel = 2 bytes */ break; case 8: break; /* 1 pixel = 1 byte */ default: result = codecErr; /* we dont handle these cases, thow we could */ goto bail; } offsetV = (dRect.top - p->dstPixMap.bounds.top) * rowBytes; baseAddr = p->dstPixMap.baseAddr + offsetH + offsetV; // Start the decompressor going if it isn't already if ((*glob)->avctx == NULL) { (*glob)->avctx = make_my_av_ctx(width,height); } /* * If theres a dataproc spooling the data to us, then we have to do the data * in whatever size chunks they want to give us, or if there is a progressProc * make sure to call it as we go along. */ if ( p->dataProcRecord.dataProc || p->progressProcRecord.progressProc ) { SharedGlobals *sg = (*glob)->sharedGlob; result = codecAbortErr; goto bail; } /* * otherwise - do the fast case. */ else { int len = process_my_av_ctx( (*glob)->avctx, (unsigned char *)cDataPtr, p->bufferSize, (unsigned char*)baseAddr, rowBytes ); if (len >= 0) cDataPtr += len; } /* * Update pointer to data in params, so when we get the next * band we'll be at the right place in our data (not for us I think) */ p->data = cDataPtr; if ( p->conditionFlags & codecConditionLastBand ) { /* Tie up any loose ends on the last band of the frame, if we had any */ } bail: /* If there is a progress proc, give it a close call at the end of this band. */ if (p->progressProcRecord.progressProc) CallICMProgressProc(p->progressProcRecord.progressProc,codecProgressClose,0, p->progressProcRecord.progressRefCon); return(result); } /************************************************************************************ * CDGetCodecInfo allows us to return information about ourselves to the codec manager. * * There will be a tool for determining appropriate values for the accuracy, speed * and level information. For now we estimate with scientific wild guessing. * * The info is stored as a resource in the same file with our component. */ pascal ComponentResult CDGetCodecInfo(Handle storage,CodecInfo *info) { Globals **glob = (Globals **)storage; if ( info == nil ) return(paramErr); BlockMove((Ptr)*((*glob)->sharedGlob)->info,(Ptr)info,sizeof(CodecInfo)); return(noErr); } /************************************************************************************ * When CDGetCompressedImageSize is called, we return the size in bytes of the given compressed * data ( for one image frame). */ pascal ComponentResult CDGetCompressedImageSize(Handle storage,ImageDescriptionHandle desc,Ptr data,long dataSize, ICMDataProcRecordPtr dataProc,long *size) { #pragma unused(storage,data,dataSize,dataProc) short width =(*desc)->width; short height = (*desc)->height; if ( size == nil ) return(paramErr); /* * Our data has a size which is deterministic based on the image size. If it were not we * could encode the size in the compressed data, or figure it out by walking the * compressed data. */ *size = ((width+1)/2) * 5 * ((height+1)/2); return(noErr); } /************************************************************************************ * When CDGetMaxCompressionSize is called, we return the maximum size the compressed data for * the given image would be in bytes. */ pascal ComponentResult CDGetMaxCompressionSize(Handle storage,PixMapHandle src,const Rect *srcRect,short depth, CodecQ quality,long *size) { #pragma unused(storage,src,depth,quality) short width = srcRect->right - srcRect->left; short height = srcRect->bottom - srcRect->top; /* we always end up with a fixed size. If we did not, we would return the worst case size */ *size = ((width+1)/2) * 5 * ((height+1)/2); return(noErr); } /************************************************************************************ * When CDGetCompressionTime is called, we return the approximate time for compressing * the given image would be in milliseconds. We also return the closest actual quality * we can handle for the requested value. */ pascal ComponentResult CDGetCompressionTime(Handle storage,PixMapHandle src,const Rect *srcRect,short depth, CodecQ *spatialQuality,CodecQ *temporalQuality,unsigned long *time) { #pragma unused(storage,src,srcRect,depth) if (time) *time = 0; /* we don't know how many msecs */ if (spatialQuality) *spatialQuality = codecNormalQuality; /* we have only one quality level for now */ if (temporalQuality) *temporalQuality = 0; /* we cannot do temporal compression */ return(noErr); } /** * Glue functions so we can link to MSL C without SIOUX */ extern "C" { extern short InstallConsole(short fd) { return 0; } extern void RemoveConsole(void) { } struct NMRecMore : public NMRec { unsigned char mesgStr[256]; }; extern long WriteCharsToConsole(char *buffer, long n) { unsigned char tempbuf[256]; long m = (n >= 256) ? 255 : n; memcpy( tempbuf+1, buffer, m ); tempbuf[0] = m; //DebugStr( tempbuf ); NMRecMore * pNMRec = (NMRecMore*)NewPtrSys( sizeof(NMRecMore) ); memset( pNMRec, 0, sizeof(NMRec) ); pNMRec->qType=nmType; pNMRec->nmStr=pNMRec->mesgStr; pNMRec->nmResp=(NMUPP)-1; memcpy( pNMRec->mesgStr, tempbuf, 256 ); NMInstall(pNMRec); return n; } extern long ReadCharsFromConsole(char *buffer, long n) { return 0; } }