Skip to content

Commit

Permalink
[HLSTree] Improved GetAudioCodec easier to maintain
Browse files Browse the repository at this point in the history
  • Loading branch information
CastagnaIT committed Jul 20, 2023
1 parent 94e035d commit 46380c7
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 29 deletions.
44 changes: 15 additions & 29 deletions src/parser/HLSTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,35 +101,21 @@ ContainerType DetectContainerTypeFromExt(std::string_view extension)
return ContainerType::INVALID;
}

// \brief Workaround to get audio codec from CODECS attribute list
// \brief Get the first audio codec string from CODECS attribute list
std::string GetAudioCodec(std::string_view codecs)
{
//! @todo: this way to get the audio codec is inappropriate and can lead to bad playback
//! this because CODECS attribute its optionals and not guarantee to provide full codec list
//! the codec format should be provided by MP4 demuxer

// The codec search must follow exactly the following order, this is currently the best workaround
// to make multi-channel audio formats work, but since CODECS attribute is unreliable
// this workaround can still cause playback problems
if (codecs.find(CODEC::FOURCC_EC_3) != std::string::npos)
return CODEC::FOURCC_EC_3;
else if (codecs.find(CODEC::FOURCC_AC_3) != std::string::npos)
return CODEC::FOURCC_AC_3;
else
return CODEC::FOURCC_MP4A;
}
// \brief Workaround to get audio codec from representation codecs list
std::string GetAudioCodec(const PLAYLIST::CRepresentation* repr)
{
const auto& codecs = repr->GetCodecs();
if (CODEC::Contains(codecs, CODEC::FOURCC_EC_3))
return CODEC::FOURCC_EC_3;
else if (CODEC::Contains(codecs, CODEC::FOURCC_AC_3))
return CODEC::FOURCC_AC_3;
else
return CODEC::FOURCC_MP4A;
// Some manifests can provide CODECS attribute with more audio codecs
// it seems that usually the first in order of apparence is the one referring to the specified
// AUDIO group attribute, so we return the first one found
// e.g. CODECS="dvh1.05.01,ec-3,mp4a.40.2", ..., AUDIO="eac-3"
const std::vector<std::string> list = STRING::SplitToVec(codecs, ',');
for (const std::string& codecStr : list)
{
if (CODEC::IsAudio(codecStr))
return codecStr;
}
return codecs.data();
}

} // unnamed namespace

adaptive::CHLSTree::CHLSTree(const CHLSTree& left) : AdaptiveTree(left)
Expand Down Expand Up @@ -1019,15 +1005,15 @@ bool adaptive::CHLSTree::ParseManifest(const std::string& data)
repr->SetTimescale(1000000);

// Try to get the codecs from first representation
std::string codec = CODEC::FOURCC_MP4A;
std::set<std::string> codecs{CODEC::FOURCC_MP4A};
auto& adpSets = period->GetAdaptationSets();
if (!adpSets.empty())
{
auto& reprs = adpSets[0]->GetRepresentations();
if (!reprs.empty())
codec = GetAudioCodec(reprs[0].get());
codecs = reprs[0]->GetCodecs();
}
repr->AddCodecs(codec);
repr->AddCodecs(codecs);
repr->SetAudioChannels(2);
repr->SetIsIncludedStream(true);

Expand Down
15 changes: 15 additions & 0 deletions src/utils/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,18 @@ std::string UTILS::CODEC::GetVideoDesc(const std::set<std::string>& list)
}
return "";
}

bool UTILS::CODEC::IsAudio(std::string_view codec)
{
for (const auto fourcc : CODEC::AUDIO_FOURCC_LIST)
{
if (STRING::Contains(codec, fourcc))
return true;
}
for (const auto name : CODEC::AUDIO_NAME_LIST)
{
if (STRING::Contains(codec, name))
return true;
}
return false;
}
16 changes: 16 additions & 0 deletions src/utils/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#pragma once

#include <array>
#include <cstdint>
#include <ctime> // time
#include <map>
Expand Down Expand Up @@ -62,6 +63,9 @@ constexpr char* NAME_EAC3 = "eac3"; // Enhanced AC-3
constexpr char* NAME_OPUS = "opus";
constexpr char* NAME_VORBIS = "vorbis";

constexpr std::array AUDIO_NAME_LIST = {NAME_AAC, NAME_DTS, NAME_AC3,
NAME_EAC3, NAME_OPUS, NAME_VORBIS};

// Subtitles definitions

constexpr char* NAME_SRT = "srt";
Expand Down Expand Up @@ -97,6 +101,11 @@ constexpr char* FOURCC_VORB3 = "vor3"; // Vorbis 3
constexpr char* FOURCC_VORB3P = "vo3+"; // Vorbis 3+
constexpr char* FOURCC_DTS_ = "dts"; // Generic prefix for all dts* fourcc, e.g. dtsx

constexpr std::array AUDIO_FOURCC_LIST = {FOURCC_MP4A, FOURCC_AAC_, FOURCC_AACL,
FOURCC_AC_3, FOURCC_EC_3, FOURCC_OPUS, FOURCC_VORB, FOURCC_VORB1,
FOURCC_VORB1P, FOURCC_VORB2, FOURCC_VORB2P, FOURCC_VORB3,
FOURCC_VORB3P, FOURCC_DTS_};

// Fourcc subtitles definitions

constexpr char* FOURCC_WVTT = "wvtt"; // WebVTT
Expand Down Expand Up @@ -150,6 +159,13 @@ bool Contains(const std::set<std::string>& list, std::string_view codec, std::st
*/
std::string GetVideoDesc(const std::set<std::string>& list);

/*!
* \brief Determines if the codec string is of type audio, regardless of whether it is a name or fourcc.
* \param codec The codec string
* \return True if it is audio type, otherwise false
*/
bool IsAudio(std::string_view codec);

}

} // namespace UTILS

0 comments on commit 46380c7

Please sign in to comment.