Ejemplo n.º 1
0
static void get_track_dimensions_for_codec(AVStream *st, Fixed *fixedWidth, Fixed *fixedHeight)
{
    AVCodecContext *codec = st->codec;
    *fixedHeight = IntToFixed(codec->height);

    if (!st->sample_aspect_ratio.num) *fixedWidth = IntToFixed(codec->width);
    else *fixedWidth = FloatToFixed(codec->width * av_q2d(st->sample_aspect_ratio));
}
Ejemplo n.º 2
0
int NesApuDMChannel::render(int cycleRate)
{
	if (m_dmaLength) {
		m_timer -= cycleRate;

		int freqFixed = IntToFixed(m_frequency);
		while (m_timer < 0) {
			m_timer += freqFixed;

			if (!clockDma())
				break;
			// only alter DAC value if the sample buffer has data
			clockDac();
		}
	}
	return m_dac - 0x40;
}
Ejemplo n.º 3
0
//------------------------------------------------------------------------------
bool MacCarbFont::create( const char* name, U32 size, U32 charset)
{
   String nameStr = name;
   nameStr = nameStr.trim();
   
   // create and cache the style and layout.
   // based on apple sample code at http://developer.apple.com/qa/qa2001/qa1027.html

   // note: charset is ignored on mac. -- we don't need it to get the right chars.
   // But do we need it to translate encodings? hmm...

   CFStringRef       cfsName;
   ATSUFontID        atsuFontID;
   ATSFontRef        atsFontRef;
   Fixed             atsuSize;
   ATSURGBAlphaColor black;
   ATSFontMetrics    fontMetrics;
   U32               scaledSize;
   
   bool              isBold = false;
   bool              isItalic = false;
   
   bool haveModifier;
   do
   {
      haveModifier = false;
      if( nameStr.compare( "Bold", 4, String::NoCase | String::Right ) == 0 )
      {
         isBold = true;
         nameStr = nameStr.substr( 0, nameStr.length() - 4 ).trim();
         haveModifier = true;
      }
      if( nameStr.compare( "Italic", 6, String::NoCase | String::Right ) == 0 )
      {
         isItalic = true;
         nameStr = nameStr.substr( 0, nameStr.length() - 6 ).trim();
         haveModifier = true;
      }
   }
   while( haveModifier );
      
   // Look up the font. We need it in 2 differnt formats, for differnt Apple APIs.
   cfsName = CFStringCreateWithCString( kCFAllocatorDefault, nameStr.c_str(), kCFStringEncodingUTF8);
   if(!cfsName)
      Con::errorf("Error: could not make a cfstring out of \"%s\" ",nameStr.c_str());
      
   atsFontRef =  ATSFontFindFromName( cfsName, kATSOptionFlagsDefault);
   atsuFontID = FMGetFontFromATSFontRef( atsFontRef);

   // make sure we found it. ATSFontFindFromName() appears to return 0 if it cant find anything. Apple docs contain no info on error returns.
   if( !atsFontRef || !atsuFontID )
   {
      Con::errorf("MacCarbFont::create - could not load font -%s-",name);
      return false;
   }

   // adjust the size. win dpi = 96, mac dpi = 72. 72/96 = .75
   // Interestingly enough, 0.75 is not what makes things the right size.
   scaledSize = size - 2 - (int)((float)size * 0.1);
   mSize = scaledSize;
   
   // Set up the size and color. We send these to ATSUSetAttributes().
   atsuSize = IntToFixed(scaledSize);
   black.red = black.green = black.blue = black.alpha = 1.0;

   // Three parrallel arrays for setting up font, size, and color attributes.
   ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag, kATSURGBAlphaColorTag};
   ByteCount theSizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(ATSURGBAlphaColor) };
   ATSUAttributeValuePtr theValues[] = { &atsuFontID, &atsuSize, &black };
   
   // create and configure the style object.
   ATSUCreateStyle(&mStyle);
   ATSUSetAttributes( mStyle, 3, theTags, theSizes, theValues );
   
   if( isBold )
   {
      ATSUAttributeTag tag = kATSUQDBoldfaceTag;
      ByteCount size = sizeof( Boolean );
      Boolean value = true;
      ATSUAttributeValuePtr valuePtr = &value;
      ATSUSetAttributes( mStyle, 1, &tag, &size, &valuePtr );
   }
   
   if( isItalic )
   {
      ATSUAttributeTag tag = kATSUQDItalicTag;
      ByteCount size = sizeof( Boolean );
      Boolean value = true;
      ATSUAttributeValuePtr valuePtr = &value;
      ATSUSetAttributes( mStyle, 1, &tag, &size, &valuePtr );
   }
   
   // create the layout object, 
   ATSUCreateTextLayout(&mLayout);  
   // we'll bind the layout to a bitmap context when we actually draw.
   // ATSUSetTextPointerLocation()  - will set the text buffer
   // ATSUSetLayoutControls()       - will set the cg context.
   
   // get font metrics, save our baseline and height
   ATSFontGetHorizontalMetrics(atsFontRef, kATSOptionFlagsDefault, &fontMetrics);
   mBaseline = scaledSize * fontMetrics.ascent;
   mHeight   = scaledSize * ( fontMetrics.ascent - fontMetrics.descent + fontMetrics.leading ) + 1;
   
   // cache our grey color space, so we dont have to re create it every time.
   mColorSpace = CGColorSpaceCreateDeviceGray();
   
   // and finally cache the font's name. We use this to cheat some antialiasing options below.
   mName = StringTable->insert(name);
   
   return true;
}    
Ejemplo n.º 4
0
PlatformFont::CharInfo& MacCarbFont::getCharInfo(const UTF16 ch) const
{
   // We use some static data here to avoid re allocating the same variable in a loop.
   // this func is primarily called by GFont::loadCharInfo(),
   Rect                 imageRect;
   CGContextRef         imageCtx;
   U32                  bitmapDataSize;
   ATSUTextMeasurement  tbefore, tafter, tascent, tdescent;
   OSStatus             err;

   // 16 bit character buffer for the ATUSI calls.
   // -- hey... could we cache this at the class level, set style and loc *once*, 
   //    then just write to this buffer and clear the layout cache, to speed up drawing?
   static UniChar chUniChar[1];
   chUniChar[0] = ch;

   // Declare and clear out the CharInfo that will be returned.
   static PlatformFont::CharInfo c;
   dMemset(&c, 0, sizeof(c));
   
   // prep values for GFont::addBitmap()
   c.bitmapIndex = 0;
   c.xOffset = 0;
   c.yOffset = 0;

   // put the text in the layout.
   // we've hardcoded a string length of 1 here, but this could work for longer strings... (hint hint)
   // note: ATSUSetTextPointerLocation() also clears the previous cached layout information.
   ATSUSetTextPointerLocation( mLayout, chUniChar, 0, 1, 1);
   ATSUSetRunStyle( mLayout, mStyle, 0,1);
   
   // get the typographic bounds. this tells us how characters are placed relative to other characters.
   ATSUGetUnjustifiedBounds( mLayout, 0, 1, &tbefore, &tafter, &tascent, &tdescent);
   c.xIncrement =  FixedToInt(tafter);
   
   // find out how big of a bitmap we'll need.
   // as a bonus, we also get the origin where we should draw, encoded in the Rect.
   ATSUMeasureTextImage( mLayout, 0, 1, 0, 0, &imageRect);
   U32 xFudge = 2;
   U32 yFudge = 1;
   c.width  = imageRect.right - imageRect.left + xFudge; // add 2 because small fonts don't always have enough room
   c.height = imageRect.bottom - imageRect.top + yFudge;
   c.xOrigin = imageRect.left; // dist x0 -> center line
   c.yOrigin = -imageRect.top; // dist y0 -> base line
   
   // kick out early if the character is undrawable
   if( c.width == xFudge || c.height == yFudge)
      return c;
   
   // allocate a greyscale bitmap and clear it.
   bitmapDataSize = c.width * c.height;
   c.bitmapData = new U8[bitmapDataSize];
   dMemset(c.bitmapData,0x00,bitmapDataSize);
   
   // get a graphics context on the bitmap
   imageCtx = CGBitmapContextCreate( c.bitmapData, c.width, c.height, 8, c.width, mColorSpace, kCGImageAlphaNone);
   if(!imageCtx) {
      Con::errorf("Error: failed to create a graphics context on the CharInfo bitmap! Drawing a blank block.");
      c.xIncrement = c.width;
      dMemset(c.bitmapData,0x0F,bitmapDataSize);
      return c;
   }

   // Turn off antialiasing for monospaced console fonts. yes, this is cheating.
   if(mSize < 12  && ( dStrstr(mName,"Monaco")!=NULL || dStrstr(mName,"Courier")!=NULL ))
      CGContextSetShouldAntialias(imageCtx, false);

   // Set up drawing options for the context.
   // Since we're not going straight to the screen, we need to adjust accordingly
   CGContextSetShouldSmoothFonts(imageCtx, false);
   CGContextSetRenderingIntent(imageCtx, kCGRenderingIntentAbsoluteColorimetric);
   CGContextSetInterpolationQuality( imageCtx, kCGInterpolationNone);
   CGContextSetGrayFillColor( imageCtx, 1.0, 1.0);
   CGContextSetTextDrawingMode( imageCtx,  kCGTextFill);
   
   // tell ATSUI to substitute fonts as needed for missing glyphs
   ATSUSetTransientFontMatching(mLayout, true); 

   // set up three parrallel arrays for setting up attributes. 
   // this is how most options in ATSUI are set, by passing arrays of options.
   ATSUAttributeTag theTags[] = { kATSUCGContextTag };
   ByteCount theSizes[] = { sizeof(CGContextRef) };
   ATSUAttributeValuePtr theValues[] = { &imageCtx };
   
   // bind the layout to the context.
   ATSUSetLayoutControls( mLayout, 1, theTags, theSizes, theValues );

   // Draw the character!
   int yoff = c.height < 3 ? 1 : 0; // kludge for 1 pixel high characters, such as '-' and '_'
   int xoff = 1;
   err = ATSUDrawText( mLayout, 0, 1, IntToFixed(-imageRect.left + xoff), IntToFixed(imageRect.bottom + yoff ) );
   CGContextRelease(imageCtx);
   
   if(err != noErr) {
      Con::errorf("Error: could not draw the character! Drawing a blank box.");
      dMemset(c.bitmapData,0x0F,bitmapDataSize);
   }


#if TORQUE_DEBUG
//   Con::printf("Font Metrics: Rect = %2i %2i %2i %2i  Char= %C, 0x%x  Size= %i, Baseline= %i, Height= %i",imageRect.top, imageRect.bottom, imageRect.left, imageRect.right,ch,ch, mSize,mBaseline, mHeight);
//   Con::printf("Font Bounds:  left= %2i right= %2i  Char= %C, 0x%x  Size= %i",FixedToInt(tbefore), FixedToInt(tafter), ch,ch, mSize);
#endif
      
   return c;
}
//--------------------------------------------------------------------
bool ofQuickTimeGrabber::initGrabber(int w, int h){

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		//---------------------------------- 1 - open the sequence grabber
		if( !qtInitSeqGrabber() ){
			ofLogError("ofQuickTimeGrabber") << "initGrabber(): unable to initialize the seq grabber";
			return false;
		}

		//---------------------------------- 2 - set the dimensions
		//width 		= w;
		//height 		= h;

		MacSetRect(&videoRect, 0, 0, w, h);

		//---------------------------------- 3 - buffer allocation
		// Create a buffer big enough to hold the video data,
		// make sure the pointer is 32-byte aligned.
		// also the rgb image that people will grab

		offscreenGWorldPixels 	= (unsigned char*)malloc(4 * w * h + 32);
		pixels.allocate(w, h, OF_IMAGE_COLOR);
		
		#if defined(TARGET_OSX) && defined(__BIG_ENDIAN__)
			QTNewGWorldFromPtr (&(videogworld), k32ARGBPixelFormat, &(videoRect), NULL, NULL, 0, (offscreenGWorldPixels), 4 * w);		
		#else
			QTNewGWorldFromPtr (&(videogworld), k24RGBPixelFormat, &(videoRect), NULL, NULL, 0, (pixels.getPixels()), 3 * w);
		#endif		
		
		LockPixels(GetGWorldPixMap(videogworld));
		SetGWorld (videogworld, NULL);
		SGSetGWorld(gSeqGrabber, videogworld, nil);

		
		//---------------------------------- 4 - device selection
		bool didWeChooseADevice = bChooseDevice;
		bool deviceIsSelected	=  false;

		//if we have a device selected then try first to setup
		//that device
		if(didWeChooseADevice){
			deviceIsSelected = qtSelectDevice(deviceID, true);
			if(!deviceIsSelected && bVerbose)
				ofLogError("ofQuickTimeGrabber") << "initGrabber(): unable to open device[" << deviceID << "], will attempt other devices";
		}

		//if we couldn't select our required device
		//or we aren't specifiying a device to setup
		//then lets try to setup ANY device!
		if(deviceIsSelected == false){
			//lets list available devices
			listDevices();

			setDeviceID(0);
			deviceIsSelected = qtSelectDevice(deviceID, false);
		}

		//if we still haven't been able to setup a device
		//we should error and stop!
		if( deviceIsSelected == false){
			goto bail;
		}

		//---------------------------------- 5 - final initialization steps
		OSStatus err;

	 	err = SGSetChannelUsage(gVideoChannel,seqGrabPreview);
		if ( err != noErr ) goto bail;

	
		//----------------- callback method for notifying new frame
		err = SGSetChannelRefCon(gVideoChannel, (long)&bHavePixelsChanged );
		if(!err) {

			VideoBottles vb; 
			/* get the current bottlenecks */ 
			vb.procCount = 9; 
			err = SGGetVideoBottlenecks(gVideoChannel, &vb); 
			if (!err) { 			
				myGrabCompleteProc = NewSGGrabCompleteBottleUPP(frameIsGrabbedProc);
				vb.grabCompleteProc = myGrabCompleteProc;
			
				/* add our GrabFrameComplete function */ 
				err = SGSetVideoBottlenecks(gVideoChannel, &vb); 	
			}
		
		}
				
		err = SGSetChannelBounds(gVideoChannel, &videoRect);
		if ( err != noErr ) goto bail;

		err = SGPrepare(gSeqGrabber,  true, false); //theo swapped so preview is true and capture is false
		if ( err != noErr ) goto bail;

		err = SGStartPreview(gSeqGrabber);
		if ( err != noErr ) goto bail;

		bGrabberInited = true;
		loadSettings();
		
		if( attemptFramerate >= 0 ){
			err = SGSetFrameRate(gVideoChannel, IntToFixed(attemptFramerate) );
			if ( err != noErr ){
				ofLogError("ofQuickTimeGrabber") << "initGrabber: couldn't setting framerate to " << attemptFramerate << ": OSStatus " << err;
			}		
		}
		
		ofLogNotice("ofQuickTimeGrabber") << "           inited grabbed            ";
		ofLogNotice("ofQuickTimeGrabber") << "-------------------------------------";

		// we are done
		return true;


		//--------------------- (bail) something's wrong -----
		bail:

			ofLogError("ofQuickTimeGrabber") << "***** ofQuickTimeGrabber error *****";
			ofLogError("ofQuickTimeGrabber") << "------------------------------------";

			//if we don't close this - it messes up the next device!
			if(bSgInited) qtCloseSeqGrabber();

			bGrabberInited = false;
			return false;
			
	//---------------------------------
	#else
	//---------------------------------
		return false;
	//---------------------------------
	#endif
	//---------------------------------

}
Ejemplo n.º 6
0
/**
 * Set default fragment attributes for the span using the
 * current raster values.  Used prior to glDraw/CopyPixels
 * and glBitmap.
 */
