summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrant Thomsen <brant.thomsen@harman.com>2017-08-21 16:20:00 -0600
committerBrant Thomsen <brant.thomsen@harman.com>2017-08-22 11:52:14 -0600
commitbb7868bd875257f4716ec61cb09d3a4bbbbbfc04 (patch)
tree33e903b6ab2851d7c5a4dade31f72511b01d613d
parent944c6977ace0e4e11b5f40401ff5d9a6e22d4359 (diff)
downloadOpen-AVB-bb7868bd875257f4716ec61cb09d3a4bbbbbfc04.tar.gz
AAF Integer Conversion Support Added
When using AAF in 16-bit, 24-bit, or 32-bit integer mode, the incoming audio can be 16-bit, 24-bit, or 32-bit integer data. The incoming audio is converted to the desired internal format. Note that the conversion only works correctly if the incoming audio is big- endian, which IEEE 1722-2016 Clause 7.3.5 lists as a requirement for AAF. INI files updated to match IEEE 1722-2016 specification.
-rwxr-xr-xlib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio.c110
-rwxr-xr-xlib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio_pub.h2
-rw-r--r--lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_file_talker.ini4
-rw-r--r--lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener.ini11
-rw-r--r--lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener_auto.ini11
-rw-r--r--lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_talker.ini10
6 files changed, 116 insertions, 32 deletions
diff --git a/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio.c b/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio.c
index b29563d2..ef3b4a91 100755
--- a/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio.c
+++ b/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio.c
@@ -32,7 +32,7 @@ https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
/*
* MODULE SUMMARY : Implementation for AAF mapping module
*
- * AAF is defined in IEEE 1722-rev1/D12 (still in draft as of Feb 2015).
+ * AAF (AVTP Audio Format) is defined in IEEE 1722-2016 Clause 7.
*/
#include <stdlib.h>
@@ -141,6 +141,7 @@ typedef struct {
aaf_sample_format_t aaf_format;
U8 aaf_bit_depth;
U32 payloadSize;
+ U32 payloadSizeMax;
U8 aaf_event_field;
@@ -273,13 +274,19 @@ static void x_calculateSizes(media_q_t *pMediaQ)
// AAF packet size calculations
pPubMapInfo->packetFrameSizeBytes = pPubMapInfo->packetSampleSizeBytes * pPubMapInfo->audioChannels;
- pPvtData->payloadSize = pPubMapInfo->framesPerPacket * pPubMapInfo->packetFrameSizeBytes;
+ pPvtData->payloadSize = pPvtData->payloadSizeMax =
+ pPubMapInfo->framesPerPacket * pPubMapInfo->packetFrameSizeBytes;
AVB_LOGF_INFO("packet: sampleSz=%d * channels=%d => frameSz=%d * %d => payloadSz=%d",
pPubMapInfo->packetSampleSizeBytes,
pPubMapInfo->audioChannels,
pPubMapInfo->packetFrameSizeBytes,
pPubMapInfo->framesPerPacket,
pPvtData->payloadSize);
+ if (pPvtData->aaf_format >= AAF_FORMAT_INT_32 && pPvtData->aaf_format <= AAF_FORMAT_INT_16) {
+ // Determine the largest size we could receive before adjustments.
+ pPvtData->payloadSizeMax = 4 * pPubMapInfo->audioChannels * pPubMapInfo->framesPerPacket;
+ AVB_LOGF_DEBUG("packet: payloadSizeMax=%d", pPvtData->payloadSizeMax);
+ }
// MediaQ item size calculations
pPubMapInfo->packingFactor = pPvtData->packingFactor;
@@ -378,7 +385,7 @@ U16 openavbMapAVTPAudioMaxDataSizeCB(media_q_t *pMediaQ)
}
AVB_TRACE_EXIT(AVB_TRACE_MAP);
- return pPvtData->payloadSize + TOTAL_HEADER_SIZE;
+ return pPvtData->payloadSizeMax + TOTAL_HEADER_SIZE;
}
AVB_TRACE_EXIT(AVB_TRACE_MAP);
return 0;
@@ -626,8 +633,11 @@ bool openavbMapAVTPAudioRxCB(media_q_t *pMediaQ, U8 *pData, U32 dataLen)
return FALSE;
}
+ aaf_sample_format_t incoming_aaf_format;
+ U8 incoming_bit_depth;
int tmp;
bool dataValid = TRUE;
+ bool dataConversionEnabled = FALSE;
U32 timestamp = ntohl(*pHdr++);
U32 format_info = ntohl(*pHdr++);
@@ -637,18 +647,26 @@ bool openavbMapAVTPAudioRxCB(media_q_t *pMediaQ, U8 *pData, U32 dataLen)
bool streamSparseMode = (pHdrV0[HIDX_AVTP_HIDE7_SP] & SP_M0_BIT) ? TRUE : FALSE;
U16 payloadLen = ntohs(*(U16 *)(&pHdrV0[HIDX_STREAM_DATA_LEN16]));
- if (payloadLen > dataLen - TOTAL_HEADER_SIZE) {
+ if (payloadLen > dataLen - TOTAL_HEADER_SIZE) {
if (pPvtData->dataValid)
AVB_LOGF_ERROR("header data len %d > actual data len %d",
payloadLen, dataLen - TOTAL_HEADER_SIZE);
dataValid = FALSE;
}
- if ((tmp = ((format_info >> 24) & 0xFF)) != pPvtData->aaf_format) {
- if (pPvtData->dataValid)
- AVB_LOGF_ERROR("Listener format %d doesn't match received data (%d)",
- pPvtData->aaf_format, tmp);
- dataValid = FALSE;
+ if ((incoming_aaf_format = (aaf_sample_format_t) ((format_info >> 24) & 0xFF)) != pPvtData->aaf_format) {
+ // Check if we can convert the incoming data.
+ if (incoming_aaf_format >= AAF_FORMAT_INT_32 && incoming_aaf_format <= AAF_FORMAT_INT_16 &&
+ pPvtData->aaf_format >= AAF_FORMAT_INT_32 && pPvtData->aaf_format <= AAF_FORMAT_INT_16) {
+ // Integer conversion should be supported.
+ dataConversionEnabled = TRUE;
+ }
+ else {
+ if (pPvtData->dataValid)
+ AVB_LOGF_ERROR("Listener format %d doesn't match received data (%d)",
+ pPvtData->aaf_format, incoming_aaf_format);
+ dataValid = FALSE;
+ }
}
if ((tmp = ((format_info >> 20) & 0x0F)) != pPvtData->aaf_rate) {
if (pPvtData->dataValid)
@@ -662,17 +680,29 @@ bool openavbMapAVTPAudioRxCB(media_q_t *pMediaQ, U8 *pData, U32 dataLen)
pPubMapInfo->audioChannels, tmp);
dataValid = FALSE;
}
- if ((tmp = (format_info & 0xFF)) != pPvtData->aaf_bit_depth) {
+ if ((incoming_bit_depth = (U8) (format_info & 0xFF)) == 0) {
if (pPvtData->dataValid)
- AVB_LOGF_ERROR("Listener bit depth (%d) doesn't match received data (%d)",
- pPvtData->aaf_bit_depth, tmp);
+ AVB_LOGF_ERROR("Listener bit depth (%d) not valid",
+ incoming_bit_depth);
dataValid = FALSE;
}
if ((tmp = ((packet_info >> 16) & 0xFFFF)) != pPvtData->payloadSize) {
- if (pPvtData->dataValid)
- AVB_LOGF_ERROR("Listener payload size (%d) doesn't match received data (%d)",
- pPvtData->payloadSize, tmp);
- dataValid = FALSE;
+ if (!dataConversionEnabled) {
+ if (pPvtData->dataValid)
+ AVB_LOGF_ERROR("Listener payload size (%d) doesn't match received data (%d)",
+ pPvtData->payloadSize, tmp);
+ dataValid = FALSE;
+ }
+ else {
+ int nInSampleLength = 6 - incoming_aaf_format; // Calculate the number of integer bytes per sample received
+ int nOutSampleLength = 6 - pPvtData->aaf_format; // Calculate the number of integer bytes per sample we want
+ if (tmp / nInSampleLength != pPvtData->payloadSize / nOutSampleLength) {
+ if (pPvtData->dataValid)
+ AVB_LOGF_ERROR("Listener payload samples (%d) doesn't match received data samples (%d)",
+ pPvtData->payloadSize / nOutSampleLength, tmp / nInSampleLength);
+ dataValid = FALSE;
+ }
+ }
}
if ((tmp = ((packet_info >> 8) & 0x0F)) != pPvtData->aaf_event_field) {
if (pPvtData->dataValid)
@@ -724,11 +754,53 @@ bool openavbMapAVTPAudioRxCB(media_q_t *pMediaQ, U8 *pData, U32 dataLen)
}
}
if (dataValid) {
- if (pPubMapInfo->intf_rx_translate_cb) {
- pPubMapInfo->intf_rx_translate_cb(pMediaQ, pPayload, pPvtData->payloadSize);
+ if (!dataConversionEnabled) {
+ // Just use the raw incoming data, and ignore the incoming bit_depth.
+ if (pPubMapInfo->intf_rx_translate_cb) {
+ pPubMapInfo->intf_rx_translate_cb(pMediaQ, pPayload, pPvtData->payloadSize);
+ }
+
+ memcpy((uint8_t *)pMediaQItem->pPubData + pMediaQItem->dataLen, pPayload, pPvtData->payloadSize);
+ }
+ else {
+ static U8 s_audioBuffer[1500];
+ U8 *pInData = pPayload;
+ U8 *pInDataEnd = pPayload + payloadLen;
+ U8 *pOutData = s_audioBuffer;
+ int nInSampleLength = 6 - incoming_aaf_format; // Calculate the number of integer bytes per sample received
+ int nOutSampleLength = 6 - pPvtData->aaf_format; // Calculate the number of integer bytes per sample we want
+ int i;
+ if (nInSampleLength < nOutSampleLength) {
+ // We need to pad the data supplied.
+ while (pInData < pInDataEnd) {
+ for (i = 0; i < nInSampleLength; ++i) {
+ *pOutData++ = *pInData++;
+ }
+ for ( ; i < nOutSampleLength; ++i) {
+ *pOutData++ = 0; // Value specified in Clause 7.3.4.
+ }
+ }
+ }
+ else {
+ // We need to truncate the data supplied.
+ while (pInData < pInDataEnd) {
+ for (i = 0; i < nOutSampleLength; ++i) {
+ *pOutData++ = *pInData++;
+ }
+ pInData += (nInSampleLength - nOutSampleLength);
+ }
+ }
+ if (pOutData - s_audioBuffer != pPvtData->payloadSize) {
+ AVB_LOGF_ERROR("Output not expected size (%d instead of %d)", pOutData - s_audioBuffer, pPvtData->payloadSize);
+ }
+
+ if (pPubMapInfo->intf_rx_translate_cb) {
+ pPubMapInfo->intf_rx_translate_cb(pMediaQ, s_audioBuffer, pPvtData->payloadSize);
+ }
+
+ memcpy((uint8_t *)pMediaQItem->pPubData + pMediaQItem->dataLen, s_audioBuffer, pPvtData->payloadSize);
}
- memcpy((uint8_t *)pMediaQItem->pPubData + pMediaQItem->dataLen, pPayload, pPvtData->payloadSize);
pMediaQItem->dataLen += pPvtData->payloadSize;
}
diff --git a/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio_pub.h b/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio_pub.h
index d8f82906..213f3bb6 100755
--- a/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio_pub.h
+++ b/lib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio_pub.h
@@ -32,7 +32,7 @@ https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
/*
* HEADER SUMMARY : AVTP Audio Format mapping module public interface
*
- * AAF is defined in IEEE 1722a (still in draft as of Feb 2015).
+ * AAF (AVTP Audio Format) is defined in IEEE 1722-2016 Clause 7.
*
* map_nv_tx_rate must be set in the .ini file.
*/
diff --git a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_file_talker.ini b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_file_talker.ini
index 18535347..210ae966 100644
--- a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_file_talker.ini
+++ b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_file_talker.ini
@@ -127,3 +127,7 @@ intf_fn = openavbIntfWavFileInitialize
# intf_nv_file_name: The fully qualified file name.
intf_nv_file_name = test.wav
+
+# AAF is defined to be big-endian.
+intf_nv_audio_endian = big
+
diff --git a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener.ini b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener.ini
index 3ba10918..c7c799de 100644
--- a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener.ini
+++ b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener.ini
@@ -115,15 +115,14 @@ intf_fn = openavbIntfAlsaInitialize
intf_nv_device_name = default
# intf_nv_audio_rate: Valid values that are supported by AAF are:
-# 8000, 16000, 32000, 44100, 48000, 88200, 96000, 176400 and 192000
+# 8000, 16000, 24000, 32000, 44100, 48000, 88200, 96000, 176400 and 192000
intf_nv_audio_rate = 48000
# intf_nv_audio_bit_depth: Valid values that are supported by AAF are:
-# 8, 16, 32
+# 16, 24, 32
intf_nv_audio_bit_depth = 32
-# intf_nv_audio_channels: Valid values that are supported by AAF are:
-# 1 - 8
+# intf_nv_audio_channels
intf_nv_audio_channels = 2
# intf_nv_allow_resampling: 0 = disable software resampling. 1 = allow software resampling. Default is disable.
@@ -137,3 +136,7 @@ intf_nv_start_threshold_periods = 3
# This influence ALSA's period_time and period_size parameters and the result value should be the nearest possible.
# Initial playback latency is equal intf_nv_start_threshold_periods * intf_nv_period_time. If not set internal defaults are used.
# intf_nv_period_time = 31250
+
+# AAF is defined to be big-endian.
+intf_nv_audio_endian = big
+
diff --git a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener_auto.ini b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener_auto.ini
index 7c1f48b3..d3d064b1 100644
--- a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener_auto.ini
+++ b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_listener_auto.ini
@@ -111,15 +111,14 @@ intf_fn = openavbIntfAlsaInitialize
intf_nv_device_name = default
# intf_nv_audio_rate: Valid values that are supported by AAF are:
-# 8000, 16000, 32000, 44100, 48000, 88200, 96000, 176400 and 192000
+# 8000, 16000, 24000, 32000, 44100, 48000, 88200, 96000, 176400 and 192000
intf_nv_audio_rate = 48000
# intf_nv_audio_bit_depth: Valid values that are supported by AAF are:
-# 8, 16, 32
+# 16, 24, 32
intf_nv_audio_bit_depth = 16
-# intf_nv_audio_channels: Valid values that are supported by AAF are:
-# 1 - 8
+# intf_nv_audio_channels
intf_nv_audio_channels = 2
# intf_nv_allow_resampling: 0 = disable software resampling. 1 = allow software resampling. Default is disable.
@@ -133,3 +132,7 @@ intf_nv_start_threshold_periods = 3
# This influence ALSA's period_time and period_size parameters and the result value should be the nearest possible.
# Initial playback latency is equal intf_nv_start_threshold_periods * intf_nv_period_time. If not set internal defaults are used.
# intf_nv_period_time = 31250
+
+# AAF is defined to be big-endian.
+intf_nv_audio_endian = big
+
diff --git a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_talker.ini b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_talker.ini
index 5ff3d2d5..a6a85071 100644
--- a/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_talker.ini
+++ b/lib/avtp_pipeline/platform/Linux/intf_alsa/aaf_talker.ini
@@ -152,17 +152,19 @@ intf_fn = openavbIntfAlsaInitialize
intf_nv_device_name = default
# intf_nv_audio_rate: Valid values that are supported by AAF are:
-# 8000, 16000, 32000, 44100, 48000, 88200, 96000, 176400 and 192000
+# 8000, 16000, 24000, 32000, 44100, 48000, 88200, 96000, 176400 and 192000
intf_nv_audio_rate = 48000
# intf_nv_audio_bit_depth: Valid values that are supported by AAF are:
-# 8, 16, 32
+# 16, 24, 32
intf_nv_audio_bit_depth = 32
-# intf_nv_audio_channels: Valid values that are supported by AAF are:
-# 1 - 8
+# intf_nv_audio_channels
intf_nv_audio_channels = 2
# intf_nv_allow_resampling: 0 = disable software resampling. 1 = allow software resampling. Default is disable.
intf_nv_allow_resampling = 1
+# AAF is defined to be big-endian.
+intf_nv_audio_endian = big
+