1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <TextRtpPayloadDecoderNode.h>
18 #include <TextConfig.h>
19 #include <ImsMediaTrace.h>
20 #include <list>
21 
TextRtpPayloadDecoderNode(BaseSessionCallback * callback)22 TextRtpPayloadDecoderNode::TextRtpPayloadDecoderNode(BaseSessionCallback* callback) :
23         BaseNode(callback)
24 {
25     mCodecType = TextConfig::TEXT_CODEC_NONE;
26 }
27 
~TextRtpPayloadDecoderNode()28 TextRtpPayloadDecoderNode::~TextRtpPayloadDecoderNode() {}
29 
GetNodeId()30 kBaseNodeId TextRtpPayloadDecoderNode::GetNodeId()
31 {
32     return kNodeIdTextPayloadDecoder;
33 }
34 
Start()35 ImsMediaResult TextRtpPayloadDecoderNode::Start()
36 {
37     IMLOGD1("[Start] codec[%d]", mCodecType);
38 
39     if (mCodecType == TextConfig::TEXT_CODEC_NONE)
40     {
41         return RESULT_INVALID_PARAM;
42     }
43 
44     mNodeState = kNodeStateRunning;
45     return RESULT_SUCCESS;
46 }
47 
Stop()48 void TextRtpPayloadDecoderNode::Stop()
49 {
50     IMLOGD0("[Stop]");
51     mNodeState = kNodeStateStopped;
52 }
53 
IsRunTime()54 bool TextRtpPayloadDecoderNode::IsRunTime()
55 {
56     return true;
57 }
58 
IsSourceNode()59 bool TextRtpPayloadDecoderNode::IsSourceNode()
60 {
61     return false;
62 }
63 
OnDataFromFrontNode(ImsMediaSubType subtype,uint8_t * data,uint32_t size,uint32_t timestamp,bool mark,uint32_t seqNum,ImsMediaSubType dataType,uint32_t arrivalTime)64 void TextRtpPayloadDecoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* data,
65         uint32_t size, uint32_t timestamp, bool mark, uint32_t seqNum, ImsMediaSubType dataType,
66         uint32_t arrivalTime)
67 {
68     (void)dataType;
69     (void)arrivalTime;
70 
71     if (subtype == MEDIASUBTYPE_REFRESHED)
72     {
73         SendDataToRearNode(subtype, nullptr, size, 0, 0, 0, MEDIASUBTYPE_UNDEFINED);
74         return;
75     }
76 
77     switch (mCodecType)
78     {
79         case TextConfig::TEXT_T140:
80         case TextConfig::TEXT_T140_RED:
81             DecodeT140(data, size, subtype, timestamp, mark, seqNum);
82             break;
83         default:
84             IMLOGE1("[OnDataFromFrontNode invalid codec type[%u]", mCodecType);
85             break;
86     }
87 }
88 
SetConfig(void * config)89 void TextRtpPayloadDecoderNode::SetConfig(void* config)
90 {
91     if (config == nullptr)
92     {
93         return;
94     }
95 
96     TextConfig* pConfig = reinterpret_cast<TextConfig*>(config);
97     mCodecType = pConfig->getCodecType();
98 }
99 
IsSameConfig(void * config)100 bool TextRtpPayloadDecoderNode::IsSameConfig(void* config)
101 {
102     if (config == nullptr)
103     {
104         return true;
105     }
106 
107     TextConfig* pConfig = reinterpret_cast<TextConfig*>(config);
108 
109     return (mCodecType == pConfig->getCodecType());
110 }
111 
DecodeT140(uint8_t * data,uint32_t size,ImsMediaSubType subtype,uint32_t timestamp,bool mark,uint32_t seq)112 void TextRtpPayloadDecoderNode::DecodeT140(uint8_t* data, uint32_t size, ImsMediaSubType subtype,
113         uint32_t timestamp, bool mark, uint32_t seq)
114 {
115     IMLOGD_PACKET5(IM_PACKET_LOG_PH,
116             "[DecodeT140] subtype[%u], size[%u], timestamp[%d], mark[%d], seq[%d]", subtype, size,
117             timestamp, mark, seq);
118 
119     if (subtype == MEDIASUBTYPE_BITSTREAM_T140 || subtype == MEDIASUBTYPE_BITSTREAM_T140_RED)
120     {
121         std::list<uint32_t> listTimestampOffset;
122         std::list<uint32_t> listLength;
123         uint32_t readByte = 0;
124         uint16_t redundantCount = 0;
125 
126         mBitReader.SetBuffer(data, size);
127 
128         /*
129         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130         |1|   T140 PT   |  timestamp offset of "R"  | "R" block length  |
131         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132         |0|   T140 PT   | "R" T.140 encoded redundant data              |
133         +-+-+-+-+-+-+-+-+                               +---------------+
134         |                                               |
135         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136         */
137 
138         // Primary Data Only
139         if (subtype == MEDIASUBTYPE_BITSTREAM_T140 || size == 0)
140         {
141             SendDataToRearNode(MEDIASUBTYPE_BITSTREAM_T140, data, size, timestamp, mark, seq);
142             return;
143         }
144 
145         // Redundant data included
146         while (mBitReader.Read(1) == 1)  // redundant flag bit
147         {
148             uint32_t payloadType = mBitReader.Read(7);  // T140 payload type
149             uint32_t timestampOffset = mBitReader.Read(14);
150             uint32_t length = mBitReader.Read(10);
151 
152             listTimestampOffset.push_back(timestampOffset);  // timestamp offset
153             listLength.push_back(length);                    // block length
154 
155             IMLOGD_PACKET3(IM_PACKET_LOG_PH, "[DecodeT140] PT[%u], TSOffset[%u], size[%u]",
156                     payloadType, timestampOffset, length);
157             readByte += 4;
158             redundantCount++;
159         }
160 
161         mBitReader.Read(7);  // T140 payload type (111)
162         readByte += 1;
163 
164         // redundant data
165         while (listTimestampOffset.size() > 0)
166         {
167             uint32_t redundantTimestamp = listTimestampOffset.front();
168             uint32_t redundantLength = listLength.front();
169 
170             // read redundant payload
171             mBitReader.ReadByteBuffer(mPayload, redundantLength * 8);
172             readByte += redundantLength;
173 
174             uint16_t redundantSeqNum = seq - redundantCount;
175 
176             IMLOGD_PACKET3(IM_PACKET_LOG_PH, "[DecodeT140] red TS[%u], size[%u], seq[%u]",
177                     timestamp - redundantTimestamp, redundantLength, redundantSeqNum);
178             SendDataToRearNode(MEDIASUBTYPE_BITSTREAM_T140, mPayload, redundantLength,
179                     timestamp - redundantTimestamp, mark, redundantSeqNum);
180 
181             redundantCount--;
182             listTimestampOffset.pop_front();
183             listLength.pop_front();
184         }
185 
186         // primary data
187         if (size - readByte > 0)
188         {
189             mBitReader.ReadByteBuffer(mPayload, (size - readByte) * 8);
190         }
191 
192         SendDataToRearNode(
193                 MEDIASUBTYPE_BITSTREAM_T140, mPayload, (size - readByte), timestamp, mark, seq);
194     }
195     else
196     {
197         IMLOGW1("[DecodeT140] INVALID media sub type[%u]", subtype);
198     }
199 }
200