From 452021a395a6c227f79867a295b00172ffe1ff5b Mon Sep 17 00:00:00 2001 From: ggoussard Date: Mon, 9 Jan 2017 16:06:53 -0800 Subject: [PATCH 1/4] Parse DAC3 Atom ETSI TS 102 366 V1.2.1 (2008-08) F4 --- Source/C++/Core/Ap4Atom.h | 1 + Source/C++/Core/Ap4AtomFactory.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/Source/C++/Core/Ap4Atom.h b/Source/C++/Core/Ap4Atom.h index c5680df3f..5ced04f0b 100644 --- a/Source/C++/Core/Ap4Atom.h +++ b/Source/C++/Core/Ap4Atom.h @@ -489,6 +489,7 @@ const AP4_Atom::Type AP4_ATOM_TYPE_UUID = AP4_ATOM_TYPE('u','u','i','d'); const AP4_Atom::Type AP4_ATOM_TYPE_8ID_ = AP4_ATOM_TYPE('8','i','d',' '); const AP4_Atom::Type AP4_ATOM_TYPE_8BDL = AP4_ATOM_TYPE('8','b','d','l'); const AP4_Atom::Type AP4_ATOM_TYPE_AC_3 = AP4_ATOM_TYPE('a','c','-','3'); +const AP4_Atom::Type AP4_ATOM_TYPE_DAC3 = AP4_ATOM_TYPE('d','a','c','3'); const AP4_Atom::Type AP4_ATOM_TYPE_EC_3 = AP4_ATOM_TYPE('e','c','-','3'); const AP4_Atom::Type AP4_ATOM_TYPE_DTSC = AP4_ATOM_TYPE('d','t','s','c'); const AP4_Atom::Type AP4_ATOM_TYPE_DTSH = AP4_ATOM_TYPE('d','t','s','h'); diff --git a/Source/C++/Core/Ap4AtomFactory.cpp b/Source/C++/Core/Ap4AtomFactory.cpp index 8ad0b933f..d5a2475eb 100644 --- a/Source/C++/Core/Ap4AtomFactory.cpp +++ b/Source/C++/Core/Ap4AtomFactory.cpp @@ -101,6 +101,7 @@ #include "Ap4AinfAtom.h" #include "Ap4PsshAtom.h" #include "Ap4Dec3Atom.h" +#include "Ap4Dac3Atom.h" #include "Ap4SidxAtom.h" #include "Ap4SbgpAtom.h" #include "Ap4SgpdAtom.h" @@ -711,6 +712,13 @@ AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, atom = AP4_Dec3Atom::Create(size_32, stream); } break; + case AP4_ATOM_TYPE_DAC3: + if (atom_is_large) return AP4_ERROR_INVALID_FORMAT; + if (GetContext() == AP4_ATOM_TYPE_AC_3) { + atom = AP4_Dac3Atom::Create(size_32, stream); + } + break; + // track ref types case AP4_ATOM_TYPE_HINT: From af19be09750a04721dc3f83bd1d713389777a85f Mon Sep 17 00:00:00 2001 From: ggoussard Date: Mon, 9 Jan 2017 18:46:58 -0800 Subject: [PATCH 2/4] Fix support for AC-3 in mp4-dash --- Source/C++/Apps/Mp4Info/Mp4Info.cpp | 37 +++++++++++++++++++++++++++++ Source/C++/Core/Ap4.h | 1 + Source/Python/utils/mp4-dash.py | 2 +- Source/Python/utils/mp4utils.py | 4 ++-- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Source/C++/Apps/Mp4Info/Mp4Info.cpp b/Source/C++/Apps/Mp4Info/Mp4Info.cpp index 76a27c366..ead3738d4 100644 --- a/Source/C++/Apps/Mp4Info/Mp4Info.cpp +++ b/Source/C++/Apps/Mp4Info/Mp4Info.cpp @@ -422,6 +422,23 @@ ShowSampleDescription_Text(AP4_SampleDescription& description, bool verbose) } // Dolby Digital specifics + if (desc->GetFormat() == AP4_SAMPLE_FORMAT_AC_3) { + AP4_Dac3Atom* dac3 = AP4_DYNAMIC_CAST(AP4_Dac3Atom, desc->GetDetails().GetChild(AP4_ATOM_TYPE('d', 'a', 'c', '3'))); + if (dac3) { + printf(" AC3 stream:\n"); + printf(" fscod = %d\n", dac3->GetFscod()); + printf(" bsid = %d\n", dac3->GetBsid()); + printf(" bsmod = %d\n", dac3->GetBsmod()); + printf(" acmod = %d\n", dac3->GetAcmod()); + printf(" lfeon = %d\n", dac3->GetLfeon()); + printf(" bit_rate_code = %d\n", dac3->GetBitRateCode()); + printf(" AC3 dac3 payload: ["); + ShowData(dac3->GetRawBytes()); + printf("]\n"); + } + } + + // Enhanced Dolby Digital specifics if (desc->GetFormat() == AP4_SAMPLE_FORMAT_EC_3) { AP4_Dec3Atom* dec3 = AP4_DYNAMIC_CAST(AP4_Dec3Atom, desc->GetDetails().GetChild(AP4_ATOM_TYPE('d', 'e', 'c', '3'))); if (dec3) { @@ -619,6 +636,26 @@ ShowSampleDescription_Json(AP4_SampleDescription& description, bool verbose) } // Dolby Digital specifics + if (desc->GetFormat() == AP4_SAMPLE_FORMAT_AC_3) { + AP4_Dac3Atom* dac3 = AP4_DYNAMIC_CAST(AP4_Dac3Atom, desc->GetDetails().GetChild(AP4_ATOM_TYPE('d', 'a', 'c', '3'))); + if (dac3) { + printf(",\n"); + printf("\"dolby_digital_info\": {\n"); + printf(" \"fscod\": %d,\n", dac3->GetFscod()); + printf(" \"bsid\": %d,\n", dac3->GetBsid()); + printf(" \"bsmod\": %d,\n", dac3->GetBsmod()); + printf(" \"acmod\": %d,\n", dac3->GetAcmod()); + printf(" \"lfeon\": %d,\n", dac3->GetLfeon()); + printf(" \"bit_rate_code\": %d,\n", dac3->GetBitRateCode()); + printf(" \"dec3_payload\": \""); + ShowData(dac3->GetRawBytes()); + printf("\"}"); + } + } + + + + // Enhanced Dolby Digital specifics if (desc->GetFormat() == AP4_SAMPLE_FORMAT_EC_3) { AP4_Dec3Atom* dec3 = AP4_DYNAMIC_CAST(AP4_Dec3Atom, desc->GetDetails().GetChild(AP4_ATOM_TYPE('d', 'e', 'c', '3'))); if (dec3) { diff --git a/Source/C++/Core/Ap4.h b/Source/C++/Core/Ap4.h index a237ef309..e8a01f7bd 100644 --- a/Source/C++/Core/Ap4.h +++ b/Source/C++/Core/Ap4.h @@ -310,6 +310,7 @@ #include "Ap4TfraAtom.h" #include "Ap4SbgpAtom.h" #include "Ap4MfroAtom.h" +#include "Ap4Dac3Atom.h" #include "Ap4Dec3Atom.h" #include "Ap4SidxAtom.h" #include "Ap4AdtsParser.h" diff --git a/Source/Python/utils/mp4-dash.py b/Source/Python/utils/mp4-dash.py index d0084891e..f0a4ca5a3 100755 --- a/Source/Python/utils/mp4-dash.py +++ b/Source/Python/utils/mp4-dash.py @@ -460,7 +460,7 @@ def OutputDash(options, set_attributes, audio_sets, video_sets, subtitles_sets, codecs=audio_track.codec, bandwidth=str(audio_track.bandwidth), audioSamplingRate=str(audio_track.sample_rate)) - if audio_track.codec == 'ec-3': + if audio_track.codec in ['ac-3', 'ec-3']: audio_channel_config_value = ComputeDolbyDigitalAudioChannelConfig(audio_track) scheme_id_uri = DOLBY_DIGITAL_AUDIO_CHANNEL_CONFIGURATION_SCHEME_ID_URI else: diff --git a/Source/Python/utils/mp4utils.py b/Source/Python/utils/mp4utils.py index ffd82d615..f85e1f45b 100644 --- a/Source/Python/utils/mp4utils.py +++ b/Source/Python/utils/mp4utils.py @@ -843,11 +843,11 @@ def GetDolbyDigitalChannels(track): sample_desc = track.info['sample_descriptions'][0] if 'dolby_digital_info' not in sample_desc: return (track.channels, []) - dd_info = sample_desc['dolby_digital_info']['substreams'][0] + dd_info = sample_desc['dolby_digital_info']['substreams'][0] if sample_desc['coding'] == 'ec-3' else sample_desc['dolby_digital_info'] channels = DolbyDigital_acmod[dd_info['acmod']][:] if dd_info['lfeon'] == 1: channels.append('LFE') - if dd_info['num_dep_sub'] and 'chan_loc' in dd_info: + if 'num_dep_sub' in dd_info and dd_info['num_dep_sub'] and 'chan_loc' in dd_info: chan_loc_value = dd_info['chan_loc'] for i in range(9): if chan_loc_value & (1< Date: Mon, 9 Jan 2017 18:53:27 -0800 Subject: [PATCH 3/4] Add DAC3 Atom definition --- Source/C++/Core/Ap4Dac3Atom.cpp | 113 ++++++++++++++++++++++++++++++++ Source/C++/Core/Ap4Dac3Atom.h | 83 +++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 Source/C++/Core/Ap4Dac3Atom.cpp create mode 100644 Source/C++/Core/Ap4Dac3Atom.h diff --git a/Source/C++/Core/Ap4Dac3Atom.cpp b/Source/C++/Core/Ap4Dac3Atom.cpp new file mode 100644 index 000000000..b781d66c5 --- /dev/null +++ b/Source/C++/Core/Ap4Dac3Atom.cpp @@ -0,0 +1,113 @@ +/***************************************************************** +| +| AP4 - dac3 Atoms +| +| Copyright 2002-2008 Axiomatic Systems, LLC +| +| +| This file is part of Bento4/AP4 (MP4 Atom Processing Library). +| +| Unless you have obtained Bento4 under a difference license, +| this version of Bento4 is Bento4|GPL. +| Bento4|GPL is free software; you can redistribute it and/or modify +| it under the terms of the GNU General Public License as published by +| the Free Software Foundation; either version 2, or (at your option) +| any later version. +| +| Bento4|GPL is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +| GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License +| along with Bento4|GPL; see the file COPYING. If not, write to the +| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA +| 02111-1307, USA. +| +****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "Ap4Dac3Atom.h" +#include "Ap4AtomFactory.h" +#include "Ap4Utils.h" +#include "Ap4Types.h" + +/*---------------------------------------------------------------------- +| dynamic cast support ++---------------------------------------------------------------------*/ +AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_Dac3Atom) + +/*---------------------------------------------------------------------- +| AP4_Dac3Atom::Create ++---------------------------------------------------------------------*/ +AP4_Dac3Atom* +AP4_Dac3Atom::Create(AP4_Size size, AP4_ByteStream& stream) +{ + // read the raw bytes in a buffer + unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE; + AP4_DataBuffer payload_data(payload_size); + AP4_Result result = stream.Read(payload_data.UseData(), payload_size); + if (AP4_FAILED(result)) return NULL; + + // check the version + const AP4_UI08* payload = payload_data.GetData(); + return new AP4_Dac3Atom(size, payload); +} + +/*---------------------------------------------------------------------- +| AP4_Dac3Atom::AP4_Dac3Atom ++---------------------------------------------------------------------*/ +AP4_Dac3Atom::AP4_Dac3Atom(AP4_UI32 size, const AP4_UI08* payload) : + AP4_Atom(AP4_ATOM_TYPE_DAC3, size), + m_Fscod(0), + m_Bsid(0), + m_Bsmod(0), + m_Acmod(0), + m_Lfeon(0), + m_BitRateCode(0), + m_Reserved(0) +{ + // make a copy of our configuration bytes + unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE; + m_RawBytes.SetData(payload, payload_size); + + // sanity check + if (payload_size < 2) return; + + // parse the payload + m_Fscod = (payload[0]>>6) & 0x3; + m_Bsid = (payload[0]>>1) & 0x1F; + m_Bsmod = (payload[0]<<2 | payload[1]>>6) & 0x3; + m_Acmod = (payload[1]>>3) & 0x7; + m_Lfeon = (payload[1]>>2) & 0x1; + m_BitRateCode = (payload[1]<<3 | payload[2]>>5) & 0x1F; + m_Reserved = payload[2] & 0x1F; + +} + +/*---------------------------------------------------------------------- +| AP4_Dac3Atom::WriteFields ++---------------------------------------------------------------------*/ +AP4_Result +AP4_Dac3Atom::WriteFields(AP4_ByteStream& stream) +{ + return stream.Write(m_RawBytes.GetData(), m_RawBytes.GetDataSize()); +} + +/*---------------------------------------------------------------------- +| AP4_Dac3Atom::InspectFields ++---------------------------------------------------------------------*/ +AP4_Result +AP4_Dac3Atom::InspectFields(AP4_AtomInspector& inspector) +{ + inspector.AddField("fscod", m_Fscod); + inspector.AddField("bsid", m_Bsid); + inspector.AddField("bsmod", m_Bsmod); + inspector.AddField("acmod", m_Acmod); + inspector.AddField("lfeon", m_Lfeon); + inspector.AddField("bit_rate_code", m_BitRateCode); + + return AP4_SUCCESS; +} diff --git a/Source/C++/Core/Ap4Dac3Atom.h b/Source/C++/Core/Ap4Dac3Atom.h new file mode 100644 index 000000000..ab7e119fe --- /dev/null +++ b/Source/C++/Core/Ap4Dac3Atom.h @@ -0,0 +1,83 @@ +/***************************************************************** +| +| AP4 - dac3 Atoms +| +| Copyright 2002-2008 Axiomatic Systems, LLC +| +| +| This file is part of Bento4/AP4 (MP4 Atom Processing Library). +| +| Unless you have obtained Bento4 under a difference license, +| this version of Bento4 is Bento4|GPL. +| Bento4|GPL is free software; you can redistribute it and/or modify +| it under the terms of the GNU General Public License as published by +| the Free Software Foundation; either version 2, or (at your option) +| any later version. +| +| Bento4|GPL is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +| GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License +| along with Bento4|GPL; see the file COPYING. If not, write to the +| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA +| 02111-1307, USA. +| +****************************************************************/ + +#ifndef _AP4_DAC3_ATOM_H_ +#define _AP4_DAC3_ATOM_H_ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "Ap4Atom.h" +#include "Ap4Array.h" + +/*---------------------------------------------------------------------- +| constants ++---------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- +| AP4_Dac3Atom ++---------------------------------------------------------------------*/ +class AP4_Dac3Atom : public AP4_Atom +{ +public: + AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_Dac3Atom, AP4_Atom) + + // class methods + static AP4_Dac3Atom* Create(AP4_Size size, AP4_ByteStream& stream); + + // methods + virtual AP4_Result InspectFields(AP4_AtomInspector& inspector); + virtual AP4_Result WriteFields(AP4_ByteStream& stream); + virtual AP4_Atom* Clone() { return new AP4_Dac3Atom(m_Size32, m_RawBytes.GetData()); } + + // accessors + const AP4_DataBuffer& GetRawBytes() const { return m_RawBytes; } + unsigned int GetFscod() const { return m_Fscod; } + unsigned int GetBsid() const { return m_Bsid; } + unsigned int GetBsmod() const { return m_Bsmod; } + unsigned int GetAcmod() const { return m_Acmod; } + unsigned int GetLfeon() const { return m_Lfeon; } + unsigned int GetBitRateCode() const { return m_BitRateCode; } + unsigned int GetReserved() const { return m_Reserved; } + +private: + // methods + AP4_Dac3Atom(AP4_UI32 size, const AP4_UI08* payload); + + // members + unsigned int m_Fscod; + unsigned int m_Bsid; + unsigned int m_Bsmod; + unsigned int m_Acmod; + unsigned int m_Lfeon; + unsigned int m_BitRateCode; + unsigned int m_Reserved; + AP4_DataBuffer m_RawBytes; +}; + +#endif // _AP4_DAC3_ATOM_H_ From c27161c9686c08ed781683db642f0aaef37c3baa Mon Sep 17 00:00:00 2001 From: ggoussard Date: Mon, 9 Jan 2017 19:24:28 -0800 Subject: [PATCH 4/4] DASH doesn't support AC-3 --- Source/Python/utils/mp4-dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Python/utils/mp4-dash.py b/Source/Python/utils/mp4-dash.py index f0a4ca5a3..d0084891e 100755 --- a/Source/Python/utils/mp4-dash.py +++ b/Source/Python/utils/mp4-dash.py @@ -460,7 +460,7 @@ def OutputDash(options, set_attributes, audio_sets, video_sets, subtitles_sets, codecs=audio_track.codec, bandwidth=str(audio_track.bandwidth), audioSamplingRate=str(audio_track.sample_rate)) - if audio_track.codec in ['ac-3', 'ec-3']: + if audio_track.codec == 'ec-3': audio_channel_config_value = ComputeDolbyDigitalAudioChannelConfig(audio_track) scheme_id_uri = DOLBY_DIGITAL_AUDIO_CHANNEL_CONFIGURATION_SCHEME_ID_URI else: