Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
547 changes: 547 additions & 0 deletions Source/MediaInfo/Audio/Auro.cpp

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions Source/MediaInfo/Audio/Auro.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license that can
* be found in the License.html file in the root of the source tree.
*/

//---------------------------------------------------------------------------
#ifndef MediaInfo_AuroH
#define MediaInfo_AuroH
//---------------------------------------------------------------------------

#include <string>
#include <cstddef>
#include <cstdint>

namespace MediaInfoLib
{

//---------------------------------------------------------------------------
/// @brief Convert Auro channel layout ID to string (e.g. 63 -> "5.1")
std::string Auro_ChannelLayoutToString(std::uint32_t layout_id);

//---------------------------------------------------------------------------
/// @brief Detect Auro-3D embedded in 24-bit little-endian PCM.
/// @param buffer Interleaved PCM, 3 bytes per sample, little-endian
/// @param size Size in bytes (must be multiple of 3*channels)
/// @param channels Number of channels
/// @return Layout string if detected (e.g. "5.1"), empty string otherwise
std::string Auro_DetectInPcm24Le(const unsigned char* buffer, size_t size, int channels);

} //NameSpace

#endif
32 changes: 32 additions & 0 deletions Source/MediaInfo/Audio/File_Pcm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
//---------------------------------------------------------------------------
#include "MediaInfo/Audio/File_Pcm.h"
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if defined(MEDIAINFO_PCM_YES)
#include "MediaInfo/Audio/Auro.h"
#include <cstring>
#endif
//---------------------------------------------------------------------------

namespace MediaInfoLib
Expand Down Expand Up @@ -87,6 +91,9 @@ File_Pcm::File_Pcm()
Sign='\0';

