Skip to content

Commit

Permalink
Added multichannel PCM output support
Browse files Browse the repository at this point in the history
Requires updated firmware (22/10/13).
  • Loading branch information
popcornmix committed Oct 22, 2013
1 parent dafe174 commit 38f05ee
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 259 deletions.
258 changes: 123 additions & 135 deletions OMXAudio.cpp

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions OMXAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ class COMXAudio
unsigned int GetAudioRenderingLatency();
float GetMaxLevel(double &pts);
COMXAudio();
bool Initialize(const CStdString& device, int iChannels, enum PCMChannels *channelMap,
COMXStreamInfo &hints, unsigned int downmixChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool boostOnDownmix,
bool Initialize(const CStdString& device, int iChannels, uint64_t channelMap,
COMXStreamInfo &hints, enum PCMLayout layout, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool boostOnDownmix,
OMXClock *clock, bool bUsePassthrough = false, bool bUseHWDecode = false, bool is_live = false, float fifo_size = 0);
~COMXAudio();
bool PortSettingsChanged();
Expand Down Expand Up @@ -91,6 +91,10 @@ class COMXAudio
unsigned int SyncDTS(BYTE* pData, unsigned int iSize);
unsigned int SyncAC3(BYTE* pData, unsigned int iSize);
void UpdateAttenuation();
void BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout);
int BuildChannelMapCEA(enum PCMChannels *channelMap, uint64_t layout);
void BuildChannelMapOMX(enum OMX_AUDIO_CHANNELTYPE *channelMap, uint64_t layout);
uint64_t GetChannelLayout(enum PCMLayout layout);

private:
bool m_Initialized;
Expand All @@ -105,7 +109,6 @@ class COMXAudio
unsigned int m_ChunkLen;
unsigned int m_InputChannels;
unsigned int m_OutputChannels;
unsigned int m_downmix_channels;
unsigned int m_BitsPerSample;
float m_maxLevel;
float m_amplification;
Expand All @@ -126,6 +129,9 @@ class COMXAudio
bool m_failed_eos;
float m_fifo_size;
bool m_live;

OMX_AUDIO_CHANNELTYPE m_input_channels[OMX_AUDIO_MAXCHANNELS];
OMX_AUDIO_CHANNELTYPE m_output_channels[OMX_AUDIO_MAXCHANNELS];
OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output;
OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input;
OMX_AUDIO_PARAM_DTSTYPE m_dtsParam;
Expand All @@ -135,6 +141,7 @@ class COMXAudio
float level;
} amplitudes_t;
std::deque<amplitudes_t> m_ampqueue;
float m_downmix_matrix[OMX_AUDIO_MAXCHANNELS*OMX_AUDIO_MAXCHANNELS];

protected:
COMXCoreComponent m_omx_render;
Expand All @@ -144,8 +151,6 @@ class COMXAudio
COMXCoreTunel m_omx_tunnel_mixer;
COMXCoreTunel m_omx_tunnel_decoder;
DllAvUtil m_dllAvUtil;
OMX_AUDIO_CHANNELTYPE m_input_channels[OMX_AUDIO_MAXCHANNELS];
CPCMRemap m_remap;
CCriticalSection m_critSection;
};
#endif
Expand Down
109 changes: 11 additions & 98 deletions OMXAudioCodecOMX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ COMXAudioCodecOMX::COMXAudioCodecOMX()
m_pConvert = NULL;
m_bOpenedCodec = false;

