xref: /aosp_15_r20/external/webrtc/modules/video_coding/frame_buffer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/frame_buffer.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <string.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "api/video/encoded_image.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_timing.h"
17*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/include/video_codec_interface.h"
18*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/packet.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
22*d9f75844SAndroid Build Coastguard Worker 
23*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
24*d9f75844SAndroid Build Coastguard Worker 
VCMFrameBuffer()25*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer::VCMFrameBuffer()
26*d9f75844SAndroid Build Coastguard Worker     : _state(kStateEmpty), _nackCount(0), _latestPacketTimeMs(-1) {}
27*d9f75844SAndroid Build Coastguard Worker 
~VCMFrameBuffer()28*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer::~VCMFrameBuffer() {}
29*d9f75844SAndroid Build Coastguard Worker 
FrameType() const30*d9f75844SAndroid Build Coastguard Worker webrtc::VideoFrameType VCMFrameBuffer::FrameType() const {
31*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.FrameType();
32*d9f75844SAndroid Build Coastguard Worker }
33*d9f75844SAndroid Build Coastguard Worker 
GetLowSeqNum() const34*d9f75844SAndroid Build Coastguard Worker int32_t VCMFrameBuffer::GetLowSeqNum() const {
35*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.LowSequenceNumber();
36*d9f75844SAndroid Build Coastguard Worker }
37*d9f75844SAndroid Build Coastguard Worker 
GetHighSeqNum() const38*d9f75844SAndroid Build Coastguard Worker int32_t VCMFrameBuffer::GetHighSeqNum() const {
39*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.HighSequenceNumber();
40*d9f75844SAndroid Build Coastguard Worker }
41*d9f75844SAndroid Build Coastguard Worker 
PictureId() const42*d9f75844SAndroid Build Coastguard Worker int VCMFrameBuffer::PictureId() const {
43*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.PictureId();
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker 
TemporalId() const46*d9f75844SAndroid Build Coastguard Worker int VCMFrameBuffer::TemporalId() const {
47*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.TemporalId();
48*d9f75844SAndroid Build Coastguard Worker }
49*d9f75844SAndroid Build Coastguard Worker 
LayerSync() const50*d9f75844SAndroid Build Coastguard Worker bool VCMFrameBuffer::LayerSync() const {
51*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.LayerSync();
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker 
Tl0PicId() const54*d9f75844SAndroid Build Coastguard Worker int VCMFrameBuffer::Tl0PicId() const {
55*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.Tl0PicId();
56*d9f75844SAndroid Build Coastguard Worker }
57*d9f75844SAndroid Build Coastguard Worker 
GetNaluInfos() const58*d9f75844SAndroid Build Coastguard Worker std::vector<NaluInfo> VCMFrameBuffer::GetNaluInfos() const {
59*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.GetNaluInfos();
60*d9f75844SAndroid Build Coastguard Worker }
61*d9f75844SAndroid Build Coastguard Worker 
SetGofInfo(const GofInfoVP9 & gof_info,size_t idx)62*d9f75844SAndroid Build Coastguard Worker void VCMFrameBuffer::SetGofInfo(const GofInfoVP9& gof_info, size_t idx) {
63*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::SetGofInfo");
64*d9f75844SAndroid Build Coastguard Worker   _sessionInfo.SetGofInfo(gof_info, idx);
65*d9f75844SAndroid Build Coastguard Worker   // TODO(asapersson): Consider adding hdr->VP9.ref_picture_id for testing.
66*d9f75844SAndroid Build Coastguard Worker   _codecSpecificInfo.codecSpecific.VP9.temporal_idx =
67*d9f75844SAndroid Build Coastguard Worker       gof_info.temporal_idx[idx];
68*d9f75844SAndroid Build Coastguard Worker   _codecSpecificInfo.codecSpecific.VP9.temporal_up_switch =
69*d9f75844SAndroid Build Coastguard Worker       gof_info.temporal_up_switch[idx];
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker // Insert packet
InsertPacket(const VCMPacket & packet,int64_t timeInMs,const FrameData & frame_data)73*d9f75844SAndroid Build Coastguard Worker VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(const VCMPacket& packet,
74*d9f75844SAndroid Build Coastguard Worker                                                 int64_t timeInMs,
75*d9f75844SAndroid Build Coastguard Worker                                                 const FrameData& frame_data) {
76*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::InsertPacket");
77*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!(NULL == packet.dataPtr && packet.sizeBytes > 0));
78*d9f75844SAndroid Build Coastguard Worker   if (packet.dataPtr != NULL) {
79*d9f75844SAndroid Build Coastguard Worker     _payloadType = packet.payloadType;
80*d9f75844SAndroid Build Coastguard Worker   }
81*d9f75844SAndroid Build Coastguard Worker 
82*d9f75844SAndroid Build Coastguard Worker   if (kStateEmpty == _state) {
83*d9f75844SAndroid Build Coastguard Worker     // First packet (empty and/or media) inserted into this frame.
84*d9f75844SAndroid Build Coastguard Worker     // store some info and set some initial values.
85*d9f75844SAndroid Build Coastguard Worker     SetTimestamp(packet.timestamp);
86*d9f75844SAndroid Build Coastguard Worker     // We only take the ntp timestamp of the first packet of a frame.
87*d9f75844SAndroid Build Coastguard Worker     ntp_time_ms_ = packet.ntp_time_ms_;
88*d9f75844SAndroid Build Coastguard Worker     _codec = packet.codec();
89*d9f75844SAndroid Build Coastguard Worker     if (packet.video_header.frame_type != VideoFrameType::kEmptyFrame) {
90*d9f75844SAndroid Build Coastguard Worker       // first media packet
91*d9f75844SAndroid Build Coastguard Worker       SetState(kStateIncomplete);
92*d9f75844SAndroid Build Coastguard Worker     }
93*d9f75844SAndroid Build Coastguard Worker   }
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker   size_t oldSize = encoded_image_buffer_ ? encoded_image_buffer_->size() : 0;
96*d9f75844SAndroid Build Coastguard Worker   uint32_t requiredSizeBytes =
97*d9f75844SAndroid Build Coastguard Worker       size() + packet.sizeBytes +
98*d9f75844SAndroid Build Coastguard Worker       (packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
99*d9f75844SAndroid Build Coastguard Worker   if (requiredSizeBytes > oldSize) {
100*d9f75844SAndroid Build Coastguard Worker     const uint8_t* prevBuffer = data();
101*d9f75844SAndroid Build Coastguard Worker     const uint32_t increments =
102*d9f75844SAndroid Build Coastguard Worker         requiredSizeBytes / kBufferIncStepSizeBytes +
103*d9f75844SAndroid Build Coastguard Worker         (requiredSizeBytes % kBufferIncStepSizeBytes > 0);
104*d9f75844SAndroid Build Coastguard Worker     const uint32_t newSize = oldSize + increments * kBufferIncStepSizeBytes;
105*d9f75844SAndroid Build Coastguard Worker     if (newSize > kMaxJBFrameSizeBytes) {
106*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Failed to insert packet due to frame being too "
107*d9f75844SAndroid Build Coastguard Worker                            "big.";
108*d9f75844SAndroid Build Coastguard Worker       return kSizeError;
109*d9f75844SAndroid Build Coastguard Worker     }
110*d9f75844SAndroid Build Coastguard Worker     if (data() == nullptr) {
111*d9f75844SAndroid Build Coastguard Worker       encoded_image_buffer_ = EncodedImageBuffer::Create(newSize);
112*d9f75844SAndroid Build Coastguard Worker       SetEncodedData(encoded_image_buffer_);
113*d9f75844SAndroid Build Coastguard Worker       set_size(0);
114*d9f75844SAndroid Build Coastguard Worker     } else {
115*d9f75844SAndroid Build Coastguard Worker       RTC_CHECK(encoded_image_buffer_ != nullptr);
116*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(encoded_image_buffer_->data(), data());
117*d9f75844SAndroid Build Coastguard Worker       encoded_image_buffer_->Realloc(newSize);
118*d9f75844SAndroid Build Coastguard Worker     }
119*d9f75844SAndroid Build Coastguard Worker     _sessionInfo.UpdateDataPointers(prevBuffer, data());
120*d9f75844SAndroid Build Coastguard Worker   }
121*d9f75844SAndroid Build Coastguard Worker 
122*d9f75844SAndroid Build Coastguard Worker   if (packet.width() > 0 && packet.height() > 0) {
123*d9f75844SAndroid Build Coastguard Worker     _encodedWidth = packet.width();
124*d9f75844SAndroid Build Coastguard Worker     _encodedHeight = packet.height();
125*d9f75844SAndroid Build Coastguard Worker   }
126*d9f75844SAndroid Build Coastguard Worker 
127*d9f75844SAndroid Build Coastguard Worker   // Don't copy payload specific data for empty packets (e.g padding packets).
128*d9f75844SAndroid Build Coastguard Worker   if (packet.sizeBytes > 0)
129*d9f75844SAndroid Build Coastguard Worker     CopyCodecSpecific(&packet.video_header);
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker   int retVal = _sessionInfo.InsertPacket(
132*d9f75844SAndroid Build Coastguard Worker       packet, encoded_image_buffer_ ? encoded_image_buffer_->data() : nullptr,
133*d9f75844SAndroid Build Coastguard Worker       frame_data);
134*d9f75844SAndroid Build Coastguard Worker   if (retVal == -1) {
135*d9f75844SAndroid Build Coastguard Worker     return kSizeError;
136*d9f75844SAndroid Build Coastguard Worker   } else if (retVal == -2) {
137*d9f75844SAndroid Build Coastguard Worker     return kDuplicatePacket;
138*d9f75844SAndroid Build Coastguard Worker   } else if (retVal == -3) {
139*d9f75844SAndroid Build Coastguard Worker     return kOutOfBoundsPacket;
140*d9f75844SAndroid Build Coastguard Worker   }
141*d9f75844SAndroid Build Coastguard Worker   // update size
142*d9f75844SAndroid Build Coastguard Worker   set_size(size() + static_cast<uint32_t>(retVal));
143*d9f75844SAndroid Build Coastguard Worker 
144*d9f75844SAndroid Build Coastguard Worker   _latestPacketTimeMs = timeInMs;
145*d9f75844SAndroid Build Coastguard Worker 
146*d9f75844SAndroid Build Coastguard Worker   // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
147*d9f75844SAndroid Build Coastguard Worker   // ts_126114v120700p.pdf Section 7.4.5.
148*d9f75844SAndroid Build Coastguard Worker   // The MTSI client shall add the payload bytes as defined in this clause
149*d9f75844SAndroid Build Coastguard Worker   // onto the last RTP packet in each group of packets which make up a key
150*d9f75844SAndroid Build Coastguard Worker   // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265
151*d9f75844SAndroid Build Coastguard Worker   // (HEVC)).
152*d9f75844SAndroid Build Coastguard Worker   if (packet.markerBit) {
153*d9f75844SAndroid Build Coastguard Worker     rotation_ = packet.video_header.rotation;
154*d9f75844SAndroid Build Coastguard Worker     content_type_ = packet.video_header.content_type;
155*d9f75844SAndroid Build Coastguard Worker     if (packet.video_header.video_timing.flags != VideoSendTiming::kInvalid) {
156*d9f75844SAndroid Build Coastguard Worker       timing_.encode_start_ms =
157*d9f75844SAndroid Build Coastguard Worker           ntp_time_ms_ + packet.video_header.video_timing.encode_start_delta_ms;
158*d9f75844SAndroid Build Coastguard Worker       timing_.encode_finish_ms =
159*d9f75844SAndroid Build Coastguard Worker           ntp_time_ms_ +
160*d9f75844SAndroid Build Coastguard Worker           packet.video_header.video_timing.encode_finish_delta_ms;
161*d9f75844SAndroid Build Coastguard Worker       timing_.packetization_finish_ms =
162*d9f75844SAndroid Build Coastguard Worker           ntp_time_ms_ +
163*d9f75844SAndroid Build Coastguard Worker           packet.video_header.video_timing.packetization_finish_delta_ms;
164*d9f75844SAndroid Build Coastguard Worker       timing_.pacer_exit_ms =
165*d9f75844SAndroid Build Coastguard Worker           ntp_time_ms_ + packet.video_header.video_timing.pacer_exit_delta_ms;
166*d9f75844SAndroid Build Coastguard Worker       timing_.network_timestamp_ms =
167*d9f75844SAndroid Build Coastguard Worker           ntp_time_ms_ +
168*d9f75844SAndroid Build Coastguard Worker           packet.video_header.video_timing.network_timestamp_delta_ms;
169*d9f75844SAndroid Build Coastguard Worker       timing_.network2_timestamp_ms =
170*d9f75844SAndroid Build Coastguard Worker           ntp_time_ms_ +
171*d9f75844SAndroid Build Coastguard Worker           packet.video_header.video_timing.network2_timestamp_delta_ms;
172*d9f75844SAndroid Build Coastguard Worker     }
173*d9f75844SAndroid Build Coastguard Worker     timing_.flags = packet.video_header.video_timing.flags;
174*d9f75844SAndroid Build Coastguard Worker   }
175*d9f75844SAndroid Build Coastguard Worker 
176*d9f75844SAndroid Build Coastguard Worker   if (packet.is_first_packet_in_frame()) {
177*d9f75844SAndroid Build Coastguard Worker     playout_delay_ = packet.video_header.playout_delay;
178*d9f75844SAndroid Build Coastguard Worker   }
179*d9f75844SAndroid Build Coastguard Worker 
180*d9f75844SAndroid Build Coastguard Worker   if (_sessionInfo.complete()) {
181*d9f75844SAndroid Build Coastguard Worker     SetState(kStateComplete);
182*d9f75844SAndroid Build Coastguard Worker     return kCompleteSession;
183*d9f75844SAndroid Build Coastguard Worker   }
184*d9f75844SAndroid Build Coastguard Worker   return kIncomplete;
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker 
LatestPacketTimeMs() const187*d9f75844SAndroid Build Coastguard Worker int64_t VCMFrameBuffer::LatestPacketTimeMs() const {
188*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::LatestPacketTimeMs");
189*d9f75844SAndroid Build Coastguard Worker   return _latestPacketTimeMs;
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker 
IncrementNackCount()192*d9f75844SAndroid Build Coastguard Worker void VCMFrameBuffer::IncrementNackCount() {
193*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::IncrementNackCount");
194*d9f75844SAndroid Build Coastguard Worker   _nackCount++;
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker 
GetNackCount() const197*d9f75844SAndroid Build Coastguard Worker int16_t VCMFrameBuffer::GetNackCount() const {
198*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::GetNackCount");
199*d9f75844SAndroid Build Coastguard Worker   return _nackCount;
200*d9f75844SAndroid Build Coastguard Worker }
201*d9f75844SAndroid Build Coastguard Worker 
HaveFirstPacket() const202*d9f75844SAndroid Build Coastguard Worker bool VCMFrameBuffer::HaveFirstPacket() const {
203*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::HaveFirstPacket");
204*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.HaveFirstPacket();
205*d9f75844SAndroid Build Coastguard Worker }
206*d9f75844SAndroid Build Coastguard Worker 
NumPackets() const207*d9f75844SAndroid Build Coastguard Worker int VCMFrameBuffer::NumPackets() const {
208*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::NumPackets");
209*d9f75844SAndroid Build Coastguard Worker   return _sessionInfo.NumPackets();
210*d9f75844SAndroid Build Coastguard Worker }
211*d9f75844SAndroid Build Coastguard Worker 
Reset()212*d9f75844SAndroid Build Coastguard Worker void VCMFrameBuffer::Reset() {
213*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::Reset");
214*d9f75844SAndroid Build Coastguard Worker   set_size(0);
215*d9f75844SAndroid Build Coastguard Worker   _sessionInfo.Reset();
216*d9f75844SAndroid Build Coastguard Worker   _payloadType = 0;
217*d9f75844SAndroid Build Coastguard Worker   _nackCount = 0;
218*d9f75844SAndroid Build Coastguard Worker   _latestPacketTimeMs = -1;
219*d9f75844SAndroid Build Coastguard Worker   _state = kStateEmpty;
220*d9f75844SAndroid Build Coastguard Worker   VCMEncodedFrame::Reset();
221*d9f75844SAndroid Build Coastguard Worker }
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker // Set state of frame
SetState(VCMFrameBufferStateEnum state)224*d9f75844SAndroid Build Coastguard Worker void VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) {
225*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::SetState");
226*d9f75844SAndroid Build Coastguard Worker   if (_state == state) {
227*d9f75844SAndroid Build Coastguard Worker     return;
228*d9f75844SAndroid Build Coastguard Worker   }
229*d9f75844SAndroid Build Coastguard Worker   switch (state) {
230*d9f75844SAndroid Build Coastguard Worker     case kStateIncomplete:
231*d9f75844SAndroid Build Coastguard Worker       // we can go to this state from state kStateEmpty
232*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(_state, kStateEmpty);
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker       // Do nothing, we received a packet
235*d9f75844SAndroid Build Coastguard Worker       break;
236*d9f75844SAndroid Build Coastguard Worker 
237*d9f75844SAndroid Build Coastguard Worker     case kStateComplete:
238*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(_state == kStateEmpty || _state == kStateIncomplete);
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker       break;
241*d9f75844SAndroid Build Coastguard Worker 
242*d9f75844SAndroid Build Coastguard Worker     case kStateEmpty:
243*d9f75844SAndroid Build Coastguard Worker       // Should only be set to empty through Reset().
244*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
245*d9f75844SAndroid Build Coastguard Worker       break;
246*d9f75844SAndroid Build Coastguard Worker   }
247*d9f75844SAndroid Build Coastguard Worker   _state = state;
248*d9f75844SAndroid Build Coastguard Worker }
249*d9f75844SAndroid Build Coastguard Worker 
250*d9f75844SAndroid Build Coastguard Worker // Get current state of frame
GetState() const251*d9f75844SAndroid Build Coastguard Worker VCMFrameBufferStateEnum VCMFrameBuffer::GetState() const {
252*d9f75844SAndroid Build Coastguard Worker   return _state;
253*d9f75844SAndroid Build Coastguard Worker }
254*d9f75844SAndroid Build Coastguard Worker 
PrepareForDecode(bool continuous)255*d9f75844SAndroid Build Coastguard Worker void VCMFrameBuffer::PrepareForDecode(bool continuous) {
256*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "VCMFrameBuffer::PrepareForDecode");
257*d9f75844SAndroid Build Coastguard Worker   size_t bytes_removed = _sessionInfo.MakeDecodable();
258*d9f75844SAndroid Build Coastguard Worker   set_size(size() - bytes_removed);
259*d9f75844SAndroid Build Coastguard Worker   // Transfer frame information to EncodedFrame and create any codec
260*d9f75844SAndroid Build Coastguard Worker   // specific information.
261*d9f75844SAndroid Build Coastguard Worker   _frameType = _sessionInfo.FrameType();
262*d9f75844SAndroid Build Coastguard Worker   _missingFrame = !continuous;
263*d9f75844SAndroid Build Coastguard Worker }
264*d9f75844SAndroid Build Coastguard Worker 
265*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
266