source/Sources/AirPlayReceiverSession.c
static OSStatus
	_GeneralAudioDecodePacket( 
		AirPlayReceiverSessionRef	inSession, 
		uint8_t *					inAAD, 
		size_t						inAADSize,
		uint8_t *					inSrc, 
		size_t						inSrcSize, 
		uint8_t *					inDst, 
		size_t						inDstSize, 
		size_t *					outSize )
{
	OSStatus					err;
	Boolean						decrypt;
	int							decompress;
	size_t						size;
	uint32_t					percent;
	
	// inSrc may be the same as inDst, but otherwise they cannot overlap. Neither can overlap the temp buffer.
	
	if( inSrc != inDst ) check_ptr_overlap( inSrc, inSrcSize, inDst, inDstSize );
	check_ptr_overlap( inSrc, inSrcSize, inSession->decodeBuffer, inSession->decodeBufferSize );
	check_ptr_overlap( inDst, inDstSize, inSession->decodeBuffer, inSession->decodeBufferSize );

	decrypt = ( inSession->decryptor != NULL );
	decrypt = ( decrypt || inSession->mainAudioCtx.outputCryptor.isValid );
	decompress = ( inSession->compressionType != kAirPlayCompressionType_PCM );
	if( decrypt && decompress ) // Encryption and Compression (most common case)
	{
		// Decrypt into a temp buffer then decompress back into the node buffer. Note: decoder result is in host byte order.
		
		require_action( inSrcSize <= inSession->decodeBufferSize, exit, err = kSizeErr );
		
		err = _GeneralAudioDecryptPacket( 
				inSession,
				inAAD, 
				inAADSize, 
				inSrc, 
				inSrcSize, 
				inSession->decodeBuffer, 
				&size );
		require_noerr( err, exit );
		inSrcSize = size;
		
		size = 0;
		err = _AudioDecoderDecodeFrame( inSession, inSession->decodeBuffer, inSrcSize, inDst, inDstSize, &size );
		require_noerr( err, exit );
	}
	else if( decrypt ) // Encryption only
	{
		// Decrypt into a temp buffer then swap to host byte order back into the node buffer.
		
		require_action( inSrcSize <= inSession->decodeBufferSize, exit, err = kSizeErr );
		
		err = _GeneralAudioDecryptPacket( 
				inSession,
				inAAD, 
				inAADSize, 
				inSrc, 
				inSrcSize, 
				inSession->decodeBuffer, 
				&size );
		require_noerr( err, exit );
		
		BigToHost16Mem( inSession->decodeBuffer, size, inDst );
	}
	else if( decompress ) // Compression only
	{
		// Decompress into a temp buffer then copy back into the node buffer. Note: decoder result is in host byte order.
		// This does an extra memcpy due to the lack of in-place decoding, but this case is not normally used.
		
		size = 0;
		err = _AudioDecoderDecodeFrame( inSession, inSrc, inSrcSize, inSession->decodeBuffer, 
			inSession->decodeBufferSize, &size );
		require_noerr( err, exit );
		
		require_action( size <= inDstSize, exit, err = kSizeErr );
		memcpy( inDst, inSession->decodeBuffer, size );
	}
	else // No Encryption or Compression (raw data)
	{
		require_action( inSrcSize <= inDstSize, exit, err = kSizeErr );
		
		BigToHost16Mem( inSrc, inSrcSize, inDst );
		size = inSrcSize;
	}
	
	// Track the amount of compression we're getting.
	
	percent = ( size > 0 ) ? ( (uint32_t)( ( inSrcSize * ( 100 * 100 ) ) / size ) ) : 0;
	inSession->compressionPercentAvg = ( ( inSession->compressionPercentAvg * 63 ) + percent ) / 64;
	
	*outSize = size;
	err = kNoErr;
	
exit:
	return( err );
}
//===========================================================================================================================
//	_GeneralAudioDecodePacket
//
//	Warning: Assumes the AirTunes lock is held.
//===========================================================================================================================
_GeneralAudioDecodePacket
Warning: Assumes the AirTunes lock is held.
_GeneralAudioDecodePacket Warning : Assumes the AirTunes lock is held .
static OSStatus
	_GeneralAudioDecodePacket( 
		AirPlayReceiverSessionRef	inSession, 
		uint8_t *					inAAD, 
		size_t						inAADSize,
		uint8_t *					inSrc, 
		size_t						inSrcSize, 
		uint8_t *					inDst, 
		size_t						inDstSize, 
		size_t *					outSize )
{
	OSStatus					err;
	Boolean						decrypt;
	int							decompress;
	size_t						size;
	uint32_t					percent;
	if( inSrc != inDst ) check_ptr_overlap( inSrc, inSrcSize, inDst, inDstSize );
	check_ptr_overlap( inSrc, inSrcSize, inSession->decodeBuffer, inSession->decodeBufferSize );
	check_ptr_overlap( inDst, inDstSize, inSession->decodeBuffer, inSession->decodeBufferSize );
	decrypt = ( inSession->decryptor != NULL );
	decrypt = ( decrypt || inSession->mainAudioCtx.outputCryptor.isValid );
	decompress = ( inSession->compressionType != kAirPlayCompressionType_PCM );
	if( decrypt && decompress ) 
	{
		require_action( inSrcSize <= inSession->decodeBufferSize, exit, err = kSizeErr );
		err = _GeneralAudioDecryptPacket( 
				inSession,
				inAAD, 
				inAADSize, 
				inSrc, 
				inSrcSize, 
				inSession->decodeBuffer, 
				&size );
		require_noerr( err, exit );
		inSrcSize = size;
		size = 0;
		err = _AudioDecoderDecodeFrame( inSession, inSession->decodeBuffer, inSrcSize, inDst, inDstSize, &size );
		require_noerr( err, exit );
	}
	else if( decrypt ) 
	{
		require_action( inSrcSize <= inSession->decodeBufferSize, exit, err = kSizeErr );
		err = _GeneralAudioDecryptPacket( 
				inSession,
				inAAD, 
				inAADSize, 
				inSrc, 
				inSrcSize, 
				inSession->decodeBuffer, 
				&size );
		require_noerr( err, exit );
		BigToHost16Mem( inSession->decodeBuffer, size, inDst );
	}
	else if( decompress ) 
	{
		size = 0;
		err = _AudioDecoderDecodeFrame( inSession, inSrc, inSrcSize, inSession->decodeBuffer, 
			inSession->decodeBufferSize, &size );
		require_noerr( err, exit );
		require_action( size <= inDstSize, exit, err = kSizeErr );
		memcpy( inDst, inSession->decodeBuffer, size );
	}
	else 
	{
		require_action( inSrcSize <= inDstSize, exit, err = kSizeErr );
		BigToHost16Mem( inSrc, inSrcSize, inDst );
		size = inSrcSize;
	}
	percent = ( size > 0 ) ? ( (uint32_t)( ( inSrcSize * ( 100 * 100 ) ) / size ) ) : 0;
	inSession->compressionPercentAvg = ( ( inSession->compressionPercentAvg * 63 ) + percent ) / 64;
	*outSize = size;
	err = kNoErr;
exit:
	return( err );
}
static OSStatus _GeneralAudioDecodePacket ( AirPlayReceiverSessionRef inSession , uint8_t * inAAD , size_t inAADSize , uint8_t * inSrc , size_t inSrcSize , uint8_t * inDst , size_t inDstSize , size_t * outSize ) { OSStatus err ; Boolean decrypt ; int decompress ; size_t size ; uint32_t percent ; if ( inSrc != inDst ) check_ptr_overlap ( inSrc , inSrcSize , inDst , inDstSize ) ; check_ptr_overlap ( inSrc , inSrcSize , inSession -> decodeBuffer , inSession -> decodeBufferSize ) ; check_ptr_overlap ( inDst , inDstSize , inSession -> decodeBuffer , inSession -> decodeBufferSize ) ; decrypt = ( inSession -> decryptor != NULL ) ; decrypt = ( decrypt || inSession -> mainAudioCtx . outputCryptor . isValid ) ; decompress = ( inSession -> compressionType != kAirPlayCompressionType_PCM ) ; if ( decrypt && decompress ) { require_action ( inSrcSize <= inSession -> decodeBufferSize , exit , err = kSizeErr ) ; err = _GeneralAudioDecryptPacket ( inSession , inAAD , inAADSize , inSrc , inSrcSize , inSession -> decodeBuffer , & size ) ; require_noerr ( err , exit ) ; inSrcSize = size ; size = 0 ; err = _AudioDecoderDecodeFrame ( inSession , inSession -> decodeBuffer , inSrcSize , inDst , inDstSize , & size ) ; require_noerr ( err , exit ) ; } else if ( decrypt ) { require_action ( inSrcSize <= inSession -> decodeBufferSize , exit , err = kSizeErr ) ; err = _GeneralAudioDecryptPacket ( inSession , inAAD , inAADSize , inSrc , inSrcSize , inSession -> decodeBuffer , & size ) ; require_noerr ( err , exit ) ; BigToHost16Mem ( inSession -> decodeBuffer , size , inDst ) ; } else if ( decompress ) { size = 0 ; err = _AudioDecoderDecodeFrame ( inSession , inSrc , inSrcSize , inSession -> decodeBuffer , inSession -> decodeBufferSize , & size ) ; require_noerr ( err , exit ) ; require_action ( size <= inDstSize , exit , err = kSizeErr ) ; memcpy ( inDst , inSession -> decodeBuffer , size ) ; } else { require_action ( inSrcSize <= inDstSize , exit , err = kSizeErr ) ; BigToHost16Mem ( inSrc , inSrcSize , inDst ) ; size = inSrcSize ; } percent = ( size > 0 ) ? ( ( uint32_t ) ( ( inSrcSize * ( 100 * 100 ) ) / size ) ) : 0 ; inSession -> compressionPercentAvg = ( ( inSession -> compressionPercentAvg * 63 ) + percent ) / 64 ; * outSize = size ; err = kNoErr ; exit : return ( err ) ; }
_GeneralAudioDecodePacket
Warning: Assumes the AirTunes lock is held.
_GeneralAudioDecodePacket Warning : Assumes the AirTunes lock is held .
// inSrc may be the same as inDst, but otherwise they cannot overlap. Neither can overlap the temp buffer. // Encryption and Compression (most common case) // Decrypt into a temp buffer then decompress back into the node buffer. Note: decoder result is in host byte order. // Encryption only // Decrypt into a temp buffer then swap to host byte order back into the node buffer. // Compression only // Decompress into a temp buffer then copy back into the node buffer. Note: decoder result is in host byte order. // This does an extra memcpy due to the lack of in-place decoding, but this case is not normally used. // No Encryption or Compression (raw data) // Track the amount of compression we're getting.