//Temp
#if defined(MEDIAINFO_PCM_YES)
Auro_Detected=false;
#endif
#if MEDIAINFO_CONFORMANCE
IsNotSilence=false;
#endif
Expand Down Expand Up @@ -444,6 +451,31 @@ void File_Pcm::Data_Parse()
if (Frame_Count_NotParsedIncluded!=(int64u)-1)
Frame_Count_NotParsedIncluded++;
}
#if defined(MEDIAINFO_PCM_YES)
if (BitDepth==24 && Channels && (Endianness=='L' || !Endianness) && !Auro_Detected && Element_Size)
{
const size_t frame_bytes=3*(size_t)Channels;
if (frame_bytes && (size_t)Element_Size%frame_bytes==0)
{
const size_t max_auro_buffer=2*1024*1024;
if (Auro_Buffer.size()+Element_Size>max_auro_buffer)
Auro_Buffer.clear();
size_t old_size=Auro_Buffer.size();
Auro_Buffer.resize(old_size+(size_t)Element_Size);
std::memcpy(Auro_Buffer.data()+old_size, Buffer+Buffer_Offset, (size_t)Element_Size);
const size_t min_size=1000*frame_bytes;
if (Auro_Buffer.size()>=min_size)
{
std::string layout=Auro_DetectInPcm24Le((const unsigned char*)Auro_Buffer.data(), Auro_Buffer.size(), Channels);
if (!layout.empty())
{
Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, Ztring(__T("Auro-3D ("))+Ztring().From_UTF8(layout)+__T(")"));
Auro_Detected=true;
}
}
}
}
#endif
if ((!Status[IsAccepted] && Frame_Count>=Frame_Count_Valid) || File_Offset+Buffer_Size>=File_Size)
{
Accept();
Expand Down
5 changes: 5 additions & 0 deletions Source/MediaInfo/Audio/File_Pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//---------------------------------------------------------------------------
#include "MediaInfo/File__Analyze.h"
#include <deque>
#include <vector>
//---------------------------------------------------------------------------

namespace MediaInfoLib
Expand Down Expand Up @@ -68,6 +69,10 @@ public :
File_Pcm();

private :
#if defined(MEDIAINFO_PCM_YES)
std::vector<int8u> Auro_Buffer;
bool Auro_Detected;
#endif
//Streams management
void Streams_Fill();
void Streams_Finish();
Expand Down
29 changes: 13 additions & 16 deletions Source/MediaInfo/Multiple/File_Mk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4049,25 +4049,22 @@ void File_Mk::Segment_Tracks_TrackEntry_CodecPrivate_auds_ExtensibleWave(int16u
Fill(Stream_Audio, StreamPos_Last, Audio_CodecID, __T("A_MS/ACM / ")+Ztring().From_GUID(SubFormat), true);
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, MediaInfoLib::Config.Codec_Get(Ztring().From_Number(LegacyCodecID, 16)), true);

//Creating the parser
//Creating the parser so block data is fed to it (e.g. for Auro-3D detection in 24-bit PCM)
#if defined(MEDIAINFO_PCM_YES)
if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Ztring().From_Number(LegacyCodecID, 16))==__T("PCM"))
if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Ztring().From_Number(LegacyCodecID, 16))==__T("PCM") && TrackNumber!=(int64u)-1 && !Stream[TrackNumber].Parser)
{
//Creating the parser
File_Pcm MI;
MI.Frame_Count_Valid=0;
MI.Codec=Ztring().From_GUID(SubFormat);
MI.BitDepth=(int8u)BitsPerSample;
File_Pcm* Parser=new File_Pcm;
Parser->Codec=Ztring().From_GUID(SubFormat);
Parser->BitDepth=(int8u)BitsPerSample;
if (ValidBitsPerSample!=BitsPerSample)
MI.BitDepth_Significant=(int8u)ValidBitsPerSample;

//Parsing
Open_Buffer_Init(&MI);
Open_Buffer_Continue(&MI, 0);

//Filling
Finish(&MI);
Merge(MI, StreamKind_Last, 0, StreamPos_Last);
Parser->BitDepth_Significant=(int8u)ValidBitsPerSample;
Parser->Endianness='L';
Parser->Channels=(int8u)Retrieve(Stream_Audio, StreamPos_Last, Audio_Channel_s_).To_int8u();
Parser->SamplingRate=Retrieve(Stream_Audio, StreamPos_Last, Audio_SamplingRate).To_int32u();
Parser->Sign=(BitsPerSample==8?'U':'S');
Stream[TrackNumber].Parser=Parser;
Stream[TrackNumber].StreamKind=Stream_Audio;
Open_Buffer_Init(Stream[TrackNumber].Parser);
}
#endif
}
Expand Down
1 change: 1 addition & 0 deletions Source/MediaInfo/Multiple/File_Mpeg4.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ private :
void moov_trak_mdia_minf_stbl_stsd_xxxx_ccst();
void moov_trak_mdia_minf_stbl_stsd_xxxx_chan();
void moov_trak_mdia_minf_stbl_stsd_xxxx_chnl();
void moov_trak_mdia_minf_stbl_stsd_xxxx_acxd();
void moov_trak_mdia_minf_stbl_stsd_xxxx_clap();
void moov_trak_mdia_minf_stbl_stsd_xxxx_clli();
void moov_trak_mdia_minf_stbl_stsd_xxxx_colr();
Expand Down
171 changes: 171 additions & 0 deletions Source/MediaInfo/Multiple/File_Mpeg4_Elements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,123 @@ const char* Mpeg4_chan_Layout(int16u Ordering)
}
}

//---------------------------------------------------------------------------
// Auro-Cx channel IDs 0..15 (from auro3d-decode / Auro channel mask)
static const char* Mpeg4_AuroCx_ChannelLayout_List[16] =
{
"L", "R", "C", "LFE", "Ls", "Rs", "Cb", "Lb",
"Rb", "Tfl", "Tfr", "Tfc", "Tc", "Tbl", "Tbr", "Tbc",
};

