int LayoutScale::Process(const vector<string>& args) { if (args.size() != 8) throw LayoutScaleArgsErr(); auto_ptr<TLayParseLayout> sourceLayout(TLayParseLayout::Parse(args[2])); int sourceWidth = CdlTkUtil::ParseInt(args[3]); int sourceHeight = CdlTkUtil::ParseInt(args[4]); string destLayout = args[5]; int destWidth = CdlTkUtil::ParseInt(args[6]); int destHeight = CdlTkUtil::ParseInt(args[7]); LayoutScale scale(*sourceLayout, sourceWidth, sourceHeight, destLayout, destWidth, destHeight); scale.Run(); return 0; }
CCoreAudioMixMap *CCoreAudioMixMap::CreateMixMap(CAUOutputDevice *audioUnit, AEAudioFormat &format, AudioChannelLayoutTag layoutTag) { if (!audioUnit) return NULL; AudioStreamBasicDescription fmt; AudioStreamBasicDescription inputFormat; // get the stream input format audioUnit->GetFormatDesc(format, &inputFormat, &fmt); unsigned int channels = format.m_channelLayout.Count(); CAEChannelInfo channelLayout = format.m_channelLayout; bool hasLFE = false; // Convert XBMC input channel layout format to CoreAudio layout format AudioChannelLayout* pInLayout = (AudioChannelLayout*)malloc(sizeof(AudioChannelLayout) + sizeof(AudioChannelDescription) * channels); pInLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; pInLayout->mChannelBitmap = 0; pInLayout->mNumberChannelDescriptions = channels; for (unsigned int chan=0; chan < channels; chan++) { AudioChannelDescription* pDesc = &pInLayout->mChannelDescriptions[chan]; // Convert from XBMC channel tag to CoreAudio channel tag pDesc->mChannelLabel = g_LabelMap[(unsigned int)channelLayout[chan]]; pDesc->mChannelFlags = kAudioChannelFlags_AllOff; pDesc->mCoordinates[0] = 0.0f; pDesc->mCoordinates[1] = 0.0f; pDesc->mCoordinates[2] = 0.0f; if (pDesc->mChannelLabel == kAudioChannelLabel_LFEScreen) hasLFE = true; } // HACK: Fix broken channel layouts coming from some aac sources // that include rear channel but no side channels. // 5.1 streams should include front and side channels. // Rear channels are added by 6.1 and 7.1, so any 5.1 // source that claims to have rear channels is wrong. if (inputFormat.mChannelsPerFrame == 6 && hasLFE) { // Check for 5.1 configuration (as best we can without getting too silly) for (unsigned int chan=0; chan < inputFormat.mChannelsPerFrame; chan++) { AudioChannelDescription* pDesc = &pInLayout->mChannelDescriptions[chan]; if (pDesc->mChannelLabel == kAudioChannelLabel_LeftSurround || pDesc->mChannelLabel == kAudioChannelLabel_RightSurround) break; // Required condition cannot be true if (pDesc->mChannelLabel == kAudioChannelLabel_LeftSurroundDirect) { // Change [Back Left] to [Side Left] pDesc->mChannelLabel = kAudioChannelLabel_LeftSurround; CLog::Log(LOGINFO, "CCoreAudioGraph::CreateMixMap: " "Detected faulty input channel map...fixing(Back Left-->Side Left)"); } if (pDesc->mChannelLabel == kAudioChannelLabel_RightSurroundDirect) { // Change [Back Left] to [Side Left] pDesc->mChannelLabel = kAudioChannelLabel_RightSurround; CLog::Log(LOGINFO, "CCoreAudioGraph::CreateMixMap: " "Detected faulty input channel map...fixing(Back Right-->Side Right)"); } } } CCoreAudioChannelLayout sourceLayout(*pInLayout); free(pInLayout); pInLayout = NULL; std::string strInLayout; CLog::Log(LOGDEBUG, "CCoreAudioGraph::CreateMixMap: Source Stream Layout: %s", CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)sourceLayout, strInLayout)); // Get User-Configured (XBMC) Speaker Configuration AudioChannelLayout guiLayout; guiLayout.mChannelLayoutTag = layoutTag; CCoreAudioChannelLayout userLayout(guiLayout); std::string strUserLayout; CLog::Log(LOGDEBUG, "CCoreAudioGraph::CreateMixMap: User-Configured Speaker Layout: %s", CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)userLayout, strUserLayout)); // Get OS-Configured (Audio MIDI Setup) Speaker Configuration (Channel Layout) CCoreAudioChannelLayout deviceLayout; if (!audioUnit->GetPreferredChannelLayout(deviceLayout)) return NULL; // When all channels on the output device are unknown take the gui layout //if(deviceLayout.AllChannelUnknown()) // deviceLayout.CopyLayout(guiLayout); std::string strOutLayout; CLog::Log(LOGDEBUG, "CCoreAudioGraph::CreateMixMap: Output Device Layout: %s", CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)deviceLayout, strOutLayout)); // TODO: // Reconcile the OS and GUI layout configurations. Clamp to the minimum number of speakers // For each OS-defined output, see if it exists in the GUI configuration // If it does, add it to the 'union' layout (bitmap?) // User may have configured 5.1 in GUI, but only 2.0 in OS // Resulting layout would be {FL, FR} // User may have configured 2.0 in GUI, and 5.1 in OS // Resulting layout would be {FL, FR} // Correct any configuration incompatibilities //if (CCoreAudioChannelLayout::GetChannelCountForLayout(guiLayout) < CCoreAudioChannelLayout::GetChannelCountForLayout(deviceLayout)) // deviceLayout.CopyLayout(guiLayout); // TODO: Skip matrix mixer if input/output are compatible AudioChannelLayout* layoutCandidates[] = {(AudioChannelLayout*)deviceLayout, (AudioChannelLayout*)userLayout, NULL}; // Try to construct a mapping matrix for the mixer. // Work through the layout candidates and see if any will work CCoreAudioMixMap *mixMap = new CCoreAudioMixMap(); for (AudioChannelLayout** pLayout = layoutCandidates; *pLayout != NULL; pLayout++) { mixMap->Rebuild(*sourceLayout, **pLayout); if (mixMap->IsValid()) break; } return mixMap; }