1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rtp_unpack_impl.h"
17 #include <arpa/inet.h>
18 #include <chrono>
19 #include "common/common_macro.h"
20 #include "common/media_log.h"
21 #include "rtp_codec_aac.h"
22 #include "rtp_codec_g711.h"
23 #include "rtp_codec_h264.h"
24 #include "rtp_codec_ts.h"
25 #include "common/sharing_sink_hisysevent.h"
26
27 namespace OHOS {
28 namespace Sharing {
RtpUnpackImpl(const RtpPlaylodParam & rpp)29 RtpUnpackImpl::RtpUnpackImpl(const RtpPlaylodParam &rpp)
30 {
31 CreateRtpDecoder(rpp);
32 }
33
~RtpUnpackImpl()34 RtpUnpackImpl::~RtpUnpackImpl()
35 {
36 SHARING_LOGI("~RtpUnpackImpl.");
37 Release();
38 }
39
ParseRtp(const char * data,size_t len)40 void RtpUnpackImpl::ParseRtp(const char *data, size_t len)
41 {
42 RETURN_IF_NULL(data);
43 if (len < sizeof(RtpHeader)) {
44 SHARING_LOGE("RtpHeader size error");
45 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::RTP_DEMUX,
46 SinkErrorCode::WIFI_DISPLAY_RTP_DATA_INVALID);
47 return;
48 }
49 RtpHeader *header = (RtpHeader *)data;
50 auto pt = header->pt_;
51 auto decoder = rtpDecoder_[pt];
52
53 if (!decoder) {
54 if (rtpDecoder_.size() > 2) { // 2:fixed size
55 return;
56 }
57 switch (pt) {
58 case 33: { // 33:mpeg-2 ts code
59 // todo judge ps/ts
60 CreateRtpDecoder(RtpPlaylodParam{pt, 90000, RtpPayloadStream::MPEG2_TS}); // 90000:audio clock cycle
61 break;
62 }
63 default:
64 // todo not support this pt
65 if (WfdSinkHiSysEvent::GetInstance().GetCurrentScene() ==
66 static_cast<int32_t>(SinkBizScene::ESTABLISH_MIRRORING)) {
67 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::FIRST_FRAME_PROCESSED,
68 SinkErrorCode::WIFI_DISPLAY_RTP_DATA_INVALID);
69 } else if (WfdSinkHiSysEvent::GetInstance().GetCurrentScene() ==
70 static_cast<int32_t>(SinkBizScene::MIRRORING_STABILITY)) {
71 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::RTP_DEMUX,
72 SinkErrorCode::WIFI_DISPLAY_RTP_DATA_INVALID);
73 }
74 return;
75 }
76 }
77
78 if (rtpSort_[pt]) {
79 rtpSort_[pt]->InputRtp(TRACK_VIDEO, (unsigned char *)data, len);
80 }
81 }
82
SetOnRtpUnpack(const OnRtpUnpack & cb)83 void RtpUnpackImpl::SetOnRtpUnpack(const OnRtpUnpack &cb)
84 {
85 onRtpUnpack_ = std::move(cb);
86 }
87
SetOnRtpNotify(const OnRtpNotify & cb)88 void RtpUnpackImpl::SetOnRtpNotify(const OnRtpNotify &cb)
89 {
90 onRtpNotify_ = std::move(cb);
91 }
92
OnRtpSorted(uint16_t seq,const RtpPacket::Ptr & rtp)93 void RtpUnpackImpl::OnRtpSorted(uint16_t seq, const RtpPacket::Ptr &rtp)
94 {
95 RETURN_IF_NULL(rtp);
96 if (rtpDecoder_[rtp->GetHeader()->pt_]) {
97 MEDIA_LOGD("rtpUnpackImpl::OnRtpSorted seq: %{public}d, pt: %{public}d.", rtp->GetSeq(), rtp->GetHeader()->pt_);
98
99 if (nextOutSeq_ == 0xffff) {
100 nextOutSeq_ = 1;
101 } else {
102 nextOutSeq_ = rtp->GetSeq() + 1;
103 }
104
105 rtpDecoder_[rtp->GetHeader()->pt_]->InputRtp(rtp);
106 }
107 }
108
OnRtpDecode(int32_t pt,const Frame::Ptr & frame)109 void RtpUnpackImpl::OnRtpDecode(int32_t pt, const Frame::Ptr &frame)
110 {
111 if (onRtpUnpack_) {
112 onRtpUnpack_(rtpSort_[pt]->GetSSRC(), frame);
113 }
114 }
115
Release()116 void RtpUnpackImpl::Release()
117 {
118 rtpDecoder_.clear();
119 rtpSort_.clear();
120 }
121
CreateRtpDecoder(const RtpPlaylodParam & rpp)122 void RtpUnpackImpl::CreateRtpDecoder(const RtpPlaylodParam &rpp)
123 {
124 switch (rpp.ps_) {
125 case RtpPayloadStream::H264:
126 rtpDecoder_[rpp.pt_] = std::make_shared<RtpDecoderH264>();
127 break;
128 case RtpPayloadStream::MPEG4_GENERIC:
129 rtpDecoder_[rpp.pt_] = std::make_shared<RtpDecoderAAC>(rpp);
130 break;
131 case RtpPayloadStream::PCMA: // fall-through
132 case RtpPayloadStream::PCMU:
133 rtpDecoder_[rpp.pt_] = std::make_shared<RtpDecoderG711>();
134 break;
135 case RtpPayloadStream::MPEG2_TS:
136 rtpDecoder_[rpp.pt_] = std::make_shared<RtpDecoderTs>();
137 break;
138 default:
139 // todo log
140 break;
141 }
142 if (rtpDecoder_[rpp.pt_]) {
143 auto &ref = rtpSort_[rpp.pt_];
144 ref = std::make_shared<RtpPacketSortor>(rpp.sampleRate_);
145 ref->SetOnSort(std::bind(&RtpUnpackImpl::OnRtpSorted, this, std::placeholders::_1, std::placeholders::_2));
146 rtpDecoder_[rpp.pt_]->SetOnFrame(std::bind(&RtpUnpackImpl::OnRtpDecode, this, rpp.pt_, std::placeholders::_1));
147 }
148 }
149 } // namespace Sharing
150 } // namespace OHOS