m_channelMap[0] = PCM_INVALID;
m_channels = 0;
m_layout = 0;
m_pFrame1 = NULL;
m_bGotFrame = false;
m_iSampleFormat = AV_SAMPLE_FMT_NONE;
Expand Down Expand Up @@ -194,7 +192,10 @@ int COMXAudioCodecOMX::GetData(BYTE** dst)
if(m_pCodecContext->sample_fmt != m_desiredSampleFormat)
{
if(m_pConvert && (m_pCodecContext->sample_fmt != m_iSampleFormat || m_channels != m_pCodecContext->channels))
{
m_dllSwResample.swr_free(&m_pConvert);
m_channels = m_pCodecContext->channels;
}

if(!m_pConvert)
{
Expand Down Expand Up @@ -290,106 +291,18 @@ static unsigned count_bits(int64_t value)
return bits;
}

void COMXAudioCodecOMX::BuildChannelMap()
uint64_t COMXAudioCodecOMX::GetChannelMap()
{
if (m_channels == m_pCodecContext->channels && m_layout == m_pCodecContext->channel_layout)
return; //nothing to do here

m_channels = m_pCodecContext->channels;
m_layout = m_pCodecContext->channel_layout;

int index = 0;
if(m_pCodecContext->codec_id == CODEC_ID_AAC && m_pCodecContext->channels == 3)
{
m_channelMap[index++] = PCM_FRONT_CENTER;
m_channelMap[index++] = PCM_FRONT_LEFT;
m_channelMap[index++] = PCM_FRONT_RIGHT;
}
else if(m_pCodecContext->codec_id == CODEC_ID_AAC && m_pCodecContext->channels == 4)
{
m_channelMap[index++] = PCM_FRONT_CENTER;
m_channelMap[index++] = PCM_FRONT_LEFT;
m_channelMap[index++] = PCM_FRONT_RIGHT;
m_channelMap[index++] = PCM_BACK_CENTER;
}
else if(m_pCodecContext->codec_id == CODEC_ID_AAC && m_pCodecContext->channels == 5)
{
m_channelMap[index++] = PCM_FRONT_CENTER;
m_channelMap[index++] = PCM_FRONT_LEFT;
m_channelMap[index++] = PCM_FRONT_RIGHT;
m_channelMap[index++] = PCM_BACK_LEFT;
m_channelMap[index++] = PCM_BACK_RIGHT;
}
else if(m_pCodecContext->codec_id == CODEC_ID_AAC && m_pCodecContext->channels == 6)
{
m_channelMap[index++] = PCM_FRONT_CENTER;
m_channelMap[index++] = PCM_FRONT_LEFT;
m_channelMap[index++] = PCM_FRONT_RIGHT;
m_channelMap[index++] = PCM_BACK_LEFT;
m_channelMap[index++] = PCM_BACK_RIGHT;
m_channelMap[index++] = PCM_LOW_FREQUENCY;
}
else if(m_pCodecContext->codec_id == CODEC_ID_AAC && m_pCodecContext->channels == 7)
{
m_channelMap[index++] = PCM_FRONT_CENTER;
m_channelMap[index++] = PCM_FRONT_LEFT;
m_channelMap[index++] = PCM_FRONT_RIGHT;
m_channelMap[index++] = PCM_BACK_LEFT;
m_channelMap[index++] = PCM_BACK_RIGHT;
m_channelMap[index++] = PCM_BACK_CENTER;
m_channelMap[index++] = PCM_LOW_FREQUENCY;
}
else if(m_pCodecContext->codec_id == CODEC_ID_AAC && m_pCodecContext->channels == 8)
{
m_channelMap[index++] = PCM_FRONT_CENTER;
m_channelMap[index++] = PCM_SIDE_LEFT;
m_channelMap[index++] = PCM_SIDE_RIGHT;
m_channelMap[index++] = PCM_FRONT_LEFT;
m_channelMap[index++] = PCM_FRONT_RIGHT;
m_channelMap[index++] = PCM_BACK_LEFT;
m_channelMap[index++] = PCM_BACK_RIGHT;
m_channelMap[index++] = PCM_LOW_FREQUENCY;
}
uint64_t layout;
int bits = count_bits(m_pCodecContext->channel_layout);
if (bits == m_pCodecContext->channels)
layout = m_pCodecContext->channel_layout;
else
{

int64_t layout;
int bits = count_bits(m_pCodecContext->channel_layout);
if (bits == m_pCodecContext->channels)
layout = m_pCodecContext->channel_layout;
else
{
CLog::Log(LOGINFO, "COMXAudioCodecOMX::GetChannelMap - FFmpeg reported %d channels, but the layout contains %d ignoring", m_pCodecContext->channels, bits);
layout = m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels);
}

if (layout & AV_CH_FRONT_LEFT ) m_channelMap[index++] = PCM_FRONT_LEFT ;
if (layout & AV_CH_FRONT_RIGHT ) m_channelMap[index++] = PCM_FRONT_RIGHT ;
if (layout & AV_CH_FRONT_CENTER ) m_channelMap[index++] = PCM_FRONT_CENTER ;
if (layout & AV_CH_LOW_FREQUENCY ) m_channelMap[index++] = PCM_LOW_FREQUENCY ;
if (layout & AV_CH_BACK_LEFT ) m_channelMap[index++] = PCM_BACK_LEFT ;
if (layout & AV_CH_BACK_RIGHT ) m_channelMap[index++] = PCM_BACK_RIGHT ;
if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;
if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;
if (layout & AV_CH_BACK_CENTER ) m_channelMap[index++] = PCM_BACK_CENTER ;
if (layout & AV_CH_SIDE_LEFT ) m_channelMap[index++] = PCM_SIDE_LEFT ;
if (layout & AV_CH_SIDE_RIGHT ) m_channelMap[index++] = PCM_SIDE_RIGHT ;
if (layout & AV_CH_TOP_CENTER ) m_channelMap[index++] = PCM_TOP_CENTER ;
if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelMap[index++] = PCM_TOP_FRONT_LEFT ;
if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelMap[index++] = PCM_TOP_FRONT_CENTER ;
if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelMap[index++] = PCM_TOP_FRONT_RIGHT ;
if (layout & AV_CH_TOP_BACK_LEFT ) m_channelMap[index++] = PCM_TOP_BACK_LEFT ;
if (layout & AV_CH_TOP_BACK_CENTER ) m_channelMap[index++] = PCM_TOP_BACK_CENTER ;
if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelMap[index++] = PCM_TOP_BACK_RIGHT ;
CLog::Log(LOGINFO, "COMXAudioCodecOMX::GetChannelMap - FFmpeg reported %d channels, but the layout contains %d ignoring", m_pCodecContext->channels, bits);
layout = m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels);
}
}

