//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // SendFrameArrivedMessage() //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void ClientStream::SendFrameArrivedMessage(mach_port_t& recipient, Frame& frame) { // Setup the message FrameArrivedMessage message = { { MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | MACH_MSGH_BITS_COMPLEX, // mHeader.msgh_bits sizeof(FrameArrivedMessage), // mHeader.msgh_size recipient, // mHeader.msgh_remote_port MACH_PORT_NULL, // mHeader.msgh_local_port 0, // mHeader.msgh_reserved kFrameArrived // mHeader.msgh_id }, { 1 // mBody.msgh_descriptor_count }, { // The mach_msg_ool_descriptor_t structure is layed out differently for 32 vs 64 bit architectures, so it is not intialiazed here }, frame.GetFrameType(), // mFrameType frame.GetHostTime(), // mHostTime frame.GetTimingInfo(), // mTimingInfo frame.GetDiscontinuityFlags() | GetDiscontinuityFlags(), // mDiscontinuityFlags frame.GetDroppedFrameCount(), // mDroppedFrameCount frame.GetFirstFrameTime() // mFirstFrameTime }; // Initialize the mach_msg_ool_descriptor_t portion of the message message.mDescriptor.address = frame.Get(); message.mDescriptor.size = frame.Size(); message.mDescriptor.deallocate = false; message.mDescriptor.copy = MACH_MSG_VIRTUAL_COPY; message.mDescriptor.type = MACH_MSG_OOL_DESCRIPTOR; // If this frame or the ClientStream has any "hard" discontinuities in it, "extended duration" timing can't be used if (~kCMIOSampleBufferDiscontinuityFlag_DurationWasExtended & (frame.GetDiscontinuityFlags() | GetDiscontinuityFlags())) mExtendedFrameHostTime = 0; // Use the "extended duration" timing if needed (indicated by a non-zero value for mExtendedFrameHostTime) if (0 != mExtendedFrameHostTime) { // Use the extended frame host & cycle time message.mHostTime = mExtendedFrameHostTime; // Use the extended frame timing info & add the current frame's duration to the extended frame's duration message.mTimingInfo = mExtendedFrameTimingInfo; message.mTimingInfo.duration = CMTimeAdd(message.mTimingInfo.duration, frame.GetTimingInfo().duration); // Indicate this frame has an extended duration message.mDiscontinuityFlags |= kCMIOSampleBufferDiscontinuityFlag_DurationWasExtended; } // Send the message mach_msg_return_t err = mach_msg(&message.mHeader, MACH_SEND_MSG | MACH_SEND_TIMEOUT, message.mHeader.msgh_size, 0, MACH_PORT_NULL, 15, MACH_PORT_NULL); if (MACH_MSG_SUCCESS == err) { // The message was sent successfully, so clear the discontinuity flags SetDiscontinuityFlags(kCMIOSampleBufferNoDiscontinuities); // Reset the extended frame host time to 0 to signify that no extension is needed mExtendedFrameHostTime = 0; } else { DebugMessage("SendFrameArrivedMessage() - Error sending frame to port %d 0x%08X", recipient, err); // Something went wrong, so destroy the message so that all of its resources will be properly released mach_msg_destroy(&message.mHeader); // Update the recipient since it might have a new value since the send failed recipient = message.mHeader.msgh_remote_port; // Try and use "extended duration" timing if this frame and the ClientStream lacks any "hard" discontinuities if (~kCMIOSampleBufferDiscontinuityFlag_DurationWasExtended & (frame.GetDiscontinuityFlags() | GetDiscontinuityFlags())) { // The were hard discontinuities, so update the ClientStream's discontinuity flags so they logical sum can be passed on with the next frame SetDiscontinuityFlags(GetDiscontinuityFlags() | frame.GetDiscontinuityFlags() | kCMIOSampleBufferDiscontinuityFlag_StreamDiscontinuity); } else { // Rather than mark a "hard" discontinuity, remember the frame's duration and so the NEXT frame's can be extended accordingly if (0 == mExtendedFrameHostTime) { // This is the first extension needed, so use this frame's host & cycle time for the next frame mExtendedFrameHostTime = frame.GetHostTime(); mExtendedFrameTimingInfo = frame.GetTimingInfo(); } else { // An extension is already taking place, so simply add this frame's duration to the extended frame's duration mExtendedFrameTimingInfo.duration = CMTimeAdd(mExtendedFrameTimingInfo.duration, frame.GetTimingInfo().duration); } } } // Remove this client from the set of the native frame needs to message frame.RemoveClient(mClient); }