Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
ComponentVideoRTP/Sources/RTPMPComponentVideo.c
/* |
File: RTPMPComponentVideo.c |
Contains: Definition of Component Video RTPMediaPacketizer |
Copyright: © 1997-1999 by Apple Computer, Inc., all rights reserved. |
OVERVIEW |
QuickTime Streaming software uses an RTPMediaPacketizer to encapsulate |
sample data in network packets. When preparing to packetize sample data, |
Streaming software first determines a packetizer's capabilities and |
operational parameters. If the packetizer is suitable, the Streaming |
software provides the packetizer with an RTPPacketBuilder. The packetizer |
uses the RTPPacketBuilder to construct network packets from sample data. |
The Streaming software specifies what sample data to packetize by calling |
the packetizer's RTPMPSetSampleData() implementation. |
This packetizer implements the following interface and delegates all other |
calls to a base RTPMediaPacketizer defined by QuickTime Streaming. |
STANDARD COMPONENT INTERFACE |
---------------------------- |
CallComponentOpen() Allocate and initialize storage for |
instance variables. |
CallComponentClose() Reverse the effects of |
CallComponentOpen(). |
CallComponentVersion() Return the instance's version. |
CallComponentTarget() Update the instance's inheritance graph. |
RTP MEDIA PACKETIZER INTERFACE |
------------------------------ |
RTPMPInitialize() Prepare to packetize sample data. |
RTPMPPreflightMedia() Determine whether the packetizer can |
packetize the described data. |
RTPMPSetSampleData() Use the instance's RTPPacketBuilder to |
packetize sample data. |
RTPMPFlush() Finish any packetization in progress. |
RTPMPReset() Abort any packetization in progress. |
RTPMPGetInfo() Return the requested information. |
RTPMPSetTimeScale() |
RTPMPGetTimeScale() |
RTPMPSetTimeBase() |
RTPMPGetTimeBase() |
RTPMPHasCharacteristic() |
RTPMPSetPacketBuilder() |
RTPMPGetPacketBuilder() |
RTPMPSetMediaType() |
RTPMPGetMediaType() |
RTPMPSetMaxPacketSize() |
RTPMPGetMaxPacketSize() |
RTPMPSetMaxPacketDuration() |
RTPMPGetMaxPacketDuration() |
*/ |
/* --------------------------------------------------------------------------- |
* H E A D E R S |
* --------------------------------------------------------------------------- |
*/ |
#include "RTPMPComponentVideo.h" |
#include "RTPMPComponentVideoResources.h" |
/* --------------------------------------------------------------------------- |
* R T P M E D I A P A C K E T I Z E R P R O T O T Y P E S |
* --------------------------------------------------------------------------- |
* |
* QTStreamingComponents.k.h uses these macros to declare prototypes for |
* the RTPMediaPacketizer calls defined in this file. |
* |
*/ |
#define RTPMP_BASENAME() RTPMPComponentVideo_ |
#define RTPMP_GLOBALS() RTPMPComponentVideoInstanceData ** |
#include <QTStreamingComponents.k.h> |
/* --------------------------------------------------------------------------- |
* C O M P O N E N T D I S P A T C H H E L P E R |
* --------------------------------------------------------------------------- |
* |
* ComponentDispatchHelper.c uses these macros to define a dispatcher and to |
* declare prototypes for the core component calls defined in this file. For |
* Mac OS, it defines the routine descriptor that serves as the component |
* entry point. The name of the routine descriptor is the macro expansion of |
* |
* CALLCOMPONENT_BASENAME()##ComponentDispatchRD |
* |
* The name of the dispatcher is the macro expansion of |
* |
* CALLCOMPONENT_BASENAME()##ComponentDispatch |
* |
*/ |
#define CALLCOMPONENT_BASENAME() RTPMP_BASENAME() |
#define CALLCOMPONENT_GLOBALS() RTPMP_GLOBALS() storage |
#define COMPONENT_DISPATCH_FILE "RTPMPComponentVideoDispatch.h" |
#define COMPONENT_C_DISPATCHER 1 |
#define COMPONENT_UPP_SELECT_ROOT() RTPMP |
#define GET_DELEGATE_COMPONENT() ( ( **storage ).itsBase ) |
#include <ComponentDispatchHelper.c> |
#pragma mark * INTERNAL IMPLEMENTATION |
#pragma mark - |
/* --------------------------------------------------------------------------- |
* I N T E R N A L I M P L E M E N T A T I O N |
* --------------------------------------------------------------------------- |
*/ |
enum |
{ |
__kNoLimit = 0xFFFFFFFF, |
__kNoFlags = 0, |
__kDefaultPacketDurationLimit = __kNoLimit, |
__kPayloadDataSizeMask = 0xFFFFFFFC, |
__kTypicalMTUSize = 1500, /* Ethernet */ |
__kTypicalNetworkHeaderSize = 20, /* IP, no options */ |
__kTypicalTransportHeaderSize = 8, /* UDP */ |
__kTypicalRTPHeaderSize = 12, /* no CSRCs, no extension */ |
__kDefaultPacketSizeLimit = |
__kTypicalMTUSize - __kTypicalNetworkHeaderSize - __kTypicalTransportHeaderSize - |
__kTypicalRTPHeaderSize |
}; |
/* --------------------------------------------------------------------------- |
* __UpdateDataSizes() |
* --------------------------------------------------------------------------- |
* |
* Update data sizes the instance uses to construct network packets. |
* |
*/ |
static |
void |
__UpdateDataSizes( |
RTPMPComponentVideoInstanceData ** inGlobals ) |
{ |
UInt16 theWidth; |
UInt16 theHeight; |
theWidth = ComponentVideoPayloadWidth( &( **inGlobals ).itsPayloadHeader ); |
theHeight = ComponentVideoPayloadHeight( &( **inGlobals ).itsPayloadHeader ); |
/* YUV 4:2:2 encoding uses four octets to represent a pair of pixels. |
The number of octets in a frame is therefore |
padded-width x height x 2 octets |
where padded-width is the row width in pixels padded to an |
even number. */ |
( **inGlobals ).itsFrameDataSize = |
( ( ( theWidth + 1 ) & ( ~1L ) ) * theHeight ) << 1; |
/* This packetizer sends an integral number of sample packets in |
each network packet. Since YUV 4:2:2 encodes samples in four-octet |
sample packets, the amount of data sent in a network packet will be |
a multiple of four octets. Most network packets will carry a fixed |
header and enough sample data to fill the network packet as closely |
as possible to the network packet size limit. */ |
( **inGlobals ).itsPayloadDataSize = |
( ( **inGlobals ).itsPacketSizeLimit - |
sizeof( ( **inGlobals ).itsPayloadHeader.itsFixedHeader ) ) & |
__kPayloadDataSizeMask; |
/* Whatever data would be left over after dividing a frame into |
maximal-length network packets must fit into the first packet along |
with a fixed header and a payload description. If the leftover |
data won't fit, adjust the size of the other network packets. */ |
while( |
( ( ( **inGlobals ).itsFrameDataSize % ( **inGlobals ).itsPayloadDataSize ) + |
sizeof( ( **inGlobals ).itsPayloadHeader ) > |
( **inGlobals ).itsPacketSizeLimit ) ) |
{ |
( **inGlobals ).itsPayloadDataSize -= 4; |
} |
} |
/* --------------------------------------------------------------------------- |
* __UpdateSampleDescription() |
* --------------------------------------------------------------------------- |
* |
* Determine whether the SampleDescription of incoming sample data has |
* changed and update instance variables accordingly. |
* |
*/ |
static |
ComponentResult |
__UpdateSampleDescription( |
RTPMPComponentVideoInstanceData ** inGlobals, |
const RTPMPSampleDataParams * inSampleData ) |
{ |
ComponentResult theError = noErr; |
SInt32 theFlags; |
ImageDescriptionHandle theDescription; |
/* Check the SampleDescription if it is the first description or if the cached |
sample description seed doesn't match the current seed. */ |
if( |
!ComponentVideoPayloadHasDescription( &( **inGlobals ).itsPayloadHeader ) || |
( **inGlobals ).itsSampleDescriptionSeed != inSampleData->sampleDescSeed ) |
{ |
theDescription = |
REINTERPRET_CAST( ImageDescriptionHandle )( inSampleData->sampleDescription ); |
/* Only update if the differences in the new SampleDescription are pertinent. */ |
if( |
ComponentVideoPayloadWidth( &( **inGlobals ).itsPayloadHeader ) != |
( **theDescription ).width || |
ComponentVideoPayloadHeight( &( **inGlobals ).itsPayloadHeader ) != |
( **theDescription ).height ) |
{ |
/* If the RTPMPSetSampleData() implementation queues data, then any |
queued sample data, which uses the obsolete SampleDescription, must |
be flushed before updating to the new SampleDescription. */ |
theError = RTPMPFlush( ( **inGlobals ).itsFinalDerivation, 0, &theFlags ); |
if( !theError ) |
{ |
/* Update the payload description that the packetizer includes in |
some network packets. */ |
ComponentVideoPayloadSetDescription( |
&( **inGlobals ).itsPayloadHeader, ( **theDescription ).width, |
( **theDescription ).height ); |
/* Update data sizes the packetizer uses to construct network |
packets. */ |
__UpdateDataSizes( inGlobals ); |
} |
} |
/* Update the cached sample description seed to indicate that the |
packetizer state is now consistent with the new SampleDescription. */ |
if( !theError ) |
( **inGlobals ).itsSampleDescriptionSeed = inSampleData->sampleDescSeed; |
} |
return( theError ); |
} |
/* --------------------------------------------------------------------------- |
* __PacketizeSampleData() |
* --------------------------------------------------------------------------- |
* |
* Construct network packets from the specified sample data. |
* |
*/ |
static |
ComponentResult |
__PacketizeSampleData( |
RTPMPComponentVideoInstanceData ** inGlobals, |
const RTPMPSampleDataParams * inSampleData ) |
{ |
ComponentResult theError; |
RTPPacketGroupRef thePacketGroup; |
UInt32 theDataOffset; |
RTPPacketRef thePacket; |
UInt32 theDataSize; |
ComponentVideoPayload theHeader; |
UInt32 theHeaderSize; |
/* This packetizer sends all the data for one frame in a single packet group. */ |
theError = |
RTPPBBeginPacketGroup( |
( **inGlobals ).itsPacketBuilder, __kNoFlags, inSampleData->timeStamp, |
&thePacketGroup ); |
if( !theError ) |
{ |
/* Most network packets for the frame will be uniformly sized, with a |
fixed header and a fixed amount of sample data. The first network |
packet will include whatever data is left over (taken from the |
start of the sample data, not the end), as well as a fixed header |
and a payload description. */ |
theDataOffset = 0; |
theDataSize = ( **inGlobals ).itsFrameDataSize % ( **inGlobals ).itsPayloadDataSize; |
theHeader = ( **inGlobals ).itsPayloadHeader; |
theHeaderSize = sizeof( theHeader ); |
/* Construct network packets until the sample data for this frame is exhausted. */ |
while( theDataOffset < ( **inGlobals ).itsFrameDataSize && !theError ) |
{ |
theError = |
RTPPBBeginPacket( |
( **inGlobals ).itsPacketBuilder, __kNoFlags, thePacketGroup, |
( **inGlobals ).itsPacketSizeLimit, &thePacket ); |
if( !theError ) |
{ |
/* The header (with optional payload description) is added to the |
network packet as literal data. The data is written directly |
to the network packet. If the RTPPacketBuilder is storing |
network packet data to disk, it must store a copy of literal data. */ |
theError = |
RTPPBAddPacketLiteralData( |
( **inGlobals ).itsPacketBuilder, __kNoFlags, thePacketGroup, |
thePacket, REINTERPRET_CAST( UInt8 * )( &theHeader ), |
theHeaderSize, NULL ); |
if( !theError ) |
{ |
/* The RTPPacketBuilder provides a routine specifically for adding |
sample data. For stored movies, the RTPPacketBuilder need not |
store a copy of sample data, since the data is already stored |
in the movie. */ |
theError = |
RTPPBAddPacketSampleData( |
( **inGlobals ).itsPacketBuilder, __kNoFlags, thePacketGroup, |
thePacket, CONST_CAST( RTPMPSampleDataParams * )( inSampleData ), |
theDataOffset, theDataSize, NULL ); |
if( !theError ) |
{ |
/* The packetizer sets the RTP/AVP marker bit in the last network |
packet of a frame. The QuickTime Streaming base RTPReassembler |
can better assist in reassembling the payload data if this bit |
is used to mark the end of a packet group. |
Most payloads have no duration, except for the last payload, |
which absorbs the duration for the entire frame. */ |
if( theDataOffset + theDataSize < ( **inGlobals ).itsFrameDataSize ) |
{ |
theError = |
RTPPBEndPacket( |
( **inGlobals ).itsPacketBuilder, __kNoFlags, |
thePacketGroup, thePacket, 0 /* inTimeOffset */, |
0 /* inDuration */ ); |
} |
else |
{ |
theError = |
RTPPBEndPacket( |
( **inGlobals ).itsPacketBuilder, kRTPPBSetMarkerFlag, |
thePacketGroup, thePacket, 0 /* inTimeOffset */, |
inSampleData->duration ); |
} |
} |
} |
} |
/* For this packetizer, packets after the first network packet of a frame |
are uniformly sized and have no payload description. */ |
if( theDataOffset ) |
{ |
theDataOffset += theDataSize; |
} |
else |
{ |
theDataOffset += theDataSize; |
theDataSize = ( **inGlobals ).itsPayloadDataSize; |
theHeaderSize = sizeof( theHeader.itsFixedHeader ); |
ComponentVideoPayloadSetDescription( &theHeader, 0, 0 ); |
} |
/* Update the Offset field of the header to indicate the next block |
of sample data. */ |
ComponentVideoPayloadSetOffset( &theHeader, theDataOffset ); |
} |
if( theError ) |
{ |
RTPPBEndPacketGroup( |
( **inGlobals ).itsPacketBuilder, kRTPPBDontSendFlag, thePacketGroup ); |
} |
else |
{ |
/* For this packetizer, every group contains only sync samples. That |
means the sample data for the group can be decoded independently of |
any previous sample data. When randomly accessing stored movies, |
a streaming server can look for sync samples. */ |
theError = |
RTPPBEndPacketGroup( |
( **inGlobals ).itsPacketBuilder, kRTPPBSyncSampleFlag, thePacketGroup ); |
} |
} |
return( theError ); |
} |
#pragma mark - |
#pragma mark * STANDARD COMPONENT INTERFACE |
#pragma mark - |
/* --------------------------------------------------------------------------- |
* S T A N D A R D C O M P O N E N T I N T E R F A C E |
* --------------------------------------------------------------------------- |
*/ |
/* --------------------------------------------------------------------------- |
* + CallComponentOpen() implementation |
* --------------------------------------------------------------------------- |
* |
* Allocate and initialize storage for instance variables. When a packetizer |
* is opened, it is not always called to packetize data, so this function |
* doesn't perform any allocations or time-consuming operations that are |
* needed only for packetizing sample data. The RTPMPInitialize() |
* implementation performs such operations. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Open( |
RTPMPComponentVideoInstanceData ** inGlobals, |
ComponentInstance self ) |
{ |
ComponentResult theResult = noErr; |
RTPMediaPacketizer theBase; |
inGlobals = |
REINTERPRET_CAST( RTPMPComponentVideoInstanceData ** )( |
NewHandleClear( sizeof( **inGlobals ) ) ); |
if( inGlobals ) |
{ |
( **inGlobals ).itself = self; |
( **inGlobals ).itsFinalDerivation = self; |
( **inGlobals ).itsInitialized = false; |
SetComponentInstanceStorage( self, REINTERPRET_CAST( Handle )( inGlobals ) ); |
theResult = |
OpenADefaultComponent( |
kRTPMediaPacketizerType, kRTPBaseMediaPacketizerType, &theBase ); |
if( theResult == noErr ) |
{ |
( **inGlobals ).itsBase = theBase; |
theResult = CallComponentTarget( ( **inGlobals ).itsBase, self ); |
} |
} |
else |
{ |
theResult = MemError(); |
if( theResult == noErr ) |
theResult = memFullErr; |
} |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + CallComponentClose() implementation |
* --------------------------------------------------------------------------- |
* |
* Reverse the effects of the CallComponentOpen() implementation. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Close( |
RTPMPComponentVideoInstanceData ** inGlobals, |
ComponentInstance self ) |
{ |
#pragma unused( self ) |
if( inGlobals ) |
{ |
if( ( **inGlobals ).itsBase ) |
CloseComponent( ( **inGlobals ).itsBase ); |
DisposeHandle( REINTERPRET_CAST( Handle )( inGlobals ) ); |
} |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + CallComponentVersion() implementation |
* --------------------------------------------------------------------------- |
* |
* Return the instance's version. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Version( |
RTPMPComponentVideoInstanceData ** inGlobals ) |
{ |
#pragma unused( inGlobals ) |
return( kComponentVersion ); |
} |
/* --------------------------------------------------------------------------- |
* + CallComponentTarget() implementation |
* --------------------------------------------------------------------------- |
* |
* Update the instance's inheritance graph with a new most-derived instance. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Target( |
RTPMPComponentVideoInstanceData ** inGlobals, |
ComponentInstance target ) |
{ |
ComponentResult theResult; |
if( ( **inGlobals ).itsBase ) |
theResult = ComponentSetTarget( ( **inGlobals ).itsBase, target ); |
else |
theResult = noErr; |
if( theResult == noErr ) |
( **inGlobals ).itsFinalDerivation = target; |
return( theResult ); |
} |
#pragma mark - |
#pragma mark * RTP MEDIA PACKETIZER INTERFACE |
#pragma mark - |
/* --------------------------------------------------------------------------- |
* R T P M E D I A P A C K E T I Z E R I N T E R F A C E |
* --------------------------------------------------------------------------- |
*/ |
/* --------------------------------------------------------------------------- |
* + RTPMPInitialize() implementation |
* --------------------------------------------------------------------------- |
* |
* Prepare to packetize sample data. This implementation initializes |
* instance variables that represent the packetization state. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Initialize( |
RTPMPComponentVideoInstanceData ** inGlobals, |
SInt32 inFlags ) |
{ |
ComponentResult theResult; |
if( CallComponentCanDo( ( **inGlobals ).itsBase, kRTPMPInitializeSelect ) ) |
theResult = RTPMPInitialize( ( **inGlobals ).itsBase, inFlags ); |
else |
theResult = noErr; |
if( theResult == noErr ) |
{ |
( **inGlobals ).itsPacketBuilder = NULL; |
( **inGlobals ).itsPacketSizeLimit = __kDefaultPacketSizeLimit; |
( **inGlobals ).itsPacketDurationLimit = __kDefaultPacketDurationLimit; |
ComponentVideoPayloadInitialize( &( **inGlobals ).itsPayloadHeader, 0, 0 ); |
( **inGlobals ).itsInitialized = true; |
} |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPPreflightMedia() implementation |
* --------------------------------------------------------------------------- |
* |
* Determine whether the packetizer can packetize data described by the |
* given SampleDescription. This implementation verifies that the sample |
* data is in Component Video format, and that the image has positive width |
* and height. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_PreflightMedia( |
RTPMPComponentVideoInstanceData ** inGlobals, |
OSType inMediaType, |
SampleDescriptionHandle inSampleDescription ) |
{ |
#pragma unused( inGlobals ) |
ComponentResult theResult; |
ImageDescriptionHandle theDescription; |
theDescription = REINTERPRET_CAST( ImageDescriptionHandle )( inSampleDescription ); |
if( |
inMediaType != VideoMediaType || |
( **theDescription ).cType != kComponentVideoDataFormat ) |
{ |
theResult = qtsUnsupportedDataTypeErr; |
} |
else if( ( **theDescription ).width <= 0 || ( **theDescription ).height <= 0 ) |
{ |
theResult = qtsUnsupportedFeatureErr; |
} |
else |
{ |
theResult = noErr; |
} |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetSampleData() implementation |
* --------------------------------------------------------------------------- |
* |
* Use the instance's RTPPacketBuilder to packetize the sample data described |
* by the RTPMPSampleDataParams parameter. The sample time of the data in |
* successive calls is non-decreasing. In the case of Component Video, this |
* function is called with parameters describing one frame of data at a time. |
* |
* The RTPMPSampleDataParams structure includes a SampleDescription. This |
* implementation calls __UpdateSampleDescription() to detect when the |
* SampleDescription changes and to make any updates necessary to accomodate |
* the new SampleDescription. |
* |
* The function then calls __PacketizeSampleData() to divide the data into |
* network packets using the instance's RTPPacketBuilder. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetSampleData( |
RTPMPComponentVideoInstanceData ** inGlobals, |
const RTPMPSampleDataParams * inSampleData, |
SInt32 * outFlags ) |
{ |
ComponentResult theError = noErr; |
/* Ignore requests that have no data */ |
if( inSampleData->dataLength ) |
{ |
theError = __UpdateSampleDescription( inGlobals, inSampleData ); |
if( !theError ) |
theError = __PacketizeSampleData( inGlobals, inSampleData ); |
} |
*outFlags = 0; |
return( theError ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPFlush() implementation |
* --------------------------------------------------------------------------- |
* |
* Finish any packetization in progress. This packetizer doesn't defer any |
* packetization, so its RTPMPFlush() implementation just gives its base a |
* chance to flush. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Flush( |
RTPMPComponentVideoInstanceData ** inGlobals, |
SInt32 inFlags, |
SInt32 * outFlags ) |
{ |
ComponentResult theResult; |
if( CallComponentCanDo( ( **inGlobals ).itsBase, kRTPMPFlushSelect ) ) |
{ |
theResult = RTPMPFlush( ( **inGlobals ).itsBase, inFlags, outFlags ); |
} |
else |
{ |
theResult = noErr; |
*outFlags = 0; |
} |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPReset() implementation |
* --------------------------------------------------------------------------- |
* |
* Abort any packetization in progress and prepare to packetize a new data |
* stream. This implementation reinitializes its packetization state and |
* resets its base. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_Reset( |
RTPMPComponentVideoInstanceData ** inGlobals, |
SInt32 inFlags ) |
{ |
ComponentResult theResult; |
ComponentVideoPayloadInitialize( &( **inGlobals ).itsPayloadHeader, 0, 0 ); |
if( CallComponentCanDo( ( **inGlobals ).itsBase, kRTPMPResetSelect ) ) |
theResult = RTPMPReset( ( **inGlobals ).itsBase, inFlags ); |
else |
theResult = noErr; |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetInfo() implementation |
* --------------------------------------------------------------------------- |
* |
* Return the information indicated by the selector. This implemenation |
* computes a result for the following selectors and delegates all others to |
* its base. |
* |
* |
* kRTPMPPayloadTypeInfo ioParams points to an RTPMPPayloadTypeParams |
* structure. This implementation fills in this |
* structure to indicate it uses a dynamic AVP |
* payload type. It copies its payload encoding |
* name to a buffer described by this structure. |
* |
* kRTPMPRTPTimeScaleInfo ioParams points to a TimeScale where the |
* implementation returns the clock rate, in |
* Hertz, to be used for RTP timestamps. |
* |
* kRTPMPMinPayloadSize ioParams points to a UInt32 where the |
* implementation returns the number of octets |
* needed for the fixed header and payload |
* description used by this packetizer. |
* |
* kRTPMPPayloadNameInfo ioParams points to a Str255 where the |
* implementation returns a human-readable name |
* for the payload encoding used by this |
* packetizer. |
* |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetInfo( |
RTPMPComponentVideoInstanceData ** inGlobals, |
OSType inSelector, |
void * ioParams ) |
{ |
ComponentResult theError = noErr; |
RTPMPPayloadTypeParams * thePayloadInfo; |
Str255 theEncodingName; |
switch( inSelector ) |
{ |
case kRTPMPPayloadTypeInfo: |
thePayloadInfo = STATIC_CAST( RTPMPPayloadTypeParams * )( ioParams ); |
thePayloadInfo->flags = kRTPPayloadTypeDynamicFlag; |
thePayloadInfo->payloadNumber = kRTPPayload_Unknown; |
theError = |
GetComponentIndString( |
REINTERPRET_CAST( Component )( ( **inGlobals ).itself ), |
theEncodingName, kRTPMPComponentVideoStringListResource, |
kRTPMPComponentVideoProtocolEncodingString ); |
if( !theError ) |
{ |
if( thePayloadInfo->nameLength < ( theEncodingName[ 0 ] + 1 ) ) |
{ |
theError = paramErr; |
} |
else |
{ |
BlockMoveData( |
&theEncodingName[ 1 ], thePayloadInfo->payloadName, |
theEncodingName[ 0 ] ); |
thePayloadInfo->payloadName[ theEncodingName[ 0 ] ] = '\0'; |
} |
thePayloadInfo->nameLength = theEncodingName[ 0 ] + 1; |
} |
break; |
case kRTPMPRTPTimeScaleInfo: |
*STATIC_CAST( TimeScale * )( ioParams ) = kComponentVideoRTPTimeScale; |
break; |
case kRTPMPMinPayloadSize: |
*STATIC_CAST( UInt32 * )( ioParams ) = sizeof( ComponentVideoPayload ); |
break; |
case kRTPMPPayloadNameInfo: |
theError = |
GetComponentIndString( |
REINTERPRET_CAST( Component )( ( **inGlobals ).itself ), |
STATIC_CAST( StringPtr )( ioParams ), |
kRTPMPComponentVideoStringListResource, |
kRTPMPComponentVideoHIEncodingString ); |
break; |
case kRTPMPRequiredSampleDescriptionInfo: |
case kRTPMPMinPacketDuration: |
case kRTPMPSuggestedRepeatPktCountInfo: |
case kRTPMPSuggestedRepeatPktSpacingInfo: |
case kRTPMPMaxPartialSampleSizeInfo: |
case kRTPMPPreferredBufferDelayInfo: |
default: |
theError = |
RTPMPGetInfo( ( **inGlobals ).itsBase, inSelector, ioParams ); |
break; |
} |
return( theError ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetTimeScale() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetTimeScale( |
RTPMPComponentVideoInstanceData ** inGlobals, |
TimeScale inTimeScale ) |
{ |
( **inGlobals ).itsMediaTimeScale = inTimeScale; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetTimeScale() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetTimeScale( |
RTPMPComponentVideoInstanceData ** inGlobals, |
TimeScale * outTimeScale ) |
{ |
*outTimeScale = ( **inGlobals ).itsMediaTimeScale; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetTimeBase() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetTimeBase( |
RTPMPComponentVideoInstanceData ** inGlobals, |
TimeBase inTimeBase ) |
{ |
( **inGlobals ).itsMediaTimeBase = inTimeBase; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetTimeBase() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetTimeBase( |
RTPMPComponentVideoInstanceData ** inGlobals, |
TimeBase * outTimeBase ) |
{ |
*outTimeBase = ( **inGlobals ).itsMediaTimeBase; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPHasCharacteristic() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_HasCharacteristic( |
RTPMPComponentVideoInstanceData ** inGlobals, |
OSType inSelector, |
Boolean * outHasIt ) |
{ |
ComponentResult theResult = noErr; |
switch( inSelector ) |
{ |
case kRTPMPNoSampleDataRequiredCharacteristic: |
*outHasIt = true; |
break; |
case kRTPMPPartialSamplesRequiredCharacteristic: |
case kRTPMPHasUserSettingsDialogCharacteristic: |
case kRTPMPPrefersReliableTransportCharacteristic: |
case kRTPMPRequiresOutOfBandDimensionsCharacteristic: |
*outHasIt = false; |
break; |
default: |
theResult = |
RTPMPHasCharacteristic( ( **inGlobals ).itsBase, inSelector, outHasIt ); |
break; |
} |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetPacketBuilder() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetPacketBuilder( |
RTPMPComponentVideoInstanceData ** inGlobals, |
ComponentInstance inPacketBuilder ) |
{ |
ComponentResult theError; |
SInt32 theFlags; |
if( ( **inGlobals ).itsInitialized && ( **inGlobals ).itsPacketBuilder ) |
theError = RTPMPFlush( ( **inGlobals ).itsFinalDerivation, 0, &theFlags ); |
else |
theError = noErr; |
if( !theError ) |
( **inGlobals ).itsPacketBuilder = inPacketBuilder; |
return( theError ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetPacketBuilder() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetPacketBuilder( |
RTPMPComponentVideoInstanceData ** inGlobals, |
ComponentInstance * outPacketBuilder ) |
{ |
*outPacketBuilder = ( **inGlobals ).itsPacketBuilder; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetMediaType() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetMediaType( |
RTPMPComponentVideoInstanceData ** inGlobals, |
OSType inMediaType ) |
{ |
#pragma unused( inGlobals ) |
ComponentResult theResult; |
if( inMediaType == VideoMediaType ) |
theResult = noErr; |
else |
theResult = qtsBadDataErr; |
return( theResult ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetMediaType() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetMediaType( |
RTPMPComponentVideoInstanceData ** inGlobals, |
OSType * outMediaType ) |
{ |
#pragma unused(inGlobals) |
*outMediaType = VideoMediaType; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetMaxPacketSize() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetMaxPacketSize( |
RTPMPComponentVideoInstanceData ** inGlobals, |
UInt32 inMaxPacketSize ) |
{ |
( **inGlobals ).itsPacketSizeLimit = inMaxPacketSize; |
__UpdateDataSizes( inGlobals ); |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetMaxPacketSize() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetMaxPacketSize( |
RTPMPComponentVideoInstanceData ** inGlobals, |
UInt32 * outMaxPacketSize ) |
{ |
*outMaxPacketSize = ( **inGlobals ).itsPacketSizeLimit; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPSetMaxPacketDuration() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_SetMaxPacketDuration( |
RTPMPComponentVideoInstanceData ** inGlobals, |
UInt32 inMaxPacketDuration ) |
{ |
( **inGlobals ).itsPacketDurationLimit = inMaxPacketDuration; |
return( noErr ); |
} |
/* --------------------------------------------------------------------------- |
* + RTPMPGetMaxPacketDuration() implementation |
* --------------------------------------------------------------------------- |
*/ |
EXTERN_API( ComponentResult ) |
RTPMPComponentVideo_GetMaxPacketDuration( |
RTPMPComponentVideoInstanceData ** inGlobals, |
UInt32 * outMaxPacketDuration ) |
{ |
*outMaxPacketDuration = ( **inGlobals ).itsPacketDurationLimit; |
return( noErr ); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14