enum PCMChannels* COMXAudioCodecOMX::GetChannelMap()
{
BuildChannelMap();

if (m_channelMap[0] == PCM_INVALID)
return NULL;

return m_channelMap;
return layout;
}
6 changes: 1 addition & 5 deletions OMXAudioCodecOMX.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class COMXAudioCodecOMX
int GetData(BYTE** dst);
void Reset();
int GetChannels();
enum PCMChannels *GetChannelMap();
uint64_t GetChannelMap();
int GetSampleRate();
int GetBitsPerSample();
static const char* GetName() { return "FFmpeg"; }
Expand All @@ -52,7 +52,6 @@ class COMXAudioCodecOMX
SwrContext* m_pConvert;
enum AVSampleFormat m_iSampleFormat;
enum AVSampleFormat m_desiredSampleFormat;
enum PCMChannels m_channelMap[PCM_MAX_CH + 1];

AVFrame* m_pFrame1;

Expand All @@ -62,13 +61,10 @@ class COMXAudioCodecOMX
bool m_bOpenedCodec;

int m_channels;
uint64_t m_layout;

bool m_bFirstFrame;
bool m_bGotFrame;
DllAvCodec m_dllAvCodec;
DllAvUtil m_dllAvUtil;
DllSwResample m_dllSwResample;

void BuildChannelMap();
};
12 changes: 5 additions & 7 deletions OMXPlayerAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ OMXPlayerAudio::OMXPlayerAudio()
m_decoder = NULL;
m_flush = false;
m_cached_size = 0;
m_pChannelMap = NULL;
m_pAudioCodec = NULL;
m_player_error = true;
m_max_data_size = 3 * 1024 * 1024;
m_fifo_size = 2.0f;
m_live = false;
m_layout = PCM_LAYOUT_2_0;

pthread_cond_init(&m_packet_cond, NULL);
pthread_cond_init(&m_audio_cond, NULL);
Expand Down Expand Up @@ -91,7 +91,7 @@ void OMXPlayerAudio::UnLockDecoder()

bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader,
std::string device, bool passthrough, bool hw_decode,
bool boost_on_downmix, bool use_thread, bool is_live, float queue_size, float fifo_size)
bool boost_on_downmix, bool use_thread, bool is_live, enum PCMLayout layout, float queue_size, float fifo_size)
{
if(ThreadHandle())
Close();
Expand All @@ -115,9 +115,9 @@ bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *
m_use_thread = use_thread;
m_flush = false;
m_live = is_live;
m_layout = layout;
m_cached_size = 0;
m_pAudioCodec = NULL;
m_pChannelMap = NULL;
if (queue_size != 0.0)
m_max_data_size = queue_size * 1024 * 1024;
if (fifo_size != 0.0)
Expand Down Expand Up @@ -382,7 +382,6 @@ bool OMXPlayerAudio::OpenAudioCodec()
return false;
}

m_pChannelMap = m_pAudioCodec->GetChannelMap();
return true;
}

Expand Down Expand Up @@ -431,9 +430,8 @@ bool OMXPlayerAudio::OpenDecoder()
if(m_passthrough)
m_hw_decode = false;

