summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrant Thomsen <brant.thomsen@harman.com>2017-12-06 16:35:57 -0700
committerBrant Thomsen <brant.thomsen@harman.com>2017-12-06 16:35:57 -0700
commit23681b9c4e7db6bf6ab1d97c83f2dbb3c6ec6ddc (patch)
treeb69a96ce4f030df6516485571b47ff9ad71f4241
parent5486b92890334c3a80bcd2af84866add9a94a04a (diff)
parent80c9fd28a6f926850b39df310e1736d45317ac5c (diff)
downloadOpen-AVB-feature-avtp-pipeline-experimental.tar.gz
Merge branch 'avb_endpoint' of ssh://git.ctg-server.hmg.ad.harman.com:2222/clones/Open-AVB into feature-avtp-pipeline-experimentalfeature-avtp-pipeline-experimental
# Conflicts: # lib/avtp_pipeline/README.md
-rw-r--r--Makefile10
-rw-r--r--lib/avtp_pipeline/README.md41
-rw-r--r--lib/avtp_pipeline/avtp/openavb_avtp.c84
-rw-r--r--lib/avtp_pipeline/avtp/openavb_avtp.h11
-rwxr-xr-xlib/avtp_pipeline/include/openavb_map_pub.h2
-rwxr-xr-xlib/avtp_pipeline/map_aaf_audio/openavb_map_aaf_audio.c2
-rw-r--r--lib/avtp_pipeline/platform/Linux/intf_alsa/example_listener.ini135
-rw-r--r--lib/avtp_pipeline/platform/Linux/intf_alsa/example_talker.ini181
-rwxr-xr-xrun_avtp_pipeline.sh24
-rwxr-xr-xstop_avtp_pipeline.sh19
10 files changed, 469 insertions, 40 deletions
diff --git a/Makefile b/Makefile
index 2a931c3a..8c5157bd 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,6 @@ help:
@echo ' avtp_pipeline - AVTP pipeline'
@echo ' avtp_pipeline_doc - AVTP pipeline doc'
@echo ' avtp_avdecc - AVTP avdecc'
- @echo ' avtp_avdecc_doc - AVTP avdecc doc'
@echo ''
@echo ' examples_all - build all examples (simple_talker simple_listener mrp_client live_stream jackd-talker jackd-listener)'
@echo ' simple_talker - simple_talker application'
@@ -131,24 +130,21 @@ live_stream:
live_stream_clean:
$(call descend,examples/live_stream/,clean)
-avtp_pipeline: lib
+avtp_pipeline:
$(MAKE) -s -C lib/avtp_pipeline -f avtp_pipeline.mk
avtp_pipeline_clean:
$(MAKE) -s -C lib/avtp_pipeline -f avtp_pipeline.mk clean
-avtp_pipeline_doc: lib
+avtp_pipeline_doc:
$(MAKE) -s -C lib/avtp_pipeline -f avtp_pipeline.mk doc
-avtp_avdecc: lib
+avtp_avdecc:
$(MAKE) -s -C lib/avtp_pipeline -f avtp_avdecc.mk
avtp_avdecc_clean:
$(MAKE) -s -C lib/avtp_pipeline -f avtp_avdecc.mk clean
-avtp_avdecc_doc: lib
- $(MAKE) -s -C lib/avtp_pipeline -f avtp_avdecc.mk doc
-
examples_all: examples_common simple_talker simple_listener mrp_client live_stream jackd-talker \
jackd-listener simple_rx
diff --git a/lib/avtp_pipeline/README.md b/lib/avtp_pipeline/README.md
index cbf89a1a..ac03a856 100644
--- a/lib/avtp_pipeline/README.md
+++ b/lib/avtp_pipeline/README.md
@@ -63,22 +63,35 @@ The openavb_avdecc binary needs to be run in addition to the AVTP pipeline binar
## Running OpenAvnu daemons
- Helper scripts in the repo root.
- `$ sudo ./run_igb.sh eth1`
- - Load the igb driver. Supply the interface name (ethx) as parameter. Only needed if using IGB support for the Intel i210 adapter.
+ - Load the igb driver. Supply the interface name (ethx) as parameter. Only needed if using IGB support for the Intel i210 adapter.
- `$ sudo ./run_daemons.sh eth1`
- - Start gptp, msrp, maap, and shaper daemons. Supply the interface name (ethx) as parameter.
+ - Start the gptp, msrp, maap, and shaper daemons. Supply the interface name (ethx) as parameter.
- Daemons can also be started individually using the run_gptp.sh, run_srp.sh, run_maap.sh, and run_shaper.sh scripts.
-
-## Running OpenAvnu simple talker example
-- `$ sudo ./run_simple_talker.sh eth1`
- - Run the current OpenAvnu simple talker example. Supply the interface name (ethx) as parameter.
-
-## Running OpenAvnu Echo Talker
-- `$ sudo ./run_echo_talker.sh eth1`
- - Run the AVTP Echo talker test stream. Supply the interface name (ethx) as parameter.
-
-## Running OpenAvnu Echo Listener
-- `$ sudo ./run_echo_listener.sh eth1`
- - Run the AVTP Echo talker test stream. Supply the interface name (ethx) as parameter.
+- `$ sudo ./stop_daemons.sh`
+ - Stop the gptp, msrp, maap, and shaper daemons. Don't use this command while AVTP Pipeline is running.
+
+## Running OpenAvnu AVTP Pipeline example
+- `$ sudo ./run_avtp_pipeline.sh eth1`
+ - Run the current OpenAvnu AVTP Pipeline example. Supply the interface name (ethx) as parameter.
+- `$ sudo ./stop_avtp_pipeline.sh eth1`
+ - Stop the current OpenAvnu AVTP Pipeline example. The script will also attempt to cleanly recover if the AVTP pipeline binaries crashed.
+
+The AVTP Pipeline example is expected to be run simultaneously on two or more different Linux computers,
+with the network interfaces connected using AVB-capable switches.
+(The daemons do not currently support using two different network interfaces on the same computer, so different computers must be used.)
+You can refer to the list of [Avnu Certified Products](http://avnu.org/certified-products/) for switches with AVB/TSN support.
+
+To connect the Talker and Listener with the example implementation, you need to use an AVDECC controller.
+(These are also referred to as 1722.1 or ATDECC controllers.)
+This will tell the Listener(s) which stream to listen to,
+and allow the Talker and Listener(s) to coordinate when they should start streaming.
+There are several AVDECC controllers available, including one in the OpenAvnu avdecc-lib/controller folder.
+
+The AVTP Pipeline example Talker and Listener should also be compatible with other AVB/TSN products that support 8-channel,
+48K/24-bit [IEC 61883-6](https://webstore.iec.ch/preview/info_iec61883-6%7Bed2.0%7Den.pdf) audio and AVDECC management.
+The list of [Avnu Certified Products](http://avnu.org/certified-products/) includes some of them.
+The example Talker and Listener has also been used successfully to stream audio to and from Apple Macbooks running macOS version 10.12 (Sierra) and later,
+and controlled with the Apple Macbook built-in AVDECC controller (avbutil).
## Benchmark results
diff --git a/lib/avtp_pipeline/avtp/openavb_avtp.c b/lib/avtp_pipeline/avtp/openavb_avtp.c
index cfea6adc..a753dff0 100644
--- a/lib/avtp_pipeline/avtp/openavb_avtp.c
+++ b/lib/avtp_pipeline/avtp/openavb_avtp.c
@@ -322,12 +322,23 @@ static openavbRC fillAvtpHdr(avtp_stream_t *pStream, U8 *pFill)
// - 1 bit tv (timestamp valid) = 1
// TODO: set mr correctly
*pFill++ = 0x81;
+#ifdef EXTENDED_SEQUENCE_NUMBERS
+ // - 8 bits sequence num = increments with each frame
+ *pFill++ = (pStream->avtp_sequence_num & 0x00FF);
+ // - 4 bits upper bits of sequence num = increments every 256 frames
+ // - 1 bit using extended seq numbers = 1
+ // - 2 bits reserved = 0
+ // - 1 bit tu (timestamp uncertain) = 1 when no PTP sync
+ // TODO: set tu correctly
+ *pFill++ = (U8) ((pStream->avtp_sequence_num & 0x0F00) >> 4) | 0x08;
+#else
// - 8 bits sequence num = increments with each frame
*pFill++ = pStream->avtp_sequence_num;
- // - 7 bits reserved = 0;
+ // - 7 bits reserved = 0
// - 1 bit tu (timestamp uncertain) = 1 when no PTP sync
// TODO: set tu correctly
*pFill++ = 0;
+#endif
// - 8 bytes stream_id
memcpy(pFill, (U8 *)&pStream->streamIDnet, 8);
break;
@@ -424,7 +435,11 @@ openavbRC openavbAvtpTx(void *pv, bool bSend, bool txBlockingInIntf)
}
// Increment the sequence number now that we are sure this is a good packet.
+#ifdef EXTENDED_SEQUENCE_NUMBERS
+ pStream->avtp_sequence_num = ((pStream->avtp_sequence_num + 1) & 0x0FFF);
+#else
pStream->avtp_sequence_num++;
+#endif
// Mirror the frame.
int i;
@@ -544,8 +559,13 @@ static void x_avtpRxFrame(avtp_stream_t *pStream, U8 *pFrame, U32 frameLen)
{
AVB_TRACE_ENTRY(AVB_TRACE_AVTP_DETAIL);
IF_LOG_INTERVAL(4096) AVB_LOGF_DEBUG("pFrame=%p, len=%u", pFrame, frameLen);
- U8 subtype, flags, flags2, rxSeq, nLost, avtpVersion;
+ U8 subtype, flags, flags2, avtpVersion;
U8 *pRead = pFrame;
+#ifdef EXTENDED_SEQUENCE_NUMBERS
+ U16 rxSeq, nLost;
+#else
+ U8 rxSeq, nLost;
+#endif
// AVTP Header
//
@@ -561,23 +581,53 @@ static void x_avtpRxFrame(avtp_stream_t *pStream, U8 *pFrame, U32 frameLen)
rxSeq = *pRead++;
- if (pStream->nLost == -1) {
- // first frame received, don't check for mismatch
- pStream->nLost = 0;
- }
- else if (pStream->avtp_sequence_num != rxSeq) {
- nLost = (rxSeq - pStream->avtp_sequence_num)
- + (rxSeq < pStream->avtp_sequence_num ? 256 : 0);
- AVB_LOGF_INFO("AVTP sequence mismatch: expected: %3u,\tgot: %3u,\tlost %3d",
- pStream->avtp_sequence_num, rxSeq, nLost);
- pStream->nLost += nLost;
-
- // Notify the map that frames were lost.
- if (pStream->pMapCB->map_rx_lost_cb) {
- pStream->pMapCB->map_rx_lost_cb(pStream->pMediaQ, nLost);
+#ifdef EXTENDED_SEQUENCE_NUMBERS
+ if ((*pRead & 0x08) != 0) {
+ // Get the upper 4 bits of the sequence number.
+ rxSeq |= (((U16) (*pRead & 0xF0)) << 4);
+
+ if (pStream->nLost == -1) {
+ // first frame received, don't check for mismatch
+ pStream->nLost = 0;
+ }
+ else if (pStream->avtp_sequence_num != rxSeq) {
+ nLost = (rxSeq - pStream->avtp_sequence_num)
+ + (rxSeq < pStream->avtp_sequence_num ? 0x1000 : 0);
+ AVB_LOGF_INFO("AVTP sequence mismatch: expected: %4u,\tgot: %4u,\tlost %4d",
+ pStream->avtp_sequence_num, rxSeq, nLost);
+ pStream->nLost += nLost;
+
+ // Notify the map that frames were lost.
+ if (pStream->pMapCB->map_rx_lost_cb) {
+ pStream->pMapCB->map_rx_lost_cb(pStream->pMediaQ, nLost);
+ }
+ }
+ pStream->avtp_sequence_num = ((rxSeq + 1) & 0x0FFF);
+ } else
+#endif
+ {
+ if (pStream->nLost == -1) {
+ // first frame received, don't check for mismatch
+ pStream->nLost = 0;
+ }
+ else if (pStream->avtp_sequence_num != rxSeq) {
+ nLost = (rxSeq - pStream->avtp_sequence_num)
+ + (rxSeq < pStream->avtp_sequence_num ? 0x100 : 0);
+ AVB_LOGF_INFO("AVTP sequence mismatch: expected: %3u,\tgot: %3u,\tlost %3d",
+ pStream->avtp_sequence_num, rxSeq, nLost);
+ pStream->nLost += nLost;
+
+ // Notify the map that frames were lost.
+ if (pStream->pMapCB->map_rx_lost_cb) {
+ pStream->pMapCB->map_rx_lost_cb(pStream->pMediaQ, nLost);
+ }
}
+#ifdef EXTENDED_SEQUENCE_NUMBERS
+ pStream->avtp_sequence_num = ((rxSeq + 1) & 0x00FF);
+#else
+ pStream->avtp_sequence_num = rxSeq + 1;
+#endif
}
- pStream->avtp_sequence_num = rxSeq + 1;
pStream->bytes += frameLen;
diff --git a/lib/avtp_pipeline/avtp/openavb_avtp.h b/lib/avtp_pipeline/avtp/openavb_avtp.h
index 71139271..eb163373 100644
--- a/lib/avtp_pipeline/avtp/openavb_avtp.h
+++ b/lib/avtp_pipeline/avtp/openavb_avtp.h
@@ -83,6 +83,13 @@ typedef struct {
} avtp_state_t;
+/* If EXTENDED_SEQUENCE_NUMBERS is defined, uses the 4 most significant bits of the reserved space
+ * immediately following the sequence_num value to allow for larger sequence numbers.
+ * The bit following those 4 bits is also set to indicate that
+ * extended sequence numbers are in use.
+ */
+//#define EXTENDED_SEQUENCE_NUMBERS
+
/* Info associated with an AVTP stream (RX or TX).
*
* The void* handle that is returned to the client
@@ -117,7 +124,11 @@ typedef struct
// Max frame size
U16 frameLen;
// AVTP sequence number
+#ifdef EXTENDED_SEQUENCE_NUMBERS
+ U16 avtp_sequence_num;
+#else
U8 avtp_sequence_num;
+#endif
// Paused state of the stream
bool bPause;
// Encapsulation-specific state information
diff --git a/lib/avtp_pipeline/include/openavb_map_pub.h b/lib/avtp_pipeline/include/openavb_map_pub.h
index 8e4abeea..feb8a9e5 100755
--- a/lib/avtp_pipeline/include/openavb_map_pub.h
+++ b/lib/avtp_pipeline/include/openavb_map_pub.h
@@ -141,7 +141,7 @@ typedef bool (*openavb_map_rx_cb_t)(media_q_t *pMediaQ, U8 *pData, U32 datalen);
* \param pMediaQ A pointer to the media queue for this stream
* \param numLost The number of sequence numbers missing (i.e. number of lost packets)
*/
-typedef bool (*openavb_map_rx_lost_cb_t)(media_q_t *pMediaQ, U8 numLost);
+typedef bool (*openavb_map_rx_lost_cb_t)(media_q_t *pMediaQ, U16 numLost);
/** This callback will be called when the stream is closing.
*
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 e3a5906a..12636619 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
@@ -1063,7 +1063,7 @@ bool openavbMapAVTPAudioRxCB(media_q_t *pMediaQ, U8 *pData, U32 dataLen)
}
// This callback occurs when running as a listener and data is not available.
-bool openavbMapAVTPAudioRxLostCB(media_q_t *pMediaQ, U8 numLost)
+bool openavbMapAVTPAudioRxLostCB(media_q_t *pMediaQ, U16 numLost)
{
AVB_TRACE_ENTRY(AVB_TRACE_MAP_DETAIL);
diff --git a/lib/avtp_pipeline/platform/Linux/intf_alsa/example_listener.ini b/lib/avtp_pipeline/platform/Linux/intf_alsa/example_listener.ini
new file mode 100644
index 00000000..7b15b48c
--- /dev/null
+++ b/lib/avtp_pipeline/platform/Linux/intf_alsa/example_listener.ini
@@ -0,0 +1,135 @@
+#####################################################################
+# General Talker Configuration for ALSA and
+# uncompressed 61883-6 audio mapping
+#####################################################################
+
+# role: Sets the process as a talker or listener. Valid values are
+# talker or listener
+role = listener
+
+# initial_state: Specify whether the talker or listener should be
+# running or stopped on startup. Valid values are running or stopped.
+# If not specified, the default will depend on how the talker or
+# listener is launched.
+initial_state = stopped
+
+# stream_addr: Used on the listener and should be set to the
+# mac address of the talker.
+#stream_addr = 01:23:45:67:89:ab
+
+# stream_uid: The unique stream ID. The talker and listener must
+# both have this set the same.
+#stream_uid = 0
+
+# dest_addr: When SRP is being used the destination address only needs to
+# be set in the talker. If SRP is not being used the destination address
+# needs to be set in both side the talker and listener.
+# The destination is a multicast address, not a real MAC address, so it
+# does not match the talker or listener's interface MAC. There are
+# several pools of those addresses for use by AVTP defined in 1722.
+# At this time they need to be locally administered and must be in the range
+# of 91:E0:F0:00:FE:00 - 91:E0:F0:00:FE:FF.
+# Typically :00 for the first stream, :01 for the second, etc.
+#dest_addr = 91:e0:f0:00:fe:00
+
+# max_interval_frames: The maximum number of packets that will be sent during
+# an observation interval. This is only used on the talker.
+#max_interval_frames = 1
+
+# max_transit_usec: Allows manually specifying a maximum transit time.
+# On the talker this value is added to the PTP walltime to create the AVTP Timestamp.
+# On the listener this value is used to validate an expected valid timestamp range.
+# Note: For the listener the map_nv_item_count value must be set large enough to
+# allow buffering at least as many AVTP packets that can be transmitted during this
+# max transit time.
+max_transit_usec = 50000
+
+# raw_tx_buffers: The number of raw socket transmit buffers. Typically 4 - 8 are good values.
+# This is only used by the talker. If not set internal defaults are used.
+#raw_tx_buffers = 1
+
+# raw_rx_buffers: The number of raw socket receive buffers. Typically 50 - 100 are good values.
+# This is only used by the listener. If not set internal defaults are used.
+raw_rx_buffers = 200
+
+# report_seconds: How often to output stats. Defaults to 10 seconds. 0 turns off the stats.
+#report_seconds = 1
+
+# Ethernet Interface Name. Only needed on some platforms when stack is built with no endpoint functionality
+ifname = pcap:eth0
+
+# Bit mask used for CPU pinning. Defaults to all cpus can be used (0xffffffff).
+#thread_affinity = 12
+
+# Enable real time scheduling with this priority. Defaults to not use RT sched (0).
+thread_rt_priority = 10
+
+#####################################################################
+# Mapping module configuration
+#####################################################################
+# map_lib: The name of the library file (commonly a .so file) that
+# implements the Initialize function. Comment out the map_lib name
+# and link in the .c file to the openavb_tl executable to embed the mapper
+# directly into the executable unit. There is no need to change anything
+# else. The Initialize function will still be dynamically linked in.
+map_lib = ./libopenavb_map_uncmp_audio.so
+
+# map_fn: The name of the initialize function in the mapper.
+map_fn = openavbMapUncmpAudioInitialize
+
+# map_nv_item_count: The number of media queue elements to hold.
+map_nv_item_count = 400
+
+# map_nv_tx_rate: Transmit rate.
+# This must be set for the uncompressed audio mapping module.
+map_nv_tx_rate = 8000
+
+# map_nv_packing_factor: Multiple of how many packets of audio frames to place in a media queue item.
+# Note: Typically when decreasing the map_nv_tx_rate the packing factor will also be decreased since
+# the number of frames per packet will be increasing.
+map_nv_packing_factor = 256
+
+#####################################################################
+# Interface module configuration
+#####################################################################
+# intf_lib: The name of the library file (commonly a .so file) that
+# implements the Initialize function. Comment out the intf_lib name
+# and link in the .c file to the openavb_tl executable to embed the interface
+# directly into the executable unit. There is no need to change anything
+# else. The Initialize function will still be dynamically linked in.
+# intf_fn: The name of the initialize function in the interface.
+intf_lib = ./libopenavb_intf_alsa.so
+
+# intf_fn: The name of the initialize function in the interface.
+intf_fn = openavbIntfAlsaInitialize
+
+# intf_nv_ignore_timestamp: If set the listener will ignore the timestamp on media queue items.
+# intf_nv_ignore_timestamp = 1
+
+# intf_nv_device_name: ALSA device name. Commonly "default" or "plug:dmix"
+intf_nv_device_name = default
+
+# intf_nv_audio_rate: Sampling rate of the audio (samples/second)
+intf_nv_audio_rate = 48000
+
+# intf_nv_audio_bit_depth: Number of bits per audio sample. Typical values are 16, 24, and 32.
+intf_nv_audio_bit_depth = 24
+
+# intf_nv_audio_channels: Number of channels of audio.
+intf_nv_audio_channels = 8
+
+# intf_nv_allow_resampling: 0 = disable software resampling. 1 = allow software resampling. Default is disable.
+intf_nv_allow_resampling = 1
+
+# intf_nv_start_threshold_periods: The number of period to wait before starting playback. The larger the value to great
+# the latency. The small the number the great chance for a buffer underrun. A good range is 1 - 5.
+intf_nv_start_threshold_periods = 3
+
+# intf_nv_period_time: the number of microseconds which should be set to unify latency between different platforms.
+# 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 = 0
+
+# Default PC audio is little-endian
+intf_nv_audio_endian = little
+
diff --git a/lib/avtp_pipeline/platform/Linux/intf_alsa/example_talker.ini b/lib/avtp_pipeline/platform/Linux/intf_alsa/example_talker.ini
new file mode 100644
index 00000000..d301ea79
--- /dev/null
+++ b/lib/avtp_pipeline/platform/Linux/intf_alsa/example_talker.ini
@@ -0,0 +1,181 @@
+#####################################################################
+# General Talker Configuration for ALSA and
+# uncompressed 61883-6 audio mapping
+#####################################################################
+
+# role: Sets the process as a talker or listener. Valid values are
+# talker or listener
+role = talker
+
+# initial_state: Specify whether the talker or listener should be
+# running or stopped on startup. Valid values are running or stopped.
+# If not specified, the default will depend on how the talker or
+# listener is launched.
+initial_state = stopped
+
+# stream_addr: Used on the listener and should be set to the
+# mac address of the talker.
+#stream_addr = 01:23:45:67:89:ab
+
+# stream_uid: The unique stream ID. The talker and listener must
+# both have this set the same.
+stream_uid = 0
+
+# dest_addr: destination multicast address for the stream.
+#
+# If using SRP and MAAP, dynamic destination addresses are generated
+# automatically by the talker and passed to the listner, and don't
+# need to be configured.
+#
+# Without MAAP, locally administered (static) addresses must be
+# configured. Thouse addresses are in the range of:
+# 91:E0:F0:00:FE:00 - 91:E0:F0:00:FE:FF.
+# Typically use :00 for the first stream, :01 for the second, etc.
+#
+# When SRP is being used the static destination address only needs to
+# be set in the talker. If SRP is not being used the destination address
+# needs to be set (to the same value) in both the talker and listener.
+#
+# The destination is a multicast address, not a real MAC address, so it
+# does not match the talker or listener's interface MAC. There are
+# several pools of those addresses for use by AVTP defined in 1722.
+#
+#dest_addr = 91:e0:f0:00:fe:00
+
+# max_interval_frames: The maximum number of packets that will be sent during
+# an observation interval. This is only used on the talker.
+max_interval_frames = 1
+
+# sr_class: A talker only setting. Values are either A or B. If not set an internal
+# default is used.
+sr_class = A
+
+# sr_rank: A talker only setting. If not set an internal default is used.
+#sr_rank = 1
+
+# max_transit_usec: Allows manually specifying a maximum transit time.
+# On the talker this value is added to the PTP walltime to create the AVTP Timestamp.
+# On the listener this value is used to validate an expected valid timestamp range.
+# Note: For the listener the map_nv_item_count value must be set large enough to
+# allow buffering at least as many AVTP packets that can be transmitted during this
+# max transit time.
+max_transit_usec = 4000
+
+# max_transmit_deficit_usec: Allows setting the maximum packet transmit rate deficit that will
+# be recovered when a talker falls behind. This is only used on a talker side. When a talker
+# can not keep up with the specified transmit rate it builds up a deficit and will attempt to
+# make up for this deficit by sending more packets. There is normally some variability in the
+# transmit rate because of other demands on the system so this is expected. However, without this
+# bounding value the deficit could grew too large in cases such where more streams are started
+# than the system can support and when the number of streams is reduced the remaining streams
+# will attempt to recover this deficit by sending packets at a higher rate. This can cause a problem
+# at the listener side and significantly delay the recovery time before media playback will return
+# to normal. Typically this value can be set to the expected buffer size (in usec) that listeners are
+# expected to be buffering. For low latency solutions this is normally a small value. For non-live
+# media playback such as video playback the listener side buffers can often be large enough to held many
+# seconds of data.
+max_transmit_deficit_usec = 50000
+
+# internal_latency: Allows manually specifying an internal latency time. This is used
+# only on the talker.
+#internal_latency = 0
+
+# max_stale: The number of microseconds beyond the presentation time that media queue items will be purged
+# because they are too old (past the presentation time). This is only used on listener end stations.
+# Note: needing to purge old media queue items is often a sign of some other problem. For example: a delay at
+# stream startup before incoming packets are ready to be processed by the media sink. If this deficit
+# in processing or purging the old (stale) packets is not handled, syncing multiple listeners will be problematic.
+#max_stale = 1000
+
+# raw_tx_buffers: The number of raw socket transmit buffers. Typically 4 - 8 are good values.
+# This is only used by the talker. If not set internal defaults are used.
+#raw_tx_buffers = 4
+
+# raw_rx_buffers: The number of raw socket receive buffers. Typically 50 - 100 are good values.
+# This is only used by the listener. If not set internal defaults are used.
+#raw_rx_buffers = 100
+
+# report_seconds: How often to output stats. Defaults to 10 seconds. 0 turns off the stats.
+#report_seconds = 1
+
+# Ethernet Interface Name. Only needed on some platforms when stack is built with no endpoint functionality
+ifname = pcap:eth0
+
+# vlan_id: VLAN Identifier (1-4094). Used in "no endpoint" builds. Defaults to 2.
+# vlan_id = 2
+
+# Enable fixed timestamping in interface. Defaults to disable (0).
+fixed_timestamp = 1
+
+# Tx packets to process per wake; for values > 1, traffic shaping must be enabled to evenly space the packets.
+#batch_factor = 1
+
+# Bit mask used for CPU pinning. Defaults to all cpus can be used (0xffffffff).
+#thread_affinity = 12
+
+# Enable real time scheduling with this priority. Defaults to not use RT sched (0).
+thread_rt_priority = 20
+
+#####################################################################
+# Mapping module configuration
+#####################################################################
+# map_lib: The name of the library file (commonly a .so file) that
+# implements the Initialize function. Comment out the map_lib name
+# and link in the .c file to the openavb_tl executable to embed the mapper
+# directly into the executable unit. There is no need to change anything
+# else. The Initialize function will still be dynamically linked in.
+map_lib = ./libopenavb_map_uncmp_audio.so
+
+# map_fn: The name of the initialize function in the mapper.
+map_fn = openavbMapUncmpAudioInitialize
+
+# map_nv_item_count: The number of media queue elements to hold.
+map_nv_item_count = 20
+
+# map_nv_tx_rate: Transmit rate.
+# This must be set for the uncompressed audio mapping module.
+map_nv_tx_rate = 8000
+
+# map_nv_packing_factor: Multiple of how many packets of audio frames to place in a media queue item.
+# Note: Typically when decreasing the map_nv_tx_rate the packing factor will also be decreased since
+# the number of frames per packet will be increasing.
+map_nv_packing_factor = 1
+
+#####################################################################
+# Interface module configuration
+#####################################################################
+# intf_lib: The name of the library file (commonly a .so file) that
+# implements the Initialize function. Comment out the intf_lib name
+# and link in the .c file to the openavb_tl executable to embed the interface
+# directly into the executable unit. There is no need to change anything
+# else. The Initialize function will still be dynamically linked in.
+# intf_fn: The name of the initialize function in the interface.
+intf_lib = ./libopenavb_intf_alsa.so
+
+# intf_fn: The name of the initialize function in the interface.
+intf_fn = openavbIntfAlsaInitialize
+
+# intf_nv_ignore_timestamp: If set the listener will ignore the timestamp on media queue items.
+# intf_nv_ignore_timestamp = 1
+
+# intf_nv_device_name: ALSA device name. Commonly "default" or "plug:dmix"
+intf_nv_device_name = default
+
+# intf_nv_audio_rate: Sampling rate of the audio (samples/second)
+intf_nv_audio_rate = 48000
+
+# intf_nv_audio_bit_depth: Number of bits per audio sample. Typical values are 16, 24, and 32.
+intf_nv_audio_bit_depth = 24
+
+# intf_nv_audio_channels: Number of channels of audio.
+intf_nv_audio_channels = 8
+
+# intf_nv_allow_resampling: 0 = disable software resampling. 1 = allow software resampling. Default is disable.
+intf_nv_allow_resampling = 1
+
+# Default PC audio is little-endian
+intf_nv_audio_endian = little
+
+# Clock skew between media clock and PTP clock in nanoseconds-per-second - adjust this to correct Fixed/Real TS Delta drift
+intf_nv_clock_skew_ppb = 0
+
diff --git a/run_avtp_pipeline.sh b/run_avtp_pipeline.sh
new file mode 100755
index 00000000..0a632bb0
--- /dev/null
+++ b/run_avtp_pipeline.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Script to start the AVTP Pipeline talker/listener with 8-channel, 48K/24-bit IEC 61883-6 audio.
+# For more details, refer to the lib/avtp_pipeline/README.md file.
+
+if [ "$#" -eq "0" ]; then
+ echo "Please enter network interface name as parameter. For example:"
+ echo "sudo $0 eth1"
+ echo ""
+ exit -1
+fi
+
+nic=$1
+echo "Starting AVTP Pipeline on "$nic
+
+scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+pushd .
+cd $scriptdir/lib/avtp_pipeline/build/bin
+./openavb_avdecc -I pcap:$nic example_talker.ini example_listener.ini &
+sleep 5
+./openavb_host -I pcap:$nic example_talker.ini example_listener.ini &
+popd
+
diff --git a/stop_avtp_pipeline.sh b/stop_avtp_pipeline.sh
new file mode 100755
index 00000000..81f9ab3c
--- /dev/null
+++ b/stop_avtp_pipeline.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+killall -2 openavb_host
+sleep 1
+killall -2 openavb_avdecc
+
+# Code below this point is to recover in case one of the applications crashes.
+
+sleep 5
+
+killall -9 openavb_host
+killall -9 openavb_avdecc
+sleep 1
+
+scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+$scriptdir/lib/avtp_pipeline/build/bin/shutdown_openavb_endpoint.sh
+$scriptdir/lib/avtp_pipeline/build/bin/shutdown_openavb_avdecc.sh
+