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 );
}
Beispiel #2
0
ComponentResult XMRTPH264Packetizer_SetSampleData(XMRTPH264PacketizerGlobals globals,
                                                  const RTPMPSampleDataParams *sampleData,
                                                  SInt32 *outFlags)
{	
  UInt32 maxPacketLength = globals->maxPacketSize_Hard;
  if (globals->useNonInterleavedMode == true) {
    maxPacketLength = globals->maxPacketSize_Soft;
  }
  const UInt8 *data = sampleData->data;
  UInt32 dataLength = sampleData->dataLength;
  UInt32 index = 0;
  ComponentInstance packetBuilder = globals->packetBuilder;
	
  RTPPacketGroupRef packetGroupRef;
	
  RTPPBBeginPacketGroup(packetBuilder,
                        0,
                        sampleData->timeStamp,
                        &packetGroupRef);
	
  // Check whether SPS and PPS units should be sent
  if ((sampleData->flags & 1) != 0) {
    RTPPacketRef packetRef;
    RTPPBBeginPacket(packetBuilder,
                     0,
                     packetGroupRef,
                     globals->spsAtomLength,
                     &packetRef);
    RTPPBAddPacketLiteralData(packetBuilder,
                              0,
                              packetGroupRef,
                              packetRef,
                              globals->spsAtomData,
                              globals->spsAtomLength,
                              NULL);
    RTPPBEndPacket(packetBuilder,
                   0,
                   packetGroupRef,
                   packetRef,
                   0,
                   0);
    RTPPBBeginPacket(packetBuilder,
                     0,
                     packetGroupRef,
                     globals->ppsAtomLength,
                     &packetRef);
    RTPPBAddPacketLiteralData(packetBuilder,
                              0,
                              packetGroupRef,
                              packetRef,
                              globals->ppsAtomData,
                              globals->ppsAtomLength,
                              NULL);
    RTPPBEndPacket(packetBuilder,
                   0,
                   packetGroupRef,
                   packetRef,
                   0,
                   0);
  }
	
  do {
    // Getting the size of this NAL unit
    UInt32 *lengthPtr = (UInt32 *)&(data[index]);
    index += 4;
    UInt32 nalLength = ntohl(lengthPtr[0]);
		
    // If the NAL does not fit within one single packet,
    // we have to use FU-A packets, which are only available
    // in the non-interleaved mode
    if (nalLength > maxPacketLength && globals->useNonInterleavedMode == true) {
      // Send some FU-A packets
      UInt8 nri = (data[index] >> 5) & 0x03;
      UInt8 type = data[index] & 0x1f;
    
      UInt32 remainingLength = nalLength;
      index += 1;
      remainingLength -= 1;
		
      while (remainingLength > 0) {
        UInt8 s = 0;
        UInt8 e = 0;
				
        UInt32 sendDataLength = maxPacketLength-2;
			
        if (remainingLength == nalLength-1) {
          s = 1;
        } else if (remainingLength <= (maxPacketLength - 2)) {
          e = 1;
          sendDataLength = remainingLength;
        }
				
        UInt8 header[2];
				
        header[0] = 0;
        header[0] |= (nri << 5);
        header[0] |= 28;
        header[1] = 0;
        header[1] = (s << 7);
        header[1] |= (e << 6);
        header[1] |= type;
		
        RTPPacketRef packetRef;
        RTPPBBeginPacket(packetBuilder,
                         0,
                         packetGroupRef,
                         sendDataLength+2,
                         &packetRef);
					
        RTPPBAddPacketLiteralData(packetBuilder,
                                  0,
                                  packetGroupRef,
                                  packetRef,
                                  header,
                                  2,
                                  NULL);
					
        RTPPBAddPacketSampleData(packetBuilder,
                                 0,
                                 packetGroupRef,
                                 packetRef,
                                 (RTPMPSampleDataParams *)sampleData,
                                 index,
                                 sendDataLength,
                                 NULL);
					
        index += sendDataLength;
        remainingLength -= sendDataLength;
					
        SInt32 flags = 0;
        if (index >= dataLength) {
          flags = 1;
        }
        RTPPBEndPacket(packetBuilder,
                       flags,
                       packetGroupRef,
                       packetRef,
                       0,
                       0);
      }
    } else if (nalLength > maxPacketLength) {
      // Generating a packet of short length indicates to the subsystem
      // to drop this packet and increment the RTP Sequence Number by one
      RTPPacketRef packetRef;
      RTPPBBeginPacket(packetBuilder,
                       0,
                       packetGroupRef,
                       0,
                       &packetRef);
			
      UInt8 empty[2];
      empty[0] = 0;
      empty[1] = 0;
      RTPPBAddPacketLiteralData(packetBuilder,
                                0,
                                packetGroupRef,
                                packetRef,
                                empty,
                                2,
                                NULL);
			
      RTPPBEndPacket(packetBuilder,
                     0,
                     packetGroupRef,
                     packetRef,
                     0,
                     0);
      index += nalLength;
    } else {
      RTPPacketRef packetRef;
      RTPPBBeginPacket(packetBuilder,
                       0,
                       packetGroupRef,
                       nalLength,
                       &packetRef);
      RTPPBAddPacketSampleData(packetBuilder,
                               0,
                               packetGroupRef,
                               packetRef,
                               (RTPMPSampleDataParams *)sampleData,
                               index,
                               nalLength,
                               NULL);
      index += nalLength;
			
      SInt32 flags = 0;
      if (index >= dataLength) {
        flags = 1;
      }
			
      RTPPBEndPacket(packetBuilder,
                     flags,
                     packetGroupRef,
                     packetRef,
                     0,
                     0);
    }
		
  } while (index < dataLength);