summaryrefslogtreecommitdiffstats
path: root/src/AVTEDIInput.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/AVTEDIInput.h')
-rw-r--r--src/AVTEDIInput.h183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/AVTEDIInput.h b/src/AVTEDIInput.h
new file mode 100644
index 0000000..4ec6086
--- /dev/null
+++ b/src/AVTEDIInput.h
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2017 AVT GmbH - Fabien Vercasson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+
+/*! \section AVT Input
+ *
+ * Extract audio frame from EDI frames produced by AVT encoder.
+ *
+ * The EDI frames are not special, it is just assumed that the audio is transported
+ * into the first stream.
+ *
+ * PFT with spreaded packets is supported. TODO
+ * Error correction is applied TODO
+ * AF without PFT supported TODO
+ * Resend not supported
+ *
+ * ref: ETSI TS 102 821 V1.4.1
+ * ETSI TS 102 693 V1.1.2
+ */
+
+#ifndef _AVT_EDI_INPUT_
+#define _AVT_EDI_INPUT_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string>
+#include <map>
+#include <vector>
+#include <chrono>
+
+class OrderedQueue;
+class PFTFrag;
+class PFT;
+class EDISubCh;
+
+/* ------------------------------------------------------------------
+ *
+ */
+class AVTEDIInput
+{
+ public:
+ /*\param fragmentTimeoutMs How long to wait for all fragment before applying FEC or dropping old frames*/
+ AVTEDIInput(uint32_t fragmentTimeoutMs = 120);
+ ~AVTEDIInput();
+
+ /*! Push new data to edi decoder
+ * \return false is data is not EDI
+ */
+ bool pushData(uint8_t* buf, size_t length);
+
+ /*! Give next available audio frame from EDI
+ * \return The size of the buffer. 0 if not data available
+ */
+ size_t popFrame(std::vector<uint8_t>& data, int32_t& frameNumber);
+
+ private:
+ uint32_t _fragmentTimeoutMs;
+ std::map<int, PFT*> _pft;
+ typedef std::map<int, PFT*>::iterator PFTIterator;
+
+ OrderedQueue* _subChannelQueue;
+
+ bool _pushPFTFrag(uint8_t* buf, size_t length);
+ bool _pushAF(uint8_t* buf, size_t length, bool checked);
+};
+
+/* ------------------------------------------------------------------
+ *
+ */
+class PFTFrag
+{
+ public:
+ PFTFrag(uint8_t* buf, size_t length);
+ ~PFTFrag();
+
+ inline bool isValid() { return _valid; }
+ inline uint32_t Pseq() { return _Pseq; }
+ inline uint32_t Findex() { return _Findex; }
+ inline uint32_t Fcount() { return _Fcount; }
+ inline uint32_t FEC() { return _FEC; }
+ inline uint32_t Plen() { return _Plen; }
+ inline uint32_t RSk() { return _RSk; }
+ inline uint32_t RSz() { return _RSz; }
+ inline uint8_t* payload() { return _payload.data(); }
+ inline const std::vector<uint8_t>& payloadVector()
+ { return _payload; }
+
+ private:
+ std::vector<uint8_t> _payload;
+
+ uint32_t _Pseq;
+ uint32_t _Findex;
+ uint32_t _Fcount;
+ uint32_t _FEC;
+ uint32_t _Addr;
+ uint32_t _Plen;
+ uint32_t _RSk;
+ uint32_t _RSz;
+ uint32_t _Source;
+ uint32_t _Dest;
+ bool _valid;
+
+ bool _parse(uint8_t* buf, size_t length);
+};
+
+/* ------------------------------------------------------------------
+ *
+ */
+class PFT
+{
+ public:
+ PFT(uint32_t Pseq, uint32_t Fcount);
+ ~PFT();
+
+ /*! the given frag belongs to the PFT class,
+ *! it will be deleted by the class */
+ void pushPFTFrag(PFTFrag* frag);
+
+ /* \return true if all framgnements are received*/
+ bool complete();
+
+ /*! try to build the AF with received fragments.
+ *! Apply error correction if necessary (missing packets/CRC errors)
+ * \return true if the AF is completed
+ */
+ bool extractAF(std::vector<uint8_t>& afdata);
+
+ inline std::chrono::steady_clock::time_point creation()
+ { return _creation; }
+
+ private:
+ PFTFrag** _frags;
+ uint32_t _Pseq;
+ uint32_t _Fcount;
+ uint32_t _Plen;
+ uint32_t _nbFrag;
+ uint32_t _RSk;
+ uint32_t _RSz;
+ uint32_t _cmax;
+ uint32_t _rxmin;
+
+ std::chrono::steady_clock::time_point _creation;
+
+ bool _canAttemptToDecode();
+
+ static void* _rs_handler;
+ static void _initRSDecoder();
+};
+
+/* ------------------------------------------------------------------
+ *
+ */
+class EDISubCh {
+ public:
+ EDISubCh(uint8_t* buf, size_t length);
+ ~EDISubCh();
+
+ inline uint32_t frameCount() { return _frameCount; }
+ inline uint8_t* payload() { return _payload.data(); }
+ inline const std::vector<uint8_t>& payloadVector()
+ { return _payload; }
+
+ private:
+ uint32_t _frameCount;
+ std::vector<uint8_t> _payload;
+};
+
+#endif // _AVT_EDI_INPUT_