Example #1
0
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;
	}
Example #2
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;
}