static const char* Mpeg4_AuroCx_LayoutName(int16u Layout)
{
switch (Layout)
{
case 0x01BF : return "7.1";
case 0x663F : return "5.1+4H (9.1)";
case 0x67BF : return "7.1+4H (11.1)";
case 0x7FBF : return "7.1+5H+T (13.1)";
default : return NULL;
}
}

static std::string Mpeg4_AuroCx_ChannelLayout(int16u Layout)
{
std::string Text;
for (int8u i=0; i<16; i++)
if (Layout&(1<<i))
{
if (!Text.empty())
Text+=' ';
Text+=Mpeg4_AuroCx_ChannelLayout_List[i];
}
return Text;
}

static std::string Mpeg4_AuroCx_ChannelPositions(int16u Layout)
{
std::string Text;
if (Layout&0x0007)
{
Text+="Front:";
if (Layout&0x0001) Text+=" L";
if (Layout&0x0004) Text+=" C";
if (Layout&0x0002) Text+=" R";
}
if (Layout&0x0030)
{
if (!Text.empty()) Text+=", ";
Text+="Side:";
if (Layout&0x0010) Text+=" L";
if (Layout&0x0020) Text+=" R";
}
if (Layout&0x01C0)
{
if (!Text.empty()) Text+=", ";
Text+="Back:";
if (Layout&0x0080) Text+=" L";
if (Layout&0x0040) Text+=" C";
if (Layout&0x0100) Text+=" R";
}
if (Layout&0x0E00)
{
if (!Text.empty()) Text+=", ";
Text+="TopFront:";
if (Layout&0x0200) Text+=" L";
if (Layout&0x0800) Text+=" C";
if (Layout&0x0400) Text+=" R";
}
if (Layout&0x1000)
{
if (!Text.empty()) Text+=", ";
Text+="Top: C";
}
if (Layout&0xE000)
{
if (!Text.empty()) Text+=", ";
Text+="TopRear:";
if (Layout&0x2000) Text+=" L";
if (Layout&0x8000) Text+=" C";
if (Layout&0x4000) Text+=" R";
}
if (Layout&0x0008)
{
if (!Text.empty()) Text+=", ";
Text+="LFE";
}
return Text;
}

static std::string Mpeg4_AuroCx_ChannelPositions2(int16u Layout)
{
int8u Front=0, Side=0, Back=0, LFE=0, Height=0;
if (Layout&0x0001) Front++;
if (Layout&0x0002) Front++;
if (Layout&0x0004) Front++;
if (Layout&0x0010) Side++;
if (Layout&0x0020) Side++;
if (Layout&0x0040) Back++;
if (Layout&0x0080) Back++;
if (Layout&0x0100) Back++;
if (Layout&0x0008) LFE++;
if (Layout&0x0200) Height++;
if (Layout&0x0400) Height++;
if (Layout&0x0800) Height++;
if (Layout&0x1000) Height++;
if (Layout&0x2000) Height++;
if (Layout&0x4000) Height++;
if (Layout&0x8000) Height++;

Ztring Text;
Text+=Ztring::ToZtring(Front);
Text+=__T('/')+Ztring::ToZtring(Side);
Text+=__T('/')+Ztring::ToZtring(Back);
Text+=__T('.')+Ztring::ToZtring(LFE);
if (Height)
Text+=__T('.')+Ztring::ToZtring(Height);
return Text.To_UTF8();
}

