October 28, 2020, 11:02:44 PM

Author Topic: [bmx] Quicktime for Blitzmax by AdamRedwoods [ 1+ years ago ]  (Read 1442 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Quicktime for Blitzmax
Author : AdamRedwoods
Posted : 1+ years ago

Description : Here is my implementation for Quicktime for Blitzmax. It currently only runs under Windows and MacOSX.

Updated: 2011 Dec 27 - improved playback speed with DrawMovieImage()

TO USE:
I have this module living under the "blitzmax/mods/addons.mod" directory.

MACOSX: You will have the framework installed with XCode. No need to install additional libraries.

WINDOWS: In order for this to work, you will need to register and download Apple's Quicktime SDK for Windows (its free). Copy these files into the module's folder. Here is a sample folder layout:
+blitzmax
++mod
+++addons.mod
++++quicktime.mod
+++++maxquicktime_glue.cpp
+++++quicktime.bmx
+++++QuicktimeSDK
++++++CIncludes
++++++Libraries
++++++RIncludes
++++++ComponentIncludes
++++++Tools

You will also need to modify a couple lines in the "Math64.h" file (to compile under MINGW) to read as follows:
Code: [Select]
#if TYPE_LONGLONG && TARGET_OS_WIN32 && !defined(__MINGW32__)
    #define S64Max() 9223372036854775807i64

..and...

#if TYPE_LONGLONG && TARGET_OS_WIN32 && !defined(__MINGW32__)
    #define U64Max() 0xffffffffffffffffui64


WINDOWS & MACOSX
You will then need the "maxquicktime_glue.cpp" file, and place it in the quicktime.mod folder.

maxquicktime_glue.cpp
Code: [Select]
#pragma once

#ifndef __QTMOVIE_H
#define __QTMOVIE_H



#include <stdio.h>
#include <stdbool.h>

#if defined (_WIN32)
#include <brl.mod/blitz.mod/blitz.h>
#include "QuickTimeSDK/CIncludes/QTML.h"
#include "QuickTimeSDK/CIncludes/Movies.h"

const int kNativeEndianPixMap = 0;
#endif

#if defined (__APPLE__)
#include <brl.mod/blitz.mod/blitz.h>
#include <QuickTime/Quicktime.h>
#include <QuickTime/Movies.h>
#endif


/*stop using gworlds:
CGBitmapContext around your data buffer, and then call
CGBitmapContextCreateImage() to obtain a
CGImageRef for just-in- time drawing of that context
*/

class bmx_qt
{
public:
Movie theMovie;
GWorldPtr    movieGWorld ;
Rect        movieRect ;
FSSpec m_fileSpec;
OSType m_pixelFormat;
short resRefNum; //theFile
Rect bufferBounds;
MovieController  theController;
short resID;
OSErr err;

//CGContextRef ccr;
//CGColorSpaceRef colorspace;

CTabHandle cTable;
GDHandle aGD;
short monitorPixelDepth;
TimeValue currentTime;

bmx_qt() {
cTable=NULL;
aGD=0;
theController=NULL;
monitorPixelDepth=24;
};
~bmx_qt() {
delete this;
}
};

/*
typedef long                            TimeValue;
typedef long                            TimeScale;
typedef wide                            CompTimeValue;
typedef SInt64                          TimeValue64;
struct TimeRecord {
  CompTimeValue       value;                  // units (duration or absolute) (comptimevalue = wide)
  TimeScale           scale;                  // units per second
  TimeBase            base;                   // refernce to the time base
};
#if TARGET_RT_BIG_ENDIAN
struct wide {
  SInt32              hi;
  UInt32              lo;
};
/*


/* SET EXTERNS */
extern "C" {
bmx_qt * bmx_CreateQT();


int bmx_NewMovieFromFile( bmx_qt * qtclass, char * filename);
int bmx_NewMovieFromURL( bmx_qt * qtclass, char * filename);
int bmx_NewMovieFromFileRef( bmx_qt * qtclass, int flag);
void bmx_DisposeMovie (bmx_qt * qtclass) ;
int bmx_OpenMovieFile( bmx_qt * qtclass, SInt8 permission);
int bmx_CloseMovieFile(bmx_qt * qtclass);
int bmx_NativePathNameToFSSpec(bmx_qt * qtclass, char * filename, int flag);
int bmx_FSMakeFSSpec(bmx_qt * qtclass, const unsigned char * filename);
int bmx_GetMovieLoadState(bmx_qt * qtclass);

void bmx_GetMovieBox(  bmx_qt * qtclass);
int bmx_GetMovieWidth (bmx_qt * qtclass);
int bmx_GetMovieHeight (bmx_qt * qtclass);
int bmx_GetMovieTrackCount(bmx_qt * qtclass);
void bmx_SetMoviePlayHints(bmx_qt * qtclass , int hint1, int hint2) ;

int bmx_NewMovieController(  bmx_qt * qtclass,  long flags);
void bmx_DisposeMovieController (bmx_qt * qtclass);
void bmx_SetMovieActive(bmx_qt * qtclass , bool flag);
void bmx_StartMovie(bmx_qt * qtclass );
int bmx_UpdateMovie(bmx_qt * qtclass );
void bmx_StopMovie(bmx_qt * qtclass );
int bmx_IsMovieDone(bmx_qt * qtclass );

long bmx_GetMovieNextInterestingTime(bmx_qt * qtclass, int flags);
void bmx_SetMovieTimeValue(bmx_qt * qtclass, long newtime);

void bmx_GoToBeginningOfMovie(bmx_qt * qtclass );
int bmx_GetMovieDuration(bmx_qt * qtclass);
long bmx_GetMovieTime(bmx_qt * qtclass);
long bmx_GetMovieTimeScale(bmx_qt * qtclass);
void bmx_SetMovieVolume ( bmx_qt * qtclass, float volume);
void bmx_MoviesTask(bmx_qt * qtclass, int flags);

int bmx_NewGWorld(bmx_qt * qtclass, int w, int h, long flags);
int bmx_QTNewGWorldFromPtr( bmx_qt * qtclass,int pixelformat, int w, int h, char *buffer, long rowbytes, GWorldFlags flags);
void bmx_SetGWorld(bmx_qt * qtclass);
void bmx_SetMovieGWorld(bmx_qt * qtclass);
void bmx_DisposeGWorld(bmx_qt * qtclass);
int bmx_GetGWorldDevice( bmx_qt * qtclass);
int bmx_LockPixels (bmx_qt * qtclass);
void bmx_UnlockPixels (bmx_qt * qtclass);

void bmx_PreRollMovie( bmx_qt * qtclass ,  TimeValue   time);
}


/*DEFINE EXTERN FUNCTIONS */
bmx_qt * bmx_CreateQT() {
return new bmx_qt();
}

// create a data reference from a full path CFString
Movie GetMovieFromFileString(char * filename,  OSErr err, short * id)
{
    Movie theMovie = 0;
    Handle dataRef = NULL;
    OSType dataRefType;

    //OSErr err;

CFStringRef inPath = CFStringCreateWithCString (0,  filename,  0);

    // create the data reference
    err = QTNewDataReferenceFromFullPathCFString(inPath, 0, 0, &dataRef, &dataRefType); //kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);

    if (NULL != dataRef) {
        // get a movie
        //err = NewMovieFromDataRef(&theMovie,
//                       (allowUserInteraction ? 0 :
//   newMovieDontAskUnresolvedDataRefs),
//                     id, dataRef, dataRefType);
err = NewMovieFromDataRef(&theMovie,
 newMovieActive|newMovieDontAskUnresolvedDataRefs,
 id, dataRef, dataRefType);

        // remember to dispose of the data reference handle
        DisposeHandle(dataRef);
    }

    return theMovie;
}

Movie GetMovieFromURLString(char * filename, OSErr err, short * id)
{
    Movie theMovie = 0;
    Handle dataRef = NULL;
    OSType dataRefType;

    //OSErr err;

CFStringRef url = CFStringCreateWithCString (0,  filename, 0);
CFURLRef inPath = CFURLCreateWithString(NULL, url, NULL);

    // create the data reference
    //err = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);
err = QTNewDataReferenceFromCFURL(inPath, 0, &dataRef, &dataRefType);

    if (NULL != dataRef) {
        // get a movie
        //err = NewMovieFromDataRef(&theMovie,
           //                       (allowUserInteraction ? 0 :
//   newMovieDontAskUnresolvedDataRefs|newMovieAsyncOK),
             //                     id, dataRef, dataRefType);
err = NewMovieFromDataRef(&theMovie,
 newMovieActive|newMovieDontAskUnresolvedDataRefs|newMovieAsyncOK,
 0, dataRef, dataRefType); //used to have id there where 0 is

        // remember to dispose of the data reference handle
        DisposeHandle(dataRef);
    }

    return theMovie;
}

int bmx_NewMovieFromURL( bmx_qt * qtclass, char * filename) {
qtclass->theMovie = GetMovieFromURLString(filename,  qtclass->err, &qtclass->resID);
if (!qtclass->theMovie) return qtclass->err;
return 0;
}
int bmx_NewMovieFromFile( bmx_qt * qtclass, char * filename) {
qtclass->theMovie = GetMovieFromFileString(filename,  qtclass->err, &qtclass->resID);
if (!qtclass->theMovie) return qtclass->err;
return 0;
}

// NewMovieFromFile (&theMovie, theFile, nil, nil, newMovieActive, nil);   // Get movie from file
int bmx_NewMovieFromFileRef(  bmx_qt * qtclass, int flag) {
return NewMovieFromFile( &qtclass->theMovie, qtclass->resRefNum, &qtclass->resID,0, flag, 0);
}
void bmx_DisposeMovie (bmx_qt * qtclass) {
DisposeMovie (qtclass->theMovie);
}
int bmx_OpenMovieFile( bmx_qt * qtclass, SInt8 permission) {
return OpenMovieFile(  &qtclass->m_fileSpec,  &qtclass->resRefNum,  permission);
}
int bmx_CloseMovieFile( bmx_qt * qtclass) {
return CloseMovieFile( qtclass->resRefNum);
}
int bmx_NativePathNameToFSSpec(bmx_qt * qtclass, char * filename, int flag) {

#ifdef _WIN32
return NativePathNameToFSSpec(filename, &qtclass->m_fileSpec, flag);
#endif

}
int bmx_FSMakeFSSpec(bmx_qt * qtclass, const unsigned char * filename) {
//being depricated by QT?
//c2pstr (filename);
return FSMakeFSSpec(0, 0L, filename, &qtclass->m_fileSpec);
}
int bmx_GetMovieLoadState(bmx_qt * qtclass) {
return GetMovieLoadState(qtclass->theMovie);
}

int bmx_NewGWorld(bmx_qt * qtclass, int w, int h, long flags) {
qtclass->bufferBounds.left =0;
qtclass->bufferBounds.top =0;
qtclass->bufferBounds.right =w;
qtclass->bufferBounds.bottom =h;
return NewGWorld(&qtclass->movieGWorld, qtclass->monitorPixelDepth, &qtclass->bufferBounds, qtclass->cTable, qtclass->aGD, flags);
}

//QTNewGWorldFromPtr(    GWorldPtr      *gw,       OSType         pixelFormat,     const Rect     *boundsRect,     CTabHandle     cTable,   GDHandle       aGDevice,  GWorldFlags    flags,  void   *baseAddr,     long           rowBytes );
int bmx_QTNewGWorldFromPtr( bmx_qt * qtclass,int pixelformat, int w, int h, char *buffer, long rowbytes, GWorldFlags flags) {
qtclass->bufferBounds.left =0;
qtclass->bufferBounds.top =0;
qtclass->bufferBounds.right =w;
qtclass->bufferBounds.bottom =h;
return QTNewGWorldFromPtr(&qtclass->movieGWorld, pixelformat, &qtclass->bufferBounds, qtclass->cTable, qtclass->aGD, flags|kNativeEndianPixMap , (char *)buffer, rowbytes);
}
void bmx_SetGWorld(bmx_qt * qtclass) {
SetGWorld(qtclass->movieGWorld, NULL); //GetGWorldDevice( qtclass->movieGWorld));
}
void bmx_SetMovieGWorld(bmx_qt * qtclass) {
SetMovieGWorld(qtclass->theMovie, qtclass->movieGWorld, NULL); //GetGWorldDevice( qtclass->movieGWorld));
}
int bmx_GetGWorldDevice( bmx_qt * qtclass) {
//GDevice aGD;
qtclass->aGD = GetGWorldDevice( qtclass->movieGWorld);
if(qtclass->aGD) return 0;
return -99;
}
void bmx_DisposeGWorld(bmx_qt * qtclass) {
DisposeGWorld(qtclass->movieGWorld);
}

/* doesn't exist for mswin
int bmx_CGBitmapContextCreate (bmx_qt * qtclass, void * buffer, int w, int h, int bitsPerComponent, int bytesPerRow, int flags) {
//CGContextRef ccr;
//CGBitmapContextCreate (void *data,size_t width,size_t height,size_t bitsPerComponent,size_t bytesPerRow,CGColorSpaceRef colorspace,CGBitmapInfo bitmapInfo);
qtclass->ccr = CGBitmapContextCreate (void *buffer,w,h,bitsPerComponent,bytesPerRow,qtclass->colorspace,flags | kCGImageAlphaLast);
if (ccr) return 0;
return -99;
}
*/
/*
QTPixelBufferContextCreate (
   CFAllocatorRef allocator,
   CFDictionaryRef attributes,
   QTVisualContextRef *newPixelBufferContext
);
*/

int bmx_LockPixels (bmx_qt * qtclass) {
#ifdef _WIN32
return LockPixels (qtclass->movieGWorld->portPixMap);
#endif
}
void bmx_UnlockPixels (bmx_qt * qtclass) {
#ifdef _WIN32
UnlockPixels (qtclass->movieGWorld->portPixMap);
#endif
}


int bmx_NewMovieController(  bmx_qt * qtclass,  long flags) {
ComponentInstance x = NewMovieController(  qtclass->theMovie,  &qtclass->movieRect,  flags);
qtclass->theController = x;
if(x) return 0;
return -99;
}
void bmx_DisposeMovieController (bmx_qt * qtclass) {
// Close movie controller, if any
DisposeMovieController(qtclass->theController);
}

void bmx_MoviesTask(bmx_qt * qtclass, int flags) {
if (qtclass->theController) MCIdle(qtclass->theController);
MoviesTask(qtclass->theMovie, flags);

}
void bmx_SetMovieActive(bmx_qt * qtclass , bool flag) {
return SetMovieActive(qtclass->theMovie , flag);
}
void bmx_StartMovie(bmx_qt * qtclass ) {
StartMovie(qtclass->theMovie);
}
int bmx_UpdateMovie(bmx_qt * qtclass  ) {
return UpdateMovie(qtclass->theMovie);
}
void bmx_StopMovie(bmx_qt * qtclass ) {
StopMovie(qtclass->theMovie);
}
void bmx_GoToBeginningOfMovie(bmx_qt * qtclass ) {
GoToBeginningOfMovie(qtclass->theMovie );
}
int bmx_IsMovieDone(bmx_qt * qtclass ) {
return IsMovieDone(qtclass->theMovie );
}

long bmx_GetMovieNextInterestingTime(bmx_qt * qtclass, int flags) {
//OSType MovieMediaType
TimeValue gNextTime;
GetMovieNextInterestingTime(qtclass->theMovie, flags, 0, NULL, GetMovieTime(  qtclass->theMovie, 0), 0, &gNextTime, NULL);
return (long) gNextTime;
}
void bmx_SetMovieTimeValue(bmx_qt * qtclass, long newtime) {
SetMovieTimeValue(qtclass->theMovie, (TimeValue) newtime);
}

void bmx_SetMovieVolume ( bmx_qt * qtclass, float volume) {
SetMovieVolume ( qtclass->theMovie, volume );
}

void bmx_GetMovieBox(  bmx_qt * qtclass) {
GetMovieBox(  qtclass->theMovie,  &qtclass->movieRect);
}
int bmx_GetMovieWidth (bmx_qt * qtclass) {
return qtclass->movieRect.right - qtclass->movieRect.left ;
}
int bmx_GetMovieHeight (bmx_qt * qtclass) {
return qtclass->movieRect.bottom - qtclass->movieRect.top ;
}
int bmx_GetMovieDuration(bmx_qt * qtclass) {
return (int) GetMovieDuration(qtclass->theMovie);
}
long bmx_GetMovieTime(bmx_qt * qtclass) {
TimeValue tv;
tv = GetMovieTime(  qtclass->theMovie, 0); //&tm
qtclass->currentTime =tv;
return tv;
}
long bmx_GetMovieTimeScale(bmx_qt * qtclass) {
TimeValue tv;
return GetMovieTimeScale(  qtclass->theMovie);
}
int bmx_GetMovieTrackCount(bmx_qt * qtclass) {
return GetMovieTrackCount(qtclass->theMovie );
}


void bmx_SetMoviePlayHints(bmx_qt * qtclass , int hint1, int hint2) {
SetMoviePlayHints( qtclass->theMovie , hint1, hint2);
}

void bmx_PreRollMovie( bmx_qt * qtclass ,  TimeValue   time) {
PrerollMovie( qtclass->theMovie, time,  GetMoviePreferredRate(qtclass->theMovie) );
}


/*
unsigned DLL_CALLCONV bmx_NewMovieFromFile( int &theMovie, int filenum, int &a, int &b, int flag, int &c) {
return NewMovieFromFile( *theMovie, filenum, *a, *b, flag, *c);
}*/

#endif


/* */


The code is not foolproof, but it works. I've tested under win vista, win7, macosx 10.5.6 with QT 7.

quicktime.bmx: [/i]

Code :
Code: BlitzMax
  1. ''
  2. ''Quicktime Module for MSWin & MacOSX
  3. ''by AdamRedwoods 2011
  4. ''
  5.  
  6. Module addons.quicktime
  7.  
  8. ?Win32
  9. ModuleInfo "CC_OPTS: -IQuickTimeSDK/CIncludes/"
  10. ModuleInfo "CC_OPTS: -IQuickTimeSDK/CIncludes/CoreFoundation"
  11. ModuleInfo "CC_OPTS: -IQuickTimeSDK/CIncludes/GNUCompatibility"
  12. Import "maxquicktime_glue.cpp"
  13. Import "QuickTimeSDK/Libraries/QTMLClient.lib"
  14. Import "QuickTimeSDK/Libraries/CVClient.lib"
  15. ?MacOS
  16. 'ModuleInfo "LD_OPTS: -framework/System/Library/Frameworks/QuickTime.framework"
  17. ModuleInfo "LD_OPTS: -framework QuickTime"
  18. Import "maxquicktime_glue.cpp"
  19. ?
  20.  
  21. Import brl.Pixmap
  22. Import brl.glmax2d
  23. Import brl.standardio
  24. Import brl.GLGraphics
  25.  
  26.  
  27. Extern
  28.        
  29.         Function bmx_CreateQT:Byte Ptr() ''cpp class
  30.         Function EnterMovies() ' Initialize QuickTime
  31.         Function ExitMovies() ' Terminate QuickTime
  32. ?Win32
  33.         Function TerminateQTML() 'terminate QTML
  34.         Function InitializeQTML:Int(i:Int)  ' Initialize QTML
  35. ?
  36.  
  37.         Function bmx_OpenMovieFile:Int( qtclass:Byte Ptr, permission:Int) ''return -1 if error
  38.         Function bmx_CloseMovieFile(qtclass:Byte Ptr)
  39.         Function bmx_NewMovieFromFile:Int( qtclass:Byte Ptr, filename:Byte Ptr)
  40.         Function bmx_NewMovieFromURL:Int( qtclass:Byte Ptr, filename:Byte Ptr)
  41.         Function bmx_NewMovieFromFileRef:Int(qtclass:Byte Ptr, flags:Int)
  42.         Function bmx_GetMovieLoadState:Int(qtclass:Byte Ptr)
  43.        
  44.         '''EXTERN_API( ComponentInstance ) NewMovieController(  Movie         theMovie,  Const Rect *  movieRect,  Long someFlags);
  45.         Function bmx_NewMovieController:Int( qtclass:Byte Ptr, flags:Int=0) '' create new movie controller
  46.        
  47.         Function bmx_SetMovieActive(qtclass:Byte Ptr , boolean:Int)
  48.         Function bmx_StartMovie(qtclass:Byte Ptr )
  49.         Function bmx_MoviesTask( qtclass:Byte Ptr, flags:Int=0)
  50.         Function bmx_UpdateMovie:Int(qtclass:Byte Ptr )
  51.         Function bmx_StopMovie(qtclass:Byte Ptr)
  52.         Function bmx_GoToBeginningOfMovie(qtclass:Byte Ptr )
  53.         Function bmx_IsMovieDone(qtclass:Byte Ptr )
  54.         Function bmx_SetMovieVolume ( qtclass:Byte Ptr, volume:Float) ''volume is signed short: -1.0 to 1.0 ''neg volume is silent
  55.        
  56.         Function bmx_GetMovieNextInterestingTime:Int(qtclass:Byte Ptr, flags:Int)
  57.         Function bmx_SetMovieTimeValue(qtclass:Byte Ptr, newtime:Int)
  58.        
  59.         Function bmx_DisposeMovieController (qtclass:Byte Ptr) '                     // Close movie controller, if any
  60.         Function bmx_DisposeMovie (qtclass:Byte Ptr) ' // Destroy movie Object, If any
  61.         Function bmx_FSMakeFSSpec:Int(qtclass:Byte Ptr, fullPath:Byte Ptr) ''in windows, pass full pathname
  62.         ''' FSMakeFSRefUnicode (   Const FSRef *parentRef, UniCharCount nameLength, Const UniChar *name, TextEncoding textEncodingHint,FSRef *newRef)
  63.         ''Function FSMakeFSRefUnicode (x:Int=0, filenamelength:Int, name:String, econdingHintConst:Int=0, newf:FSRef)
  64.         Function bmx_NativePathNameToFSSpec:Int(qtclass:Byte Ptr, filename:Byte Ptr, flag:Int=0)
  65.        
  66.         Function bmx_QTNewGWorldFromPtr:Int(qtclass:Byte Ptr, pixelformat:Int, w:Int, h:Int, buffer:Byte Ptr, rowbytes:Int, GWorldFlags:Int=0)
  67.         Function bmx_NewGWorld:Int(qtclass:Byte Ptr, w:Int, h:Int, flags:Int)
  68.         Function bmx_SetMovieGWorld:Int(qtclass:Byte Ptr)
  69.         Function bmx_SetGWorld(qtclass:Byte Ptr)   ' // Port Or Graphics world To make Current ''gdhandle null if gworld
  70.         Function bmx_DisposeGWorld(qtclass:Byte Ptr) ''; //close gworld
  71.         Function bmx_GetGWorldDevice:Int(qtclass:Byte Ptr)
  72.         Function bmx_LockPixels:Int(qtclass:Byte Ptr) ''return true 1 or false 0
  73.         Function bmx_UnlockPixels(qtclass:Byte Ptr)
  74.                
  75.         ''Function CopyCStringToPascal(src:String, dst:String)
  76.         Function  c2pstr:Int(src:Byte Ptr)
  77.        
  78.         Function bmx_SetMoviePlayHints(qtclass:Byte Ptr , hints:Int=0, hint2:Int=0)
  79.         'hintsDontUseVideoOverlaySurface
  80.        
  81.         Function GetPixBaseAddr:Byte Ptr(pmhd:Object )
  82.         Function GetGWorldPixMap:Byte Ptr(gw:Byte Ptr )
  83.         '''EXTERN_API( Boolean ) PixMap32Bit(PixMapHandle pmHandle)
  84.         ''Function GetPixRowBytes:int(pmhd:Object) ''NOT IN MSWIN
  85.  
  86.         Function bmx_GetMovieBox(qtclass:Byte Ptr)
  87.         Function bmx_GetMovieWidth(qtclass:Byte Ptr)
  88.         Function bmx_GetMovieHeight(qtclass:Byte Ptr)
  89.         Function bmx_GetMovieDuration:Int(qtclass:Byte Ptr)
  90.         Function bmx_GetMovieTime:Int(qtclass:Byte Ptr)
  91.         Function bmx_GetMovieTimeScale:Int(qtclass:Byte Ptr)
  92.         Function bmx_GetMovieTrackCount:Int(qtclass:Byte Ptr)
  93.        
  94.         Function bmx_PreRollMovie( qtclass:Byte Ptr,  time:Int)
  95.        
  96.                
  97. EndExtern
  98.  
  99.  
  100.  
  101. Const k1MonochromePixelFormat:Int       = $00000001', /* 1 bit indexed*/
  102. Const  k2IndexedPixelFormat:Int          = $00000002', /* 2 bit indexed*/
  103. Const  k4IndexedPixelFormat:Int          = $00000004', /* 4 bit indexed*/
  104. Const  k8IndexedPixelFormat:Int          = $00000008', /* 8 bit indexed*/
  105. Const  k16BE555PixelFormat:Int           = $00000010', /* 16 bit BE rgb 555 (Mac)*/
  106. Const  k24RGBPixelFormat:Int             = $00000018', /* 24 bit rgb */
  107. Const  k32ARGBPixelFormat:Int            = $00000020', /* 32 bit argb    (Mac)*/
  108. Const  k1IndexedGrayPixelFormat:Int      = $00000021', /* 1 bit indexed gray*/
  109. Const  k2IndexedGrayPixelFormat:Int      = $00000022', /* 2 bit indexed gray*/
  110. Const  k4IndexedGrayPixelFormat:Int      = $00000024', /* 4 bit indexed gray*/
  111. Const  k8IndexedGrayPixelFormat:Int      = $00000028' /* 8 bit indexed gray*/
  112. Const  k32BGRAPixelFormat:Int           = 1111970369
  113. Const   keepLocal:Int   =8
  114.  
  115. Const NEWMOVIEACTIVE:Int = 1 Shl 0
  116.  
  117. Const mcTopLeftMovie:Int                = 1 Shl 0 ', /* usually centered */
  118. Const mcScaleMovieToFit:Int              = 1 Shl 1 ', /* usually only scales down */
  119. Const mcWithBadge:Int                    = 1 Shl 2 ', /* give me a badge */
  120. Const mcNotVisible:Int                   = 1 Shl 3 ', /* don't show controller */
  121. Const mcWithFrame :Int                          = 1 Shl 4
  122.  
  123. Const hintsDontUseVideoOverlaySurface:Int = 1 Shl 16
  124. Const hintsOffscreen:Int                = 1 Shl 12
  125. Const hintsUseScreenBuffer:Int          = 1 Shl 5
  126. Const hintsAllowDynamicResize:Int       = 1 Shl 19
  127.  
  128. Const kInitializeQTMLUseGDIFlag:Int   = 1 Shl 1
  129.  
  130. Const deviceIsExternalBuffer:Int        = (1 Shl 3)
  131. Const deviceIsGDISurface:Int =  64
  132. Const deviceIsIndirect:Int =    1
  133.  
  134. ''nextInterestingTime flags
  135. Const nextTimeStep:Int =  1 Shl 4
  136. 'nextTimeMediaSample ''not recommended since messes up on mpeg
  137. 'nextTimeEdgeOK
  138.  
  139. Const   kMovieLoadStateError:Int                     = -1
  140. Const   kMovieLoadStateLoading:Int                  = 1000
  141. Const   kMovieLoadStateLoaded:Int                    = 2000
  142. Const   kMovieLoadStatePlayable:Int                  = 10000
  143. Const   kMovieLoadStatePlaythroughOK:Int            = 20000
  144. Const   kMovieLoadStateComplete:Int                  = 100000
  145.  
  146. Rem
  147.  
  148. hintsScrubMode                = 1 << 0, /* mask == && (if flags == scrub on, flags != scrub off) */
  149.   hintsLoop                     = 1 << 1,
  150.   hintsDontPurge                = 1 << 2,
  151.   hintsUseScreenBuffer          = 1 << 5,
  152.   hintsAllowInterlace           = 1 << 6,
  153.   hintsUseSoundInterp           = 1 << 7,
  154.   hintsHighQuality              = 1 << 8, /* slooooow */
  155.   hintsPalindrome               = 1 << 9,
  156.   hintsInactive                 = 1 << 11,
  157.   hintsOffscreen                = 1 << 12,
  158.   hintsDontDraw                 = 1 << 13,
  159.   hintsAllowBlacklining         = 1 << 14,
  160.   hintsDontUseVideoOverlaySurface = 1 << 16,
  161.   hintsIgnoreBandwidthRestrictions = 1 << 17,
  162.   hintsPlayingEveryFrame        = 1 << 18,
  163.   hintsAllowDynamicResize       = 1 << 19,
  164.   hintsSingleField              = 1 << 20,
  165.   hintsNoRenderingTimeOut       = 1 << 21,
  166.   hintsFlushVideoInsteadOfDirtying = 1 << 22,
  167.   hintsEnableSubPixelPositioning = 1L << 23,
  168.   hintsRenderingMode            = 1L << 24,
  169.   hintsAllowIdleSleep           = 1L << 25, /* asks media handlers not to call UpdateSystemActivity etc */
  170.   hintsDeinterlaceFields        = 1L << 26
  171. EndRem
  172.  
  173.  
  174. Type TQuickTime
  175.         Field isQTInit:Int =0
  176.         Field myQTClass:Byte Ptr = Null
  177.         Field debug:Int
  178.         Field _pixmap:TPixmap
  179.         Field texid:Int
  180.         Field imageframe:TGLImageFrame
  181.        
  182.         Method Init:Int(flags:Int=0)
  183.                 If (isQTInit) Then Return True
  184.                 If StartQT(flags) <> 0 Then Return False
  185.  
  186.                 If EnterMovies() <> 0
  187.                         If debug Then Print "EnterMovies fail"
  188.                         EndQT()
  189.                         Return False
  190.                 EndIf
  191.                 myQTClass = bmx_CreateQT()
  192.                 isQTInit =1
  193.                 If debug Then Print "INIT ok"
  194.                 Return True
  195.         EndMethod
  196.        
  197.         Method StartQT:Int(flags:Int =0)
  198.                 ?Win32
  199.                 Local r:Int = InitializeQTML(flags) ''the check for QT on system
  200.                 If r Then Print "Quicktime not found."
  201.                 Return r
  202.                 ?MacOS
  203.                 Return 0 ''assume QT is installed
  204.                 ?
  205.                 Return 0 ''0= success (error code) in QT
  206.  
  207.         EndMethod
  208.        
  209.         Method EndQT()
  210.                
  211.                 ?Win32
  212.                
  213.                 TerminateQTML()
  214.                 ?
  215.                 Return
  216.         EndMethod
  217.        
  218.         Method LoadMovieToPixmap:Int(filename:String, pixmap:TPixmap, flags:Int=0, isURL:Int=0)
  219.  
  220.                 Init()
  221.                
  222.                 If Not myQTClass Or Not pixmap Then Return False
  223.                 Local r:Int
  224.                 Local pixw:Int = pixmap.width
  225.                 Local pixh:Int = pixmap.height
  226.                 r = OpenMovie(filename, 0, isURL)'newMovieActive)
  227.                 If r Then Return False
  228.                
  229.                 SetupGWorld(pixmap, flags)
  230.                
  231.                 Return True
  232.         EndMethod
  233.        
  234.         Method LoadMovieToImage:Int(filename:String, img:TImage, flags:Int=0, isURL:Int=0)
  235.  
  236.                 Init()
  237.                
  238.                 If Not myQTClass Or Not img Then Return False
  239.                 Local r:Int
  240.                 Local pixw:Int = img.width
  241.                 Local pixh:Int = img.height
  242.                 r = OpenMovie(filename, 0, isURL)'newMovieActive)
  243.                 If r Then Return False
  244.                
  245.                 If Not img.pixmaps[0] Then img.pixmaps[0] = TPixmap.Create( img.width,img.height,PF_RGB888 )
  246.                 If img.pixmaps[0].format <> PF_RGB888 Then img.pixmaps[0] = img.pixmaps[0].convert(PF_RGB888) ;Print "convert to rgb888"
  247.                
  248.                 SetupGWorld(img.pixmaps[0], flags)
  249.                
  250.                 Return True
  251.         EndMethod
  252.        
  253.         Method SetupGWorld:Int(pixmap:TPixmap, flags:Int=0)
  254.                 If Not pixmap Then Return False
  255.                 Local r:Int
  256.                
  257.                 'r=bmx_NewGWorld(myQTClass, 900, 600, 0)
  258.                 r=bmx_QTNewGWorldFromPtr(myQTClass, 24, pixmap.width, pixmap.height,  PixmapPixelPtr(pixmap), pixmap.pitch, deviceIsExternalBuffer)'deviceIsIndirect)
  259.                 If debug Then Print "Gworld: "+uinttoint(r)
  260.                
  261.                 r = bmx_SetGWorld(myQTClass) ''works better than setmoviegworld in osx
  262.                 r = bmx_SetMovieGWorld(myQTClass) ''need both for windows
  263.                 If debug Then Print "setGW: "+uinttoint(r)
  264.                
  265.                 r = bmx_NewMovieController (myQTClass, mcTopLeftMovie|mcNotVisible|flags)
  266.                 If debug Then Print "controller: " +uinttoint(r)
  267.                 bmx_SetMoviePlayHints(myQTClass, hintsOffscreen|hintsAllowDynamicResize, hintsOffscreen|hintsAllowDynamicResize )
  268.                 If debug Then Print "hints ok"
  269.                 r=bmx_SetMovieActive(myQTClass,True)
  270.                 If debug Print "setactivem: "+uinttoint(r)
  271.                 GotoBeginning()
  272.                                
  273.                 _pixmap = pixmap
  274.                
  275.                 Return True
  276.         EndMethod
  277.        
  278.         ''Opening a movie does not necessarily load the entirety
  279.         Method OpenMovie:Int(filename:String, flags:Int =0, isURL:Int = 0)
  280.                 Init()
  281.                 If Not myQTClass Then Return -1
  282.                
  283.                 ''determine isURL
  284.                 If Not isURL And filename.StartsWith("http:") Then isURL = 1
  285.                
  286.                 Local r:Int
  287.                 'r = bmx_NativePathNameToFSSpec(myQTClass, filename, 0)
  288.                 'If debug Then Print "fsspec: " +uinttoint(r)
  289.                 'r= bmx_OpenMovieFile( myQTClass, 1)
  290.                 'If debug Then Print "openfile "+uinttoint(r)
  291.                 'If(r) Then Return -1
  292.                
  293.                 ''flags = newMovieActive
  294.                 'r=bmx_NewMovieFromFile(myQTClass, flags)
  295.                 If isURL Then   r = bmx_NewMovieFromURL(myQTClass, filename) Else r = bmx_NewMovieFromFile(myQTClass, filename)
  296.                
  297.                 Local myLoadState:Int= kMovieLoadStateLoading
  298.                 Local tick:Int =MilliSecs()
  299.                
  300.                 While  Not (myLoadState & kMovieLoadStatePlaythroughOK) 'And tick <> 0
  301.                         bmx_GetMovieDuration(myQTClass)
  302.                         myLoadState = bmx_GetMovieLoadState(myQTClass)
  303.                 Wend
  304.                
  305.                 If debug Then Print "newmovie: "+uinttoint(r)
  306.                 bmx_CloseMovieFile(myQTClass) ''success close file
  307.                 ''get width and height and etc
  308.                 bmx_GetMovieBox(myQTClass)
  309.                 Return 0
  310.         EndMethod
  311.        
  312.         Method IsMovieReady:Int()
  313.                 Local k:Int = bmx_GetMovieLoadState(myQTClass)
  314.                 If k & kMovieLoadStatePlaythroughOK Then Return True
  315.                 Return False
  316.         EndMethod
  317.        
  318.         Method CloseMovie()
  319.                 If Not myQTClass Then Return
  320.                 ExitMovies()
  321.                 bmx_DisposeMovieController (myQTClass)
  322.                 bmx_DisposeGWorld(myQTClass)
  323.                
  324.                 EndQT()
  325.                 isQtInit =0
  326.                 If debug Then Print "CloseMovie ok"
  327.         EndMethod
  328.        
  329.         Method GetMovieWidth:Int()
  330.                 Return bmx_GetMovieWidth(myQTClass)
  331.         EndMethod
  332.         Method GetMovieHeight:Int()
  333.                 Return bmx_GetMovieHeight(myQTClass)
  334.         EndMethod
  335.         '' in seconds
  336.         Method GetMovieDuration:Float()
  337.                 Return bmx_GetMovieDuration(myQTClass)/Float(bmx_GetMovieTimeScale(myQTClass))
  338.         EndMethod
  339.         Method GetMovieTracks:Int()
  340.                 Return bmx_GetMovieTrackCount(myQTClass)
  341.         EndMethod
  342.         ''in ticks
  343.         Method GetMovieTime:Int()
  344.                 Return bmx_GetMovieTime(myQTClass)
  345.         EndMethod
  346.         '' in seconds
  347.         Method GetMovieTimeSecs:Float()
  348.                 Return bmx_GetMovieTime(myQTClass)/Float(bmx_GetMovieTimeScale(myQTClass))
  349.         EndMethod
  350.        
  351.         '' volume is between 0.0 and 1.0
  352.         Method SetMovieVolume(vol:Float)
  353.                 bmx_SetMovieVolume(myQTClass, vol)
  354.         EndMethod
  355.  
  356.         ''movie time in ticks
  357.         Method SetMovieTime(ms:Int)
  358.                 bmx_SetMovieTimeValue(myQTClass, ms )
  359.         EndMethod
  360.  
  361.         Method StartMovie()
  362.                 If Not myQTClass Then Return
  363.                 bmx_StartMovie(myQTClass)
  364.                 If debug Then Print "startmovie ok"
  365.         EndMethod
  366.  
  367.         Method StopMovie()
  368.                 If Not myQTClass Then Return
  369.                 bmx_StopMovie(myQTClass)
  370.                 If debug Then Print "stopmovie ok"
  371.         EndMethod
  372.  
  373.         Method UpdateMovie(update:Int=0)
  374.                 'If update Then bmx_UpdateMovie(myQTClass)
  375.                 bmx_MoviesTask(myQTClass,0)
  376.                 'bmx_UpdateMovie(myQTClass)
  377.         EndMethod
  378.        
  379.         Method IsMovieDone:Int()
  380.                 Return bmx_IsMovieDone(myQTClass)
  381.         EndMethod
  382.  
  383.         Method DrawMovieImage(img:TImage, x:Int, y:Int)
  384.                 If Not img Or Not _pixmap Then Return
  385.                
  386.                 If Not texid
  387.                         imageframe = TGLImageFrame.CreateFromPixmap( _pixmap,0 )
  388.                         texid = imageframe.name
  389.                         If debug Then Print "draw movie bind"
  390.                 EndIf
  391.  
  392.                 img.pixmaps[0]=_pixmap
  393.                 img.seqs[0]=0
  394.  
  395.                 If texid
  396.                         glBindTexture(GL_TEXTURE_2D, texid)
  397.                         glPixelStorei GL_UNPACK_ROW_LENGTH, _pixmap.pitch/BytesPerPixel[_pixmap.format]
  398.                        
  399.                         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _pixmap.width, _pixmap.height, GL_RGB, GL_UNSIGNED_BYTE, _pixmap.pixels)
  400.                         glPixelStorei GL_UNPACK_ROW_LENGTH,0
  401.                        
  402.                         imageframe.Draw( 0,0,_pixmap.width,_pixmap.height, x, y ,0,0,_pixmap.width,_pixmap.height)
  403.  
  404.                 EndIf
  405.                        
  406.         EndMethod
  407.        
  408.         Method GotoBeginning()
  409.                 bmx_GoToBeginningOfMovie(myQTClass)
  410.         EndMethod
  411.  
  412. EndType
  413.  
  414.  
  415.  
  416. Function UintToInt:Int(value:Int)
  417.       Const OFFSET_2:Int = 65536
  418.       Const MAXINT_2:Int = 32767
  419.  
  420.         If Value < 0 Or Value >= OFFSET_2 Then Return value ' Overflow
  421.         If Value <= MAXINT_2 Then
  422.           Return Value
  423.         Else
  424.           Return Value - OFFSET_2
  425.         End If
  426. End Function


Comments :


AdamRedwoods(Posted 1+ years ago)

 Here is a sample test program. You will need to grab your own "Ironman2" trailer for the test or use the URLs.Use the mouse to click to pause/play and click-hold with a move left/right to scrub the movie.SEE UPDATED CODE BELOW


xlsior(Posted 1+ years ago)

 <div class="quote"> I have this module living under Blitzmax's "pub" module directory. </div>Not a good idea -- the pub and brl trees both get erased each time you install a blitzmax update on top of an existing installation.You really should make your own subfolder under the mod folder to prevent that from happening. :-?but an interesting addition nonetheless.  Does it do both video and audio, or just video?


Brucey(Posted 1+ years ago)

 
Code: [Select]
ModuleInfo "BCC_OPTS: -O2"I don't think there is such an option - unless Mark sneaked something in there when I wasn't looking?The latest version of BlitzMax may already be using -O2, however.


AdamRedwoods(Posted 1+ years ago)

 Thanks for the tips!I've updated and revised the source code.Yes, this quicktime module plays audio and video. The sample test program also allows scrubbing through the movie as well.


AdamRedwoods(Posted 1+ years ago)

 - Updated module, now works with OSX.- Also added capabilities to load from URL.See example test file for cool trailers to view.


AdamRedwoods(Posted 1+ years ago)

 UPDATED 2011 dec 27- improved playback speed using DrawMovieImage( myimage, x, y)... I was able to play two apple trailers at the same time- allows scaling, coloring, etc.- can only use OpenGLUPDATED sample code:
Code: [Select]
''
'' sample test code for Quicktime in BMax
'' MSWin & MacOSX
'' by AdamRedwoods 2011

SuperStrict

Framework brl.GLMax2D
Import addons.quicktime
Import brl.standardio
Import brl.filesystem
Import brl.pixmap


SetGraphicsDriver GLMax2DDriver()
Local gd:TGraphicsDriver = GetGraphicsDriver()
Graphics(900,600,0,60,GRAPHICS_BACKBUFFER)


Local curdir:String = CurrentDir()
'Local filename:String = curdir+"/ironman2_480p.mov"
Local filename:String = "http://trailers.apple.com/movies/wb/thedarkknightrises/darkknightrises-tsr1_h480p.mov"
'Local filename:String = "http://trailers.apple.com/movies/wb/harrypotterandthedeathlyhallowspart2/hp7part2-tlr2_h480p.mov"


'Local mypix:TPixmap = CreatePixmap(900,600,PF_RGB888 ,3)
Local myimage:TImage = CreateImage(900,600)


Local myQT:TQuickTime = New TQuickTime
'myQT.debug = True
'If (Not myQT.LoadMovieToPixmap(filename, mypix))
If (Not myQT.LoadMovieToImage(filename, myimage ))
Print "error"
End
EndIf




Print "width: "+myQT.GetMovieWidth()
Print "height: "+myQT.GetMovieHeight()
Print "duration: "+myQT.GetMovieDuration()
Print "tracks: "+myQT.GetMovieTracks()

myQT.StartMovie()

Local j:Float
Local i:Int=0
Local stopstate:Int=0
'SetBlend solidblend

Repeat
SetClsColor 0,0,0
Cls

SetColor 255,255,255
myQT.UpdateMovie()

'SetScale 2.0,2.0 ''now allows scaling, coloring, etc
myQT.DrawMovieImage (myimage, 0,0)

j = myQT.GetMovieTimeSecs()
DrawText ("s:"+j+" "+" t:"+myQT.GetMovieTime(), 1,1)

If myQT.IsMovieDone() Then DrawText ("done.",1,10)

Flip

PollSystem()
Local xs:Int = MouseXSpeed()
If(AppTerminate())
myQT.StopMovie()
myQT.CloseMovie() ''save memory
End
Else If(MouseDown(1))
'Print MouseXSpeed()

If(Abs(xs)>2)
myQT.StopMovie()
myQT.SetMovieTime(myQT.GetMovieTime() + xs*100) ''in milliseconds
myQT.UpdateMovie()
stopstate = True
Else If(stopstate And MouseHit(1))
myQT.StartMovie()

stopstate =0
Else If MouseHit(1)

myQT.StopMovie()
stopstate=1
EndIf
EndIf
Forever
End




burpy(Posted 1+ years ago)

 (deleted)


AdamRedwoods(Posted 1+ years ago)

 mar 2012- possible case issue for win32 CCOPTS in "QuickTime". corrected above.


Cobra Blade(Posted 1+ years ago)

 Recently I tried rebuilding all of BlitzMax's modules using the latest version of OS X & Xcode and received this error from maxquicktime_glue.cpp.Compile Error error: 'NewGWorld' was not declared in this scope


Captain Wicker (crazy hillbilly)(Posted 1+ years ago)

 @CB:Same here. [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal