home *** CD-ROM | disk | FTP | other *** search
- // MPEGView.m
-
- #import <appkit/NXImage.h>
- #import <appkit/graphics.h>
- #import <stdio.h>
- #import <stdlib.h>
- #import <appkit/NXBitmapImageRep.h>
- #import <appkit/Application.h>
- #import <appkit/Panel.h>
- #import <streams/streams.h>
- #import <sys/file.h>
- #import <sys/time.h>
- #import <string.h>
- #import <appkit/tiff.h>
- #import <dpsclient/event.h> /* for NXEvent */
- #import <dpsclient/dpsNeXT.h> // for DPSTimedEntry
- #import <dpsclient/psops.h> // for PSshow()
- #import <objc/NXBundle.h>
- #import <mach/mach.h> // vm_deallocate()
- #import <mach/mach_error.h>
- // Local Categories
- #import "BitmapImageRepData.h"
- // Local Objects
- #import "wraps.h"
- #import "Controller.h"
- #import "MPEGThread.h"
- #import "MPEGView.h"
-
- #define PERIOD_KEY 46 /* period's character code (portable), used in checking for abort (command-period) */
-
- @implementation MPEGView : View
-
- /*** Initialization methods ***/
-
- - initSize:(const NXSize *)aSize info:(mpegInfo *)pInfo
- {
- NXRect imageRect;
-
- NXSetRect(&imageRect, 0.0, 0.0, aSize->width, aSize->height);
- if (![super initFrame:&imageRect])
- return nil;
- if (nil == (theBitmap = [[NXBitmapImageRep alloc] initData:NULL
- pixelsWide:(int)aSize->width
- pixelsHigh:(int)aSize->height
- bitsPerSample:8
- samplesPerPixel:3 // (cSpace == RGB_COLOR) ? 3 : 1
- hasAlpha:NO
- isPlanar:NO
- colorSpace:NX_RGBColorSpace
- bytesPerRow:0
- bitsPerPixel:0]))
- return [self free];
- frameLength = 3 * [theBitmap pixelsWide] * [theBitmap pixelsHigh];
- if (nil == (mpegThread = [[MPEGThread alloc]
- initSize:(4 + frameLength) forView:self]))
- {
- [theBitmap free];
- return [self free];
- }
- data = [(NXBitmapImageRep *)theBitmap data];
- theSize = *aSize;
- info = pInfo;
- [self newZoom:pInfo->zoom];
- procIndex = (pInfo->drop << 1) + pInfo->sync;
- controller = [NXApp delegate];
- tag = (DPSTimedEntry)-1;
- return self;
- }
-
- - free
- {
- [mpegThread free];
- if ((DPSTimedEntry)-1 != tag)
- DPSRemoveTimedEntry(tag);
- [theBitmap setData:data];
- theBitmap = [theBitmap free];
- if (address && len)
- {
- kern_return_t kr;
-
- kr = vm_deallocate(task_self(), (vm_address_t)address, len);
- if (KERN_SUCCESS != kr)
- mach_error("vm_deallocate() failed in -free", kr);
- }
- address = NULL;
- if (info)
- free(info);
- info = NULL;
- return [super free];
- }
-
-
- /*** Standard C functions ***/
-
- double ReadSysClock(void)
- {
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- return (tv.tv_sec + tv.tv_usec / 1000000.0);
- }
-
-
- #define DROP_FRAME \
- if (0.0 == self->now) \
- { \
- self->now = now; \
- frameNumber = 0; \
- } \
- else \
- frameNumber = (int)((now - self->now) * self->info->fps); \
- if (frameNumber == self->frameNumber) \
- return; \
- self->adrs = self->address + (4 + self->frameLength) * frameNumber;
- #define CHECK_FOR_END \
- if (self->adrs >= self->end) \
- { \
- self->info->elapsedTime = ReadSysClock() - self->startTime; \
- DPSRemoveTimedEntry(tag); \
- self->tag = (DPSTimedEntry)-1; \
- [self display]; \
- self->info->frameCount = self->frameCount; \
- if ([self->controller respondsTo:@selector(updateInfoPanels:)]) \
- [self->controller updateInfoPanels:self]; \
- return; \
- }
- #define SLOW_STUFF [controller setFrameNumber:frameNumber];
- #define SHOW_FRAME \
- [self->theBitmap setData:self->adrs]; \
- [self display]; \
- self->adrs += self->frameLength; \
- self->frameCount++;
-
- #define FAST
-
- void te_none(DPSTimedEntry tag, double now, void *userData)
- {
- MPEGView *self = userData;
- int frameNumber;
-
- CHECK_FOR_END
- frameNumber = *((long *)self->adrs)++;
- #ifndef FAST
- SLOW_STUFF
- #endif
- SHOW_FRAME
- }
-
- void te_sync(DPSTimedEntry tag, double now, void *userData)
- {
- MPEGView *self = userData;
- int frameNumber;
-
- CHECK_FOR_END
- frameNumber = *((long *)self->adrs)++;
- #ifndef FAST
- SLOW_STUFF
- #endif
- SHOW_FRAME
- NXPing();
- }
-
- void te_drop(DPSTimedEntry tag, double now, void *userData)
- {
- MPEGView *self = userData;
- int frameNumber;
-
- DROP_FRAME
- CHECK_FOR_END
- frameNumber = *((long *)self->adrs)++;
- #ifndef FAST
- SLOW_STUFF
- #endif
- SHOW_FRAME
- }
-
- void te_syncNdrop(DPSTimedEntry tag, double now, void *userData)
- {
- MPEGView *self = userData;
- int frameNumber;
-
- DROP_FRAME
- CHECK_FOR_END
- frameNumber = *((long *)self->adrs)++;
- #ifndef FAST
- SLOW_STUFF
- #endif
- SHOW_FRAME
- NXPing();
- }
-
- DPSTimedEntryProc procs[] = { te_none, te_sync, te_drop, te_syncNdrop };
-
-
- /*** Instance methods ***/
-
- - runAgain
- {
- double period = 1.0 / info->fps;
- DPSTimedEntryProc proc = procs[procIndex];
-
- frameCount = 0;
- frameNumber = -1;
- [controller setFrameNumber:0];
- [controller updateInfoPanels:self];
- adrs = address;
- end = address + len - 4;
- now = 0.0;
- startTime = ReadSysClock();
- tag = DPSAddTimedEntry(period, proc, self, MAX_PRIORITY);
- if ((DPSTimedEntry)-1 == tag)
- fprintf(stderr, "DSPAddTimedEntry() failed in -runAgain\n");
- return self;
- }
-
-
- - runFromFile:(const char *)mpegFile
- {
- // show something in the new window while preloading
- [self banner];
-
- [mpegThread decodeFile:mpegFile];
- return self;
- }
-
-
- - banner
- {
- if ([self ready])
- return nil;
- [self lockFocus];
- PSWpreloading(theWidth, theHeight);
- [self unlockFocus];
- [[self window] flushWindow];
- return self;
- }
-
-
- - setAddress:(char *)anAddress len:(int)aLen maxlen:(int)aMaxlen
- {
- address = anAddress;
- len = aLen;
- maxlen = aMaxlen;
- info->totalFrames = [controller frameNumber];
- return self;
- }
-
- - (BOOL)ready
- {
- return address ? YES : NO;
- }
-
-
- - (mpegInfo *)info
- {
- return info;
- }
-
-
- - (NXSize *)newZoom:(int)zoom
- {
- info->zoom = zoom;
- theWidth = theSize.width * zoom;
- theHeight = theSize.height * zoom;
- NXSetRect(&theRect, 0, 0, theWidth, theHeight);
- return &theSize;
- }
-
- - newSync:(BOOL)flag
- {
- info->sync = flag;
- procIndex = (info->drop << 1) + info->sync;
- return self;
- }
-
- - newDrop:(BOOL)flag
- {
- info->drop = flag;
- procIndex = (info->drop << 1) + info->sync;
- return self;
- }
-
- - newFrameRate:(float)fps
- {
- info->fps = fps;
- return self;
- }
-
-
- /*** View Instance methods ***/
-
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
- [theBitmap drawIn:&theRect];
- // [theBitmap draw]; // this method will not scale the bitmap
- return self;
- }
-
-
- @end
-