Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_sender.h

Issue 1739273002: [Draft] RtpPacket sketched. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase to use landed version of rtp::Packet Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ 11 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_
12 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ 12 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_
13 13
14 #include <list> 14 #include <list>
15 #include <map> 15 #include <map>
16 #include <string>
16 #include <utility> 17 #include <utility>
17 #include <vector> 18 #include <vector>
18 19
19 #include "webrtc/base/criticalsection.h" 20 #include "webrtc/base/criticalsection.h"
20 #include "webrtc/base/random.h" 21 #include "webrtc/base/random.h"
21 #include "webrtc/base/thread_annotations.h" 22 #include "webrtc/base/thread_annotations.h"
23 #include "webrtc/base/thread_checker.h"
22 #include "webrtc/common_types.h" 24 #include "webrtc/common_types.h"
23 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 25 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
24 #include "webrtc/modules/rtp_rtcp/source/bitrate.h" 26 #include "webrtc/modules/rtp_rtcp/source/bitrate.h"
25 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" 27 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
28 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
29 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions_manager.h"
30 #include "webrtc/modules/rtp_rtcp/source/rtp_packet.h"
26 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" 31 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h"
27 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" 32 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
28 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 33 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
29 #include "webrtc/modules/rtp_rtcp/source/ssrc_database.h" 34 #include "webrtc/modules/rtp_rtcp/source/ssrc_database.h"
30 #include "webrtc/transport.h" 35 #include "webrtc/transport.h"
31 36
32 namespace webrtc { 37 namespace webrtc {
33 38
34 class RTPSenderAudio; 39 class RTPSenderAudio;
35 class RTPSenderVideo; 40 class RTPSenderVideo;
(...skipping 26 matching lines...) Expand all
62 virtual size_t RTPHeaderLength() const = 0; 67 virtual size_t RTPHeaderLength() const = 0;
63 // Returns the next sequence number to use for a packet and allocates 68 // Returns the next sequence number to use for a packet and allocates
64 // 'packets_to_send' number of sequence numbers. It's important all allocated 69 // 'packets_to_send' number of sequence numbers. It's important all allocated
65 // sequence numbers are used in sequence to avoid perceived packet loss. 70 // sequence numbers are used in sequence to avoid perceived packet loss.
66 virtual uint16_t AllocateSequenceNumber(uint16_t packets_to_send) = 0; 71 virtual uint16_t AllocateSequenceNumber(uint16_t packets_to_send) = 0;
67 virtual uint16_t SequenceNumber() const = 0; 72 virtual uint16_t SequenceNumber() const = 0;
68 virtual size_t MaxPayloadLength() const = 0; 73 virtual size_t MaxPayloadLength() const = 0;
69 virtual size_t MaxDataPayloadLength() const = 0; 74 virtual size_t MaxDataPayloadLength() const = 0;
70 virtual uint16_t ActualSendBitrateKbit() const = 0; 75 virtual uint16_t ActualSendBitrateKbit() const = 0;
71 76
72 virtual int32_t SendToNetwork(uint8_t* data_buffer, 77 virtual int32_t SendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
73 size_t payload_length, 78 size_t payload_length,
74 size_t rtp_header_length,
75 int64_t capture_time_ms, 79 int64_t capture_time_ms,
76 StorageType storage, 80 StorageType storage,
77 RtpPacketSender::Priority priority) = 0; 81 RtpPacketSender::Priority priority) = 0;
78 82
79 virtual bool UpdateVideoRotation(uint8_t* rtp_packet, 83 virtual bool UpdateVideoRotation(uint8_t* rtp_packet,
80 size_t rtp_packet_length, 84 size_t rtp_packet_length,
81 const RTPHeader& rtp_header, 85 const RTPHeader& rtp_header,
82 VideoRotation rotation) const = 0; 86 VideoRotation rotation) const = 0;
83 virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) = 0; 87 virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) = 0;
84 virtual CVOMode ActivateCVORtpHeaderExtension() = 0; 88 virtual CVOMode ActivateCVORtpHeaderExtension() = 0;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 // RTP header extension 163 // RTP header extension
160 int32_t SetTransmissionTimeOffset(int32_t transmission_time_offset); 164 int32_t SetTransmissionTimeOffset(int32_t transmission_time_offset);
161 int32_t SetAbsoluteSendTime(uint32_t absolute_send_time); 165 int32_t SetAbsoluteSendTime(uint32_t absolute_send_time);
162 void SetVideoRotation(VideoRotation rotation); 166 void SetVideoRotation(VideoRotation rotation);
163 int32_t SetTransportSequenceNumber(uint16_t sequence_number); 167 int32_t SetTransportSequenceNumber(uint16_t sequence_number);
164 168
165 int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id); 169 int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
166 bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override; 170 bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override;
167 int32_t DeregisterRtpHeaderExtension(RTPExtensionType type); 171 int32_t DeregisterRtpHeaderExtension(RTPExtensionType type);
168 172
173 template <typename Extension>
174 bool RegisterRtpHeaderExtension(uint8_t id) {
175 return rtp_manager_.Register<Extension>(id);
176 }
177 bool RegisterRtpHeaderExtension(const std::string& name,
178 MediaType media,
179 uint8_t id) {
180 return rtp_manager_.RegisterByName(name, media, id);
181 }
182
169 size_t RtpHeaderExtensionTotalLength() const; 183 size_t RtpHeaderExtensionTotalLength() const;
184 std::unique_ptr<RtpPacketToSend> CreatePacket() const;
185 void ReserveExtensions(RtpPacketToSend* packet) const;
170 186
171 uint16_t BuildRTPHeaderExtension(uint8_t* data_buffer, bool marker_bit) const; 187 uint16_t BuildRTPHeaderExtension(uint8_t* data_buffer, bool marker_bit) const;
172 188
173 uint8_t BuildTransmissionTimeOffsetExtension(uint8_t *data_buffer) const; 189 uint8_t BuildTransmissionTimeOffsetExtension(uint8_t *data_buffer) const;
174 uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const; 190 uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const;
175 uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const; 191 uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const;
176 uint8_t BuildVideoRotationExtension(uint8_t* data_buffer) const; 192 uint8_t BuildVideoRotationExtension(uint8_t* data_buffer) const;
177 uint8_t BuildTransportSequenceNumberExtension(uint8_t* data_buffer, 193 uint8_t BuildTransportSequenceNumberExtension(uint8_t* data_buffer,
178 uint16_t sequence_number) const; 194 uint16_t sequence_number) const;
179 195
(...skipping 30 matching lines...) Expand all
210 bool TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms, 226 bool TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms,
211 bool retransmission); 227 bool retransmission);
212 size_t TimeToSendPadding(size_t bytes); 228 size_t TimeToSendPadding(size_t bytes);
213 229
214 // NACK. 230 // NACK.
215 int SelectiveRetransmissions() const; 231 int SelectiveRetransmissions() const;
216 int SetSelectiveRetransmissions(uint8_t settings); 232 int SetSelectiveRetransmissions(uint8_t settings);
217 void OnReceivedNACK(const std::list<uint16_t>& nack_sequence_numbers, 233 void OnReceivedNACK(const std::list<uint16_t>& nack_sequence_numbers,
218 int64_t avg_rtt); 234 int64_t avg_rtt);
219 235
220 void SetStorePacketsStatus(bool enable, uint16_t number_to_store); 236 void SetStorePacketsSize(uint16_t number_to_store);
221
222 bool StorePackets() const;
223 237
224 int32_t ReSendPacket(uint16_t packet_id, int64_t min_resend_time = 0); 238 int32_t ReSendPacket(uint16_t packet_id, int64_t min_resend_time = 0);
225 239
226 bool ProcessNACKBitRate(uint32_t now); 240 bool ProcessNACKBitRate(uint32_t now);
227 241
228 // RTX. 242 // RTX.
229 void SetRtxStatus(int mode); 243 void SetRtxStatus(int mode);
230 int RtxStatus() const; 244 int RtxStatus() const;
231 245
232 uint32_t RtxSsrc() const; 246 uint32_t RtxSsrc() const;
233 void SetRtxSsrc(uint32_t ssrc); 247 void SetRtxSsrc(uint32_t ssrc);
234 248
235 void SetRtxPayloadType(int payload_type, int associated_payload_type); 249 void SetRtxPayloadType(int payload_type, int associated_payload_type);
236 250
237 // Functions wrapping RTPSenderInterface. 251 // Functions wrapping RTPSenderInterface.
238 int32_t BuildRTPheader(uint8_t* data_buffer, 252 int32_t BuildRTPheader(uint8_t* data_buffer,
239 int8_t payload_type, 253 int8_t payload_type,
240 bool marker_bit, 254 bool marker_bit,
241 uint32_t capture_timestamp, 255 uint32_t capture_timestamp,
242 int64_t capture_time_ms, 256 int64_t capture_time_ms,
243 const bool timestamp_provided = true, 257 const bool timestamp_provided = true,
244 const bool inc_sequence_number = true) override; 258 const bool inc_sequence_number = true) override;
259 void BuildRtpHeader(RtpPacketToSend* packet,
260 uint32_t capture_timestamp,
261 bool reserve_extensions);
245 262
246 size_t RTPHeaderLength() const override; 263 size_t RTPHeaderLength() const override;
247 uint16_t AllocateSequenceNumber(uint16_t packets_to_send) override; 264 uint16_t AllocateSequenceNumber(uint16_t packets_to_send) override;
248 size_t MaxPayloadLength() const override; 265 size_t MaxPayloadLength() const override;
249 266
250 // Current timestamp. 267 // Current timestamp.
251 uint32_t Timestamp() const override; 268 uint32_t Timestamp() const override;
252 uint32_t SSRC() const override; 269 uint32_t SSRC() const override;
253 270
254 int32_t SendToNetwork(uint8_t* data_buffer, 271 int32_t SendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
255 size_t payload_length, 272 size_t payload_length,
256 size_t rtp_header_length,
257 int64_t capture_time_ms, 273 int64_t capture_time_ms,
258 StorageType storage, 274 StorageType storage,
259 RtpPacketSender::Priority priority) override; 275 RtpPacketSender::Priority priority) override;
260 276
261 // Audio. 277 // Audio.
262 278
263 // Send a DTMF tone using RFC 2833 (4733). 279 // Send a DTMF tone using RFC 2833 (4733).
264 int32_t SendTelephoneEvent(uint8_t key, uint16_t time_ms, uint8_t level); 280 int32_t SendTelephoneEvent(uint8_t key, uint16_t time_ms, uint8_t level);
265 281
266 // Set audio packet size, used to determine when it's time to send a DTMF 282 // Set audio packet size, used to determine when it's time to send a DTMF
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 size_t CreateRtpHeader(uint8_t* header, 338 size_t CreateRtpHeader(uint8_t* header,
323 int8_t payload_type, 339 int8_t payload_type,
324 uint32_t ssrc, 340 uint32_t ssrc,
325 bool marker_bit, 341 bool marker_bit,
326 uint32_t timestamp, 342 uint32_t timestamp,
327 uint16_t sequence_number, 343 uint16_t sequence_number,
328 const std::vector<uint32_t>& csrcs) const; 344 const std::vector<uint32_t>& csrcs) const;
329 345
330 void UpdateNACKBitRate(uint32_t bytes, int64_t now); 346 void UpdateNACKBitRate(uint32_t bytes, int64_t now);
331 347
332 bool PrepareAndSendPacket(uint8_t* buffer, 348 bool PrepareAndSendPacket(RtpPacketToSend* packet,
333 size_t length,
334 int64_t capture_time_ms,
335 bool send_over_rtx, 349 bool send_over_rtx,
336 bool is_retransmit); 350 bool is_retransmit);
337 351
338 // Return the number of bytes sent. Note that both of these functions may 352 // Return the number of bytes sent. Note that both of these functions may
339 // return a larger value that their argument. 353 // return a larger value that their argument.
340 size_t TrySendRedundantPayloads(size_t bytes); 354 size_t TrySendRedundantPayloads(size_t bytes);
341 355
342 void BuildPaddingPacket(uint8_t* packet, 356 void BuildPaddingPacket(uint8_t* packet,
343 size_t header_length, 357 size_t header_length,
344 size_t padding_length); 358 size_t padding_length);
345 359
346 void BuildRtxPacket(uint8_t* buffer, size_t* length, 360 std::unique_ptr<RtpPacketToSend> BuildRtxPacket(
347 uint8_t* buffer_rtx); 361 const RtpPacketToSend& packet);
348 362
349 bool SendPacketToNetwork(const uint8_t* packet, 363 bool SendPacketToNetwork(RtpPacketToSend* packet);
350 size_t size,
351 const PacketOptions& options);
352 364
353 void UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms); 365 void UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms);
354 366
355 // Find the byte position of the RTP extension as indicated by |type| in 367 // Find the byte position of the RTP extension as indicated by |type| in
356 // |rtp_packet|. Return false if such extension doesn't exist. 368 // |rtp_packet|. Return false if such extension doesn't exist.
357 bool FindHeaderExtensionPosition(RTPExtensionType type, 369 bool FindHeaderExtensionPosition(RTPExtensionType type,
358 const uint8_t* rtp_packet, 370 const uint8_t* rtp_packet,
359 size_t rtp_packet_length, 371 size_t rtp_packet_length,
360 const RTPHeader& rtp_header, 372 const RTPHeader& rtp_header,
361 size_t* position) const; 373 size_t* position) const;
362 374
363 void UpdateTransmissionTimeOffset(uint8_t* rtp_packet, 375 void UpdateTransmissionTimeOffset(uint8_t* rtp_packet,
364 size_t rtp_packet_length, 376 size_t rtp_packet_length,
365 const RTPHeader& rtp_header, 377 const RTPHeader& rtp_header,
366 int64_t time_diff_ms) const; 378 int64_t time_diff_ms) const;
367 void UpdateAbsoluteSendTime(uint8_t* rtp_packet,
368 size_t rtp_packet_length,
369 const RTPHeader& rtp_header,
370 int64_t now_ms) const;
371 // Update the transport sequence number of the packet using a new sequence 379 // Update the transport sequence number of the packet using a new sequence
372 // number allocated by SequenceNumberAllocator. Returns the assigned sequence 380 // number allocated by SequenceNumberAllocator. Returns the assigned sequence
373 // number, or 0 if extension could not be updated. 381 // number, or 0 if extension could not be updated.
374 uint16_t UpdateTransportSequenceNumber(uint8_t* rtp_packet, 382 uint16_t UpdateTransportSequenceNumber(RtpPacketToSend* rtp_packet) const;
375 size_t rtp_packet_length,
376 const RTPHeader& rtp_header) const;
377 383
378 void UpdateRtpStats(const uint8_t* buffer, 384 void UpdateRtpStats(const RtpPacketToSend& packet,
379 size_t packet_length,
380 const RTPHeader& header,
381 bool is_rtx, 385 bool is_rtx,
382 bool is_retransmit); 386 bool is_retransmit);
383 bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const; 387 bool IsFecPacket(const RtpPacketToSend& packet) const;
384 388
385 class BitrateAggregator { 389 class BitrateAggregator {
386 public: 390 public:
387 explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback); 391 explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback);
388 392
389 void OnStatsUpdated() const; 393 void OnStatsUpdated() const;
390 394
391 Bitrate::Observer* total_bitrate_observer(); 395 Bitrate::Observer* total_bitrate_observer();
392 Bitrate::Observer* retransmit_bitrate_observer(); 396 Bitrate::Observer* retransmit_bitrate_observer();
393 void set_ssrc(uint32_t ssrc); 397 void set_ssrc(uint32_t ssrc);
(...skipping 14 matching lines...) Expand all
408 const BitrateAggregator& aggregator_; 412 const BitrateAggregator& aggregator_;
409 }; 413 };
410 414
411 BitrateStatisticsObserver* const callback_; 415 BitrateStatisticsObserver* const callback_;
412 BitrateObserver total_bitrate_observer_; 416 BitrateObserver total_bitrate_observer_;
413 BitrateObserver retransmit_bitrate_observer_; 417 BitrateObserver retransmit_bitrate_observer_;
414 uint32_t ssrc_; 418 uint32_t ssrc_;
415 }; 419 };
416 420
417 Clock* const clock_; 421 Clock* const clock_;
418 const int64_t clock_delta_ms_;
419 Random random_ GUARDED_BY(send_critsect_); 422 Random random_ GUARDED_BY(send_critsect_);
420 423
421 BitrateAggregator bitrates_; 424 BitrateAggregator bitrates_;
422 Bitrate total_bitrate_sent_; 425 Bitrate total_bitrate_sent_;
423 426
424 const bool audio_configured_; 427 const bool audio_configured_;
425 const rtc::scoped_ptr<RTPSenderAudio> audio_; 428 const rtc::scoped_ptr<RTPSenderAudio> audio_;
426 const rtc::scoped_ptr<RTPSenderVideo> video_; 429 const rtc::scoped_ptr<RTPSenderVideo> video_;
427 430
428 RtpPacketSender* const paced_sender_; 431 RtpPacketSender* const paced_sender_;
429 TransportSequenceNumberAllocator* const transport_sequence_number_allocator_; 432 TransportSequenceNumberAllocator* const transport_sequence_number_allocator_;
430 TransportFeedbackObserver* const transport_feedback_observer_; 433 TransportFeedbackObserver* const transport_feedback_observer_;
431 int64_t last_capture_time_ms_sent_; 434 int64_t last_capture_time_ms_sent_;
432 rtc::CriticalSection send_critsect_; 435 rtc::CriticalSection send_critsect_;
433 436
434 Transport *transport_; 437 Transport* transport_;
435 bool sending_media_ GUARDED_BY(send_critsect_); 438 bool sending_media_ GUARDED_BY(send_critsect_);
436 439
437 size_t max_payload_length_; 440 size_t max_payload_length_;
438 441
439 int8_t payload_type_ GUARDED_BY(send_critsect_); 442 int8_t payload_type_ GUARDED_BY(send_critsect_);
440 std::map<int8_t, RtpUtility::Payload*> payload_type_map_; 443 std::map<int8_t, RtpUtility::Payload*> payload_type_map_;
441 444
445 // TODO(danilchap): rtp_header_extension_map_ and rtp_manager_ do same thing
446 // Remove older rtp_header_extension_map_ when all RtpPacket code switch to
447 // use rtp_manager_
442 RtpHeaderExtensionMap rtp_header_extension_map_; 448 RtpHeaderExtensionMap rtp_header_extension_map_;
449 RtpHeaderExtensionsManager rtp_manager_;
450 rtc::ThreadChecker configuration_thread_;
451 rtc::ThreadChecker encoder_thread_;
452 rtc::ThreadChecker network_thread_;
443 int32_t transmission_time_offset_; 453 int32_t transmission_time_offset_;
444 uint32_t absolute_send_time_; 454 uint32_t absolute_send_time_;
445 VideoRotation rotation_; 455 VideoRotation rotation_;
446 CVOMode cvo_mode_; 456 CVOMode cvo_mode_;
447 uint16_t transport_sequence_number_; 457 uint16_t transport_sequence_number_;
448 458
449 // NACK 459 // NACK
450 uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE]; 460 uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE];
451 size_t nack_byte_count_[NACK_BYTECOUNT_SIZE]; 461 size_t nack_byte_count_[NACK_BYTECOUNT_SIZE];
452 Bitrate nack_bitrate_; 462 Bitrate nack_bitrate_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 // that the target bitrate is still valid. 501 // that the target bitrate is still valid.
492 rtc::CriticalSection target_bitrate_critsect_; 502 rtc::CriticalSection target_bitrate_critsect_;
493 uint32_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_); 503 uint32_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_);
494 504
495 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSender); 505 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSender);
496 }; 506 };
497 507
498 } // namespace webrtc 508 } // namespace webrtc
499 509
500 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ 510 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc ('k') | webrtc/modules/rtp_rtcp/source/rtp_sender.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698