OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 #include <cstring> | 11 #include <cstring> |
12 #include <map> | 12 #include <map> |
13 #include <set> | 13 #include <set> |
14 #include <utility> | 14 #include <utility> |
15 | 15 |
16 #include "webrtc/base/random.h" | 16 #include "webrtc/base/random.h" |
| 17 #include "webrtc/common_video/h264/h264_common.h" |
17 #include "webrtc/modules/video_coding/frame_object.h" | 18 #include "webrtc/modules/video_coding/frame_object.h" |
18 #include "webrtc/modules/video_coding/packet_buffer.h" | 19 #include "webrtc/modules/video_coding/packet_buffer.h" |
19 #include "webrtc/system_wrappers/include/clock.h" | 20 #include "webrtc/system_wrappers/include/clock.h" |
20 #include "webrtc/test/gtest.h" | 21 #include "webrtc/test/gtest.h" |
21 | 22 |
22 namespace webrtc { | 23 namespace webrtc { |
23 namespace video_coding { | 24 namespace video_coding { |
24 | 25 |
25 class TestPacketBuffer : public ::testing::Test, | 26 class TestPacketBuffer : public ::testing::Test, |
26 public OnReceivedFrameCallback { | 27 public OnReceivedFrameCallback { |
27 protected: | 28 protected: |
28 TestPacketBuffer() | 29 TestPacketBuffer() |
29 : rand_(0x7732213), | 30 : rand_(0x7732213), |
30 clock_(new SimulatedClock(0)), | 31 clock_(new SimulatedClock(0)), |
31 packet_buffer_( | 32 packet_buffer_( |
32 PacketBuffer::Create(clock_.get(), kStartSize, kMaxSize, this)) {} | 33 PacketBuffer::Create(clock_.get(), kStartSize, kMaxSize, this)) {} |
33 | 34 |
34 uint16_t Rand() { return rand_.Rand<uint16_t>(); } | 35 uint16_t Rand() { return rand_.Rand<uint16_t>(); } |
35 | 36 |
36 void OnReceivedFrame(std::unique_ptr<RtpFrameObject> frame) override { | 37 void OnReceivedFrame(std::unique_ptr<RtpFrameObject> frame) override { |
37 uint16_t first_seq_num = frame->first_seq_num(); | 38 uint16_t first_seq_num = frame->first_seq_num(); |
38 if (frames_from_callback_.find(first_seq_num) != | 39 if (frames_from_callback_.find(first_seq_num) != |
39 frames_from_callback_.end()) { | 40 frames_from_callback_.end()) { |
40 ADD_FAILURE() << "Already received frame with first sequence number " | 41 ADD_FAILURE() << "Already received frame with first sequence number " |
41 << first_seq_num << "."; | 42 << first_seq_num << "."; |
42 return; | 43 return; |
43 } | 44 } |
| 45 |
44 frames_from_callback_.insert( | 46 frames_from_callback_.insert( |
45 std::make_pair(frame->first_seq_num(), std::move(frame))); | 47 std::make_pair(frame->first_seq_num(), std::move(frame))); |
46 } | 48 } |
47 | 49 |
48 enum IsKeyFrame { kKeyFrame, kDeltaFrame }; | 50 enum IsKeyFrame { kKeyFrame, kDeltaFrame }; |
49 enum IsFirst { kFirst, kNotFirst }; | 51 enum IsFirst { kFirst, kNotFirst }; |
50 enum IsLast { kLast, kNotLast }; | 52 enum IsLast { kLast, kNotLast }; |
51 | 53 |
52 bool Insert(uint16_t seq_num, // packet sequence number | 54 bool Insert(uint16_t seq_num, // packet sequence number |
53 IsKeyFrame keyframe, // is keyframe | 55 IsKeyFrame keyframe, // is keyframe |
54 IsFirst first, // is first packet of frame | 56 IsFirst first, // is first packet of frame |
55 IsLast last, // is last packet of frame | 57 IsLast last, // is last packet of frame |
56 int data_size = 0, // size of data | 58 int data_size = 0, // size of data |
57 uint8_t* data = nullptr) { // data pointer | 59 uint8_t* data = nullptr) { // data pointer |
58 VCMPacket packet; | 60 VCMPacket packet; |
59 packet.codec = kVideoCodecGeneric; | 61 packet.codec = kVideoCodecGeneric; |
60 packet.seqNum = seq_num; | 62 packet.seqNum = seq_num; |
61 packet.frameType = | 63 packet.frameType = |
62 keyframe == kKeyFrame ? kVideoFrameKey : kVideoFrameDelta; | 64 keyframe == kKeyFrame ? kVideoFrameKey : kVideoFrameDelta; |
63 packet.is_first_packet_in_frame = first == kFirst; | 65 packet.is_first_packet_in_frame = first == kFirst; |
64 packet.markerBit = last == kLast; | 66 packet.markerBit = last == kLast; |
65 packet.sizeBytes = data_size; | 67 packet.sizeBytes = data_size; |
66 packet.dataPtr = data; | 68 packet.dataPtr = data; |
67 | 69 |
68 return packet_buffer_->InsertPacket(&packet); | 70 return packet_buffer_->InsertPacket(&packet); |
69 } | 71 } |
70 | 72 |
| 73 bool InsertH264(uint16_t seq_num, // packet sequence number |
| 74 IsKeyFrame keyframe, // is keyframe |
| 75 IsFirst first, // is first packet of frame |
| 76 IsLast last, // is last packet of frame |
| 77 uint32_t timestamp, // rtp timestamp |
| 78 int data_size = 0, // size of data |
| 79 uint8_t* data = nullptr) { // data pointer |
| 80 VCMPacket packet; |
| 81 packet.codec = kVideoCodecH264; |
| 82 packet.seqNum = seq_num; |
| 83 packet.timestamp = timestamp; |
| 84 packet.video_header.codecHeader.H264.nalus[0].type = H264::NaluType::kIdr; |
| 85 packet.video_header.codecHeader.H264.nalus_length = keyframe == kKeyFrame; |
| 86 packet.is_first_packet_in_frame = first == kFirst; |
| 87 packet.markerBit = last == kLast; |
| 88 packet.sizeBytes = data_size; |
| 89 packet.dataPtr = data; |
| 90 |
| 91 return packet_buffer_->InsertPacket(&packet); |
| 92 } |
| 93 |
71 void CheckFrame(uint16_t first_seq_num) { | 94 void CheckFrame(uint16_t first_seq_num) { |
72 auto frame_it = frames_from_callback_.find(first_seq_num); | 95 auto frame_it = frames_from_callback_.find(first_seq_num); |
73 ASSERT_FALSE(frame_it == frames_from_callback_.end()) | 96 ASSERT_FALSE(frame_it == frames_from_callback_.end()) |
74 << "Could not find frame with first sequence number " << first_seq_num | 97 << "Could not find frame with first sequence number " << first_seq_num |
75 << "."; | 98 << "."; |
76 } | 99 } |
77 | 100 |
78 const int kStartSize = 16; | 101 const int kStartSize = 16; |
79 const int kMaxSize = 64; | 102 const int kMaxSize = 64; |
80 | 103 |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 uint16_t seq_num = Rand(); | 382 uint16_t seq_num = Rand(); |
360 uint8_t data_data[] = "some plain old data"; | 383 uint8_t data_data[] = "some plain old data"; |
361 uint8_t* data = new uint8_t[sizeof(data_data)]; | 384 uint8_t* data = new uint8_t[sizeof(data_data)]; |
362 memcpy(data, data_data, sizeof(data_data)); | 385 memcpy(data, data_data, sizeof(data_data)); |
363 | 386 |
364 // EncodedImage::kBufferPaddingBytesH264 is unknown at compile time. | 387 // EncodedImage::kBufferPaddingBytesH264 is unknown at compile time. |
365 std::unique_ptr<uint8_t[]> result( | 388 std::unique_ptr<uint8_t[]> result( |
366 new uint8_t[sizeof(data_data) + EncodedImage::kBufferPaddingBytesH264]); | 389 new uint8_t[sizeof(data_data) + EncodedImage::kBufferPaddingBytesH264]); |
367 | 390 |
368 VCMPacket packet; | 391 VCMPacket packet; |
| 392 packet.video_header.codecHeader.H264.nalus_length = 1; |
| 393 packet.video_header.codecHeader.H264.nalus[0].type = H264::NaluType::kIdr; |
369 packet.seqNum = seq_num; | 394 packet.seqNum = seq_num; |
370 packet.codec = kVideoCodecH264; | 395 packet.codec = kVideoCodecH264; |
371 packet.insertStartCode = true; | 396 packet.insertStartCode = true; |
372 packet.video_header.codecHeader.H264.packetization_type = kH264SingleNalu; | 397 packet.video_header.codecHeader.H264.packetization_type = kH264SingleNalu; |
373 packet.dataPtr = data; | 398 packet.dataPtr = data; |
374 packet.sizeBytes = sizeof(data_data); | 399 packet.sizeBytes = sizeof(data_data); |
375 packet.is_first_packet_in_frame = true; | 400 packet.is_first_packet_in_frame = true; |
376 packet.markerBit = true; | 401 packet.markerBit = true; |
377 packet_buffer_->InsertPacket(&packet); | 402 packet_buffer_->InsertPacket(&packet); |
378 | 403 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 | 496 |
472 TEST_F(TestPacketBuffer, ContinuousSeqNumDoubleMarkerBit) { | 497 TEST_F(TestPacketBuffer, ContinuousSeqNumDoubleMarkerBit) { |
473 Insert(2, kKeyFrame, kNotFirst, kNotLast); | 498 Insert(2, kKeyFrame, kNotFirst, kNotLast); |
474 Insert(1, kKeyFrame, kFirst, kLast); | 499 Insert(1, kKeyFrame, kFirst, kLast); |
475 frames_from_callback_.clear(); | 500 frames_from_callback_.clear(); |
476 Insert(3, kKeyFrame, kNotFirst, kLast); | 501 Insert(3, kKeyFrame, kNotFirst, kLast); |
477 | 502 |
478 EXPECT_EQ(0UL, frames_from_callback_.size()); | 503 EXPECT_EQ(0UL, frames_from_callback_.size()); |
479 } | 504 } |
480 | 505 |
481 TEST_F(TestPacketBuffer, OneH264FrameFillBuffer) { | |
482 VCMPacket packet; | |
483 packet.seqNum = 0; | |
484 packet.codec = kVideoCodecH264; | |
485 packet.dataPtr = nullptr; | |
486 packet.sizeBytes = 0; | |
487 packet.is_first_packet_in_frame = true; | |
488 packet.markerBit = false; | |
489 packet_buffer_->InsertPacket(&packet); | |
490 | |
491 packet.is_first_packet_in_frame = false; | |
492 for (int i = 1; i < kStartSize - 1; ++i) { | |
493 packet.seqNum = i; | |
494 packet_buffer_->InsertPacket(&packet); | |
495 } | |
496 | |
497 packet.seqNum = kStartSize - 1; | |
498 packet.markerBit = true; | |
499 packet_buffer_->InsertPacket(&packet); | |
500 | |
501 EXPECT_EQ(1UL, frames_from_callback_.size()); | |
502 CheckFrame(0); | |
503 } | |
504 | |
505 TEST_F(TestPacketBuffer, OneH264FrameMaxSeqNum) { | |
506 VCMPacket packet; | |
507 packet.seqNum = 65534; | |
508 packet.codec = kVideoCodecH264; | |
509 packet.dataPtr = nullptr; | |
510 packet.sizeBytes = 0; | |
511 packet.is_first_packet_in_frame = true; | |
512 packet.markerBit = false; | |
513 packet_buffer_->InsertPacket(&packet); | |
514 | |
515 packet.is_first_packet_in_frame = false; | |
516 packet.seqNum = 65535; | |
517 packet.markerBit = true; | |
518 packet_buffer_->InsertPacket(&packet); | |
519 | |
520 EXPECT_EQ(1UL, frames_from_callback_.size()); | |
521 CheckFrame(65534); | |
522 } | |
523 | |
524 TEST_F(TestPacketBuffer, PacketTimestamps) { | 506 TEST_F(TestPacketBuffer, PacketTimestamps) { |
525 rtc::Optional<int64_t> packet_ms; | 507 rtc::Optional<int64_t> packet_ms; |
526 rtc::Optional<int64_t> packet_keyframe_ms; | 508 rtc::Optional<int64_t> packet_keyframe_ms; |
527 | 509 |
528 packet_ms = packet_buffer_->LastReceivedPacketMs(); | 510 packet_ms = packet_buffer_->LastReceivedPacketMs(); |
529 packet_keyframe_ms = packet_buffer_->LastReceivedKeyframePacketMs(); | 511 packet_keyframe_ms = packet_buffer_->LastReceivedKeyframePacketMs(); |
530 EXPECT_FALSE(packet_ms); | 512 EXPECT_FALSE(packet_ms); |
531 EXPECT_FALSE(packet_keyframe_ms); | 513 EXPECT_FALSE(packet_keyframe_ms); |
532 | 514 |
533 int64_t keyframe_ms = clock_->TimeInMilliseconds(); | 515 int64_t keyframe_ms = clock_->TimeInMilliseconds(); |
(...skipping 15 matching lines...) Expand all Loading... |
549 EXPECT_EQ(delta_ms, *packet_ms); | 531 EXPECT_EQ(delta_ms, *packet_ms); |
550 EXPECT_EQ(keyframe_ms, *packet_keyframe_ms); | 532 EXPECT_EQ(keyframe_ms, *packet_keyframe_ms); |
551 | 533 |
552 packet_buffer_->Clear(); | 534 packet_buffer_->Clear(); |
553 packet_ms = packet_buffer_->LastReceivedPacketMs(); | 535 packet_ms = packet_buffer_->LastReceivedPacketMs(); |
554 packet_keyframe_ms = packet_buffer_->LastReceivedKeyframePacketMs(); | 536 packet_keyframe_ms = packet_buffer_->LastReceivedKeyframePacketMs(); |
555 EXPECT_FALSE(packet_ms); | 537 EXPECT_FALSE(packet_ms); |
556 EXPECT_FALSE(packet_keyframe_ms); | 538 EXPECT_FALSE(packet_keyframe_ms); |
557 } | 539 } |
558 | 540 |
| 541 TEST_F(TestPacketBuffer, OneFrameFillBufferH264) { |
| 542 InsertH264(0, kKeyFrame, kFirst, kNotLast, 1000); |
| 543 for (int i = 1; i < kStartSize - 1; ++i) |
| 544 InsertH264(i, kKeyFrame, kNotFirst, kNotLast, 1000); |
| 545 InsertH264(kStartSize - 1, kKeyFrame, kNotFirst, kLast, 1000); |
| 546 |
| 547 EXPECT_EQ(1UL, frames_from_callback_.size()); |
| 548 CheckFrame(0); |
| 549 } |
| 550 |
| 551 TEST_F(TestPacketBuffer, OneFrameMaxSeqNumH264) { |
| 552 InsertH264(65534, kKeyFrame, kFirst, kNotLast, 1000); |
| 553 InsertH264(65535, kKeyFrame, kNotFirst, kLast, 1000); |
| 554 |
| 555 EXPECT_EQ(1UL, frames_from_callback_.size()); |
| 556 CheckFrame(65534); |
| 557 } |
| 558 |
| 559 TEST_F(TestPacketBuffer, ClearMissingPacketsOnKeyframeH264) { |
| 560 InsertH264(0, kKeyFrame, kFirst, kLast, 1000); |
| 561 InsertH264(2, kKeyFrame, kFirst, kLast, 3000); |
| 562 InsertH264(3, kDeltaFrame, kFirst, kNotLast, 4000); |
| 563 InsertH264(4, kDeltaFrame, kNotFirst, kLast, 4000); |
| 564 |
| 565 ASSERT_EQ(3UL, frames_from_callback_.size()); |
| 566 |
| 567 InsertH264(kStartSize + 1, kKeyFrame, kFirst, kLast, 18000); |
| 568 |
| 569 ASSERT_EQ(4UL, frames_from_callback_.size()); |
| 570 CheckFrame(0); |
| 571 CheckFrame(2); |
| 572 CheckFrame(3); |
| 573 CheckFrame(kStartSize + 1); |
| 574 } |
| 575 |
| 576 TEST_F(TestPacketBuffer, FindFramesOnPaddingH264) { |
| 577 InsertH264(0, kKeyFrame, kFirst, kLast, 1000); |
| 578 InsertH264(2, kDeltaFrame, kFirst, kLast, 1000); |
| 579 |
| 580 ASSERT_EQ(1UL, frames_from_callback_.size()); |
| 581 packet_buffer_->PaddingReceived(1); |
| 582 ASSERT_EQ(2UL, frames_from_callback_.size()); |
| 583 CheckFrame(0); |
| 584 CheckFrame(2); |
| 585 } |
| 586 |
559 } // namespace video_coding | 587 } // namespace video_coding |
560 } // namespace webrtc | 588 } // namespace webrtc |
OLD | NEW |