home *** CD-ROM | disk | FTP | other *** search
-
- /*
- **
- ** $VER: dispatch.c 1.5 (1.6.98)
- ** mpegsystem.datatype 1.5
- **
- ** Dispatch routine for a DataTypes class
- **
- ** Written 1997/1998 by Roland 'Gizzy' Mainz
- ** Original example source from David N. Junod
- **
- */
-
- /* main includes */
- #include "classbase.h"
- #include "classdata.h"
-
- /*****************************************************************************/
-
- /* is animation.datatype V41 ? */
- #define ISV41 ((cb -> cb_SuperClassBase -> lib_Version) == 41U)
-
- /*****************************************************************************/
-
-
- /* local prototypes */
-
- /* virtual demux fs-handler related */
- DISPATCHERFLAGS static void Handler( void );
- static void RunHandler( struct ClassBase *cb, struct MPEGSystemInstData *msid );
- static void KillHandler( struct ClassBase *cb, struct MPEGSystemInstData *msid );
- static void dispatch_packet( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct DosPacket *dp );
- static BPTR GetStreamLock( struct ClassBase *cb, struct MPEGSystemInstData *msid, ULONG num, BOOL isaudio );
- static void FreeLock( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct FileLock *fl );
-
- static BOOL SendSeek( struct ClassBase *, struct MPEGSystemInstData *, struct FileHandle *, LONG, LONG );
- static BOOL SendRead( struct ClassBase *, struct MPEGSystemInstData *, struct FileHandle *, UBYTE *, ULONG );
- static struct DosPacket *ObtainDOSPacket( struct ClassBase *, struct MPEGSystemInstData * );
- static void ReleaseDOSPacket( struct ClassBase *, struct MPEGSystemInstData *, struct DosPacket * );
-
- static void STRPTR2BSTR( STRPTR s );
-
- /* MPEG system stream demultiplexer related */
- static UBYTE *get_buf_data( struct ClassBase *cb, struct MPEGSystemInstData *msid, long read_len );
- static UBYTE *calc_time_stamp( struct ClassBase *cb, struct MPEGSystemInstData *msid, UBYTE *buf_ptr , long *time_stamp );
- static UBYTE get_next_start_code( struct ClassBase *cb, struct MPEGSystemInstData *msid );
- static void read_pack_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACK_header *pki );
- static void read_system_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, SYSTEM_header *si );
- static void read_packet_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACKET_header *pi );
- static void print_pack_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACK_header *pki );
- static void print_system_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, SYSTEM_header *si );
- static void print_packet_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACKET_header *pi );
-
- static void exitdemux( struct ClassBase *cb, struct MPEGSystemInstData *msid, LONG result, LONG result2 );
- static void demux( struct ClassBase *cb, struct MPEGSystemInstData *msid, BPTR file );
-
- /* class related */
- static BOOL ScanFrames( struct ClassBase *, Object * );
- static void mysprintf( struct ClassBase *, STRPTR, STRPTR, ... );
-
- static ULONG SaveMPEGSystem( struct ClassBase *cb, struct IClass *cl, Object *o, struct dtWrite *dtw );
-
- /*****************************************************************************/
-
- /* Create "mpegsystem.datatype" BOOPSI class */
- struct IClass *initClass( struct ClassBase *cb )
- {
- struct IClass *cl;
-
- /* Create our class... */
- if( cl = MakeClass( MPEGSYSTEMDTCLASS, ANIMATIONDTCLASS, NULL, (ULONG)sizeof( struct MPEGSystemInstData ), 0UL ) )
- {
- #define DTSTACKSIZE (16384UL)
- cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)StackSwapDispatch; /* see stackswap.c */
- cl -> cl_Dispatcher . h_SubEntry = (HOOKFUNC)Dispatch; /* see stackswap.c */
- cl -> cl_Dispatcher . h_Data = (APTR)DTSTACKSIZE; /* see stackswap.c */
- cl -> cl_UserData = (ULONG)cb;
-
- AddClass( cl );
- }
-
- return( cl );
- }
-
- /*****************************************************************************/
-
- /* class dispatcher */
- DISPATCHERFLAGS
- ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
- {
- struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
- struct MPEGSystemInstData *msid;
- ULONG retval = 0UL;
-
- switch( msg -> MethodID )
- {
- /****** mpegsystem.datatype/OM_NEW *******************************************
- *
- * NAME
- * OM_NEW -- Create a mpegsystem.datatype object.
- *
- * FUNCTION
- * The OM_NEW method is used to create an instance of the
- * mpegsystem.datatype class. This method is passed to the superclass
- * first. After this, mpegsystem.datatype parses the prefs file and
- * makes a scan through the system stream to get index information
- * about the single system stream packets.
- * After all, the mpegsystem.datatype starts two objects which reads
- * the single video and audio streams trougth an internal
- * "demultiplexer" (system stream splitter) filesystem.
- *
- * Subclasses of mpegsystem.datatype are not supported. Any attempt to
- * create a subclass object of mpegsystem.datatype will be rejected by
- * this method.
- *
- * ATTRIBUTES
- * The following attributes can be specified at creation time.
- *
- * DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
- * attribute. Only DTST_FILE is supported.
- * If any other type was set in a given DTA_SourceType,
- * OM_NEW will be rejected.
- * Defaults to DTST_FILE.
- *
- * DTA_Handle -- For DTST_FILE, a BPTR filehandle is expected. This
- * handle will be created by datatypesclass depeding on the DTF_#?
- * flag, which is DTF_BINARY here. DTST_FILE, datatypesclass
- * creates a file handle from the given DTA_Name and DTA_Handle
- * (a BPTR returned by Lock).
- * A DTST_RAM (create empty object) source type requires a NULL
- * handle.
- *
- * RESULT
- * If the object was created a pointer to the object is returned,
- * otherwise NULL is returned.
- *
- ******************************************************************************
- *
- */
- case OM_NEW:
- {
- struct TagItem *ti;
-
- /* We only support DTST_FILE or DTST_RAM as source type */
- if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
- {
- if( ((ti -> ti_Data) != DTST_FILE)
- #ifdef HAS_ENCODER
- && ((ti -> ti_Data) != DTST_RAM)
- #endif /* HAS_ENCODER */
- )
- {
- SetIoErr( ERROR_OBJECT_WRONG_TYPE );
-
- break;
- }
- }
-
- #ifndef HAS_ENCODER
- /* This must not be a subclass of mpegsystem.datatype
- * (not implemented yet)
- */
- if( o == (Object *)cl )
- #endif /* !HAS_ENCODER */
- {
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- /* Load/scan frames... */
- if( !ScanFrames( cb, (Object *)retval ) )
- {
- /* Something went fatally wrong, dispose object */
- CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
- retval = 0UL;
- }
- }
- }
- #ifndef HAS_ENCODER
- else
- {
- /* Subclasses of mpegsystem.datatype are not implemented */
- SetIoErr( ERROR_NOT_IMPLEMENTED );
- }
- #endif /* !HAS_ENCODER */
- }
- break;
-
- /****** mpegsystem.datatype/OM_DISPOSE ***************************************
- *
- * NAME
- * OM_DISPOSE -- Delete a mpegsystem.datatype object.
- *
- * FUNCTION
- * The OM_DISPOSE method is used to delete an instance of the
- * mpegsystem.datatype class. This method is passed to the superclass
- * when it has completed.
- *
- * RESULT
- * The object is deleted. 0UL is returned.
- *
- ******************************************************************************
- *
- */
- case OM_DISPOSE:
- {
- LONG saved_ioerr = IoErr(); /* Preserve I/O error */
-
- /* Get a pointer to our object data */
- msid = (struct MPEGSystemInstData *)INST_DATA( cl, o );
-
- /* Wait for any outstanding blitter usage (which may use one of our bitmaps) */
- WaitBlit();
-
- /* Dispose the current audio and video objects */
- DisposeDTObject( (msid -> msid_CurrVideo) );
- DisposeDTObject( (msid -> msid_CurrAudio) );
-
- /* Kill our virtual demux handler */
- KillHandler( cb, msid );
-
- /* Delete the frame pool */
- DeletePool( (msid -> msid_Pool) );
-
- /* Close verbose output file */
- if( (msid -> msid_VerboseOutput) && ((msid -> msid_VerboseOutput) != -1L) )
- {
- Close( (msid -> msid_VerboseOutput) );
- }
-
- /* Dispose object */
- DoSuperMethodA( cl, o, msg );
-
- /* Restore I/O error */
- SetIoErr( saved_ioerr );
- }
- break;
-
- case OM_UPDATE:
- {
- if( DoMethod( o, ICM_CHECKLOOP ) )
- {
- break;
- }
- }
- case OM_SET:
- {
- /* Pass the attributes to the animation class and force a refresh if we need it */
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- /* The following statement is commented out because mpegsystem.datatype does not allow
- * subclasses when the executable was compiled without the HAS_ENCODER define. Thus, the
- * following statement is NOP unless subclasses are supported...
- */
- #ifdef HAS_ENCODER
- /* Top instance ? */
- if( OCLASS( o ) == cl )
- #endif /* HAS_ENCODER */
- {
- struct RastPort *rp;
-
- /* Get a pointer to the rastport */
- if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
- {
- struct gpRender gpr;
-
- /* Force a redraw */
- gpr . MethodID = GM_RENDER;
- gpr . gpr_GInfo = ((struct opSet *)msg) -> ops_GInfo;
- gpr . gpr_RPort = rp;
- gpr . gpr_Redraw = GREDRAW_UPDATE;
-
- DoMethodA( o, (Msg)(&gpr) );
-
- /* Release the temporary rastport */
- ReleaseGIRPort( rp );
-
- /* We did an update... */
- retval = 0UL;
- }
- }
- }
- }
- break;
-
- /****** mpegsystem.datatype/DTM_WRITE *******************************************
- *
- * NAME
- * DTM_WRITE -- Save data
- *
- * FUNCTION
- * This method saves the object's contents to disk.
- *
- * If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
- * superclass, animation.datatype, which writes a single IFF ILBM
- * picture.
- *
- * If dtw_mode is DTWM_RAW, the object saved an MPEG System stream to
- * the filehandle given, starting with the current frame until
- * the end is reached.
- * The sequence saved can be controlled by the ADTA_Frame, ADTA_Frames
- * and ADTA_FrameIncrement attributes (see TAGS section below).
- *
- * TAGS
- * When writing the local ("raw") format, MPEG System movie, the
- * following attributes are recognized:
- *
- * ADTA_Frame (ULONG) - start frame, saving starts here.
- * Defaults to the current frame displayed.
- *
- * ADTA_Frames (ULONG) - the number of frames to be saved,
- * Defaults to (max_num_of_frames - curr_frame).
- *
- * ADTA_FrameIncrement (ULONG) - frame increment when saving.
- * Defaults to 1, which means: "jump to next frame".
- *
- * NOTE
- * This function is not implemented yet. A possible implementation
- * would implement ACTION_WRITE in the virtial implementation and uses
- * mpegvideo.datatype and mpegaudio.datatype encoders...
- *
- * RESULT
- * Returns 0 for failure (IoErr() returns result2), non-zero
- * for success.
- *
- ******************************************************************************
- *
- */
- case DTM_WRITE:
- {
- struct dtWrite *dtw;
-
- dtw = (struct dtWrite *)msg;
-
- /* Local data format (MPEG System) requested ? */
- if( (dtw -> dtw_Mode) == DTWM_RAW )
- {
- retval = SaveMPEGSystem( cb, cl, o, dtw );
- }
- else
- {
- /* Pass msg to superclass (which writes a single frame as an IFF ILBM picture)... */
- retval = DoSuperMethodA( cl, o, msg );
- }
- }
- break;
-
-
- /****** mpegsystem.datatype/ADTM_LOADFRAME ***********************************
- *
- * NAME
- * ADTM_LOADFRAME -- Load frame
- *
- * FUNCTION
- * The ADTM_LOADFRAME method is used to obtain the bitmap and timing
- * data of the animation.
- * The method is passed to the embedded mpegvideo.datatype object.
- * If successfull, the sample data of struct adtFrame are replaced
- * by the corresponsing audio data from the embedded
- * mpegaudio.datatype object.
- *
- * RESULT
- * Returns the result from the embedded mpegvideo.datatype object
- * (including Result2).
- *
- ******************************************************************************
- *
- */
- case ADTM_LOADFRAME:
- {
- struct adtFrame *alf = (struct adtFrame *)msg;
-
- /* Get a pointer to our object data */
- msid = (struct MPEGSystemInstData *)INST_DATA( cl, o );
-
- if( msid -> msid_CurrVideo )
- {
- if( retval = DoMethodA( (msid -> msid_CurrVideo), msg ) )
- {
- /* Add here the audio part..
- * A better way would be to send SDTM_LOADSAMPLE to load the sample
- * fragment
- */
- if( msid -> msid_Sample )
- {
- UBYTE *sample = msid -> msid_Sample;
- ULONG sample_offset = (alf -> alf_Frame) * (msid -> msid_SamplesPerFrame);
- ULONG len = ((alf -> alf_Duration) + 1UL) * (msid -> msid_SamplesPerFrame);
-
- /* Sample completely out-of-range ? */
- if( sample_offset >= (msid -> msid_SampleLength) )
- {
- /* No sample data ! */
- sample = NULL;
- sample_offset = 0UL;
- len = 0UL;
- }
- else
- {
- /* Sample partial out of range ? */
- if( (sample_offset + len) > (msid -> msid_SampleLength) )
- {
- /* Cut it ! */
- len -= ((sample_offset + len) - (msid -> msid_SampleLength));
- }
- }
-
- /* Fill in the message body */
- alf -> alf_Sample = sample + sample_offset;
- alf -> alf_SampleLength = len;
- alf -> alf_Period = msid -> msid_Period;
- }
- }
- }
- else
- {
- /* No mpegvideo.datatype object (Should not occur, but...). */
- SetIoErr( ERROR_OBJECT_NOT_FOUND );
- }
- }
- break;
-
- /****** mpegsystem.datatype/ADTM_UNLOADFRAME ************************************
- *
- * NAME
- * ADTM_UNLOADFRAME -- Unload frame contents
- *
- * FUNCTION
- * The ADTM_UNLOADFRAME method is used to release the contents of a
- * animation frame.
- *
- * This method is passed to the embedded mpegvideo.datatype object.
- *
- * RESULT
- * Returns the result from the embedded mpegvideo.datatype object.
- *
- ******************************************************************************
- *
- */
- case ADTM_UNLOADFRAME:
- {
- /* Get a pointer to our object data */
- msid = (struct MPEGSystemInstData *)INST_DATA( cl, o );
-
- if( msid -> msid_CurrVideo )
- {
- retval = DoMethodA( (msid -> msid_CurrVideo), msg );
-
- /* Here we should do an SDTM_UNLOADSAMPLE if the sample data were
- * obtained using SDTM_LOADSAMPLE
- */
- }
- }
- break;
-
- /* Let the superclass handle everything else */
- default:
- {
- retval = DoSuperMethodA( cl, o, msg );
- }
- break;
- }
-
- return( retval );
- }
-
-
- static
- BOOL ScanFrames( struct ClassBase *cb, Object *o )
- {
- struct MPEGSystemInstData *msid = (struct MPEGSystemInstData *)INST_DATA( (cb -> cb_Lib . cl_Class), o );
- BOOL success = FALSE;
- LONG error = 0L;
-
- InitSemaphore( (&(msid -> msid_SigSem)) );
-
- /* Create a memory pool for frame nodes */
- if( msid -> msid_Pool = CreatePool( MEMF_PUBLIC, 8192UL, 8192UL ) )
- {
- BPTR fh; /* handle (file handle) */
- ULONG sourcetype; /* type of stream (either DTST_FILE or DTST_RAM) */
-
- /* Prefs defaults */
-
- /* Read prefs */
- ReadENVPrefs( cb, msid );
-
- /* Get file handle, handle type and BitMapHeader */
- if( GetDTAttrs( o, DTA_SourceType, (&sourcetype),
- DTA_Handle, (&fh),
- DTA_Name, (&(msid -> msid_ProjectName)),
- TAG_DONE ) == 3UL )
- {
- switch( sourcetype )
- {
- case DTST_FILE:
- {
- /* we have the filehandle - anything what we want... */
- }
- break;
-
- #ifdef HAS_ENCODER
- case DTST_RAM:
- {
- /* do nothing */
- }
- break;
- #endif /* HAS_ENCODER */
-
- default:
- {
- /* unsupported source type */
- error = ERROR_NOT_IMPLEMENTED;
- }
- break;
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- if( fh )
- {
- /* Run system-stream demultiplexer... */
- demux( cb, msid, fh );
-
- /* ...success ? */
- if( msid -> Handler . Process )
- {
- BPTR v_lock;
-
- /* Get first video stream */
- if( v_lock = GetStreamLock( cb, msid, 0UL, FALSE ) )
- {
- if( msid -> msid_CurrVideo = NewDTObject( NULL, DTA_SourceType, DTST_FILE,
- DTA_Handle, v_lock,
- DTA_GroupID, GID_ANIMATION,
- TAG_DONE ) )
- {
- ULONG video_modeid;
- ULONG *video_cregs;
- struct ColorRegister *video_cm;
- ULONG video_numcolors;
- ULONG video_animwidth,
- video_animdepth,
- video_animheight;
- ULONG video_frame,
- video_numframes,
- video_fps = 0UL,
- video_tpf = 0UL;
- struct BitMap *video_keyframe;
-
- if( GetDTAttrs( (msid -> msid_CurrVideo),
- ADTA_ModeID, (&video_modeid),
- ADTA_CRegs, (&video_cregs),
- ADTA_ColorRegisters, (&video_cm),
- ADTA_NumColors, (&video_numcolors),
- ADTA_Width, (&video_animwidth),
- ADTA_Height, (&video_animheight),
- ADTA_Depth, (&video_animdepth),
- ADTA_Frame, (&video_frame),
- ADTA_Frames, (&video_numframes),
- XTAG( !ISV41, ADTA_FramesPerSecond ), (&video_fps),
- XTAG( ISV41, ADTA_TicksPerFrame ), (&video_tpf),
- ADTA_KeyFrame, (&video_keyframe),
- TAG_DONE ) == 11UL )
- {
- /* This should NEVER fail, but... */
- if( video_numframes && video_keyframe && (video_fps || video_tpf) )
- {
- ULONG *cregs;
- struct ColorRegister *cm;
- ULONG numcolors;
-
- SetDTAttrs( o, NULL, NULL, ADTA_NumColors, video_numcolors, TAG_DONE );
-
- if( GetDTAttrs( o, ADTA_CRegs, (&cregs),
- ADTA_ColorRegisters, (&cm),
- ADTA_NumColors, (&numcolors),
- TAG_DONE ) == 3UL )
- {
- /* Check if we got memory for the palette (if we have one) */
- if( (cregs && cm && (numcolors == video_numcolors)) || (video_numcolors == 0UL) )
- {
- BPTR a_lock;
-
- /* Copy base palette (if we have one) */
- if( video_numcolors )
- {
- CopyMem( video_cregs, cregs, (video_numcolors * 3UL * sizeof( ULONG )) );
- CopyMem( video_cm, cm, (video_numcolors * 3UL * sizeof( struct ColorRegister )) );
- }
-
- msid -> msid_TicksPerFrame = ((ISV41)?(video_tpf):(TICK_FREQ / video_fps));
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjName, (msid -> msid_ProjectName),
- ADTA_ModeID, video_modeid,
- ADTA_Width, video_animwidth,
- ADTA_Height, video_animheight,
- ADTA_Depth, video_animdepth,
- ADTA_Frame, video_frame,
- ADTA_Frames, video_numframes,
- XTAG( !ISV41, ADTA_FramesPerSecond ), video_fps,
- XTAG( ISV41, ADTA_TicksPerFrame ), video_tpf,
- ADTA_KeyFrame, video_keyframe,
- TAG_DONE );
-
- /* Get first audio stream */
- if( a_lock = GetStreamLock( cb, msid, 0UL, TRUE ) )
- {
- if( msid -> msid_CurrAudio = NewDTObject( NULL, DTA_SourceType, DTST_FILE,
- DTA_Handle, a_lock,
- DTA_GroupID, GID_SOUND,
- TAG_DONE ) )
- {
- ULONG volume;
-
- GetDTAttrs( (msid -> msid_CurrAudio), SDTA_Sample, (&(msid -> msid_Sample)),
- SDTA_SampleLength, (&(msid -> msid_SampleLength)),
- SDTA_Period, (&(msid -> msid_Period)),
- SDTA_Volume, (&volume),
- TAG_DONE );
-
- msid -> msid_SamplesPerFrame = ((SysBase -> ex_EClockFrequency) * 10UL) / ((msid -> msid_Period) * (TICK_FREQ / (msid -> msid_TicksPerFrame)) * 2UL);
-
- SetDTAttrs( o, NULL, NULL, ADTA_Sample, (msid -> msid_Sample),
- ADTA_SampleLength, (msid -> msid_SamplesPerFrame),
- ADTA_Period, (msid -> msid_Period),
- ADTA_Volume, volume,
- TAG_DONE );
-
- success = TRUE;
- }
- else
- {
- /* NewDTObjectA failed */
- error = IoErr();
- }
- }
- else
- {
- /* No audio lock */
- error = IoErr();
- }
- }
- else
- {
- /* no palette memory */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* We did not get all attributes we need... */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
- }
- }
- else
- {
- /* We did not get all attributes we need... */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
- }
- else
- {
- /* NewDTObject failed */
- error = IoErr();
- }
- }
- else
- {
- /* no video stream lock */
- error = IoErr();
- }
- }
- else
- {
- /* demuxer failed */
- error = msid -> Demux . retval2;
- }
- }
- else
- {
- /* No file handle ? - Be sure we got a DTST_RAM sourcetype */
- if( sourcetype == DTST_RAM )
- {
- success = TRUE;
- }
- else
- {
- /* No handle ! */
- error = ERROR_REQUIRED_ARG_MISSING;
- }
- }
- }
- }
- else
- {
- /* can't get required attributes from superclass */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
- }
- else
- {
- /* no memory pool */
- error = ERROR_NO_FREE_STORE;
- }
-
- SetIoErr( error );
-
- return( success );
- }
-
-
- /*****************************************************************************/
-
-
- void OpenLogfile( struct ClassBase *cb, struct MPEGSystemInstData *msid )
- {
- if( ((msid -> msid_VerboseOutput) == NULL) || ((msid -> msid_VerboseOutput) == -1L) )
- {
- STRPTR confile;
-
- if( confile = (STRPTR)AllocVec( (((msid -> msid_ProjectName)?(strlen( (msid -> msid_ProjectName) )):(0UL)) + 100UL), MEMF_PUBLIC ) )
- {
- mysprintf( cb, confile, "CON:////MPEG System DataType %s/auto/wait/close/inactive",
- ((msid -> msid_ProjectName)?(FilePart( (msid -> msid_ProjectName) )):(NULL)) );
-
- msid -> msid_VerboseOutput = Open( confile, MODE_READWRITE );
-
- FreeVec( confile );
- }
- }
- }
-
-
- static
- void mysprintf( struct ClassBase *cb, STRPTR buffer, STRPTR fmt, ... )
- {
- APTR args;
-
- args = (APTR)((&fmt) + 1);
-
- RawDoFmt( fmt, args, (void (*))"\x16\xc0\x4e\x75", buffer );
- }
-
-
- void error_printf( struct ClassBase *cb, struct MPEGSystemInstData *msid, STRPTR format, ... )
- {
- OpenLogfile( cb, msid );
-
- if( (msid -> msid_VerboseOutput) && ((msid -> msid_VerboseOutput) != -1L) )
- {
- VFPrintf( (msid -> msid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
-
-
- void syntax_printf( struct ClassBase *cb, struct MPEGSystemInstData *msid, STRPTR format, ... )
- {
- if( msid -> msid_DoSyntax )
- {
- OpenLogfile( cb, msid );
-
- if( (msid -> msid_VerboseOutput) && ((msid -> msid_VerboseOutput) != -1L) )
- {
- VFPrintf( (msid -> msid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
- }
-
-
- void debug_printf( struct ClassBase *cb, struct MPEGSystemInstData *msid, STRPTR format, ... )
- {
- if( msid -> msid_DoDebug )
- {
- OpenLogfile( cb, msid );
-
- if( (msid -> msid_VerboseOutput) && ((msid -> msid_VerboseOutput) != -1L) )
- {
- VFPrintf( (msid -> msid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
- }
-
-
- void verbose_printf( struct ClassBase *cb, struct MPEGSystemInstData *msid, STRPTR format, ... )
- {
- if( (msid -> msid_VerboseOutput) && ((msid -> msid_VerboseOutput) != -1L) )
- {
- VFPrintf( (msid -> msid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
-
-
- static
- ULONG SaveMPEGSystem( struct ClassBase *cb, struct IClass *cl, Object *o, struct dtWrite *dtw )
- {
- ULONG retval = 0UL;
- LONG error /*= 0L*/;
-
- #ifdef HAS_ENCODER
- /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
- if( dtw -> dtw_FileHandle )
- {
- struct MPEGSystemInstData *msid = (struct MPEGSystemInstData *)INST_DATA( cl, o );
-
- ULONG modeid;
- ULONG *cregs;
- ULONG numcolors;
- ULONG startframe = 0UL,
- numframes = 0UL,
- framestep = 1UL;
- ULONG fps = 0UL;
- struct BitMap *keyframe;
- ULONG animwidth,
- animheight,
- animdepth;
-
- if( GetDTAttrs( o, ADTA_ModeID, (&modeid),
- ADTA_CRegs, (&cregs),
- ADTA_NumColors, (&numcolors),
- ADTA_Width, (&animwidth),
- ADTA_Height, (&animheight),
- ADTA_Depth, (&animdepth),
- ADTA_Frame, (&startframe),
- ADTA_Frames, (&numframes),
- ADTA_FramesPerSecond, (&fps),
- ADTA_KeyFrame, (&keyframe),
- TAG_DONE ) == 10UL )
- {
- struct TagItem *tstate,
- *ti;
-
- numframes -= startframe;
-
- tstate = dtw -> dtw_AttrList;
-
- while( ti = NextTagItem( (&tstate) ) )
- {
- switch( ti -> ti_Tag )
- {
- case ADTA_Frame: startframe = ti -> ti_Data; break;
- case ADTA_Frames: numframes = ti -> ti_Data; break;
- case ADTA_FrameIncrement: framestep = ti -> ti_Data; break;
- }
- }
-
- if( framestep == 0UL ) framestep = 1UL;
-
- verbose_printf( cb, msid, "saving mpeg system movie %lu %lu %lu\n", startframe, numframes, framestep );
-
- /* here should follow the encoder part... */
- }
- else
- {
- error_printf( cb, msid, "not enougth attributes\n" );
- }
- }
- #else
- error = ERROR_NOT_IMPLEMENTED; /* no encoder yet */
- #endif /* HAS_ENCODER */
-
- SetIoErr( error );
-
- return( retval );
- }
-
- /*****************************************************************************/
-
- static
- UBYTE *get_buf_data( struct ClassBase *cb, struct MPEGSystemInstData *msid, long read_len )
- {
- long len_left;
- long len_read;
- long temp1;
- UBYTE *buf_ptr;
-
- /* Calculate how much data is left in the buffer */
- len_left = (msid -> Demux . raw_data_buf_len) - ((msid -> Demux . raw_data_buf_ptr) - (msid -> Demux . raw_data_buf));
-
- /* Not enough for the calling function's needs */
- if( len_left < read_len )
- {
- /* There is some data left, so copy to start of buffer */
- if( len_left > 0 )
- {
- memcpy( (msid -> Demux . raw_data_buf), (msid -> Demux . raw_data_buf_ptr), (size_t)len_left );
- }
-
- msid -> Demux . raw_data_buf_ptr = &msid -> Demux . raw_data_buf[ 0 ];
-
- temp1 = MAX_DATA_BUF_LEN - len_left; /* To fill the rest of the buffer */
-
- /* block pos */
- msid -> Demux . curr_file_pos = msid -> Demux . fdin_pos; /* Get file pos */
-
- msid -> Demux . curr_file_pos_in_buffer = ((msid -> Demux . raw_data_buf_ptr) + len_left);
-
- debug_printf( cb, msid, "read: %ld, len %ld, left %ld\n", (LONG)(msid -> Demux . curr_file_pos), (LONG)temp1, (LONG)len_left );
-
- len_read = Read( (msid -> Demux . fdin), (msid -> Demux . curr_file_pos_in_buffer), (LONG)temp1 );
-
- if( len_read == -1L )
- {
- LONG err = IoErr();
-
- error_printf( cb, msid, "Error: reading system file\n" );
- exitdemux( cb, msid, RETURN_FAIL, err );
- }
- else
- {
- msid -> Demux . fdin_pos += len_read;
- }
-
- /* no data left in file - data should never have been requested */
- if( len_read == 0 )
- {
- error_printf( cb, msid, "Error: reached EOF, requested %ld bytes\n", temp1 );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_NOT_ENOUGH_DATA );
- }
-
- msid -> Demux . raw_data_buf_len = len_left + len_read;
-
- /* Read done to end of file but still not enough data to complete request */
- if( (msid -> Demux . raw_data_buf_len) < read_len )
- {
- error_printf( cb, msid, "Error: insufficient data for read\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_NOT_ENOUGH_DATA );
- }
- }
-
- buf_ptr = msid -> Demux . raw_data_buf_ptr; /* For return to calling function. */
- msid -> Demux . raw_data_buf_ptr += read_len; /* Global advanced for use at next call. */
-
- return( buf_ptr );
- }
-
-
- static
- UBYTE *calc_time_stamp( struct ClassBase *cb, struct MPEGSystemInstData *msid, UBYTE *buf_ptr, long *time_stamp )
- {
- /* Determine Time Stamp
- * Contents:
- * Byte 0: 4 bits: depend on SCR/PTS/DTS
- * 3 bits: Time32..30,
- * 1 bit marker:1
- * Byte 1: 8 bits Time29..22.
- * Byte 2: 7 bits Time21..15,
- * 1 bit marker
- * Byte 3: 8 bits Time14..7.
- * Byte 4: 7 bits Time6..0,
- * 1 bit marker
- */
-
- *time_stamp = ((((long)(*buf_ptr)) & 0x0E) << 29);
-
- /* Marker_bit check */
- if( (*buf_ptr & (UBYTE)0x01) != (UBYTE)0x01 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' at calc_time_stamp A.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- *time_stamp |= ((((long)(*buf_ptr)) & 0xFF) << 22);
- buf_ptr++;
-
- *time_stamp |= ((((long)(*buf_ptr)) & 0xFE) << 14);
-
- /* Marker_bit check */
- if( (*buf_ptr & (UBYTE)0x01) != (UBYTE)0x01 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' at calc_time_stamp B.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- *time_stamp |= ((((long)(*buf_ptr)) & 0xFF) << 7);
- buf_ptr++;
-
- *time_stamp |= ((((long)(*buf_ptr)) & 0xFE) >> 1);
-
- /* Marker_bit check */
- if( (*buf_ptr & (UBYTE)0x01) != (UBYTE)0x01 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' at calc_time_stamp C.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- return( buf_ptr );
- }
-
-
- static
- UBYTE get_next_start_code( struct ClassBase *cb, struct MPEGSystemInstData *msid )
- {
- UBYTE *buf_ptr = NULL; /* dead assignment, but avoids SAS/C "Warning 317: possibly uninitialized variable" */
- UWORD zeros;
-
- /* Scan for start code; should be hex 00 00 01 for Pack Start Code,
- * System Start Code, Packet Start Code or ISO_11172_end_code.
- * Leading zeros are ignored.
- */
- for( ;; )
- {
- zeros = 0;
-
- for( ;; )
- {
- buf_ptr = get_buf_data( cb, msid, 1 );
-
- if( *buf_ptr == 0x00 )
- {
- zeros++;
- }
- else
- {
- if( zeros >= 2 )
- {
- if( *buf_ptr != 0x01 )
- {
- zeros = 0;
- }
- else
- {
- break;
- }
- }
- }
- }
-
- buf_ptr = get_buf_data( cb, msid, 1 );
-
- if( (msid -> Demux . system_found) || (*buf_ptr == 0xBB) )
- {
- break;
- }
- }
-
- switch( *buf_ptr )
- {
- case (UBYTE)0xB9:
- return( (UBYTE)ISO_11172_END_CODE );
-
- case (UBYTE)0xBA:
- return( (UBYTE)PACK_START_CODE );
-
- case (UBYTE)0xBB:
- {
- msid -> Demux . system_found = TRUE;
- verbose_printf( cb, msid, "system start\n" );
-
- return( (UBYTE)SYSTEM_START_CODE );
- }
- }
-
- return( *buf_ptr ); /* It must be a stream_id. */
- }
-
-
- static
- void read_pack_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACK_header *pki )
- {
- UBYTE *buf_ptr;
-
- pki -> SCR = 0;
-
- buf_ptr = get_buf_data( cb, msid, PACK_HEADER_LENGTH );
-
- /* Determine System Clock Reference (SCR)
- * Check marker_bits: '0010' = 0x2
- */
-
- if( (*buf_ptr & (UBYTE)0xF0) != (UBYTE)0x20 )
- {
- syntax_printf( cb, msid, "Expecting '0010' after pack_start_code.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr = calc_time_stamp( cb, msid, buf_ptr, (&(pki -> SCR)) );
-
- /* Determine Mux Rate
- * Contents:
- * Byte 5: 1 bit marker,
- * 7 bits mux_rate.
- * Byte 6: 8 bits mux_rate.
- * Byte 7: 7 bits mux_rate,
- * 1 bit marker
- */
- pki -> mux_rate = ((((long)(*buf_ptr)) & 0x7F) << 14);
-
- /* Marker_bit check */
- if( (*buf_ptr & (UBYTE)0x80) != (UBYTE)0x80 )
- {
- syntax_printf( cb, msid, "byte= %lx.\n", *buf_ptr );
- syntax_printf( cb, msid, "Expecting marker_bit value '1' at read_pack_header A.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- pki -> mux_rate |= ((((long)(*buf_ptr)) & 0xFF) << 7);
- buf_ptr++;
-
- pki -> mux_rate |= ((((long)(*buf_ptr)) & 0xFE) >> 1);
-
- /* Marker_bit check */
- if( (*buf_ptr & (UBYTE)0x01) != (UBYTE)0x01 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' at read_pack_header B.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
- }
-
-
- static
- void read_system_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, SYSTEM_header *si )
- {
- UBYTE *buf_ptr;
- long j;
- UBYTE test;
-
- /* Read System Header Length: 2 Bytes after start code.
- * Length of header after header length bytes.
- * Bytes 0 & 1: 8 bits header_length--high & low
- */
- buf_ptr = get_buf_data( cb, msid, 2 );
- si -> header_length = (ULONG)(((long)(*buf_ptr)) << 8);
- buf_ptr++;
- si -> header_length |= (ULONG)(((long)(*buf_ptr)) & 0xFF);
-
- /* Read the rest of the header */
- buf_ptr = get_buf_data( cb, msid, (si -> header_length) );
-
- /* Byte 0: 1 bit marker,
- * 7 bits rate_bound--high
- */
- si -> rate_bound = (ULONG)((((long)*buf_ptr) & 0x7F) << 15);
-
- /* Marker bit check */
- if( (*buf_ptr & (UBYTE)0x80) != (UBYTE)0x80 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' before rate_bound--high.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- /* Byte 1: 8 bits rate_bound--mid */
- si -> rate_bound += (ULONG)((((long)*buf_ptr) & 0xFF) << 7);
- buf_ptr++;
-
- /* Byte 2: 7 bits rate_bound-low,
- * 1 bit marker
- */
- si -> rate_bound += (ULONG)((((long)*buf_ptr) & 0xFE) >> 1);
-
- /* Marker bit check */
- if( (*buf_ptr & (UBYTE)0x01) != (UBYTE)0x01 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' after rate_bound.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- /* Byte 3: 6 bits audio_bound,
- * 1 bit fixed_flag,
- * 1bit CSPS_flag
- */
- si -> audio_bound = (ULONG)((((long)*buf_ptr) & 0xFF) >> 2);
- si -> fixed_flag = (BOOL)((((long)*buf_ptr) & 0x02) >> 1);
- si -> CSPS_flag = (BOOL) (((long)*buf_ptr) & 0x01);
- buf_ptr++;
-
- /* Byte 4: 1b system_audio_lock_flag,
- * 1b system_video_lock_flag,
- * 1b marker,
- * 5b video_bound
- */
- si -> system_audio_lock_flag = (BOOL)((((long)*buf_ptr) & 0x80) >> 7);
- si -> system_video_lock_flag = (BOOL)((((long)*buf_ptr) & 0x40) >> 6);
- si -> video_bound = (ULONG) (((long)*buf_ptr) & 0x1F);
-
- /* Marker bit check */
- if( (*buf_ptr & (UBYTE)0x20) != (UBYTE)0x20 )
- {
- syntax_printf( cb, msid, "Expecting marker_bit value '1' after system_video_lock_flag.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- if( *buf_ptr != (UBYTE)0xFF )
- {
- syntax_printf( cb, msid, "Reserved byte not set to default\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
-
- if( (si -> header_length) == 6 )
- {
- return;
- }
-
- j = 0;
-
- while( (ULONG)buf_ptr < (ULONG)(msid -> Demux . raw_data_buf_ptr) )
- {
- /* All lmntry stream_id's ... */
- test = (*buf_ptr & (UBYTE)0x80);
-
- if( test == 0 )
- {
- error_printf( cb, msid, "system header length incorrect\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- si -> STD_buffer_info[ j ] . stream_id = (*buf_ptr & (UBYTE)0xFF);
-
- buf_ptr++;
-
- /* Check marker_bits */
- if( (*buf_ptr & (UBYTE)0xC0) != (UBYTE)0xC0 )
- {
- syntax_printf( cb, msid, "Expecting placeholder bit values '11' after stream_id.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- si -> STD_buffer_info[ j ] . STD_buffer_bound_scale = (*buf_ptr & (UBYTE)0x20) >> 5;
- si -> STD_buffer_info[ j ] . STD_buffer_size_bound = (*buf_ptr & (UBYTE)0x1F) << 8;
-
- buf_ptr++;
-
- si -> STD_buffer_info[ j ] . STD_buffer_size_bound |= *buf_ptr & (UBYTE)0xFF;
-
- buf_ptr++;
-
- j++;
- }
- }
-
-
- static
- void read_packet_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACKET_header *pi )
- {
- UBYTE *buf_ptr;
- UBYTE test,
- test1;
- long i;
-
- pi -> PTS = 0;
- pi -> DTS = 0;
-
- /* read packet length */
- buf_ptr = get_buf_data( cb, msid, 2 );
-
- /* Bytes 0 & 1: 8 bits packet_length -- high & low */
- pi -> packetlength = (ULONG)(((long)*buf_ptr) << 8);
- buf_ptr++;
- pi -> packetlength |= (ULONG)(((long)*buf_ptr) & 0xFF);
-
- /* Get the remainder of the packet. */
- buf_ptr = get_buf_data( cb, msid, (pi -> packetlength) );
-
- /* private stream 2 */
- if( (pi -> stream_id) <= (UBYTE)0xBF )
- {
- pi -> packet_ptr = buf_ptr;
- return;
- }
-
- /* Skip over any stuffing Bytes 1111 1111 (16 max)
- * Count to 17 to see if there are more than allowed in the spec.
- */
-
- i = 0;
-
- while( (*buf_ptr == (UBYTE)0xFF) && (i < 17) )
- {
- buf_ptr++;
- pi -> packetlength--;
- i++;
- }
-
- if( i == 17 )
- {
- error_printf( cb, msid, "Too many stuffing bytes after packet_length\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- /* If nextbits =='01' read STD_buffer_scale & _size
- * Byte: 2b '01',
- * 1b STD_buffer_scale,
- * 5b STD_buffer_size-hi
- * Byte: 8 bits STD_buffer_size--lo
- */
- test1 = *buf_ptr & (UBYTE)0xC0;
-
- if( test1 == (UBYTE)0x40 )
- {
- /* read STD values */
- pi -> STD_buffer_scale = (*buf_ptr & (UBYTE)0x20) >> 5;
- pi -> STD_buffer_size = (*buf_ptr & (UBYTE)0x1F) << 8;
- buf_ptr++;
-
- pi -> packetlength--;
- pi -> STD_buffer_size |= (*buf_ptr & (UBYTE)0xFF);
- buf_ptr++;
-
- pi -> packetlength--;
- }
-
- /* Determine whether to read in PTS, PTS & DTS, or neither before data. */
- test = (*buf_ptr & (UBYTE)0xF0);
-
- switch( test )
- {
- case (UBYTE)0x20: /* Get PTS only */
- {
- buf_ptr = calc_time_stamp( cb, msid, buf_ptr, (&(pi -> PTS)) );
- pi -> packetlength -= 5;
- }
- break;
-
- case (UBYTE)0x30: /* Get PTS & DTS. Both same format as PTS above.
- * pts and data
- */
- {
- buf_ptr = calc_time_stamp( cb, msid, buf_ptr, (&(pi -> PTS)) );
-
- /* Get DTS */
- if( (*buf_ptr & (UBYTE)0xF0) != (UBYTE)0x10 )
- {
- syntax_printf( cb, msid, "Expecting bits '0001' before DTS in read_packet_header\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr = calc_time_stamp( cb, msid, buf_ptr, (&(pi -> DTS)) );
- pi -> packetlength -= 10;
- }
- break;
-
- case (UBYTE)0x00:
- {
- if( *buf_ptr != (UBYTE)0x0F )
- {
- error_printf( cb, msid, "not a valid packet time sequence\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
-
- buf_ptr++;
- pi -> packetlength--;
- }
- break;
-
- default:
- {
- error_printf( cb, msid, "invalid time code in packet\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_INVALID_DATA );
- }
- break;
- }
-
- /* packetlength should have been properly set by the above */
-
- pi -> packet_ptr = buf_ptr;
- }
-
-
- static
- void print_pack_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACK_header *pki )
- {
- long mux_byte_rate = (pki -> mux_rate) * 50;
-
- verbose_printf( cb, msid, "PACK HEADER: SCR = %ld, Mux Rate = %ld, or %ld Bytes per second\n",
- (LONG)(pki -> SCR), (LONG)(pki -> mux_rate), mux_byte_rate );
- }
-
-
- static
- void print_system_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, SYSTEM_header *si )
- {
- long i = 0;
- long stream_num = 0;
- long buf_byte_size_bound;
- UBYTE stream_type = 0;
-
- verbose_printf( cb, msid, "SYSTEM HEADER: Hdr Len = %ld, Rate bound = %ld, Audio bound = %ld,\n",
- (LONG)(si -> header_length),
- (LONG)(si -> rate_bound),
- (LONG)(si -> audio_bound) );
-
- verbose_printf( cb, msid, "Fixed flag = %ld, CSPS flag = %ld, Sys audio lock flag = %ld,\n",
- (LONG)(si -> fixed_flag),
- (LONG)(si -> CSPS_flag),
- (LONG)(si -> system_audio_lock_flag) );
-
- verbose_printf( cb, msid, "Sys video lock flag = %ld, Video bound = %ld\n",
- (LONG)(si -> system_video_lock_flag), (LONG)(si -> video_bound) );
-
- while( si -> STD_buffer_info[ i ] . stream_id != 0 )
- {
- if( ((si -> STD_buffer_info[ i ] . stream_id >> 5) & 0x6) == 0x6 )
- {
- stream_type = 'A';
- stream_num = (long)((si -> STD_buffer_info[ i ] . stream_id) & 0x1F);
- }
-
- if( ((si -> STD_buffer_info[ i ] . stream_id >> 4) & 0xE) == 0xE )
- {
- stream_type = 'V';
- stream_num = (long)((si -> STD_buffer_info[ i] . stream_id) & 0x0F);
- }
-
- if( si -> STD_buffer_info[ i ] . STD_buffer_bound_scale == 0 )
- {
- buf_byte_size_bound = si -> STD_buffer_info[ i ] . STD_buffer_size_bound * 128;
- }
- else
- {
- buf_byte_size_bound= si -> STD_buffer_info[ i ] . STD_buffer_size_bound * 1024;
- }
-
- verbose_printf( cb, msid, "STD buf %ld: Stream %lc%ld, Buf bound scale %ld, Buf size bound %ld or %ld bytes\n",
- i, stream_type, stream_num,
- (si -> STD_buffer_info[ i ] . STD_buffer_bound_scale),
- (si -> STD_buffer_info[ i ] . STD_buffer_size_bound),
- buf_byte_size_bound );
- i++;
- }
- }
-
-
- static
- void print_packet_header( struct ClassBase *cb, struct MPEGSystemInstData *msid, PACKET_header *pi )
- {
- long stream_num = 0;
- UBYTE stream_type = 0;
-
- if( ((pi -> stream_id >> 5) & 0x6) == 0x6 )
- {
- stream_type = 'A';
- stream_num = (long)((pi -> stream_id) & 0x1F);
- }
-
- if( ((pi -> stream_id >> 4) & 0xE) == 0xE )
- {
- stream_type = 'V';
- stream_num = (long)((pi -> stream_id) & 0x0F);
- }
-
- verbose_printf( cb, msid, "PACKET HDR %lc%ld: %ldB, STD buf scale %ld, ..size %ld, PTS %ld, DTS %ld\n",
- stream_type,
- stream_num,
- (pi -> packetlength),
- (pi -> STD_buffer_scale),
- (pi -> STD_buffer_size),
- (pi -> PTS),
- (pi -> DTS) );
- }
-
-
- static
- void demux( struct ClassBase *cb, struct MPEGSystemInstData *msid, BPTR file )
- {
- PACK_header pack_info;
- PACK_header *pack_info_p = &pack_info;
- SYSTEM_header sys_info;
- SYSTEM_header *sys_info_p = &sys_info;
- PACKET_header pkt_info;
- PACKET_header *pkt_info_p = &pkt_info;
-
- long i,
- j;
- long current_audio = 0;
- long current_video = 0;
- long demux_id[ MAX_MPEG_STREAMS ];
- UBYTE next_code;
-
- /* Alloc input buffer */
- if( msid -> Demux . raw_data_buf = (UBYTE *)AllocVec( MAX_DATA_BUF_LEN, MEMF_PUBLIC ) )
- {
- /* Set "point of return" on decoder exit/error */
- if( setjmp( (msid -> Demux . exit_buf) ) == 0 )
- {
- /* Init remaining fields */
- msid -> Demux . raw_data_buf_len = 0;
- msid -> Demux . raw_data_buf_ptr = msid -> Demux . raw_data_buf;
-
- msid -> Demux . fdin = file;
- msid -> Demux . fdin_pos = 0L;
-
- /* Read and write data. */
- for( ;; )
- {
- next_code = get_next_start_code( cb, msid );
-
- verbose_printf( cb, msid, "next_code = %lx\n", (LONG)next_code );
-
- /* next_code identifies whether the stream is at
- * the beginning of a system stream, a pack, or a packet,
- * or if it is at the end of a system stream.
- */
- switch( next_code )
- {
- case ((UBYTE)PACK_START_CODE): /* 0xBA */
- {
- read_pack_header( cb, msid, pack_info_p );
- print_pack_header( cb, msid, pack_info_p );
- }
- break;
-
- case ((UBYTE)SYSTEM_START_CODE): /* 0xBB */
- {
- read_system_header( cb, msid, sys_info_p );
- print_system_header( cb, msid, sys_info_p );
-
- msid -> Demux . N = sys_info_p -> audio_bound;
- msid -> Demux . M = sys_info_p -> video_bound;
-
- verbose_printf( cb, msid, " %ld audio, %ld video\n", (msid -> Demux . N), (msid -> Demux . M) );
-
- current_audio = 0;
- current_video = msid -> Demux . N;
-
- for( i = 0 ; i < MAX_MPEG_STREAMS ; i++ )
- {
- demux_id[ i ] = -1;
- }
- }
- break;
-
- case ((UBYTE)ISO_11172_END_CODE): /* 0xB9 */
- {
- verbose_printf( cb, msid, "end of system stream reached\n" );
-
- exitdemux( cb, msid, RETURN_OK, 0L );
- }
- break;
-
- default: /* PACKET START CODE & stream_id */
- {
- pkt_info_p -> stream_id = next_code;
- read_packet_header( cb, msid, pkt_info_p );
- print_packet_header( cb, msid, pkt_info_p );
-
- /* The stream_id identifies the stream by type and number */
- switch( pkt_info_p -> stream_id )
- {
- case( (UBYTE)0xB8 ): /* may need more work */
- {
- /* Following STD_buffer_scale and _size refer to
- * all audio streams in the muxed stream
- */
- error_printf( cb, msid, "Error handling common audio STD_buffer_scale and _size.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_UNKNOWN_COMPRESSION );
- }
- break;
-
- case( (UBYTE)0xB9 ): /* may need more work */
- {
- /* Following STD_buffer_scale and _size refer to
- * all video streams in the muxed stream
- */
- error_printf( cb, msid, "Error handling common video STD_buffer_scale and _size.\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_UNKNOWN_COMPRESSION );
- }
- break;
-
- case( (UBYTE)0xBC ):
- {
- /* Reserved stream: discard */
- error_printf( cb, msid, "Received reserved stream\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_UNKNOWN_COMPRESSION );
- }
- break;
-
- case( (UBYTE)0xBD ):
- {
- /* private_stream_1: discard */
- error_printf( cb, msid, "Received private_stream_1\n" );
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_UNKNOWN_COMPRESSION );
- }
- break;
-
- case( (UBYTE)0xBE ): /* data bytes all FF */
- {
- /* Padding stream: discard */
- verbose_printf( cb, msid, "Received padding stream\n" );
- }
- break;
-
- case( (UBYTE)0xBF ):
- {
- /* private_stream_2: discard */
- error_printf( cb, msid, "Received private_stream_2\n" );
-
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_UNKNOWN_COMPRESSION );
- }
- break;
-
- default:
- {
- /* The stream is an audio, video, or reserved_data stream.
- * Convert stream_id to C0 to 0, EF to 48
- */
- i = (((long)pkt_info_p -> stream_id) & 0xFF) - 192;
-
- if( i < 0 )
- {
- /* Invalid stream: do nothing */
- }
- else
- {
- /* Audio or Video stream. */
- if( i < 48 )
- {
- BOOL isaudio = (i < 32);
- struct PacketBlock *pb;
-
- if( demux_id[ i ] == -1 )
- {
- /* A new stream */
- if( isaudio )
- {
- /* Audio */
- demux_id[ i ] = current_audio;
- current_audio++;
- }
- else
- {
- demux_id[ i ] = current_video;
- current_video++;
- }
- }
-
- j = demux_id[ i ];
-
- /* No file ? - Then create it ! */
- if( (msid -> Demux . fd_demuxa[ j ] . sl_handle) == NULL )
- {
- NewList( (struct List *)(&(msid -> Demux . fd_demuxa[ j ] . sl_packetblocklist)) );
-
- msid -> Demux . fd_demuxa[ j ] . sl_handle = msid -> Demux . fdin;
- }
-
- /* block pos */
- verbose_printf( cb, msid, "write: off %ld len %ld\n", (msid -> Demux . curr_file_pos + /* file pos */
- (long)((pkt_info_p -> packet_ptr) - msid -> Demux . curr_file_pos_in_buffer)),
- (pkt_info_p -> packetlength) );
-
- /* Create, fill and queue a PacketBlock node */
- pb = (struct PacketBlock *)AllocPooled( (msid -> msid_Pool), (ULONG)sizeof( struct PacketBlock ) );
- if( pb == NULL ) exitdemux( cb, msid, RETURN_FAIL, ERROR_NO_FREE_STORE );
-
- pb -> system_offset = (msid -> Demux . curr_file_pos + (long)((pkt_info_p -> packet_ptr) - msid -> Demux . curr_file_pos_in_buffer)); /* file pos */
- pb -> length = (pkt_info_p -> packetlength);
-
- /* Inc stream size */
- msid -> Demux . fd_demuxa[ j ] . sl_size += pb -> length;
-
- AddTail( (struct List *)(&(msid -> Demux . fd_demuxa[ j ] . sl_packetblocklist)), (struct Node *)(&(pb -> node)) );
- }
- else
- {
- if( i >= 48 )
- {
- /* It's a reserved data stream.
- * Additional functionality will be implementation dependent
- */
- verbose_printf( cb, msid, "Reserved data stream %ld is being ignored.\n", i );
- break;
- }
- else
- {
- /* Should never be reached. */
- error_printf( cb, msid, "Unrecognized stream ID: %ld %lx %lc\n",
- (pkt_info_p -> stream_id),
- (pkt_info_p -> stream_id),
- (long)(pkt_info_p -> stream_id) );
-
- exitdemux( cb, msid, RETURN_FAIL, DTERROR_UNKNOWN_COMPRESSION );
- }
- }
- }
- }
- break;
- }
- }
- }
- }
- }
-
- /* Success ? */
- if( ((msid -> Demux . retval) <= RETURN_WARN) || (msid -> msid_IgnoreErrors) )
- {
- RunHandler( cb, msid );
- }
-
- FreeVec( (msid -> Demux . raw_data_buf) );
- }
- }
-
-
- static
- void exitdemux( struct ClassBase *cb, struct MPEGSystemInstData *msid, LONG result, LONG result2 )
- {
- msid -> Demux . retval = result;
- msid -> Demux . retval2 = result2;
-
- longjmp( (msid -> Demux . exit_buf), 1 );
- }
-
-
- /*****************************************************************************/
-
- static
- BPTR GetStreamLock( struct ClassBase *cb, struct MPEGSystemInstData *msid, ULONG num, BOOL isaudio )
- {
- if( msid -> Handler . Process )
- {
- BPTR lock;
-
- num += (isaudio)?(0UL):(msid -> Demux . N); /* Add video ID-offset if neccesary */
-
- lock = (BPTR)DoPkt( (&(msid -> Handler . Process -> pr_MsgPort)), ACTION_COPY_DIR, MKBADDR( (num * 16) ), 0L, 0L, 0L, 0L );
-
- return( lock );
- }
-
- return( NULL );
- }
-
-
- static
- void RunHandler( struct ClassBase *cb, struct MPEGSystemInstData *msid )
- {
- if( msid -> Handler . Process = CreateNewProcTags( NP_Entry, (ULONG)Handler,
- NP_Name, (ULONG)"mpegsystem.datatype (MPEG System Demux Handler)",
- NP_Priority, 15L,
- NP_StackSize, 16384UL,
- TAG_DONE ) )
- {
- /* Initialize the message */
- msid -> Handler . Startup . sm_Message . mn_Node . ln_Type = NT_MESSAGE;
- msid -> Handler . Startup . sm_Message . mn_Length = sizeof( struct StartupMsg );
- msid -> Handler . Startup . sm_CB = cb;
- msid -> Handler . Startup . sm_msid = msid;
-
- /* Send the information to the process */
- PutMsg( (&(msid -> Handler . Process -> pr_MsgPort)), (&(msid -> Handler . Startup . sm_Message)) );
- }
- }
-
-
- /* Kill our virtual demux filesystem and wait until it is really dead...
- * (Should be replaced by a version which uses exec.library/Wait)
- */
- static
- void KillHandler( struct ClassBase *cb, struct MPEGSystemInstData *msid )
- {
- while( (msid -> Handler . Process) )
- {
- Forbid();
-
- if( msid -> Handler . Process )
- {
- Signal( (&(msid -> Handler . Process -> pr_Task)), SIGBREAKF_CTRL_C );
- }
-
- Permit();
-
- /* Wait a 1/25 sec before trying it again... */
- Delay( (TICKS_PER_SECOND / 25UL) );
- }
- }
-
-
- /* virtual demux filesystem handler entry */
- DISPATCHERFLAGS
- static
- void Handler( void )
- {
- #ifdef SysBase
- #undef SysBase
- #endif
- struct ExecBase *SysBase = (*((struct ExecBase **)4UL));
- struct Process *pr;
- struct StartupMsg *sm;
- struct ClassBase *cb;
- struct MPEGSystemInstData *msid;
- ULONG sigflags;
- struct Message *msg;
- BOOL done = FALSE;
-
- /* Find out who we are */
- pr = (struct Process *)FindTask( NULL );
-
- /* Get the startup message */
- WaitPort( (&(pr -> pr_MsgPort)) );
- sm = (struct StartupMsg *)GetMsg( (&(pr -> pr_MsgPort)) );
-
- /* Pull all the information required from the startup message */
- cb = sm -> sm_CB;
- msid = sm -> sm_msid;
-
- /* BUG: The parent process does currently not handle a failure if this process... */
- while( (msid -> Handler . mp = CreateMsgPort()) == NULL )
- {
- }
-
- /* Init DOS_STDPKT queue which is used within the handler to avoid a AllocDOSObject
- * and fill it up with some packets...
- */
- {
- ULONG i;
-
- NewList( (struct List *)(&(msid -> Handler . pktpool)) );
-
- for( i = 0UL ; i < 16UL ; i++ )
- {
- struct DosPacket *dp;
-
- if( dp = (struct DosPacket *)AllocDosObject( DOS_STDPKT, NULL ) )
- {
- AddTail( (struct List *)(&(msid -> Handler . pktpool)), (&(dp -> dp_Link -> mn_Node)) );
- }
- else
- {
- break;
- }
- }
- }
-
- do
- {
- sigflags = Wait( (1UL << (pr -> pr_MsgPort . mp_SigBit)) | SIGBREAKF_CTRL_C );
-
- if( sigflags & SIGBREAKF_CTRL_C )
- {
- done = TRUE;
- }
-
- while( msg = GetMsg( (&(pr -> pr_MsgPort)) ) )
- {
- dispatch_packet( cb, msid, (struct DosPacket *)(msg -> mn_Node . ln_Name) );
- }
- } while( (!done) || (msid -> Handler . OpenCount) );
-
- /* Free DOS_STDPKT queue */
- {
- struct Node *node;
-
- while( node = RemHead( (struct List *)(&(msid -> Handler . pktpool)) ) )
- {
- struct DosPacket *dp = (struct DosPacket *)(node -> ln_Name);
-
- FreeDosObject( DOS_STDPKT, (APTR)dp );
- }
- }
-
- DeleteMsgPort( (msid -> Handler . mp) );
-
- Forbid();
-
- msid -> Handler . Process = NULL;
- #define SysBase (cb -> cb_SysBase)
- }
-
-
- static
- void dispatch_packet( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct DosPacket *dp )
- {
- struct MsgPort *rport;
- struct StreamHandle *sh;
-
- switch( dp -> dp_Type )
- {
- case ACTION_FINDINPUT:
- case ACTION_FH_FROM_LOCK:
- {
- struct FileHandle *fh = (struct FileHandle *)BADDR( (dp -> dp_Arg1) );
- struct FileLock *fl = (struct FileLock *)BADDR( (dp -> dp_Arg2) );
- LONG stream_index = fl -> fl_Key;
-
- if( sh = (struct StreamHandle *)AllocVec( sizeof( struct StreamHandle ), MEMF_PUBLIC ) )
- {
- /* init StreamHandle */
- sh -> sl = (&(msid -> Demux . fd_demuxa[ stream_index ]));
- sh -> currpos = 0L;
-
- /* Init FileHandle */
- fh -> fh_Port = (struct MsgPort *)DOSFALSE; /* non-interactive handler */
- fh -> fh_Arg1 = (LONG)sh; /* set to struct StreamHandle */
- fh -> fh_Type = (&(msid -> Handler . Process -> pr_MsgPort));
-
- /* Handler in-use */
- msid -> Handler . OpenCount++;
-
- if( (dp -> dp_Type) == ACTION_FH_FROM_LOCK )
- {
- /* Here we can "eat" the given filelock... */
- FreeLock( cb, msid, fl );
- }
-
- dp -> dp_Res1 = DOSTRUE; /* success */
- dp -> dp_Res2 = 0L; /* No error */
- }
- else
- {
- dp -> dp_Res1 = DOSFALSE; /* failure */
- dp -> dp_Res2 = IoErr(); /* Cause ? */
- }
- }
- break;
-
- case ACTION_END:
- {
- sh = (struct StreamHandle *)(dp -> dp_Arg1);
-
- if( sh )
- {
- FreeVec( sh );
- }
-
- msid -> Handler . OpenCount--;
-
- dp -> dp_Res1 = DOSTRUE;
- dp -> dp_Res2 = 0L;
- }
- break;
-
- case ACTION_READ:
- {
- LONG stream_offset = 0L;
- LONG read_size = (dp -> dp_Arg3);
- UBYTE *dest = (UBYTE *)(dp -> dp_Arg2);
- LONG error = 0L;
- LONG curr_read_size = 0L; /* bytes already in buffer */
- LONG numpkt = 0L; /* pending packets */
- struct FileHandle *fh;
- struct PacketBlock *worknode,
- *nextnode;
-
- sh = (struct StreamHandle *)(dp -> dp_Arg1);
- /* We use "fdin" instead of "sl_handle" here because our whole bunch of virtual streams are mapped to
- * one real system stream. "sl_handle" would only be used if we have one real stream handle for each
- * of our virtual handles. The same refers to the actual file position of the real stream handle
- * (see "classdata.h", "sl_handle_pos".
- */
- #ifdef COMMENTED_OUT
- fh = BADDR( (sh -> sl -> sl_handle) );
- #else
- fh = BADDR( (msid -> Demux . fdin) );
- #endif /* COMMENTED_OUT */
-
- worknode = (struct PacketBlock *)(sh -> sl -> sl_packetblocklist . mlh_Head);
-
- while( (nextnode = (struct PacketBlock *)(worknode -> node . mln_Succ)) && (read_size > 0UL) )
- {
- /* Find start block */
- if( (stream_offset <= (sh -> currpos)) &&
- ((stream_offset + (worknode -> length)) > (sh -> currpos)) )
- {
- LONG cut = ((sh -> currpos) - stream_offset),
- curr_readlen = MIN( read_size, ((worknode -> length) - cut) );
- LONG abs_seek_pos; /* seek position, relative from the beginning of the file */
-
- #if 0
- if( Seek( (sh -> sl -> sl_handle), ((worknode -> system_offset) + cut), OFFSET_BEGINNING ) == -1L )
- {
- break;
- }
- #else
- abs_seek_pos = ((worknode -> system_offset) + cut);
-
- if( SendSeek( cb, msid, fh, (abs_seek_pos - (LONG)(msid -> Demux . fdin_pos)), OFFSET_CURRENT ) )
- {
- numpkt++;
-
- msid -> Demux . fdin_pos = abs_seek_pos;
- }
- else
- {
- error = IoErr();
- break;
- }
- #endif
-
- /* We only need to check for a "complete fill" or failure, because the previous scan
- * (in the demuxer part) gurantees that the buffer (packet) has at least this ("curr_readlen") size
- */
- #if 0
- if( Read( (sh -> sl -> sl_handle), dest, curr_readlen ) != curr_readlen )
- {
- error = IoErr();
- break;
- }
- #else
- if( SendRead( cb, msid, fh, dest, curr_readlen ) )
- {
- numpkt++;
-
- msid -> Demux . fdin_pos += curr_readlen;
- }
- else
- {
- error = IoErr();
- break;
- }
- #endif
-
- dest += curr_readlen;
- read_size -= curr_readlen;
- curr_read_size += curr_readlen;
- sh -> currpos += curr_readlen;
-
- /* Should never ever happen, but... */
- if( read_size < 0L )
- {
- error = ERROR_BUFFER_OVERFLOW;
- break;
- }
- }
-
- stream_offset += worknode -> length;
-
- worknode = nextnode;
- }
-
- #if 1
- /* Wait for outstanding msgs and fetch success/errorc codes from them */
- while( numpkt > 0L )
- {
- struct Message *msg;
-
- WaitPort( (msid -> Handler . mp) );
-
- while( msg = GetMsg( (msid -> Handler . mp) ) )
- {
- struct DosPacket *rdp = (struct DosPacket *)(msg -> mn_Node . ln_Name);
-
- /* This assumes that we only get ACTION_SEEK/ACTION_READ here back... */
- if( (rdp -> dp_Res1) == -1L )
- {
- error = rdp -> dp_Res2;
- }
-
- ReleaseDOSPacket( cb, msid, rdp );
- numpkt--;
- }
- }
- #endif
-
- /* Resync on error. Required because we don't know whether the ACTION_READ (see above)
- * was executed or not.
- */
- if( error )
- {
- msid -> Demux . fdin_pos = Seek( (msid -> Demux . fdin), 0L, OFFSET_CURRENT );
- }
-
- dp -> dp_Res1 = ((error)?(-1L):(curr_read_size)); /* bytes read */
- dp -> dp_Res2 = error; /* result2 */
- }
- break;
-
- case ACTION_SEEK:
- {
- LONG newpos = 0L;
-
- sh = (struct StreamHandle *)(dp -> dp_Arg1);
-
- switch( dp -> dp_Arg3 )
- {
- case OFFSET_BEGINNING:
- {
- newpos = dp -> dp_Arg2;
- }
- break;
-
- case OFFSET_CURRENT:
- {
- newpos += (sh -> currpos) + (dp -> dp_Arg2);
- }
- break;
-
- case OFFSET_END:
- {
- newpos += (sh -> sl -> sl_size) + (dp -> dp_Arg2);
- }
- break;
-
- default: /* should return ERROR_SEEK_ERROR */
- {
- newpos = -1L; /* forces ERROR_SEEK_ERROR by bounds check below */
- }
- break;
- }
-
- /* Check bounds */
- if( (newpos > (sh -> sl -> sl_size)) || (newpos < 0L) )
- {
- dp -> dp_Res1 = -1L;
- dp -> dp_Res2 = ERROR_SEEK_ERROR;
- }
- else
- {
- dp -> dp_Res1 = sh -> currpos; /* Return abolsute position BEFORE the seek took place */
- dp -> dp_Res2 = 0L;
-
- sh -> currpos = newpos;
- }
- }
- break;
-
- case ACTION_COPY_DIR_FH:
- {
- struct FileLock *dest;
- struct StreamList *sl = ((struct StreamHandle *)(dp -> dp_Arg1)) -> sl;
-
- if( dest = (struct FileLock *)AllocVec( sizeof( struct FileLock ), MEMF_PUBLIC ) )
- {
- LONG stream_index = (sl - (&(msid -> Demux . fd_demuxa[ 0 ]))); /* Return array index of "sl" */
-
- dest -> fl_Link = NULL;
- dest -> fl_Key = stream_index;
- dest -> fl_Access = ACCESS_READ;
- dest -> fl_Task = (&(msid -> Handler . Process -> pr_MsgPort));
- dest -> fl_Volume = NULL;
-
- msid -> Handler . OpenCount++;
- }
-
- dp -> dp_Res1 = MKBADDR( dest );
- dp -> dp_Res2 = (dp -> dp_Res1)?(0L):(IoErr());
- }
- break;
-
- case ACTION_COPY_DIR:
- {
- struct FileLock *src = (struct FileLock *)BADDR( (dp -> dp_Arg1) ),
- *dest;
-
- if( dest = (struct FileLock *)AllocVec( sizeof( struct FileLock ), MEMF_PUBLIC ) )
- {
- if( (LONG)src > 256L )
- {
- *dest = *src;
-
- msid -> Handler . OpenCount++;
- }
- else
- {
- LONG key = ((LONG)src / 16); /* src is now the index... */
-
- /* Does we have a system stream to work on ? */
- if( msid -> Demux . fd_demuxa[ key ] . sl_handle )
- {
- dest -> fl_Link = NULL;
- dest -> fl_Key = key;
- dest -> fl_Access = ACCESS_READ;
- dest -> fl_Task = (&(msid -> Handler . Process -> pr_MsgPort));
- dest -> fl_Volume = NULL;
-
- msid -> Handler . OpenCount++;
- }
- else
- {
- FreeVec( dest );
- dest = NULL;
-
- SetIoErr( ERROR_OBJECT_NOT_FOUND );
- }
- }
- }
-
- dp -> dp_Res1 = MKBADDR( dest );
- dp -> dp_Res2 = (dp -> dp_Res1)?(0L):(IoErr());
- }
- break;
-
- case ACTION_FREE_LOCK:
- {
- struct FileLock *fl = (struct FileLock *)BADDR( (dp -> dp_Arg1) );
-
- FreeLock( cb, msid, fl );
-
- dp -> dp_Res1 = DOSTRUE;
- dp -> dp_Res2 = 0L;
- }
- break;
-
- case ACTION_IS_FILESYSTEM:
- {
- dp -> dp_Res1 = DOSTRUE; /* We are a filesystem */
- dp -> dp_Res2 = 0L; /* Avoid Lock( ":", SHARED_LOCK ); overhead,
- * see Ralf Babel's "The Amiga GURU Book",
- * section 21.2.3.17, page 621
- */
- }
- break;
-
- case ACTION_EXAMINE_OBJECT:
- {
- struct FileLock *fl = (struct FileLock *)BADDR( (dp -> dp_Arg1) );
- struct FileInfoBlock *fib = (struct FileInfoBlock *)BADDR( (dp -> dp_Arg2) );
- LONG stream_index = fl -> fl_Key;
- struct StreamList *sl = (&(msid -> Demux . fd_demuxa[ stream_index ]));
-
- dp -> dp_Res1 = ExamineFH( (sl -> sl_handle), fib );
-
- if( dp -> dp_Res1 )
- {
- TEXT buffer[ 256 ];
-
- mysprintf( cb, buffer, "%s@%ld", (fib -> fib_FileName), stream_index );
- stccpy( (fib -> fib_FileName), buffer, sizeof( (fib -> fib_FileName) ) );
-
- /* Set our stream size */
- fib -> fib_Size = sl -> sl_size;
-
- /* Bump number of blocks */
- fib -> fib_NumBlocks = INTDIVR( (sl -> sl_size), 1024UL ); /* BUG: Should be packet size to allow faster reading
- * in conjunction with async I/O
- */
-
- /* Convert to BCPL strings */
- STRPTR2BSTR( (fib -> fib_FileName) );
- STRPTR2BSTR( (fib -> fib_Comment) );
-
- dp -> dp_Res2 = 0L;
- }
- else
- {
- dp -> dp_Res2 = IoErr();
- }
- }
- break;
-
- case ACTION_PARENT:
- {
- struct FileLock *fl = (struct FileLock *)BADDR( (dp -> dp_Arg1) );
- LONG stream_index = fl -> fl_Key;
- struct StreamList *sl = (&(msid -> Demux . fd_demuxa[ stream_index ]));
-
- dp -> dp_Res1 = ParentOfFH( (sl -> sl_handle) ); /* Get parent of system stream */
- dp -> dp_Res2 = IoErr();
- }
- break;
-
- case ACTION_INFO: /* Required for async I/O */
- default:
- {
- dp -> dp_Res1 = DOSFALSE;
- dp -> dp_Res2 = ERROR_ACTION_NOT_KNOWN;
- }
- break;
- }
-
- rport = dp -> dp_Port;
- dp -> dp_Port = (&(msid -> Handler . Process -> pr_MsgPort));
-
- PutMsg( rport, (dp -> dp_Link) );
- }
-
-
- /* Convert a C string into a BCPL string */
- static
- void STRPTR2BSTR( STRPTR s )
- {
- size_t len = strlen( s );
-
- memmove( (&s[ 1 ]), s, len );
- s[ 0 ] = len; /* WARNING: Assumes that the string is less than < 255 bytes ! */
- }
-
-
- static
- void FreeLock( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct FileLock *fl )
- {
- if( fl )
- {
- fl -> fl_Task = NULL; /* Any attempt to use the FileLock again should be DEADLY !! */
-
- msid -> Handler . OpenCount--;
-
- FreeVec( fl );
- }
- }
-
-
- /* Fetch a DosPacket from our private pool */
- static
- struct DosPacket *ObtainDOSPacket( struct ClassBase *cb, struct MPEGSystemInstData *msid )
- {
- struct DosPacket *dp;
- struct Node *node;
-
- if( node = RemHead( (struct List *)(&(msid -> Handler . pktpool)) ) )
- {
- dp = (struct DosPacket *)(node -> ln_Name);
- }
- else
- {
- dp = (struct DosPacket *)AllocDosObject( DOS_STDPKT, NULL );
- }
-
- return( dp );
- }
-
-
- /* Return a DosPacket to our private pool */
- static
- void ReleaseDOSPacket( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct DosPacket *dp )
- {
- AddTail( (struct List *)(&(msid -> Handler . pktpool)), (&(dp -> dp_Link -> mn_Node)) );
- }
-
-
- /* Send a seek async */
- static
- BOOL SendSeek( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct FileHandle *fh, LONG pos, LONG mode )
- {
- struct DosPacket *dp;
-
- if( dp = ObtainDOSPacket( cb, msid ) )
- {
- dp -> dp_Type = ACTION_SEEK;
- dp -> dp_Arg1 = fh -> fh_Arg1;
- dp -> dp_Arg2 = pos;
- dp -> dp_Arg3 = mode;
-
- dp -> dp_Port = dp -> dp_Link -> mn_ReplyPort = msid -> Handler . mp;
- PutMsg( (fh -> fh_Type), (dp -> dp_Link) );
-
- return( TRUE );
- }
-
- return( FALSE );
- }
-
-
- /* Send a read async */
- static
- BOOL SendRead( struct ClassBase *cb, struct MPEGSystemInstData *msid, struct FileHandle *fh, UBYTE *buffer, ULONG len )
- {
- struct DosPacket *dp;
-
- if( dp = ObtainDOSPacket( cb, msid ) )
- {
- dp -> dp_Type = ACTION_READ;
- dp -> dp_Arg1 = fh -> fh_Arg1;
- dp -> dp_Arg2 = (LONG)buffer;
- dp -> dp_Arg3 = len;
-
- dp -> dp_Port = dp -> dp_Link -> mn_ReplyPort = msid -> Handler . mp;
- PutMsg( (fh -> fh_Type), (dp -> dp_Link) );
-
- return( TRUE );
- }
-
- return( FALSE );
- }
-
-
-
-
-
-