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