void
_swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
{
   GLchan r, g, b, a;
   /* Z*/
   {
      const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
      if (ctx->DrawBuffer->Visual.depthBits <= 16)
         span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
      else {
         GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax; 
         tmpf = MIN2(tmpf, depthMax);
         span->z = (GLint)tmpf;
      }
      span->zStep = 0;
      span->interpMask |= SPAN_Z;
   }

   /* W (for perspective correction) */
   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;

   /* primary color, or color index */
   UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
   UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
   UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
   UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
#if CHAN_TYPE == GL_FLOAT
   span->red = r;
   span->green = g;
   span->blue = b;
   span->alpha = a;
#else
   span->red   = IntToFixed(r);
   span->green = IntToFixed(g);
   span->blue  = IntToFixed(b);
   span->alpha = IntToFixed(a);
#endif
   span->redStep = 0;
   span->greenStep = 0;
   span->blueStep = 0;
   span->alphaStep = 0;
   span->interpMask |= SPAN_RGBA;

   COPY_4V(span->attrStart[FRAG_ATTRIB_COL], ctx->Current.RasterColor);
   ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL], 0.0, 0.0, 0.0, 0.0);
   ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL], 0.0, 0.0, 0.0, 0.0);

   /* fog */
   {
      const SWcontext *swrast = SWRAST_CONTEXT(ctx);
      GLfloat fogVal; /* a coord or a blend factor */
      if (swrast->_PreferPixelFog) {
         /* fog blend factors will be computed from fog coordinates per pixel */
         fogVal = ctx->Current.RasterDistance;
      }
      else {
         /* fog blend factor should be computed from fogcoord now */
         fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
      }
      span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
      span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
      span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
   }

   /* texcoords */
   {
      const GLuint attr = FRAG_ATTRIB_TEX;
      const GLfloat *tc = ctx->Current.RasterTexCoords;
      if (tc[3] > 0.0F) {
         /* use (s/q, t/q, r/q, 1) */
         span->attrStart[attr][0] = tc[0] / tc[3];
         span->attrStart[attr][1] = tc[1] / tc[3];
         span->attrStart[attr][2] = tc[2] / tc[3];
         span->attrStart[attr][3] = 1.0;
      }
      else {
         ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
      }
      ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
      ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
   }
}
Ejemplo n.º 7
0
void raster_tri_rgb_swap_rb(CRasterRGBTriangle2DInfo& info)
{
	if (info.clip_left < 0)
		info.clip_left = 0;
	if (info.clip_right > info.dest_width)
		info.clip_right = info.dest_width;
	if (info.clip_top < 0)
		info.clip_top = 0;
	if (info.clip_bottom > info.dest_height)
		info.clip_bottom = info.dest_height;

	typedef struct
	{
		float* v0, *v1;			/* Y(v0) < Y(v1) */
		float* tv0, *tv1;
		BYTE* cv0, *cv1;
		float dx;				/* X(v1) - X(v0) */
		float dy;				/* Y(v1) - Y(v0) */
		int fdxdy;				/* dx/dy in fixed-point */
		int fsx;				/* first sample point x coord */
		int fsy;
		float adjy;				/* adjust from v[0]->fy to fsy, scaled */
		int lines;				/* number of lines to be sampled on this edge */
		int fx0;				/* fixed pt X of lower endpoint */
	} EdgeT;

	EdgeT eMaj, eTop, eBot;
	float oneOverArea;

	float* vMin, *vMid, *vMax;       /* vertex indices:  Y(vMin)<=Y(vMid)<=Y(vMax) */
	float* tvMin, *tvMid, *tvMax;
	BYTE* cvMin, *cvMid, *cvMax;

	/* find the order of the 3 vertices along the Y axis */
	float y0 = info.v0[1];
	float y1 = info.v1[1];
	float y2 = info.v2[1];

	if (y0 <= y1) {
		if (y1 <= y2) {
			vMin = info.v0;   vMid = info.v1;   vMax = info.v2;   /* y0<=y1<=y2 */
			tvMin = info.tv0;   tvMid = info.tv1;   tvMax = info.tv2;   /* y0<=y1<=y2 */
			cvMin = info.cv0;   cvMid = info.cv1;   cvMax = info.cv2;   /* y0<=y1<=y2 */
		}
		else if (y2 <= y0) {
			vMin = info.v2;   vMid = info.v0;   vMax = info.v1;   /* y2<=y0<=y1 */
			tvMin = info.tv2;   tvMid = info.tv0;   tvMax = info.tv1;   /* y2<=y0<=y1 */
			cvMin = info.cv2;   cvMid = info.cv0;   cvMax = info.cv1;   /* y2<=y0<=y1 */
		}
		else {
			vMin = info.v0;   vMid = info.v2;   vMax = info.v1;   /* y0<=y2<=y1 */
			tvMin = info.tv0;   tvMid = info.tv2;   tvMax = info.tv1;   /* y0<=y2<=y1 */
			cvMin = info.cv0;   cvMid = info.cv2;   cvMax = info.cv1;   /* y0<=y2<=y1 */
		}
	}
	else {
		if (y0 <= y2) {
			vMin = info.v1;   vMid = info.v0;   vMax = info.v2;   /* y1<=y0<=y2 */
			tvMin = info.tv1;   tvMid = info.tv0;   tvMax = info.tv2;   /* y1<=y0<=y2 */
			cvMin = info.cv1;   cvMid = info.cv0;   cvMax = info.cv2;   /* y1<=y0<=y2 */
		}
		else if (y2 <= y1) {
			vMin = info.v2;   vMid = info.v1;   vMax = info.v0;   /* y2<=y1<=y0 */
			tvMin = info.tv2;  tvMid = info.tv1;   tvMax = info.tv0;   /* y2<=y1<=y0 */
			cvMin = info.cv2;  cvMid = info.cv1;   cvMax = info.cv0;   /* y2<=y1<=y0 */
		}
		else {
			vMin = info.v1;   vMid = info.v2;   vMax = info.v0;   /* y1<=y2<=y0 */
			tvMin = info.tv1;   tvMid = info.tv2;   tvMax = info.tv0;   /* y1<=y2<=y0 */
			cvMin = info.cv1;   cvMid = info.cv2;   cvMax = info.cv0;   /* y1<=y2<=y0 */
		}
	}

	/* vertex/edge relationship */
	eMaj.v0 = vMin;   eMaj.v1 = vMax;
	eTop.v0 = vMid;   eTop.v1 = vMax;
	eBot.v0 = vMin;   eBot.v1 = vMid;

	eMaj.tv0 = tvMin;   eMaj.tv1 = tvMax;
	eTop.tv0 = tvMid;   eTop.tv1 = tvMax;
	eBot.tv0 = tvMin;   eBot.tv1 = tvMid;

	eMaj.cv0 = cvMin;   eMaj.cv1 = cvMax;
	eTop.cv0 = cvMid;   eTop.cv1 = cvMax;
	eBot.cv0 = cvMin;   eBot.cv1 = cvMid;

	/* compute deltas for each edge:  vertex[v1] - vertex[v0] */
	eMaj.dx = vMax[0] - vMin[0];
	eMaj.dy = vMax[1] - vMin[1];
	eTop.dx = vMax[0] - vMid[0];
	eTop.dy = vMax[1] - vMid[1];
	eBot.dx = vMid[0] - vMin[0];
	eBot.dy = vMid[1] - vMin[1];

	float area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
	if (area > -0.05f && area < 0.05f)
		return;  /* very small; CULLED */

	oneOverArea = 1.0F / area;

	/* fixed point Y coordinates */
	int vMin_fx = FloatToFixed(vMin[0] + 0.5F);
	int vMin_fy = FloatToFixed(vMin[1] - 0.5F);
	int vMid_fx = FloatToFixed(vMid[0] + 0.5F);
	int vMid_fy = FloatToFixed(vMid[1] - 0.5F);
	int vMax_fy = FloatToFixed(vMax[1] - 0.5F);

	eMaj.fsy = FixedCeil(vMin_fy);
	eMaj.lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eMaj.fsy);
	if (eMaj.lines > 0)
	{
		float dxdy = eMaj.dx / eMaj.dy;
		eMaj.fdxdy = SignedFloatToFixed(dxdy);
		eMaj.adjy = (float)(eMaj.fsy - vMin_fy);  /* SCALED! */
		eMaj.fx0 = vMin_fx;
		eMaj.fsx = eMaj.fx0 + (int)(eMaj.adjy * dxdy);
	}
	else
		return;  /*CULLED*/

	eTop.fsy = FixedCeil(vMid_fy);
	eTop.lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eTop.fsy);
	if (eTop.lines > 0) {
		float dxdy = eTop.dx / eTop.dy;
		eTop.fdxdy = SignedFloatToFixed(dxdy);
		eTop.adjy = (float)(eTop.fsy - vMid_fy); /* SCALED! */
		eTop.fx0 = vMid_fx;
		eTop.fsx = eTop.fx0 + (int)(eTop.adjy * dxdy);
	}

	eBot.fsy = FixedCeil(vMin_fy);
	eBot.lines = FixedToInt(vMid_fy + FIXED_ONE - FIXED_EPSILON - eBot.fsy);
	if (eBot.lines > 0) {
		float dxdy = eBot.dx / eBot.dy;
		eBot.fdxdy = SignedFloatToFixed(dxdy);
		eBot.adjy = (float)(eBot.fsy - vMin_fy);  /* SCALED! */
		eBot.fx0 = vMin_fx;
		eBot.fsx = eBot.fx0 + (int)(eBot.adjy * dxdy);
	}

	int ltor = (oneOverArea < 0.0F);

	float drdx, drdy;      int fdrdx;
	float dgdx, dgdy;      int fdgdx;
	float dbdx, dbdy;      int fdbdx;
	float dadx, dady;      int fdadx;
	{
		float eMaj_dr, eBot_dr;
		eMaj_dr = (int)cvMax[0] - (int)cvMin[0];
		eBot_dr = (int)cvMid[0] - (int)cvMin[0];
		drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
		fdrdx = SignedFloatToFixed(drdx);
		drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
	}
	{
		float eMaj_dg, eBot_dg;
		eMaj_dg = (int)cvMax[1] - (int)cvMin[1];
		eBot_dg = (int)cvMid[1] - (int)cvMin[1];
		dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
		fdgdx = SignedFloatToFixed(dgdx);
		dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
	}
	{
		float eMaj_db, eBot_db;
		eMaj_db = (int)cvMax[2] - (int)cvMin[2];
		eBot_db = (int)cvMid[2] - (int)cvMin[2];
		dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
		fdbdx = SignedFloatToFixed(dbdx);
		dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
	}

	{
		float eMaj_da, eBot_da;
		eMaj_da = (int)cvMax[3] - (int)cvMin[3];
		eBot_da = (int)cvMid[3] - (int)cvMin[3];
		dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
		fdadx = SignedFloatToFixed(dadx);
		dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
	}



	float wMax = 1.0F;
	float wMin = 1.0F;
	float wMid = 1.0F;

	float eMaj_ds = tvMax[0] * wMax - tvMin[0] * wMin;
	float eBot_ds = tvMid[0] * wMid - tvMin[0] * wMin;
	float eMaj_dt = tvMax[1] * wMax - tvMin[1] * wMin;
	float eBot_dt = tvMid[1] * wMid - tvMin[1] * wMin;

	float dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
	float dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
	float dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
	float dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);

	int fx, fxLeftEdge, fxRightEdge, fdxLeftEdge, fdxRightEdge;
	int fdxOuter;
	int idxOuter;
	float dxOuter;
	int fError, fdError;
	float adjx, adjy;
	int fy;
	int iy;

	int fr, fdrOuter, fdrInner;
	int fg, fdgOuter, fdgInner;
	int fb, fdbOuter, fdbInner;
	int fa, fdaOuter, fdaInner;

	float sLeft, dsOuter, dsInner;
	float tLeft, dtOuter, dtInner;


	for (int subTriangle = 0; subTriangle <= 1; subTriangle++)
	{
		EdgeT *eLeft, *eRight;
		int setupLeft, setupRight;
		int lines;

		if (subTriangle == 0) {
			/* bottom half */
			if (ltor) {
				eLeft = &eMaj;
				eRight = &eBot;
				lines = eRight->lines;
				setupLeft = 1;
				setupRight = 1;
			}
			else {
				eLeft = &eBot;
				eRight = &eMaj;
				lines = eLeft->lines;
				setupLeft = 1;
				setupRight = 1;
			}
		}
		else {
			/* top half */
			if (ltor)
			{
				eLeft = &eMaj;
				eRight = &eTop;
				lines = eRight->lines;
				setupLeft = 0;
				setupRight = 1;
			}
			else
			{
				eLeft = &eTop;
				eRight = &eMaj;
				lines = eLeft->lines;
				setupLeft = 1;
				setupRight = 0;
			}
			if (lines == 0) return;
		}

		if (setupLeft && eLeft->lines > 0)
		{
			int fsx = eLeft->fsx;
			fx = FixedCeil(fsx);
			fError = fx - fsx - FIXED_ONE;
			fxLeftEdge = fsx - FIXED_EPSILON;
			fdxLeftEdge = eLeft->fdxdy;
			fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
			fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
			idxOuter = FixedToInt(fdxOuter);
			dxOuter = (float)idxOuter;

			fy = eLeft->fsy;
			iy = FixedToInt(fy);

			adjx = (float)(fx - eLeft->fx0);  /* SCALED! */
			adjy = eLeft->adjy;				 /* SCALED! */

			float* vLower = eLeft->v0;
			float* tvLower = eLeft->tv0;
			BYTE* cvLower = eLeft->cv0;

			sLeft = tvLower[0] * 1.0F + (dsdx * adjx + dsdy * adjy) * (1.0F / FIXED_SCALE);
			dsOuter = dsdy + dxOuter * dsdx;

			tLeft = tvLower[1] * 1.0F + (dtdx * adjx + dtdy * adjy) * (1.0F / FIXED_SCALE);
			dtOuter = dtdy + dxOuter * dtdx;

			fr = (int)(IntToFixed(cvLower[0]) + drdx * adjx + drdy * adjy) + FIXED_HALF;
			fdrOuter = SignedFloatToFixed(drdy + dxOuter * drdx);

			fg = (int)(IntToFixed(cvLower[1]) + dgdx * adjx + dgdy * adjy) + FIXED_HALF;
			fdgOuter = SignedFloatToFixed(dgdy + dxOuter * dgdx);

			fb = (int)(IntToFixed(cvLower[2]) + dbdx * adjx + dbdy * adjy) + FIXED_HALF;
			fdbOuter = SignedFloatToFixed(dbdy + dxOuter * dbdx);

			fa = (int)(IntToFixed(cvLower[3]) + dadx * adjx + dady * adjy) + FIXED_HALF;
			fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
		}

		if (setupRight && eRight->lines > 0)
		{
			fxRightEdge = eRight->fsx - FIXED_EPSILON;
			fdxRightEdge = eRight->fdxdy;
		}

		if (lines == 0)
			continue;

		fdrInner = fdrOuter + fdrdx;
		fdgInner = fdgOuter + fdgdx;
		fdbInner = fdbOuter + fdbdx;
		fdaInner = fdaOuter + fdadx;

		dsInner = dsOuter + dsdx;
		dtInner = dtOuter + dtdx;

		if (iy + lines >= info.clip_bottom)
			lines = info.clip_bottom - iy;

		while (lines > 0)
		{
			float ss = sLeft, tt = tLeft;
			int ffr = fr, ffg = fg, ffb = fb;
			int ffa = fa;

			int left = FixedToInt(fxLeftEdge);
			int right = FixedToInt(fxRightEdge);

			int ffrend = ffr + (right - left - 1)*fdrdx;
			int ffgend = ffg + (right - left - 1)*fdgdx;
			int ffbend = ffb + (right - left - 1)*fdbdx;
			if (ffrend < 0) ffr -= ffrend;
			if (ffgend < 0) ffg -= ffgend;
			if (ffbend < 0) ffb -= ffbend;
			if (ffr < 0) ffr = 0;
			if (ffg < 0) ffg = 0;
			if (ffb < 0) ffb = 0;

			int ffaend = ffa + (right - left - 1)*fdadx;
			if (ffaend < 0) ffa -= ffaend;
			if (ffa < 0) ffa = 0;

			int i;
			int n = right - left;

			if (iy >= info.clip_top)
			{

				if (n > 0)
					if (left < info.clip_left)
					{
						int diff = info.clip_left - left;
						ss += dsdx	 *diff;
						tt += dtdx	 *diff;
						ffr += fdrdx *diff;
						ffg += fdgdx *diff;
						ffb += fdbdx *diff;
						ffa += fdadx *diff;

						n -= diff;

						left = info.clip_left;
					}

				if (n > 0)
					if (left + n >= info.clip_right)
					{
						n = info.clip_right - left;
					}

				if (n > 0)
					for (i = 0; i < n; i++)
					{
						int i0, j0, i1, j1;
						float u, v;

						u = ss * info.tex_width;
						v = tt * info.tex_height;



						i0 = (int)floor(u - 0.5F);
						i1 = i0 + 1;
						j0 = (int)floor(v - 0.5F);
						j1 = j0 + 1;


						float a = frac(u - 0.5F);
						float b = frac(v - 0.5F);

						int w00 = (int)((1.0F - a)*(1.0F - b) * 256.0F);
						int w10 = (int)(a *(1.0F - b) * 256.0F);
						int w01 = (int)((1.0F - a)*      b  * 256.0F);
						int w11 = (int)(a *      b  * 256.0F);

						unsigned char red00, green00, blue00, alpha00;
						unsigned char red10, green10, blue10, alpha10;
						unsigned char red01, green01, blue01, alpha01;
						unsigned char red11, green11, blue11, alpha11;

						const unsigned char* texel;

						if (info.tex_repeat)
						{
							if (i0 < 0)
								i0 = info.tex_width + i0;
							else
								if (i0 >= info.tex_width)
									i0 = i0 - info.tex_width;

							if (i1 < 0)
								i1 = info.tex_width + i0;
							else
								if (i1 >= info.tex_width)
									i1 = i1 - info.tex_width;

							if (j0 < 0)
								j0 = info.tex_height + j0;
							else
								if (j0 >= info.tex_height)
									j0 = j0 - info.tex_height;

							if (j1 < 0)
								j1 = info.tex_height + j1;
							else
								if (j1 >= info.tex_height)
									j1 = j1 - info.tex_height;
						}

						BYTE* ppix = (BYTE*)(info.dest + (iy*info.dest_width + left) * 4);
						BYTE pix_r = ppix[i * 4 + 0];
						BYTE pix_g = ppix[i * 4 + 1];
						BYTE pix_b = ppix[i * 4 + 2];
						BYTE pix_a = ppix[i * 4 + 3];

						BYTE border_r = pix_r; //mesa3d cannot do this :)
						BYTE border_g = pix_g;
						BYTE border_b = pix_b;
						BYTE border_a = 0;

						bool i0_border = (i0 < 0 || i0 >= info.tex_width);
						bool i1_border = (i1 < 0 || i1 >= info.tex_width);
						bool j0_border = (j0 < 0 || j0 >= info.tex_height);
						bool j1_border = (j1 < 0 || j1 >= info.tex_height);

						if (i0_border | j0_border)
						{
							red00 = border_r;
							green00 = border_g;
							blue00 = border_b;
							alpha00 = border_a;
						}
						else
						{
							texel = info.tex + (info.tex_width * j0 + i0) * 4;
							red00 = texel[0];
							green00 = texel[1];
							blue00 = texel[2];
							alpha00 = texel[3];
						}

						if (i1_border | j0_border)
						{
							red10 = border_r;
							green10 = border_g;
							blue10 = border_b;
							alpha10 = border_a;
						}
						else
						{
							texel = info.tex + (info.tex_width * j0 + i1) * 4;
							red10 = texel[0];
							green10 = texel[1];
							blue10 = texel[2];
							alpha10 = texel[3];
						}

						if (j1_border | i0_border)
						{
							red01 = border_r;
							green01 = border_g;
							blue01 = border_b;
							alpha01 = border_a;
						}
						else
						{
							texel = info.tex + (info.tex_width * j1 + i0) * 4;
							red01 = texel[0];
							green01 = texel[1];
							blue01 = texel[2];
							alpha01 = texel[3];
						}

						if (i1_border | j1_border)
						{
							red11 = border_r;
							green11 = border_g;
							blue11 = border_b;
							alpha11 = border_a;
						}
						else
						{
							texel = info.tex + (info.tex_width * j1 + i1) * 4;
							red11 = texel[0];
							green11 = texel[1];
							blue11 = texel[2];
							alpha11 = texel[3];
						}

						BYTE _r = (w00*red00 + w10*red10 + w01*red01 + w11*red11) / 256;
						BYTE _g = (w00*green00 + w10*green10 + w01*green01 + w11*green11) / 256;
						BYTE _b = (w00*blue00 + w10*blue10 + w01*blue01 + w11*blue11) / 256;
						BYTE _a = (w00*alpha00 + w10*alpha10 + w01*alpha01 + w11*alpha11) / 256;


						_r = (_r * FixedToInt(ffr)) / 256;
						_g = (_g * FixedToInt(ffg)) / 256;
						_b = (_b * FixedToInt(ffb)) / 256;
						_a = (_a * FixedToInt(ffa)) / 256;

						int t = _a;
						int s = 255 - t;

						ppix[i * 4 + 0] = (_b * t + pix_r * s) / 256; //swap rb
						ppix[i * 4 + 1] = (_g * t + pix_g * s) / 256;
						ppix[i * 4 + 2] = (_r * t + pix_b * s) / 256;
						ppix[i * 4 + 3] = (_a * t + pix_a * s) / 256;

						ss += dsdx;
						tt += dtdx;
						ffr += fdrdx;
						ffg += fdgdx;
						ffb += fdbdx;
						ffa += fdadx;
					}
			}

			iy++;
			lines--;

			fxLeftEdge += fdxLeftEdge;
			fxRightEdge += fdxRightEdge;


			fError += fdError;
			if (fError >= 0)
			{
				fError -= FIXED_ONE;

				sLeft += dsOuter;
				tLeft += dtOuter;
				fr += fdrOuter;
				fg += fdgOuter;
				fb += fdbOuter;
				fa += fdaOuter;
			}
			else {
				sLeft += dsInner;
				tLeft += dtInner;
				fr += fdrInner;
				fg += fdgInner;
				fb += fdbInner;
				fa += fdaInner;
			}
		}
	}
}
Ejemplo n.º 8
0
extern	Fixed	*
ValueToFixed(
	ValueStruct	*val)
{
	Fixed	*ret;
	Fixed	*xval;

	if		(  val  ==  NULL  ) {
		ret = NewFixed(0,0);
	} else
	switch	(ValueType(val)) {
	  case	GL_TYPE_CHAR:
	  case	GL_TYPE_VARCHAR:
	  case	GL_TYPE_TEXT:
	  case	GL_TYPE_SYMBOL:
		ret = NewFixed(0,0);
		IntToFixed(ret,StrToInt(ValueString(val),strlen(ValueString(val))));
		break;
	  case	GL_TYPE_NUMBER:
		xval = &ValueFixed(val);
		ret = NewFixed(xval->flen,xval->slen);
		strcpy(ret->sval,xval->sval);
		break;
	  case	GL_TYPE_INT:
		ret = NewFixed(0,0);
		IntToFixed(ret,ValueInteger(val));
		break;
	  case	GL_TYPE_FLOAT:
		ret = NewFixed(SIZE_NUMBUF,(SIZE_NUMBUF / 2));
		FloatToFixed(ret,ValueFloat(val));
		break;
	  case	GL_TYPE_BOOL:
		ret = NewFixed(0,0);
		IntToFixed(ret,(int)ValueBool(val));
		break;
	  case	GL_TYPE_TIMESTAMP:
		ret = NewFixed(14,0);
		sprintf(ret->sval,"%04d%02d%02d%02d%02d%02d",
				ValueDateTimeYear(val),
				ValueDateTimeMon(val) + 1,
				ValueDateTimeMDay(val),
				ValueDateTimeHour(val),
				ValueDateTimeMin(val),
				ValueDateTimeSec(val));
		break;
	  case	GL_TYPE_DATE:
		ret = NewFixed(8,0);
		sprintf(ret->sval,"%04d%02d%02d",
				ValueDateTimeYear(val),
				ValueDateTimeMon(val) + 1,
				ValueDateTimeMDay(val));
		break;
	  case	GL_TYPE_TIME:
		ret = NewFixed(6,0);
		sprintf(ret->sval,"%02d%02d%02d",
				ValueDateTimeHour(val),
				ValueDateTimeMin(val),
				ValueDateTimeSec(val));
		break;
	  default:
		ret = NewFixed(0,0);
		break;
	}
	return	(ret);
}
Ejemplo n.º 9
0
BOOL FAR PASCAL DibTransparentStretch(
	PDIB pdibDst,
	LPVOID lpDst,
	int DstX,
	int DstY,
	int DstXE,
	int DstYE,
	PDIB pdibSrc,
	LPVOID lpSrc,
	int SrcX,
	int SrcY,
	int SrcXE,
	int SrcYE,
	char unsigned Transparent)
{
	int XMax, YMax;
	Fixed fClipRatio;
	int iTemp;

	assert(pdibDst && lpDst);
	assert(pdibSrc && lpSrc);

	//*** Currently, this only works with 8-bit dibs
	assert(pdibDst->biBitCount == 8); 
	assert(pdibSrc->biBitCount == 8);

	//*** This does NOT mirror
	assert (DstXE >= 0 && DstYE >= 0);
	assert (SrcXE >= 0 && SrcYE >= 0);

	XMax = (int)pdibDst->biWidth - 1;
	// [email protected]:  I changed the following line.
	// In the version I was given, the abs was not here.
	// As a result, this did not handle top-down DIBS.
	// The rest of the routine works fine.
	YMax = abs((int)pdibDst->biHeight) - 1;
	///End WWW Change.

	//*** Trivial reject
	if (DstX > XMax || DstY > YMax ||
		(DstX + DstXE) < 0 || (DstY + DstYE) < 0)
		return TRUE;

	/// [email protected]: I duplicated the following line
	// of code.  This is changing the starting position
	// of the blit from a 'standard' Windows top-down
	// coordinate system to a 'standard' DIB bottom-up
	// coordinate system.  Unfortunately, the original
	// source only changed the destination.  This meant
	// that it painted from the wrong spot in the source
	// DIB.  So, I changed the source Y spot as well.
	DstY = YMax + 1 - DstY - DstYE;
	SrcY = abs ((int)pdibSrc->biHeight) - SrcY - SrcYE;

	//*** Clip the left edge
	if (DstX < 0)
	{
		fClipRatio = FixedDivide( IntToFixed(-DstX),
			IntToFixed(DstXE) );

		//*** Remember, DstX is negative!
		DstXE = DstXE + DstX;
		DstX = 0;

		iTemp = FixedToInt( FixedMultiply( fClipRatio, IntToFixed(SrcXE) ) );
		SrcX = SrcX + iTemp;
		SrcXE = SrcXE - iTemp;
	}

	//*** Clip the top edge
	if (DstY < 0)
	{
		fClipRatio = FixedDivide( IntToFixed(-DstY),
			IntToFixed(DstYE) );

		//*** Remember, DstY is negative!
		DstYE = DstYE + DstY;
		DstY = 0;

		iTemp = FixedToInt( FixedMultiply( fClipRatio, IntToFixed(SrcYE) ) );
		SrcY = SrcY + iTemp;
		SrcYE = SrcYE - iTemp;
	}

	
	//
	// [email protected]
	// XMax (and later YMax) are being used as 0 based when
	// they are in fact the width (and height) in pixels of
	// the dib and are 1 based.
	//
	//*** Clip the X extent
	if ((DstX + DstXE) > (XMax + 1))
	{
		fClipRatio = FixedDivide( IntToFixed(XMax - DstX),
			IntToFixed(DstXE) );

		DstXE = XMax - DstX + 1;
		SrcXE = FixedToInt( FixedMultiply(fClipRatio, IntToFixed(SrcXE)) );

		//*** Make sure the round-off is correct
		if ((DstX + DstXE) < XMax)
		  ++DstXE;
	}

	//
	// [email protected]
	// As above, YMax was being used as a 0 based value
	// instead of the 1 based that it is.
	//
	//*** Clip the Y extent
	if ((DstY + DstYE) > (YMax + 1))
	{
		fClipRatio = FixedDivide( IntToFixed(YMax - DstY),
			IntToFixed(DstYE) );

		DstYE = YMax - DstY + 1;
		SrcYE = FixedToInt( FixedMultiply(fClipRatio, IntToFixed(SrcYE)) );

		//*** Make sure the round-off is correct
		if ((DstY + DstYE) < YMax)
		  ++DstYE;
	}

	DoDibTransparentStretch(
		pdibDst, lpDst, DstX, DstY, DstXE, DstYE,
		pdibSrc, lpSrc, SrcX, SrcY, SrcXE, SrcYE,
		Transparent);

	return TRUE;
}
Ejemplo n.º 10
0
/* This function prepares the movie to receivve the movie data,
 * After success, *out_map points to a valid stream maping
 * Return values:
 *	  0: ok
 */
