@@ -68,6 +68,8 @@ namespace adaptive
6868
6969 void AdaptiveTree::PostOpen (const UTILS ::PROPERTIES ::KodiProperties& kodiProps)
7070 {
71+ FixStreamsFlags (kodiProps);
72+
7173 // A manifest can provide live delay value, if not so we use our default
7274 // value of 16 secs, this is needed to ensure an appropriate playback,
7375 // an add-on can override the delay to try fix edge use cases
@@ -374,4 +376,148 @@ namespace adaptive
374376 m_cvWait.notify_all ();
375377 }
376378
379+ void AdaptiveTree::FixStreamsFlags (const UTILS ::PROPERTIES ::KodiProperties& kodiProps)
380+ {
381+ // Add-ons can override subtitles "default" flag to streams
382+ if (!kodiProps.m_subtitleLangDefault .empty ())
383+ {
384+ for (auto & period : m_periods)
385+ {
386+ for (auto & adpSet : period->GetAdaptationSets ())
387+ {
388+ if (adpSet->GetStreamType () == StreamType::SUBTITLE )
389+ {
390+ adpSet->SetIsDefault (
391+ STRING::CompareNoCase (adpSet->GetLanguage (), kodiProps.m_subtitleLangDefault ));
392+ }
393+ }
394+ }
395+ }
396+
397+ // Add-ons can override audio "original" flag to streams
398+ if (!kodiProps.m_audioLangOriginal .empty ())
399+ {
400+ for (auto & period : m_periods)
401+ {
402+ for (auto & adpSet : period->GetAdaptationSets ())
403+ {
404+ if (adpSet->GetStreamType () == StreamType::AUDIO )
405+ {
406+ adpSet->SetIsOriginal (
407+ STRING::CompareNoCase (adpSet->GetLanguage (), kodiProps.m_audioLangOriginal ));
408+ }
409+ }
410+ }
411+ }
412+
413+ // Audio streams "default" flag customization / workaround
414+
415+ // Manifest of video services dont always set appropriately the default stream flag and also
416+ // the manifest "default" stream flag dont have always the same meaning of Kodi track "default" flag,
417+ // this can lead to wrong audio track selected when playback start.
418+ // A good example is when "Media default" Kodi audio setting is set, where kodi expects just
419+ // a single track with the default flag.
420+ // Another problem is when video services provide multiple audio streams with same language code
421+ // but differents channels, most of the times we can have 1 stereo and 1 multichannels
422+ // stream with same language code, rarely there are multi-codecs with same channels,
423+ // but we simplify by ignoring codec types.
424+
425+ // To allow Kodi VP to do a better track auto-selection we need:
426+ // - Set default flag to a single track only
427+ // - Set default flag to stereo or multichannels track, not both
428+ // to do this its needed that an addon specify what to do because C++ interface dont provide
429+ // access to kodi language settings where python can do it, then we cant automatize it.
430+ const std::string langCodeDef = kodiProps.m_audioLangDefault ;
431+ const std::string langCodeOrig = kodiProps.m_audioLangOriginal ;
432+
433+ if (!langCodeDef.empty () || !langCodeOrig.empty ())
434+ {
435+ bool isDefaultStereo = kodiProps.m_audioPrefStereo ; // add-on based setting
436+
437+ for (auto & period : m_periods)
438+ {
439+ auto & adpSets = period->GetAdaptationSets ();
440+ auto itAudioStream = adpSets.cend ();
441+
442+ // Try give priority to "impaired" streams
443+ if (kodiProps.m_audioPrefType == " impaired" )
444+ {
445+ if (isDefaultStereo)
446+ {
447+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, true , true );
448+ if (itAudioStream == adpSets.cend ()) // No stereo stream, find multichannels
449+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, false , true );
450+ }
451+ else
452+ {
453+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, false , true );
454+ if (itAudioStream == adpSets.cend ()) // No multichannels stream, find stereo
455+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, true , true );
456+ }
457+
458+ // No stream found, try find a "impaired" stream with the "original" language code
459+ if (itAudioStream == adpSets.cend () && !langCodeOrig.empty ())
460+ {
461+ if (isDefaultStereo)
462+ {
463+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, true , true );
464+ if (itAudioStream == adpSets.cend ()) // No stereo stream, find multichannels
465+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, false , true );
466+ }
467+ else
468+ {
469+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, false , true );
470+ if (itAudioStream == adpSets.cend ()) // No multichannels stream, find stereo
471+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, true , true );
472+ }
473+ }
474+ }
475+
476+ // Try find a stream with specified lang code
477+ if (kodiProps.m_audioPrefType != " original" && itAudioStream == adpSets.cend () &&
478+ !langCodeDef.empty ())
479+ {
480+ if (isDefaultStereo)
481+ {
482+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, true );
483+ if (itAudioStream == adpSets.cend ()) // No stereo stream, find multichannels
484+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, false );
485+ }
486+ else
487+ {
488+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, false );
489+ if (itAudioStream == adpSets.cend ()) // No multichannels stream, find stereo
490+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeDef, true );
491+ }
492+ }
493+
494+ // No stream found, try find a stream with the "original" language code
495+ if (itAudioStream == adpSets.cend () && !langCodeOrig.empty ())
496+ {
497+ if (isDefaultStereo)
498+ {
499+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, true );
500+ if (itAudioStream == adpSets.cend ()) // No stereo stream, find multichannels
501+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, false );
502+ }
503+ else
504+ {
505+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, false );
506+ if (itAudioStream == adpSets.cend ()) // No multichannels stream, find stereo
507+ itAudioStream = CAdaptationSet::FindAudioAdpSet (adpSets, langCodeOrig, true );
508+ }
509+ }
510+
511+ // Update "default" flags
512+ if (itAudioStream != adpSets.cend ())
513+ {
514+ for (auto & adpSet : adpSets)
515+ {
516+ adpSet->SetIsDefault (adpSet.get () == itAudioStream->get ());
517+ }
518+ }
519+ }
520+ }
521+ }
522+
377523 } // namespace adaptive
0 commit comments