//---------------------------------------------------------------------------
static std::string Mpeg4_chan_ChannelDescription (int64u ChannelLabels)
{
Expand Down Expand Up @@ -906,6 +1023,7 @@ namespace Elements
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_clap=0x636C6170;
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_chan=0x6368616E;
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_chnl=0x63686E6C;
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_acxd=0x61637864;
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_clli=0x636C6C69;
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_colr=0x636F6C72;
const int64u moov_trak_mdia_minf_stbl_stsd_xxxx_colr_clcn=0x636C636E;
Expand Down Expand Up @@ -1365,6 +1483,7 @@ void File_Mpeg4::Data_Parse()
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_ccst)
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_chan)
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_chnl)
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_acxd)
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_clap)
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_clli)
ATOM(moov_trak_mdia_minf_stbl_stsd_xxxx_mdcv)
Expand Down Expand Up @@ -7552,6 +7671,58 @@ void File_Mpeg4::moov_trak_mdia_minf_stbl_stsd_xxxx_chnl()
FILLING_END();
}

//---------------------------------------------------------------------------
void File_Mpeg4::moov_trak_mdia_minf_stbl_stsd_xxxx_acxd()
{
Element_Name("Auro-Cx Decoder Config");

//Parsing
// Declared layout is a BE16 Auro channel-id bit mask near the end of acxd
// (offset 36 for the common 39-byte config; Element_Size-3 for longer boxes).
int16u Layout=0;
if (Element_Size>=39)
{
Skip_XX(Element_Size-3, "Decoder config");
Get_B2 (Layout, "channel_layout"); Param_Info1(Ztring::ToZtring(Layout, 16));
if (const char* Name=Mpeg4_AuroCx_LayoutName(Layout))
Param_Info1(Name);
Skip_B1( "reserved");
}
else if (Element_Size>=38)
{
Skip_XX(36, "Decoder config");
Get_B2 (Layout, "channel_layout"); Param_Info1(Ztring::ToZtring(Layout, 16));
if (const char* Name=Mpeg4_AuroCx_LayoutName(Layout))
Param_Info1(Name);
Skip_XX(Element_Size-Element_Offset, "reserved");
}
else
{
Skip_XX(Element_Size, "Decoder config");
return;
}

if (moov_trak_mdia_minf_stbl_stsd_Pos>1)
return; //Handling only the first description

FILLING_BEGIN();
if (StreamKind_Last==Stream_Audio && Layout)
{
int8u ChannelCount=0;
for (int8u i=0; i<16; i++)
if (Layout&(1<<i))
ChannelCount++;
if (ChannelCount)
Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, ChannelCount, 10, true);
Fill(Stream_Audio, StreamPos_Last, Audio_ChannelLayout, Mpeg4_AuroCx_ChannelLayout(Layout));
Fill(Stream_Audio, StreamPos_Last, Audio_ChannelPositions, Mpeg4_AuroCx_ChannelPositions(Layout));
Fill(Stream_Audio, StreamPos_Last, Audio_ChannelPositions_String2, Mpeg4_AuroCx_ChannelPositions2(Layout));
if (const char* Name=Mpeg4_AuroCx_LayoutName(Layout))
Fill(Stream_Audio, StreamPos_Last, Audio_Format_Settings, Name);
}
FILLING_END();
}

//---------------------------------------------------------------------------
void File_Mpeg4::moov_trak_mdia_minf_stbl_stsd_xxxx_clap()
{
Expand Down
4 changes: 4 additions & 0 deletions Source/MediaInfo/Multiple/File_Riff_Elements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4361,7 +4361,11 @@ void File_Riff::Parser_Pcm(stream& StreamItem, int16u Channels, int16u BitsPerSa
Parser->Codec=Retrieve(Stream_Audio, StreamPos_Last, Audio_CodecID);
if (Endianness)
Parser->Endianness=Endianness;
else if (BitsPerSample>=16 && BitsPerSample<=32)
Parser->Endianness='L'; // WAV PCM is little-endian by default
Parser->BitDepth=(int8u)BitsPerSample;
Parser->Channels=(int8u)Channels;
Parser->SamplingRate=SamplesPerSec;
if (ValidBitsPerSample!=BitsPerSample)
Parser->BitDepth_Significant=(int8u)ValidBitsPerSample;
#if MEDIAINFO_DEMUX
Expand Down