unsigned int downmix_channels = m_hints.channels;
bAudioRenderOpen = m_decoder->Initialize(m_device.substr(4), m_hints.channels, m_pChannelMap,
m_hints, downmix_channels, m_hints.samplerate, m_pAudioCodec->GetBitsPerSample(), m_boost_on_downmix,
bAudioRenderOpen = m_decoder->Initialize(m_device.substr(4), m_hints.channels, m_pAudioCodec->GetChannelMap(),
m_hints, m_layout, m_hints.samplerate, m_pAudioCodec->GetBitsPerSample(), m_boost_on_downmix,
m_av_clock, m_passthrough, m_hw_decode, m_live, m_fifo_size);

m_codec_name = m_omx_reader->GetCodecName(OMXSTREAM_AUDIO);
Expand Down
4 changes: 2 additions & 2 deletions OMXPlayerAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class OMXPlayerAudio : public OMXThread
bool m_use_thread;
bool m_flush;
bool m_live;
enum PCMChannels *m_pChannelMap;
enum PCMLayout m_layout;
unsigned int m_cached_size;
unsigned int m_max_data_size;
float m_fifo_size;
Expand All @@ -89,7 +89,7 @@ class OMXPlayerAudio : public OMXThread
~OMXPlayerAudio();
bool Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader,
std::string device, bool passthrough, bool hw_decode,
bool boost_on_downmix, bool use_thread, bool is_live, float queue_size, float fifo_size);
bool boost_on_downmix, bool use_thread, bool is_live, enum PCMLayout layout, float queue_size, float fifo_size);
bool Close();
bool Decode(OMXPacket *pkt);
void Process();
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Using OMXPlayer
--threshold n Amount of buffered data required to come out of buffering in seconds
--orientation n Set orientation of video (0, 90, 180 or 270)
--live Set for live tv or vod type stream
--layout Set output speaker layout (e.g. 5.1)
--key-config <file> Uses key bindings specified in <file> instead of the default

For example:
Expand Down
23 changes: 22 additions & 1 deletion omxplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ void print_usage()
printf(" --threshold n Amount of buffered data required to come out of buffering in seconds\n");
printf(" --orientation n Set orientation of video (0, 90, 180 or 270)\n");
printf(" --live Set for live tv or vod type stream\n");
printf(" --layout Set output speaker layout (e.g. 5.1)\n");
printf(" --key-config <file> Uses key bindings specified in <file> instead of the default\n");
}

Expand Down Expand Up @@ -545,6 +546,7 @@ int main(int argc, char *argv[])
float m_threshold = -1.0f; // amount of audio/video required to come out of buffering
int m_orientation = -1; // unset
bool m_live = false; // set to true for live tv or vod for low buffering
enum PCMLayout m_layout = PCM_LAYOUT_2_0;
TV_DISPLAY_STATE_T tv_state;

const int font_opt = 0x100;
Expand All @@ -569,6 +571,7 @@ int main(int argc, char *argv[])
const int no_osd_opt = 0x202;
const int orientation_opt = 0x204;
const int live_opt = 0x205;
const int layout_opt = 0x206;

struct option longopts[] = {
{ "info", no_argument, NULL, 'i' },
Expand Down Expand Up @@ -611,6 +614,7 @@ int main(int argc, char *argv[])
{ "no-osd", no_argument, NULL, no_osd_opt },
{ "orientation", required_argument, NULL, orientation_opt },
{ "live", no_argument, NULL, live_opt },
{ "layout", required_argument, NULL, layout_opt },
{ 0, 0, 0, 0 }
};

Expand Down Expand Up @@ -764,6 +768,23 @@ int main(int argc, char *argv[])
case live_opt:
m_live = true;
break;
case layout_opt:
{
const char *layouts[] = {"2.0", "2.1", "3.0", "3.1", "4.0", "4.1", "5.0", "5.1", "7.0", "7.1"};
unsigned i;
for (i=0; i<sizeof layouts/sizeof *layouts; i++)
if (strcmp(optarg, layouts[i]) == 0)
{
m_layout = (enum PCMLayout)i;
break;
}
if (i == sizeof layouts/sizeof *layouts)
{
print_usage();
return 0;
}
break;
}
case 'b':
m_blank_background = true;
break;
Expand Down Expand Up @@ -1002,7 +1023,7 @@ int main(int argc, char *argv[])

if(m_has_audio && !m_player_audio.Open(m_hints_audio, m_av_clock, &m_omx_reader, deviceString,
m_passthrough, m_use_hw_audio,
m_boost_on_downmix, m_thread_player, m_live, audio_queue_size, audio_fifo_size))
m_boost_on_downmix, m_thread_player, m_live, m_layout, audio_queue_size, audio_fifo_size))
goto do_exit;

if(m_has_audio)
Expand Down
Loading

0 comments on commit 38f05ee

Please sign in to comment.