OSErr CreateDecompSeqForGWorldData(GWorldPtr srcGWorld, Rect *srcBounds, MatrixRecordPtr mr, GWorldPtr imageDestination, ImageSequence *imageSeqID) { OSErr err; ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription)); if (imageDesc) { err = MakeImageDescriptionForPixMap (GetGWorldPixMap(srcGWorld), &imageDesc); err = DecompressSequenceBegin( imageSeqID, imageDesc, imageDestination, 0, srcBounds, mr, srcCopy, nil, 0, codecNormalQuality, bestSpeedCodec); DisposeHandle((Handle)imageDesc); } else { err = MemError(); } return err; }
OSErr CreateDecompSeqForSGChannelData(SGChannel sgChannel, Rect *srcBounds, GWorldPtr imageDestination, ImageSequence *imageSeqID) { OSErr err = noErr; ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription)); if (imageDesc) { err = SGGetChannelSampleDescription(sgChannel,(Handle)imageDesc); // The original version of this code had a bug - it passed in a Crop Rect to DecompressSequenceBegin instead of a scaling matrix // This only worked because of another bug inside QT that reated the crop Rect as a destination rect for DV // the following code does the right thing in all cases. if (err == noErr) { MatrixRecord mr; Rect fromR; fromR.left = 0; fromR.top = 0; fromR.right = (**imageDesc).width; fromR.bottom = (**imageDesc).height; RectMatrix(&mr, &fromR, srcBounds); err = DecompressSequenceBegin(imageSeqID, imageDesc, imageDestination, 0, nil, &mr,srcCopy,nil,0, codecNormalQuality, bestSpeedCodec); } DisposeHandle((Handle)imageDesc); } else { err = MemError(); } return err; }
OSErr SpriteUtils_AssignImageGroupIDsToKeyFrame (QTAtomContainer theKeySample) { QTAtom myDefaultsAtom, myImagesContainerAtom; ImageDescriptionHandle myFirstImageDesc = NULL; ImageDescriptionHandle mySecondImageDesc = NULL; short myFirstIndex, mySecondIndex, myNumImages; CodecType myFirstImageType, mySecondImageType; long myGroupID = 0, myTestID; OSErr myErr = noErr; myDefaultsAtom = QTFindChildByIndex(theKeySample, 0, kSpriteSharedDataAtomType, 1, NULL); if (myDefaultsAtom == 0) goto bail; myImagesContainerAtom = QTFindChildByIndex(theKeySample, myDefaultsAtom, kSpriteImagesContainerAtomType, 1, NULL); if (myImagesContainerAtom == 0) goto bail; myFirstImageDesc = (ImageDescriptionHandle)NewHandle(0); if (myFirstImageDesc == NULL) { myErr = memFullErr; goto bail; } mySecondImageDesc = (ImageDescriptionHandle)NewHandle(0); if (mySecondImageDesc == NULL) { myErr = memFullErr; goto bail; } myNumImages = QTCountChildrenOfType(theKeySample, myImagesContainerAtom, kSpriteImageAtomType); for (myFirstIndex = 1; myFirstIndex <= myNumImages; myFirstIndex++) { myErr = SpriteUtils_SetImageGroupID(theKeySample, myImagesContainerAtom, myFirstIndex, 0); if (myErr != noErr) goto bail; } for (myFirstIndex = 1; myFirstIndex <= (myNumImages - 1); myFirstIndex++) { myErr = SpriteUtils_GetImageGroupID(theKeySample, myImagesContainerAtom, myFirstIndex, &myTestID); if (myErr != noErr) goto bail; if (myTestID == 0) { myGroupID++; myErr = SpriteUtils_SetImageGroupID(theKeySample, myImagesContainerAtom, myFirstIndex, myGroupID); if (myErr != noErr) goto bail; myErr = SpriteUtils_GetImageDescription(theKeySample, myImagesContainerAtom, myFirstIndex, myFirstImageDesc); myFirstImageType = (**myFirstImageDesc).cType; if (myErr != noErr) goto bail; for (mySecondIndex = (myFirstIndex + 1); mySecondIndex <= myNumImages; mySecondIndex++) { myErr = SpriteUtils_GetImageGroupID(theKeySample, myImagesContainerAtom, mySecondIndex, &myTestID); if (myErr != noErr) goto bail; if (myTestID == 0) { myErr = SpriteUtils_GetImageDescription(theKeySample, myImagesContainerAtom, mySecondIndex, mySecondImageDesc); if (myErr != noErr) goto bail; mySecondImageType = (**mySecondImageDesc).cType; if (myFirstImageType == mySecondImageType) { ImageSequence mySeqID; Boolean isEquivalent; myErr = DecompressSequenceBegin(&mySeqID, myFirstImageDesc, NULL, NULL, NULL, NULL, ditherCopy, (RgnHandle)NULL, 0, codecNormalQuality, anyCodec); if (myErr != noErr) goto bail; CDSequenceEquivalentImageDescription(mySeqID, mySecondImageDesc, &isEquivalent); CDSequenceEnd(mySeqID); if (isEquivalent) { myErr = SpriteUtils_SetImageGroupID(theKeySample, myImagesContainerAtom, mySecondIndex, myGroupID); if (myErr != noErr) goto bail; } } } } } } // assign an ID to the last image myErr = SpriteUtils_GetImageGroupID(theKeySample, myImagesContainerAtom, myNumImages, &myTestID); if (myErr != noErr) goto bail; if (myTestID == 0) { myGroupID++; myErr = SpriteUtils_SetImageGroupID(theKeySample, myImagesContainerAtom, myNumImages, myGroupID); } bail: if (myFirstImageDesc != NULL) DisposeHandle((Handle)myFirstImageDesc); if (mySecondImageDesc != NULL) DisposeHandle((Handle)mySecondImageDesc); return(myErr); }
static GstStateChangeReturn gst_osx_video_src_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn result; GstOSXVideoSrc *self; ComponentResult err; result = GST_STATE_CHANGE_SUCCESS; self = GST_OSX_VIDEO_SRC (element); // ###: prepare_capture in READY->PAUSED? switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { ImageDescriptionHandle imageDesc; Rect sourceRect; MatrixRecord scaleMatrix; if (!prepare_capture (self)) return GST_STATE_CHANGE_FAILURE; // ###: should we start recording /after/ making the decompressionsequence? // CocoaSequenceGrabber does it beforehand, so we do too, but it feels // wrong. err = SGStartRecord (self->seq_grab); if (err != noErr) { /* since we prepare here, we should also unprepare */ SGRelease (self->seq_grab); GST_ERROR_OBJECT (self, "SGStartRecord returned %d", (int) err); return GST_STATE_CHANGE_FAILURE; } imageDesc = (ImageDescriptionHandle) NewHandle (0); err = SGGetChannelSampleDescription (self->video_chan, (Handle) imageDesc); if (err != noErr) { SGStop (self->seq_grab); SGRelease (self->seq_grab); DisposeHandle ((Handle) imageDesc); GST_ERROR_OBJECT (self, "SGGetChannelSampleDescription returned %d", (int) err); return GST_STATE_CHANGE_FAILURE; } GST_DEBUG_OBJECT (self, "actual capture resolution is %dx%d", (int) (**imageDesc).width, (int) (**imageDesc).height); SetRect (&sourceRect, 0, 0, (**imageDesc).width, (**imageDesc).height); RectMatrix (&scaleMatrix, &sourceRect, &self->rect); err = DecompressSequenceBegin (&self->dec_seq, imageDesc, self->world, NULL, NULL, &scaleMatrix, srcCopy, NULL, 0, codecNormalQuality, bestSpeedCodec); if (err != noErr) { SGStop (self->seq_grab); SGRelease (self->seq_grab); DisposeHandle ((Handle) imageDesc); GST_ERROR_OBJECT (self, "DecompressSequenceBegin returned %d", (int) err); return GST_STATE_CHANGE_FAILURE; } DisposeHandle ((Handle) imageDesc); break; } default: break; } result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (result == GST_STATE_CHANGE_FAILURE) return result; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: SGStop (self->seq_grab); err = CDSequenceEnd (self->dec_seq); if (err != noErr) GST_WARNING_OBJECT (self, "CDSequenceEnd returned %d", (int) err); self->dec_seq = 0; SGRelease (self->seq_grab); break; default: break; } return result; }
// init driver static int init(sh_video_t *sh){ OSErr result = 1; int extradata_size = sh->bih ? sh->bih->biSize - sizeof(*sh->bih) : 0; void *extradata = sh->bih + 1; if (!sh->ImageDesc) mp_msg(MSGT_DECVIDEO,MSGL_ERR,"sh->ImageDesc not set, try -demuxer mov if this fails.\n"); #ifndef CONFIG_QUICKTIME #ifdef WIN32_LOADER Setup_LDT_Keeper(); #endif //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll qtime_qts = LoadLibraryA("QuickTime.qts"); if(!qtime_qts){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"unable to load QuickTime.qts\n" ); return 0; } handler = LoadLibraryA("qtmlClient.dll"); if(!handler){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"unable to load qtmlClient.dll\n"); return 0; } InitializeQTML = (OSErr (*)(long))GetProcAddress(handler, "InitializeQTML"); EnterMovies = (OSErr (*)(void))GetProcAddress(handler, "EnterMovies"); ExitMovies = (void (*)(void))GetProcAddress(handler, "ExitMovies"); 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"); DisposeHandle = (void (*)(Handle))GetProcAddress(handler, "DisposeHandle"); DisposeGWorld = (void (*)(GWorldPtr))GetProcAddress(handler, "DisposeGWorld"); CDSequenceEnd = (OSErr (*)(ImageSequence))GetProcAddress(handler, "CDSequenceEnd"); if(!InitializeQTML || !EnterMovies || !DecompressSequenceBegin || !DecompressSequenceFrameS){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"invalid qtmlClient.dll!\n"); return 0; } result=InitializeQTML(kInitializeQTMLDisableDirectSound | kInitializeQTMLUseGDIFlag | kInitializeQTMLDisableDDClippers); mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"InitializeQTML returned %d\n",result); #endif /* CONFIG_QUICKTIME */ result=EnterMovies(); mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"EnterMovies returned %d\n",result); //make a yuy2 gworld OutBufferRect.top=0; OutBufferRect.left=0; OutBufferRect.right=sh->disp_w; OutBufferRect.bottom=sh->disp_h; //Fill the imagedescription for our SVQ3 frame //we can probably get this from Demuxer if (!sh->ImageDesc && extradata_size >= sizeof(ImageDescription) && ((ImageDescription *)extradata)->idSize <= extradata_size) sh->ImageDesc = extradata; if (sh->ImageDesc) { mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageDescription size: %d\n",((ImageDescription*)(sh->ImageDesc))->idSize); framedescHandle=(ImageDescriptionHandle)NewHandleClear(((ImageDescription*)(sh->ImageDesc))->idSize); memcpy(*framedescHandle,sh->ImageDesc,((ImageDescription*)(sh->ImageDesc))->idSize); } else { // assume extradata consists only of the atoms, build the other parts ImageDescription *idesc; int size = sizeof(*idesc) + extradata_size; mp_msg(MSGT_DECVIDEO, MSGL_V, "Generating a ImageDescription\n"); framedescHandle=(ImageDescriptionHandle)NewHandleClear(size); idesc = *framedescHandle; memcpy(idesc + 1, extradata, extradata_size); idesc->idSize = size; idesc->width = sh->disp_w; idesc->height = sh->disp_h; } dump_ImageDescription(*framedescHandle); (**framedescHandle).cType = bswap_32(sh->format); sh->context = (void *)kYUVSPixelFormat; { int imgfmt = sh->codec->outfmt[sh->outfmtidx]; int qt_imgfmt; switch(imgfmt) { case IMGFMT_YUY2: qt_imgfmt = kYUVSPixelFormat; break; case IMGFMT_YVU9: qt_imgfmt = 0x73797639; //kYVU9PixelFormat; break; case IMGFMT_YV12: qt_imgfmt = 0x79343230; break; case IMGFMT_UYVY: qt_imgfmt = k2vuyPixelFormat; break; case IMGFMT_YVYU: qt_imgfmt = kYVYU422PixelFormat; imgfmt = IMGFMT_YUY2; break; case IMGFMT_RGB16: qt_imgfmt = k16LE555PixelFormat; break; case IMGFMT_BGR24: qt_imgfmt = k24BGRPixelFormat; break; case IMGFMT_BGR32: qt_imgfmt = k32BGRAPixelFormat; break; case IMGFMT_RGB32: qt_imgfmt = k32RGBAPixelFormat; break; default: mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Unknown requested csp\n"); return 0; } mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"imgfmt: %s qt_imgfmt: %.4s\n", vo_format_name(imgfmt), (char *)&qt_imgfmt); sh->context = (void *)qt_imgfmt; if(!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,imgfmt)) return 0; } mpi=mpcodecs_get_image(sh, MP_IMGTYPE_STATIC, MP_IMGFLAG_PRESERVE, sh->disp_w, sh->disp_h); if(!mpi) return 0; result = QTNewGWorldFromPtr( &OutBufferGWorld, (OSType)sh->context, &OutBufferRect, //we should benchmark if yvu9 is faster for svq3, too 0, 0, 0, mpi->planes[0], mpi->stride[0]); if (result) { mp_msg(MSGT_DECVIDEO,MSGL_ERR,"QTNewGWorldFromPtr result=%d\n",result); return 0; } result = DecompressSequenceBegin(&imageSeq, framedescHandle, (CGrafPtr)OutBufferGWorld, NULL, NULL, NULL, srcCopy, NULL, 0, codecNormalQuality, 0); if(result) { mp_msg(MSGT_DECVIDEO,MSGL_ERR,"DecompressSequenceBegin result=%d\n",result); return 0; } return 1; }
pascal OSErr sgdata_callback(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon) { #pragma unused(offset,chRefCon,time,writeType) CodecFlags ignore; V4lState *s=(V4lState *)refCon; ComponentResult err = noErr; if (!s) goto bail; Rect boundsRect = {0, 0, s->vsize.height, s->vsize.width}; /* 240 , 320*/ if (s->pgworld) { if (s->decomseq == 0) { Rect sourceRect = { 0, 0 }; MatrixRecord scaleMatrix; ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(0); err = SGGetChannelSampleDescription(c,(Handle)imageDesc); BailErr(err); // make a scaling matrix for the sequence sourceRect.right = (**imageDesc).width; sourceRect.bottom = (**imageDesc).height; RectMatrix(&scaleMatrix, &sourceRect, &boundsRect); err = DecompressSequenceBegin(&s->decomseq, // pointer to field to receive unique ID for sequence imageDesc, // handle to image description structure s->pgworld, // port for the DESTINATION image NULL, // graphics device handle, if port is set, set to NULL NULL, // source rectangle defining the portion of the image to decompress &scaleMatrix, // transformation matrix srcCopy, // transfer mode specifier NULL, // clipping region in dest. coordinate system to use as a mask 0, // flags codecNormalQuality, // accuracy in decompression bestSpeedCodec); // compressor identifier or special identifiers ie. bestSpeedCodec BailErr(err); DisposeHandle((Handle)imageDesc); imageDesc = NULL; } // decompress a frame into the GWorld - can queue a frame for async decompression when passed in a completion proc // once the image is in the GWorld it can be manipulated at will err = DecompressSequenceFrameS(s->decomseq, // sequence ID returned by DecompressSequenceBegin p, // pointer to compressed image data len, // size of the buffer 0, // in flags &ignore, // out flags NULL); // async completion proc BailErr(err); { unsigned line; mblk_t *buf; int size = s->vsize.width * s->vsize.height * 3; buf=allocb(size,0); PixMap * pixmap = *GetGWorldPixMap(s->pgworld); uint8_t * data; unsigned rowBytes = pixmap->rowBytes & (((unsigned short) 0xFFFF) >> 2); unsigned pixelSize = pixmap->pixelSize / 8; // Pixel size in bytes unsigned lineOffset = rowBytes - s->vsize.width * pixelSize; data = (uint8_t *) GetPixBaseAddr(GetGWorldPixMap(s->pgworld)); for (line = 0 ; line < s->vsize.height ; line++) { unsigned offset = line * (s->vsize.width * pixelSize + lineOffset); memcpy(buf->b_wptr + ((line * s->vsize.width) * pixelSize), data + offset, (rowBytes - lineOffset)); } if (s->pix_fmt==MS_RGB24) { /* Conversion from top down bottom up (BGR to RGB and flip) */ unsigned long Index,nPixels; unsigned char *blue; unsigned char tmp; short iPixelSize; blue=buf->b_wptr; nPixels=s->vsize.width*s->vsize.height; iPixelSize=24/8; for(Index=0;Index!=nPixels;Index++) // For each pixel { tmp=*blue; *blue=*(blue+2); *(blue+2)=tmp; blue+=iPixelSize; } } buf->b_wptr+=size; ms_mutex_lock(&s->mutex); putq(&s->rq, buf); ms_mutex_unlock(&s->mutex); } } bail: return err; }