Skip to content

Commit

Permalink
[codechandler] Add audio codec handler
Browse files Browse the repository at this point in the history
  • Loading branch information
CastagnaIT committed Jul 19, 2023
1 parent 7f80b72 commit b09c6d5
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 124 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ set(ADP_SOURCES
src/AdaptiveByteStream.cpp
src/main.cpp
src/codechandler/CodecHandler.cpp
src/codechandler/AudioCodecHandler.cpp
src/codechandler/AV1CodecHandler.cpp
src/codechandler/AVCCodecHandler.cpp
src/codechandler/HEVCCodecHandler.cpp
src/codechandler/MPEGCodecHandler.cpp
src/codechandler/TTMLCodecHandler.cpp
src/codechandler/VP9CodecHandler.cpp
src/codechandler/WebVTTCodecHandler.cpp
Expand Down Expand Up @@ -77,10 +77,10 @@ set(ADP_HEADERS
src/oscompat.h
src/SSD_dll.h
src/codechandler/CodecHandler.h
src/codechandler/AudioCodecHandler.h
src/codechandler/AV1CodecHandler.h
src/codechandler/AVCCodecHandler.h
src/codechandler/HEVCCodecHandler.h
src/codechandler/MPEGCodecHandler.h
src/codechandler/TTMLCodecHandler.h
src/codechandler/VP9CodecHandler.h
src/codechandler/WebVTTCodecHandler.h
Expand Down
80 changes: 80 additions & 0 deletions src/codechandler/AudioCodecHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2022 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/

#include "AudioCodecHandler.h"

#include "../utils/Utils.h"

using namespace UTILS;

AudioCodecHandler::AudioCodecHandler(AP4_SampleDescription* sd) : CodecHandler(sd)
{
if (m_sampleDescription->GetFormat() == AP4_SAMPLE_FORMAT_MP4A)
{
// Get extradata for types like aac
AP4_MpegSampleDescription* mpegSd =
AP4_DYNAMIC_CAST(AP4_MpegSampleDescription, m_sampleDescription);
m_extraData.SetData(mpegSd->GetDecoderInfo().GetData(), mpegSd->GetDecoderInfo().GetDataSize());
}
}

bool AudioCodecHandler::GetInformation(kodi::addon::InputstreamInfo& info)
{
bool isChanged{false};

if (m_sampleDescription->GetType() == AP4_SampleDescription::TYPE_MPEG)
{
std::string codecName;

switch (static_cast<AP4_MpegSampleDescription*>(m_sampleDescription)->GetObjectTypeId())
{
case AP4_OTI_MPEG4_AUDIO:
case AP4_OTI_MPEG2_AAC_AUDIO_MAIN:
case AP4_OTI_MPEG2_AAC_AUDIO_LC:
case AP4_OTI_MPEG2_AAC_AUDIO_SSRP:
codecName = CODEC::NAME_AAC;
break;
case AP4_OTI_DTS_AUDIO:
case AP4_OTI_DTS_HIRES_AUDIO:
case AP4_OTI_DTS_MASTER_AUDIO:
case AP4_OTI_DTS_EXPRESS_AUDIO:
codecName = CODEC::NAME_DTS;
break;
case AP4_OTI_AC3_AUDIO:
codecName = CODEC::NAME_AC3;
break;
case AP4_OTI_EAC3_AUDIO:
codecName = CODEC::NAME_EAC3;
break;
}
if (!codecName.empty())
isChanged = UpdateInfoCodecName(info, codecName.c_str());
}

if (AP4_AudioSampleDescription* audioSd =
AP4_DYNAMIC_CAST(AP4_AudioSampleDescription, m_sampleDescription))
{
if (audioSd->GetChannelCount() > 0 && audioSd->GetChannelCount() != info.GetChannels())
{
info.SetChannels(audioSd->GetChannelCount());
isChanged |= true;
}
if (audioSd->GetSampleRate() > 0 && audioSd->GetSampleRate() != info.GetSampleRate())
{
info.SetSampleRate(audioSd->GetSampleRate());
isChanged |= true;
}
if (audioSd->GetSampleSize() > 0 && audioSd->GetSampleSize() != info.GetBitsPerSample())
{
info.SetBitsPerSample(audioSd->GetSampleSize());
isChanged |= true;
}
}

return isChanged;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@

#include "CodecHandler.h"

class ATTR_DLL_LOCAL MPEGCodecHandler : public CodecHandler
// \brief Generic audio codec handler
class ATTR_DLL_LOCAL AudioCodecHandler : public CodecHandler
{
public:
MPEGCodecHandler(AP4_SampleDescription* sd);
AudioCodecHandler(AP4_SampleDescription* sd);

bool GetInformation(kodi::addon::InputstreamInfo& info) override;
};
52 changes: 15 additions & 37 deletions src/codechandler/CodecHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,27 @@ constexpr const char* NETFLIX_FRAMERATE_UUID = "NetflixFrameRate";

bool CodecHandler::GetInformation(kodi::addon::InputstreamInfo& info)
{
AP4_GenericAudioSampleDescription* audioSampleDescription(nullptr);
if (m_sampleDescription)
if (m_sampleDescription->GetType() != AP4_SampleDescription::Type::TYPE_SUBTITLES &&
m_sampleDescription->GetType() != AP4_SampleDescription::Type::TYPE_UNKNOWN)
{
if ((audioSampleDescription =
dynamic_cast<AP4_GenericAudioSampleDescription*>(m_sampleDescription)))
// Netflix Framerate
AP4_Atom* atom;
AP4_UnknownUuidAtom* nxfr;
atom = m_sampleDescription->GetDetails().GetChild(
reinterpret_cast<const AP4_UI08*>(NETFLIX_FRAMERATE_UUID));
if (atom && (nxfr = dynamic_cast<AP4_UnknownUuidAtom*>(atom)) &&
nxfr->GetData().GetDataSize() == 10)
{
if ((info.GetChannels() == 0 &&
audioSampleDescription->GetChannelCount() != info.GetChannels()) ||
(info.GetSampleRate() == 0 &&
audioSampleDescription->GetSampleRate() != info.GetSampleRate()) ||
(info.GetBitsPerSample() == 0 &&
audioSampleDescription->GetSampleSize() != info.GetBitsPerSample()))
unsigned int fpsRate = nxfr->GetData().GetData()[7] | nxfr->GetData().GetData()[6] << 8;
unsigned int fpsScale = nxfr->GetData().GetData()[9] | nxfr->GetData().GetData()[8] << 8;

if (info.GetFpsScale() != fpsScale || info.GetFpsRate() != fpsRate)
{
if (info.GetChannels() == 0)
info.SetChannels(audioSampleDescription->GetChannelCount());
if (info.GetSampleRate() == 0)
info.SetSampleRate(audioSampleDescription->GetSampleRate());
if (info.GetBitsPerSample() == 0)
info.SetBitsPerSample(audioSampleDescription->GetSampleSize());
info.SetFpsScale(fpsScale);
info.SetFpsRate(fpsRate);
return true;
}
}
else
{
//Netflix Framerate
AP4_Atom* atom;
AP4_UnknownUuidAtom* nxfr;
atom = m_sampleDescription->GetDetails().GetChild(
reinterpret_cast<const AP4_UI08*>(NETFLIX_FRAMERATE_UUID));
if (atom && (nxfr = dynamic_cast<AP4_UnknownUuidAtom*>(atom)) &&
nxfr->GetData().GetDataSize() == 10)
{
unsigned int fpsRate = nxfr->GetData().GetData()[7] | nxfr->GetData().GetData()[6] << 8;
unsigned int fpsScale = nxfr->GetData().GetData()[9] | nxfr->GetData().GetData()[8] << 8;

if (info.GetFpsScale() != fpsScale || info.GetFpsRate() != fpsRate)
{
info.SetFpsScale(fpsScale);
info.SetFpsRate(fpsRate);
return true;
}
}
}
}
return false;
}
Expand Down
16 changes: 0 additions & 16 deletions src/codechandler/MPEGCodecHandler.cpp

This file was deleted.

131 changes: 64 additions & 67 deletions src/samplereader/FragmentedSampleReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
#include "FragmentedSampleReader.h"

#include "../AdaptiveByteStream.h"
#include "../codechandler/AudioCodecHandler.h"
#include "../codechandler/AV1CodecHandler.h"
#include "../codechandler/AVCCodecHandler.h"
#include "../codechandler/HEVCCodecHandler.h"
#include "../codechandler/MPEGCodecHandler.h"
#include "../codechandler/TTMLCodecHandler.h"
#include "../codechandler/VP9CodecHandler.h"
#include "../codechandler/WebVTTCodecHandler.h"
Expand Down Expand Up @@ -113,8 +113,11 @@ AP4_Result CFragmentedSampleReader::Start(bool& bStarted)

AP4_Result CFragmentedSampleReader::ReadSample()
{
if (!m_codecHandler)
return AP4_FAILURE;

AP4_Result result;
if (!m_codecHandler || !m_codecHandler->ReadNextSample(m_sample, m_sampleData))
if (!m_codecHandler->ReadNextSample(m_sample, m_sampleData))
{
bool useDecryptingDecoder =
m_protectedDesc &&
Expand Down Expand Up @@ -227,48 +230,21 @@ bool CFragmentedSampleReader::GetInformation(kodi::addon::InputstreamInfo& info)
if (!m_codecHandler)
return false;

bool edChanged(false);
bool isChanged{false};
if (m_bSampleDescChanged && m_codecHandler->m_extraData.GetDataSize() &&
!info.CompareExtraData(m_codecHandler->m_extraData.GetData(),
m_codecHandler->m_extraData.GetDataSize()))
{
info.SetExtraData(m_codecHandler->m_extraData.GetData(),
m_codecHandler->m_extraData.GetDataSize());
edChanged = true;
}

AP4_SampleDescription* desc(m_track->GetSampleDescription(0));
if (desc->GetType() == AP4_SampleDescription::TYPE_MPEG)
{
switch (static_cast<AP4_MpegSampleDescription*>(desc)->GetObjectTypeId())
{
case AP4_OTI_MPEG4_AUDIO:
case AP4_OTI_MPEG2_AAC_AUDIO_MAIN:
case AP4_OTI_MPEG2_AAC_AUDIO_LC:
case AP4_OTI_MPEG2_AAC_AUDIO_SSRP:
info.SetCodecName(CODEC::NAME_AAC);
break;
case AP4_OTI_DTS_AUDIO:
case AP4_OTI_DTS_HIRES_AUDIO:
case AP4_OTI_DTS_MASTER_AUDIO:
case AP4_OTI_DTS_EXPRESS_AUDIO:
info.SetCodecName(CODEC::NAME_DTS);
break;
case AP4_OTI_AC3_AUDIO:
info.SetCodecName(CODEC::NAME_AC3);
break;
case AP4_OTI_EAC3_AUDIO:
info.SetCodecName(CODEC::NAME_EAC3);
break;
}
isChanged |= true;
}

m_bSampleDescChanged = false;

if (m_codecHandler->GetInformation(info))
return true;
isChanged |= m_codecHandler->GetInformation(info);

return edChanged;
return isChanged;
}

bool CFragmentedSampleReader::TimeSeek(uint64_t pts, bool preceeding)
Expand Down Expand Up @@ -442,49 +418,70 @@ AP4_Result CFragmentedSampleReader::ProcessMoof(AP4_ContainerAtom* moof,
void CFragmentedSampleReader::UpdateSampleDescription()
{
if (m_codecHandler)
{
delete m_codecHandler;
m_codecHandler = 0;
m_codecHandler = nullptr;
}
m_bSampleDescChanged = true;

AP4_SampleDescription* desc(m_track->GetSampleDescription(m_sampleDescIndex - 1));
AP4_SampleDescription* desc = m_track->GetSampleDescription(m_sampleDescIndex - 1);
if (!desc)
{
LOG::LogF(LOGERROR, "Cannot get sample description from index %u", m_sampleDescIndex - 1);
return;
}

if (desc->GetType() == AP4_SampleDescription::TYPE_PROTECTED)
{
m_protectedDesc = static_cast<AP4_ProtectedSampleDescription*>(desc);
desc = m_protectedDesc->GetOriginalSampleDescription();
if (!desc)
{
LOG::LogF(LOGERROR, "Cannot sample description from protected sample description");
return;
}
}

LOG::LogF(LOGDEBUG, "Codec fourcc: %s (%u)", CODEC::FourCCToString(desc->GetFormat()).c_str(),
desc->GetFormat());

if (AP4_DYNAMIC_CAST(AP4_AudioSampleDescription, desc))
{
// Audio sample of any format
m_codecHandler = new AudioCodecHandler(desc);
}
LOG::Log(LOGDEBUG, "UpdateSampleDescription: codec %d", desc->GetFormat());
switch (desc->GetFormat())
else
{
case AP4_SAMPLE_FORMAT_AVC1:
case AP4_SAMPLE_FORMAT_AVC2:
case AP4_SAMPLE_FORMAT_AVC3:
case AP4_SAMPLE_FORMAT_AVC4:
m_codecHandler = new AVCCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_HEV1:
case AP4_SAMPLE_FORMAT_HVC1:
case AP4_SAMPLE_FORMAT_DVHE:
case AP4_SAMPLE_FORMAT_DVH1:
m_codecHandler = new HEVCCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_MP4A:
m_codecHandler = new MPEGCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_STPP:
m_codecHandler = new TTMLCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_WVTT:
m_codecHandler = new WebVTTCodecHandler(desc, false);
break;
case AP4_SAMPLE_FORMAT_VP9:
m_codecHandler = new VP9CodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_AV01:
m_codecHandler = new AV1CodecHandler(desc);
break;
default:
m_codecHandler = new CodecHandler(desc);
break;
switch (desc->GetFormat())
{
case AP4_SAMPLE_FORMAT_AVC1:
case AP4_SAMPLE_FORMAT_AVC2:
case AP4_SAMPLE_FORMAT_AVC3:
case AP4_SAMPLE_FORMAT_AVC4:
m_codecHandler = new AVCCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_HEV1:
case AP4_SAMPLE_FORMAT_HVC1:
case AP4_SAMPLE_FORMAT_DVHE:
case AP4_SAMPLE_FORMAT_DVH1:
m_codecHandler = new HEVCCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_STPP:
m_codecHandler = new TTMLCodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_WVTT:
m_codecHandler = new WebVTTCodecHandler(desc, false);
break;
case AP4_SAMPLE_FORMAT_VP9:
m_codecHandler = new VP9CodecHandler(desc);
break;
case AP4_SAMPLE_FORMAT_AV01:
m_codecHandler = new AV1CodecHandler(desc);
break;
default:
m_codecHandler = new CodecHandler(desc);
break;
}
}

if ((m_decrypterCaps.flags & SSD::SSD_DECRYPTER::SSD_CAPS::SSD_ANNEXB_REQUIRED) != 0)
Expand Down
Loading

0 comments on commit b09c6d5

Please sign in to comment.