OSStatus prepare_movie(ff_global_ptr storage, Movie theMovie, Handle dataRef, OSType dataRefType)
{
    int j;
    AVStream *st;
    NCStream *map;
    Track track = NULL;
    Track first_audio_track = NULL;
    AVFormatContext *ic = storage->format_context;
    OSStatus err = noErr;

    /* make the stream map structure */
    map = av_mallocz(ic->nb_streams * sizeof(NCStream));

    for(j = 0; j < ic->nb_streams; j++) {

        st = ic->streams[j];
        map[j].index = st->index;
        map[j].str = st;
        map[j].duration = -1;

        if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            Fixed width, height;

            get_track_dimensions_for_codec(st, &width, &height);
            track = NewMovieTrack(theMovie, width, height, kNoVolume);

            // Support for 'old' NUV files, that didn't put the codec_tag in the file.
            if( st->codec->codec_id == CODEC_ID_NUV && st->codec->codec_tag == 0 ) {
                st->codec->codec_tag = MKTAG( 'N', 'U', 'V', '1' );
            }

            initialize_video_map(&map[j], track, dataRef, dataRefType, storage->firstFrames + j);
            set_track_clean_aperture_ext((ImageDescriptionHandle)map[j].sampleHdl, width, height, IntToFixed(st->codec->width), IntToFixed(st->codec->height));
            set_track_colorspace_ext((ImageDescriptionHandle)map[j].sampleHdl, width, height);
        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            if (st->codec->sample_rate > 0) {
                track = NewMovieTrack(theMovie, 0, 0, kFullVolume);
                err = initialize_audio_map(&map[j], track, dataRef, dataRefType, storage->firstFrames + j);

                if (first_audio_track == NULL)
                    first_audio_track = track;
                else
                    SetTrackAlternate(track, first_audio_track);
            }
        } else
            continue;

        // can't import samples if neither of these were created.
        map[j].valid = map[j].media && map[j].sampleHdl;

        if (err) {
            if (track)
                DisposeMovieTrack(track);
            return err;
        }
    }

    add_metadata(ic, theMovie);

    storage->stream_map = map;

    return 0;
} /* prepare_movie() */