Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / frame_processor_unittest.cc
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <cstring>
9 #include <map>
10 #include <memory>
11 #include <string>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "base/test/task_environment.h"
20 #include "base/time/time.h"
21 #include "media/base/media_log.h"
22 #include "media/base/media_util.h"
23 #include "media/base/mock_filters.h"
24 #include "media/base/mock_media_log.h"
25 #include "media/base/test_helpers.h"
26 #include "media/base/timestamp_constants.h"
27 #include "media/filters/chunk_demuxer.h"
28 #include "media/filters/frame_processor.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 using base::Milliseconds;
32 using ::testing::_;
33 using ::testing::InSequence;
34 using ::testing::StrictMock;
35 using ::testing::Values;
36
37 namespace {
38
39 // Helpers to encode/decode a base::TimeDelta to/from a string, used in these
40 // tests to populate coded frame payloads with an encoded version of the
41 // original frame timestamp while (slightly) obfuscating the payload itself to
42 // help ensure the payload itself is neither changed by frame processing nor
43 // interpreted directly and mistakenly as a base::TimeDelta by frame processing.
44 std::string EncodeTestPayload(base::TimeDelta timestamp) {
45   return base::NumberToString(timestamp.InMicroseconds());
46 }
47
48 base::TimeDelta DecodeTestPayload(std::string payload) {
49   int64_t microseconds = 0;
50   CHECK(base::StringToInt64(payload, &microseconds));
51   return base::Microseconds(microseconds);
52 }
53
54 }  // namespace
55
56 namespace media {
57
58 typedef StreamParser::BufferQueue BufferQueue;
59 typedef StreamParser::TrackId TrackId;
60
61 // Used for setting expectations on callbacks. Using a StrictMock also lets us
62 // test for missing or extra callbacks.
63 class FrameProcessorTestCallbackHelper {
64  public:
65   FrameProcessorTestCallbackHelper() = default;
66
67   FrameProcessorTestCallbackHelper(const FrameProcessorTestCallbackHelper&) =
68       delete;
69   FrameProcessorTestCallbackHelper& operator=(
70       const FrameProcessorTestCallbackHelper&) = delete;
71
72   virtual ~FrameProcessorTestCallbackHelper() = default;
73
74   MOCK_METHOD1(OnParseWarning, void(const SourceBufferParseWarning));
75   MOCK_METHOD1(PossibleDurationIncrease, void(base::TimeDelta new_duration));
76
77   // Helper that calls the mock method as well as does basic sanity checks on
78   // |new_duration|.
79   void OnPossibleDurationIncrease(base::TimeDelta new_duration) {
80     PossibleDurationIncrease(new_duration);
81     ASSERT_NE(kNoTimestamp, new_duration);
82     ASSERT_NE(kInfiniteDuration, new_duration);
83   }
84
85   MOCK_METHOD2(OnAppend,
86                void(const DemuxerStream::Type type,
87                     const BufferQueue* buffers));
88   MOCK_METHOD3(OnGroupStart,
89                void(const DemuxerStream::Type type,
90                     DecodeTimestamp start_dts,
91                     base::TimeDelta start_pts));
92 };
93
94 class FrameProcessorTest : public ::testing::TestWithParam<bool> {
95  public:
96   FrameProcessorTest(const FrameProcessorTest&) = delete;
97   FrameProcessorTest& operator=(const FrameProcessorTest&) = delete;
98
99  protected:
100   FrameProcessorTest()
101       : append_window_end_(kInfiniteDuration),
102         frame_duration_(Milliseconds(10)),
103         audio_id_(1),
104         video_id_(2) {
105     use_sequence_mode_ = GetParam();
106     frame_processor_ = std::make_unique<FrameProcessor>(
107         base::BindRepeating(
108             &FrameProcessorTestCallbackHelper::OnPossibleDurationIncrease,
109             base::Unretained(&callbacks_)),
110         &media_log_);
111     frame_processor_->SetParseWarningCallback(
112         base::BindRepeating(&FrameProcessorTestCallbackHelper::OnParseWarning,
113                             base::Unretained(&callbacks_)));
114   }
115
116   enum StreamFlags {
117     HAS_AUDIO = 1 << 0,
118     HAS_VIDEO = 1 << 1,
119     OBSERVE_APPENDS_AND_GROUP_STARTS = 1 << 2,
120     USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES = 1 << 3
121   };
122
123   void AddTestTracks(int stream_flags) {
124     const bool has_audio = (stream_flags & HAS_AUDIO) != 0;
125     const bool has_video = (stream_flags & HAS_VIDEO) != 0;
126     ASSERT_TRUE(has_audio || has_video);
127
128     const bool setup_observers =
129         (stream_flags & OBSERVE_APPENDS_AND_GROUP_STARTS) != 0;
130
131     const bool support_audio_nonkeyframes =
132         (stream_flags & USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES) != 0;
133     ASSERT_TRUE(has_audio || !support_audio_nonkeyframes);
134
135     if (has_audio) {
136       CreateAndConfigureStream(DemuxerStream::AUDIO, setup_observers,
137                                support_audio_nonkeyframes);
138       ASSERT_TRUE(audio_);
139       EXPECT_TRUE(frame_processor_->AddTrack(audio_id_, audio_.get()));
140       SeekStream(audio_.get(), Milliseconds(0));
141     }
142     if (has_video) {
143       CreateAndConfigureStream(DemuxerStream::VIDEO, setup_observers, false);
144       ASSERT_TRUE(video_);
145       EXPECT_TRUE(frame_processor_->AddTrack(video_id_, video_.get()));
146       SeekStream(video_.get(), Milliseconds(0));
147     }
148   }
149
150   void SetTimestampOffset(base::TimeDelta new_offset) {
151     timestamp_offset_ = new_offset;
152     frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset_);
153   }
154
155   base::TimeDelta MillisecondStringToTimestamp(std::string ts_string) {
156     if (ts_string == "Min") {
157       return kNoTimestamp;
158     }
159
160     if (ts_string == "Max") {
161       return kInfiniteDuration;
162     }
163
164     // Handle large integers precisely without converting through a double.
165     if (ts_string.find('.') == std::string::npos) {
166       int64_t milliseconds;
167       CHECK(base::StringToInt64(ts_string, &milliseconds));
168       return Milliseconds(milliseconds);
169     }
170
171     double ts_double;
172     CHECK(base::StringToDouble(ts_string, &ts_double));
173     return Milliseconds(ts_double);
174   }
175
176   BufferQueue StringToBufferQueue(const std::string& buffers_to_append,
177                                   const TrackId track_id,
178                                   const DemuxerStream::Type type) {
179     std::vector<std::string> timestamps = base::SplitString(
180         buffers_to_append, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
181
182     BufferQueue buffers;
183     for (size_t i = 0; i < timestamps.size(); i++) {
184       bool is_keyframe = false;
185       if (base::EndsWith(timestamps[i], "K", base::CompareCase::SENSITIVE)) {
186         is_keyframe = true;
187         // Remove the "K" off of the token.
188         timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
189       }
190
191       // Use custom decode timestamp if included.
192       std::vector<std::string> buffer_timestamps = base::SplitString(
193           timestamps[i], "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
194       if (buffer_timestamps.size() == 1)
195         buffer_timestamps.push_back(buffer_timestamps[0]);
196       CHECK_EQ(2u, buffer_timestamps.size());
197
198       const base::TimeDelta pts =
199           MillisecondStringToTimestamp(buffer_timestamps[0]);
200       const DecodeTimestamp dts = DecodeTimestamp::FromPresentationTime(
201           MillisecondStringToTimestamp(buffer_timestamps[1]));
202
203       // Create buffer. Encode the original pts as the buffer's data to enable
204       // later verification of possible buffer relocation in presentation
205       // timeline due to coded frame processing.
206       const std::string payload_string = EncodeTestPayload(pts);
207       const char* pts_as_cstr = payload_string.c_str();
208       scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom(
209           reinterpret_cast<const uint8_t*>(pts_as_cstr), strlen(pts_as_cstr),
210           is_keyframe, type, track_id);
211       CHECK(DecodeTestPayload(
212                 std::string(reinterpret_cast<const char*>(buffer->data()),
213                             buffer->data_size())) == pts);
214
215       buffer->set_timestamp(pts);
216       if (DecodeTimestamp::FromPresentationTime(pts) != dts) {
217         buffer->SetDecodeTimestamp(dts);
218       }
219
220       buffer->set_duration(frame_duration_);
221       buffers.push_back(buffer);
222     }
223     return buffers;
224   }
225
226   bool ProcessFrames(const std::string& audio_timestamps,
227                      const std::string& video_timestamps) {
228     StreamParser::BufferQueueMap buffer_queue_map;
229     const auto& audio_buffers =
230         StringToBufferQueue(audio_timestamps, audio_id_, DemuxerStream::AUDIO);
231     if (!audio_buffers.empty())
232       buffer_queue_map.insert(std::make_pair(audio_id_, audio_buffers));
233     const auto& video_buffers =
234         StringToBufferQueue(video_timestamps, video_id_, DemuxerStream::VIDEO);
235     if (!video_buffers.empty())
236       buffer_queue_map.insert(std::make_pair(video_id_, video_buffers));
237     return frame_processor_->ProcessFrames(
238         buffer_queue_map, append_window_start_, append_window_end_,
239         &timestamp_offset_);
240   }
241
242   // Compares |expected| to the buffered ranges of |stream| formatted into a
243   // string as follows:
244   //
245   // If no ranges: "{ }"
246   // If one range: "{ [start1,end1) }"
247   // If multiple ranges, they are added space-delimited in sequence, like:
248   // "{ [start1,end1) [start2,end2) }"
249   //
250   // startN and endN are the respective buffered start and end times of the
251   // range in integer milliseconds.
252   void CheckExpectedRangesByTimestamp(ChunkDemuxerStream* stream,
253                                       const std::string& expected) {
254     // Note, DemuxerStream::TEXT streams return [0,duration (==infinity here))
255     Ranges<base::TimeDelta> r = stream->GetBufferedRanges(kInfiniteDuration);
256
257     std::stringstream ss;
258     ss << "{ ";
259     for (size_t i = 0; i < r.size(); ++i) {
260       int64_t start = r.start(i).InMilliseconds();
261       int64_t end = r.end(i).InMilliseconds();
262       ss << "[" << start << "," << end << ") ";
263     }
264     ss << "}";
265     EXPECT_EQ(expected, ss.str());
266   }
267
268   void CheckReadStalls(ChunkDemuxerStream* stream) {
269     int loop_count = 0;
270
271     do {
272       read_callback_called_ = false;
273       stream->Read(base::BindOnce(&FrameProcessorTest::StoreStatusAndBuffer,
274                                   base::Unretained(this)));
275       base::RunLoop().RunUntilIdle();
276     } while (++loop_count < 2 && read_callback_called_ &&
277              last_read_status_ == DemuxerStream::kAborted);
278
279     ASSERT_FALSE(read_callback_called_ &&
280                  last_read_status_ == DemuxerStream::kAborted)
281         << "2 kAborted reads in a row. Giving up.";
282     EXPECT_FALSE(read_callback_called_);
283   }
284
285   // Doesn't check keyframeness, but otherwise is the same as
286   // CheckReadsAndOptionallyKeyframenessThenReadStalls().
287   void CheckReadsThenReadStalls(ChunkDemuxerStream* stream,
288                                 const std::string& expected) {
289     CheckReadsAndOptionallyKeyframenessThenReadStalls(stream, expected, false);
290   }
291
292   // Checks keyframeness using
293   // CheckReadsAndOptionallyKeyframenessThenReadStalls().
294   void CheckReadsAndKeyframenessThenReadStalls(ChunkDemuxerStream* stream,
295                                                const std::string& expected) {
296     CheckReadsAndOptionallyKeyframenessThenReadStalls(stream, expected, true);
297   }
298
299   // Format of |expected| is a space-delimited sequence of
300   // timestamp_in_ms:original_timestamp_in_ms. original_timestamp_in_ms (and the
301   // colon) must be omitted if it is the same as timestamp_in_ms. If
302   // |check_keyframeness| is true, then each frame in |expected| must end with
303   // 'K' or 'N', which respectively must match the read result frames'
304   // keyframeness.
305   void CheckReadsAndOptionallyKeyframenessThenReadStalls(
306       ChunkDemuxerStream* stream,
307       const std::string& expected,
308       bool check_keyframeness) {
309     std::vector<std::string> timestamps = base::SplitString(
310         expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
311     std::stringstream ss;
312     for (size_t i = 0; i < timestamps.size(); ++i) {
313       int loop_count = 0;
314
315       do {
316         read_callback_called_ = false;
317         stream->Read(base::BindOnce(&FrameProcessorTest::StoreStatusAndBuffer,
318                                     base::Unretained(this)));
319         base::RunLoop().RunUntilIdle();
320         EXPECT_TRUE(read_callback_called_);
321       } while (++loop_count < 2 &&
322                last_read_status_ == DemuxerStream::kAborted);
323
324       ASSERT_FALSE(last_read_status_ == DemuxerStream::kAborted)
325           << "2 kAborted reads in a row. Giving up.";
326       EXPECT_EQ(DemuxerStream::kOk, last_read_status_);
327       EXPECT_FALSE(last_read_buffer_->end_of_stream());
328
329       if (i > 0)
330         ss << " ";
331
332       int time_in_ms = last_read_buffer_->timestamp().InMilliseconds();
333       ss << time_in_ms;
334
335       // Decode the original_time_in_ms from the buffer's data.
336       double original_time_in_ms;
337       original_time_in_ms =
338           DecodeTestPayload(std::string(reinterpret_cast<const char*>(
339                                             last_read_buffer_->data()),
340                                         last_read_buffer_->data_size()))
341               .InMillisecondsF();
342       if (original_time_in_ms != time_in_ms)
343         ss << ":" << original_time_in_ms;
344
345       // Detect full-discard preroll buffer.
346       if (last_read_buffer_->discard_padding().first == kInfiniteDuration &&
347           last_read_buffer_->discard_padding().second.is_zero()) {
348         ss << "P";
349       }
350
351       // Conditionally check keyframeness.
352       if (check_keyframeness) {
353         if (last_read_buffer_->is_key_frame())
354           ss << "K";
355         else
356           ss << "N";
357       }
358     }
359
360     EXPECT_EQ(expected, ss.str());
361     CheckReadStalls(stream);
362   }
363
364   // TODO(wolenetz): Refactor to instead verify the expected signalling or lack
365   // thereof of new coded frame group by the FrameProcessor. See
366   // https://crbug.com/580613.
367   bool in_coded_frame_group() {
368     return !frame_processor_->pending_notify_all_group_start_;
369   }
370
371   void SeekStream(ChunkDemuxerStream* stream, base::TimeDelta seek_time) {
372     stream->AbortReads();
373     stream->Seek(seek_time);
374     stream->StartReturningData();
375   }
376
377   base::test::SingleThreadTaskEnvironment task_environment_;
378   StrictMock<MockMediaLog> media_log_;
379   StrictMock<FrameProcessorTestCallbackHelper> callbacks_;
380
381   bool use_sequence_mode_;
382
383   std::unique_ptr<FrameProcessor> frame_processor_;
384   base::TimeDelta append_window_start_;
385   base::TimeDelta append_window_end_;
386   base::TimeDelta timestamp_offset_;
387   base::TimeDelta frame_duration_;
388   std::unique_ptr<ChunkDemuxerStream> audio_;
389   std::unique_ptr<ChunkDemuxerStream> video_;
390   const TrackId audio_id_;
391   const TrackId video_id_;
392   const BufferQueue empty_queue_;
393
394   // StoreStatusAndBuffer's most recent result.
395   DemuxerStream::Status last_read_status_;
396   scoped_refptr<DecoderBuffer> last_read_buffer_;
397   bool read_callback_called_;
398
399  private:
400   void StoreStatusAndBuffer(DemuxerStream::Status status,
401                             scoped_refptr<DecoderBuffer> buffer) {
402     if (status == DemuxerStream::kOk && buffer.get()) {
403       DVLOG(3) << __func__ << "status: " << status
404                << " ts: " << buffer->timestamp().InSecondsF();
405     } else {
406       DVLOG(3) << __func__ << "status: " << status << " ts: n/a";
407     }
408
409     read_callback_called_ = true;
410     last_read_status_ = status;
411     last_read_buffer_ = buffer;
412   }
413
414   void CreateAndConfigureStream(DemuxerStream::Type type,
415                                 bool setup_observers,
416                                 bool support_audio_nonkeyframes) {
417     // TODO(wolenetz/dalecurtis): Also test with splicing disabled?
418
419     ChunkDemuxerStream* stream;
420     switch (type) {
421       case DemuxerStream::AUDIO: {
422         ASSERT_FALSE(audio_);
423         audio_ = std::make_unique<ChunkDemuxerStream>(DemuxerStream::AUDIO,
424                                                       MediaTrack::Id("1"));
425         AudioDecoderConfig decoder_config;
426         if (support_audio_nonkeyframes) {
427           decoder_config = AudioDecoderConfig(
428               AudioCodec::kAAC, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
429               1000, EmptyExtraData(), EncryptionScheme::kUnencrypted);
430           decoder_config.set_profile(AudioCodecProfile::kXHE_AAC);
431         } else {
432           decoder_config =
433               AudioDecoderConfig(AudioCodec::kVorbis, kSampleFormatPlanarF32,
434                                  CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(),
435                                  EncryptionScheme::kUnencrypted);
436         }
437         frame_processor_->OnPossibleAudioConfigUpdate(decoder_config);
438         ASSERT_TRUE(
439             audio_->UpdateAudioConfig(decoder_config, false, &media_log_));
440
441         stream = audio_.get();
442         break;
443       }
444       case DemuxerStream::VIDEO: {
445         ASSERT_FALSE(video_);
446         ASSERT_FALSE(support_audio_nonkeyframes);
447         video_ = std::make_unique<ChunkDemuxerStream>(DemuxerStream::VIDEO,
448                                                       MediaTrack::Id("2"));
449         ASSERT_TRUE(video_->UpdateVideoConfig(TestVideoConfig::Normal(), false,
450                                               &media_log_));
451         stream = video_.get();
452         break;
453       }
454       // TODO(wolenetz): Test text coded frame processing.
455       case DemuxerStream::TEXT:
456       case DemuxerStream::UNKNOWN: {
457         ASSERT_FALSE(true);
458       }
459     }
460
461     if (setup_observers) {
462       stream->set_append_observer_for_testing(
463           base::BindRepeating(&FrameProcessorTestCallbackHelper::OnAppend,
464                               base::Unretained(&callbacks_), type));
465       stream->set_group_start_observer_for_testing(
466           base::BindRepeating(&FrameProcessorTestCallbackHelper::OnGroupStart,
467                               base::Unretained(&callbacks_), type));
468     }
469   }
470 };
471
472 TEST_P(FrameProcessorTest, WrongTypeInAppendedBuffer) {
473   AddTestTracks(HAS_AUDIO);
474   EXPECT_FALSE(in_coded_frame_group());
475
476   StreamParser::BufferQueueMap buffer_queue_map;
477   const auto& audio_buffers =
478       StringToBufferQueue("0K", audio_id_, DemuxerStream::VIDEO);
479   buffer_queue_map.insert(std::make_pair(audio_id_, audio_buffers));
480   EXPECT_MEDIA_LOG(FrameTypeMismatchesTrackType("video", "1"));
481   ASSERT_FALSE(
482       frame_processor_->ProcessFrames(buffer_queue_map, append_window_start_,
483                                       append_window_end_, &timestamp_offset_));
484   EXPECT_FALSE(in_coded_frame_group());
485   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
486   CheckExpectedRangesByTimestamp(audio_.get(), "{ }");
487   CheckReadStalls(audio_.get());
488 }
489
490 TEST_P(FrameProcessorTest, NonMonotonicallyIncreasingTimestampInOneCall) {
491   AddTestTracks(HAS_AUDIO);
492
493   EXPECT_MEDIA_LOG(ParsedBuffersNotInDTSSequence());
494   EXPECT_FALSE(ProcessFrames("10K 0K", ""));
495   EXPECT_FALSE(in_coded_frame_group());
496   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
497   CheckExpectedRangesByTimestamp(audio_.get(), "{ }");
498   CheckReadStalls(audio_.get());
499 }
500
501 TEST_P(FrameProcessorTest, AudioOnly_SingleFrame) {
502   // Tests A: P(A) -> (a)
503   InSequence s;
504   AddTestTracks(HAS_AUDIO);
505   if (use_sequence_mode_)
506     frame_processor_->SetSequenceMode(true);
507
508   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
509   EXPECT_TRUE(ProcessFrames("0K", ""));
510   EXPECT_TRUE(in_coded_frame_group());
511   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
512   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,10) }");
513   CheckReadsThenReadStalls(audio_.get(), "0");
514 }
515
516 TEST_P(FrameProcessorTest, VideoOnly_SingleFrame) {
517   // Tests V: P(V) -> (v)
518   InSequence s;
519   AddTestTracks(HAS_VIDEO);
520   if (use_sequence_mode_)
521     frame_processor_->SetSequenceMode(true);
522
523   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
524   EXPECT_TRUE(ProcessFrames("", "0K"));
525   EXPECT_TRUE(in_coded_frame_group());
526   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
527   CheckExpectedRangesByTimestamp(video_.get(), "{ [0,10) }");
528   CheckReadsThenReadStalls(video_.get(), "0");
529 }
530
531 TEST_P(FrameProcessorTest, AudioOnly_TwoFrames) {
532   // Tests A: P(A0, A10) -> (a0, a10)
533   InSequence s;
534   AddTestTracks(HAS_AUDIO);
535   if (use_sequence_mode_)
536     frame_processor_->SetSequenceMode(true);
537
538   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
539   EXPECT_TRUE(ProcessFrames("0K 10K", ""));
540   EXPECT_TRUE(in_coded_frame_group());
541   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
542   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
543   CheckReadsThenReadStalls(audio_.get(), "0 10");
544 }
545
546 TEST_P(FrameProcessorTest, AudioOnly_SetOffsetThenSingleFrame) {
547   // Tests A: STSO(50)+P(A0) -> TSO==50,(a0@50)
548   InSequence s;
549   AddTestTracks(HAS_AUDIO);
550   if (use_sequence_mode_)
551     frame_processor_->SetSequenceMode(true);
552
553   SetTimestampOffset(Milliseconds(50));
554   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(60)));
555   EXPECT_TRUE(ProcessFrames("0K", ""));
556   EXPECT_TRUE(in_coded_frame_group());
557   EXPECT_EQ(Milliseconds(50), timestamp_offset_);
558   CheckExpectedRangesByTimestamp(audio_.get(), "{ [50,60) }");
559
560   // We do not stall on reading without seeking to 50ms due to
561   // SourceBufferStream::kSeekToStartFudgeRoom().
562   CheckReadsThenReadStalls(audio_.get(), "50:0");
563 }
564
565 TEST_P(FrameProcessorTest, AudioOnly_SetOffsetThenFrameTimestampBelowOffset) {
566   // Tests A: STSO(50)+P(A20) ->
567   //   if sequence mode: TSO==30,(a20@50)
568   //   if segments mode: TSO==50,(a20@70)
569   InSequence s;
570   AddTestTracks(HAS_AUDIO);
571   if (use_sequence_mode_)
572     frame_processor_->SetSequenceMode(true);
573
574   SetTimestampOffset(Milliseconds(50));
575
576   if (use_sequence_mode_) {
577     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(60)));
578   } else {
579     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(80)));
580   }
581
582   EXPECT_TRUE(ProcessFrames("20K", ""));
583   EXPECT_TRUE(in_coded_frame_group());
584
585   // We do not stall on reading without seeking to 50ms / 70ms due to
586   // SourceBufferStream::kSeekToStartFudgeRoom().
587   if (use_sequence_mode_) {
588     EXPECT_EQ(Milliseconds(30), timestamp_offset_);
589     CheckExpectedRangesByTimestamp(audio_.get(), "{ [50,60) }");
590     CheckReadsThenReadStalls(audio_.get(), "50:20");
591   } else {
592     EXPECT_EQ(Milliseconds(50), timestamp_offset_);
593     CheckExpectedRangesByTimestamp(audio_.get(), "{ [70,80) }");
594     CheckReadsThenReadStalls(audio_.get(), "70:20");
595   }
596 }
597
598 TEST_P(FrameProcessorTest, AudioOnly_SequentialProcessFrames) {
599   // Tests A: P(A0,A10)+P(A20,A30) -> (a0,a10,a20,a30)
600   InSequence s;
601   AddTestTracks(HAS_AUDIO);
602   if (use_sequence_mode_)
603     frame_processor_->SetSequenceMode(true);
604
605   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
606   EXPECT_TRUE(ProcessFrames("0K 10K", ""));
607   EXPECT_TRUE(in_coded_frame_group());
608   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
609   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
610
611   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(40)));
612   EXPECT_TRUE(ProcessFrames("20K 30K", ""));
613   EXPECT_TRUE(in_coded_frame_group());
614   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
615   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,40) }");
616
617   CheckReadsThenReadStalls(audio_.get(), "0 10 20 30");
618 }
619
620 TEST_P(FrameProcessorTest, AudioOnly_NonSequentialProcessFrames) {
621   // Tests A: P(A20,A30)+P(A0,A10) ->
622   //   if sequence mode: TSO==-20 after first P(), 20 after second P(), and
623   //                     a(20@0,a30@10,a0@20,a10@30)
624   //   if segments mode: TSO==0,(a0,a10,a20,a30)
625   InSequence s;
626   AddTestTracks(HAS_AUDIO);
627   if (use_sequence_mode_) {
628     frame_processor_->SetSequenceMode(true);
629     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
630   } else {
631     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(40)));
632   }
633
634   EXPECT_TRUE(ProcessFrames("20K 30K", ""));
635   EXPECT_TRUE(in_coded_frame_group());
636
637   if (use_sequence_mode_) {
638     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
639     EXPECT_EQ(Milliseconds(-20), timestamp_offset_);
640     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(40)));
641   } else {
642     CheckExpectedRangesByTimestamp(audio_.get(), "{ [20,40) }");
643     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
644     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
645   }
646
647   EXPECT_TRUE(ProcessFrames("0K 10K", ""));
648   EXPECT_TRUE(in_coded_frame_group());
649
650   if (use_sequence_mode_) {
651     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,40) }");
652     EXPECT_EQ(Milliseconds(20), timestamp_offset_);
653     CheckReadsThenReadStalls(audio_.get(), "0:20 10:30 20:0 30:10");
654   } else {
655     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,40) }");
656     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
657     // Re-seek to 0ms now that we've appended data earlier than what has already
658     // satisfied our initial seek to start, above.
659     SeekStream(audio_.get(), Milliseconds(0));
660     CheckReadsThenReadStalls(audio_.get(), "0 10 20 30");
661   }
662 }
663
664 TEST_P(FrameProcessorTest, AudioVideo_SequentialProcessFrames) {
665   // Tests AV: P(A0,A10;V0k,V10,V20)+P(A20,A30,A40,V30) ->
666   //   (a0,a10,a20,a30,a40);(v0,v10,v20,v30)
667   InSequence s;
668   AddTestTracks(HAS_AUDIO | HAS_VIDEO);
669   if (use_sequence_mode_) {
670     frame_processor_->SetSequenceMode(true);
671     EXPECT_CALL(callbacks_,
672                 OnParseWarning(SourceBufferParseWarning::kMuxedSequenceMode));
673     EXPECT_MEDIA_LOG(MuxedSequenceModeWarning());
674   }
675
676   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(30)));
677   EXPECT_TRUE(ProcessFrames("0K 10K", "0K 10 20"));
678   EXPECT_TRUE(in_coded_frame_group());
679   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
680   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
681   CheckExpectedRangesByTimestamp(video_.get(), "{ [0,30) }");
682
683   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(50)));
684   EXPECT_TRUE(ProcessFrames("20K 30K 40K", "30"));
685   EXPECT_TRUE(in_coded_frame_group());
686   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
687   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,50) }");
688   CheckExpectedRangesByTimestamp(video_.get(), "{ [0,40) }");
689
690   CheckReadsThenReadStalls(audio_.get(), "0 10 20 30 40");
691   CheckReadsThenReadStalls(video_.get(), "0 10 20 30");
692 }
693
694 TEST_P(FrameProcessorTest, AudioVideo_Discontinuity) {
695   // Tests AV: P(A0,A10,A30,A40,A50;V0key,V10,V40,V50key) ->
696   //   if sequence mode: TSO==10,(a0,a10,a30,a40,a50@60);(v0,v10,v50@60)
697   //   if segments mode: TSO==0,(a0,a10,a30,a40,a50);(v0,v10,v50)
698   // This assumes A40K is processed before V40, which depends currently on
699   // MergeBufferQueues() behavior.
700   InSequence s;
701   AddTestTracks(HAS_AUDIO | HAS_VIDEO);
702   if (use_sequence_mode_) {
703     frame_processor_->SetSequenceMode(true);
704     EXPECT_CALL(callbacks_,
705                 OnParseWarning(SourceBufferParseWarning::kMuxedSequenceMode));
706     EXPECT_MEDIA_LOG(MuxedSequenceModeWarning());
707     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(70)));
708   } else {
709     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(60)));
710   }
711
712   EXPECT_TRUE(ProcessFrames("0K 10K 30K 40K 50K", "0K 10 40 50K"));
713   EXPECT_TRUE(in_coded_frame_group());
714
715   if (use_sequence_mode_) {
716     EXPECT_EQ(Milliseconds(10), timestamp_offset_);
717     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,70) }");
718     CheckExpectedRangesByTimestamp(video_.get(), "{ [0,20) [60,70) }");
719     CheckReadsThenReadStalls(audio_.get(), "0 10 30 40 60:50");
720     CheckReadsThenReadStalls(video_.get(), "0 10");
721     SeekStream(video_.get(), Milliseconds(60));
722     CheckReadsThenReadStalls(video_.get(), "60:50");
723   } else {
724     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
725     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,60) }");
726     CheckExpectedRangesByTimestamp(video_.get(), "{ [0,20) [50,60) }");
727     CheckReadsThenReadStalls(audio_.get(), "0 10 30 40 50");
728     CheckReadsThenReadStalls(video_.get(), "0 10");
729     SeekStream(video_.get(), Milliseconds(50));
730     CheckReadsThenReadStalls(video_.get(), "50");
731   }
732 }
733
734 TEST_P(FrameProcessorTest, AudioVideo_Discontinuity_TimestampOffset) {
735   InSequence s;
736   AddTestTracks(HAS_AUDIO | HAS_VIDEO);
737   frame_processor_->SetSequenceMode(use_sequence_mode_);
738   if (use_sequence_mode_) {
739     EXPECT_CALL(callbacks_,
740                 OnParseWarning(SourceBufferParseWarning::kMuxedSequenceMode));
741     EXPECT_MEDIA_LOG(MuxedSequenceModeWarning());
742   }
743
744   // Start a coded frame group at time 100ms. Note the jagged start still uses
745   // the coded frame group's start time as the range start for both streams.
746   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
747   SetTimestampOffset(Milliseconds(100));
748   EXPECT_TRUE(ProcessFrames("0K 10K 20K", "10K 20K 30K"));
749   EXPECT_EQ(Milliseconds(100), timestamp_offset_);
750   EXPECT_TRUE(in_coded_frame_group());
751   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }");
752   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) }");
753
754   // Test the behavior of both 'sequence' and 'segments' mode if the coded frame
755   // sequence jumps forward beyond the normal discontinuity threshold.
756   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(240)));
757   SetTimestampOffset(Milliseconds(200));
758   EXPECT_TRUE(ProcessFrames("0K 10K 20K", "10K 20K 30K"));
759   EXPECT_EQ(Milliseconds(200), timestamp_offset_);
760   EXPECT_TRUE(in_coded_frame_group());
761   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) [200,230) }");
762   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [200,240) }");
763
764   // Test the behavior when timestampOffset adjustment causes next frames to be
765   // in the past relative to the previously processed frame and triggers a new
766   // coded frame group.
767   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(95)));
768   SetTimestampOffset(Milliseconds(55));
769   EXPECT_TRUE(ProcessFrames("0K 10K 20K", "10K 20K 30K"));
770   EXPECT_EQ(Milliseconds(55), timestamp_offset_);
771   EXPECT_TRUE(in_coded_frame_group());
772   // The new audio range is not within SourceBufferStream's coalescing threshold
773   // relative to the next range, but the new video range is within the
774   // threshold.
775   CheckExpectedRangesByTimestamp(audio_.get(),
776                                  "{ [55,85) [100,130) [200,230) }");
777   // Note that the range adjacency logic used in this case considers
778   // DTS 85 to be close enough to [100,140), even though the first DTS in video
779   // range [100,140) is actually 110. The muxed data started a coded frame
780   // group at time 100, informing the adjacency logic.
781   CheckExpectedRangesByTimestamp(video_.get(), "{ [55,140) [200,240) }");
782
783   // Verify the buffers.
784   // Re-seek now that we've appended data earlier than what already satisfied
785   // our initial seek to start.
786   SeekStream(audio_.get(), Milliseconds(55));
787   CheckReadsThenReadStalls(audio_.get(), "55:0 65:10 75:20");
788   SeekStream(audio_.get(), Milliseconds(100));
789   CheckReadsThenReadStalls(audio_.get(), "100:0 110:10 120:20");
790   SeekStream(audio_.get(), Milliseconds(200));
791   CheckReadsThenReadStalls(audio_.get(), "200:0 210:10 220:20");
792
793   SeekStream(video_.get(), Milliseconds(55));
794   CheckReadsThenReadStalls(video_.get(),
795                            "65:10 75:20 85:30 110:10 120:20 130:30");
796   SeekStream(video_.get(), Milliseconds(200));
797   CheckReadsThenReadStalls(video_.get(), "210:10 220:20 230:30");
798 }
799
800 TEST_P(FrameProcessorTest, AudioVideo_OutOfSequence_After_Discontinuity) {
801   // Once a discontinuity is detected (and all tracks drop everything until the
802   // next keyframe per each track), we should gracefully handle the case where
803   // some tracks' first keyframe after the discontinuity are appended after, but
804   // end up earlier in timeline than some other track(s). In particular, we
805   // shouldn't notify all tracks that a new coded frame group is starting and
806   // begin dropping leading non-keyframes from all tracks.  Rather, we should
807   // notify just the track encountering this new type of discontinuity.  Since
808   // MSE doesn't require all media segments to contain media from every track,
809   // these append sequences can occur.
810   InSequence s;
811   AddTestTracks(HAS_AUDIO | HAS_VIDEO);
812   frame_processor_->SetSequenceMode(use_sequence_mode_);
813
814   // Begin with a simple set of appends for all tracks.
815   if (use_sequence_mode_) {
816     // Allow room in the timeline for the last audio append (50K, below) in this
817     // test to remain within default append window [0, +Infinity]. Moving the
818     // sequence mode appends to begin at time 100ms, the same time as the first
819     // append, below, results in a -20ms offset (instead of a -120ms offset)
820     // applied to frames beginning at the first frame after the discontinuity
821     // caused by the video append at 160K, below.
822     SetTimestampOffset(Milliseconds(100));
823     EXPECT_CALL(callbacks_,
824                 OnParseWarning(SourceBufferParseWarning::kMuxedSequenceMode));
825     EXPECT_MEDIA_LOG(MuxedSequenceModeWarning());
826   }
827   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
828   EXPECT_TRUE(ProcessFrames("100K 110K 120K", "110K 120K 130K"));
829   EXPECT_TRUE(in_coded_frame_group());
830   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
831   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }");
832   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) }");
833
834   // Trigger (normal) discontinuity with one track (video).
835   if (use_sequence_mode_)
836     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(150)));
837   else
838     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(170)));
839
840   EXPECT_TRUE(ProcessFrames("", "160K"));
841   EXPECT_TRUE(in_coded_frame_group());
842
843   if (use_sequence_mode_) {
844     // The new video buffer is relocated into [140,150).
845     EXPECT_EQ(Milliseconds(-20), timestamp_offset_);
846     CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }");
847     CheckExpectedRangesByTimestamp(video_.get(), "{ [100,150) }");
848   } else {
849     // The new video buffer is at [160,170).
850     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
851     CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }");
852     CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [160,170) }");
853   }
854
855   // Append to the other track (audio) with lower time than the video frame we
856   // just appended. Append with a timestamp such that segments mode demonstrates
857   // we don't retroactively extend the new video buffer appended above's range
858   // start back to this audio start time.
859   if (use_sequence_mode_)
860     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(150)));
861   else
862     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(170)));
863
864   EXPECT_TRUE(ProcessFrames("50K", ""));
865   EXPECT_TRUE(in_coded_frame_group());
866
867   // Because this is the first audio buffer appended following the discontinuity
868   // detected while appending the video frame, above, a new coded frame group
869   // for video is not triggered.
870   if (use_sequence_mode_) {
871     // The new audio buffer is relocated into [30,40). Note the muxed 'sequence'
872     // mode append mode results in a buffered range gap in this case.
873     EXPECT_EQ(Milliseconds(-20), timestamp_offset_);
874     CheckExpectedRangesByTimestamp(audio_.get(), "{ [30,40) [100,130) }");
875     CheckExpectedRangesByTimestamp(video_.get(), "{ [100,150) }");
876   } else {
877     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
878     CheckExpectedRangesByTimestamp(audio_.get(), "{ [50,60) [100,130) }");
879     CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [160,170) }");
880   }
881
882   // Finally, append a non-keyframe to the first track (video), to continue the
883   // GOP that started the normal discontinuity on the previous video append.
884   if (use_sequence_mode_)
885     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(160)));
886   else
887     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(180)));
888
889   EXPECT_TRUE(ProcessFrames("", "170"));
890   EXPECT_TRUE(in_coded_frame_group());
891
892   // Verify the final buffers. First, re-seek audio since we appended data
893   // earlier than what already satisfied our initial seek to start. We satisfy
894   // the seek with the first buffer in [0,1000).
895   SeekStream(audio_.get(), Milliseconds(0));
896   if (use_sequence_mode_) {
897     // The new video buffer is relocated into [150,160).
898     EXPECT_EQ(Milliseconds(-20), timestamp_offset_);
899     CheckExpectedRangesByTimestamp(audio_.get(), "{ [30,40) [100,130) }");
900     CheckReadsThenReadStalls(audio_.get(), "30:50");
901     SeekStream(audio_.get(), Milliseconds(100));
902     CheckReadsThenReadStalls(audio_.get(), "100 110 120");
903
904     CheckExpectedRangesByTimestamp(video_.get(), "{ [100,160) }");
905     CheckReadsThenReadStalls(video_.get(), "110 120 130 140:160 150:170");
906   } else {
907     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
908     CheckExpectedRangesByTimestamp(audio_.get(), "{ [50,60) [100,130) }");
909     CheckReadsThenReadStalls(audio_.get(), "50");
910     SeekStream(audio_.get(), Milliseconds(100));
911     CheckReadsThenReadStalls(audio_.get(), "100 110 120");
912
913     CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [160,180) }");
914     CheckReadsThenReadStalls(video_.get(), "110 120 130");
915     SeekStream(video_.get(), Milliseconds(160));
916     CheckReadsThenReadStalls(video_.get(), "160 170");
917   }
918 }
919
920 TEST_P(FrameProcessorTest,
921        AppendWindowFilterOfNegativeBufferTimestampsWithPrerollDiscard) {
922   InSequence s;
923   AddTestTracks(HAS_AUDIO);
924   if (use_sequence_mode_)
925     frame_processor_->SetSequenceMode(true);
926
927   SetTimestampOffset(Milliseconds(-20));
928   EXPECT_MEDIA_LOG(DroppedFrame("audio", -20000));
929   EXPECT_MEDIA_LOG(DroppedFrame("audio", -10000));
930   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
931   EXPECT_TRUE(ProcessFrames("0K 10K 20K", ""));
932   EXPECT_TRUE(in_coded_frame_group());
933   EXPECT_EQ(Milliseconds(-20), timestamp_offset_);
934   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,10) }");
935   CheckReadsThenReadStalls(audio_.get(), "0:10P 0:20");
936 }
937
938 TEST_P(FrameProcessorTest, AppendWindowFilterWithInexactPreroll) {
939   InSequence s;
940   AddTestTracks(HAS_AUDIO);
941   if (use_sequence_mode_)
942     frame_processor_->SetSequenceMode(true);
943   SetTimestampOffset(Milliseconds(-10));
944   EXPECT_MEDIA_LOG(DroppedFrame("audio", -10000));
945   EXPECT_MEDIA_LOG(TruncatedFrame(-250, 9750, "start", 0));
946   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
947   EXPECT_TRUE(ProcessFrames("0K 9.75K 20K", ""));
948   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
949   CheckReadsThenReadStalls(audio_.get(), "0P 0:9.75 10:20");
950 }
951
952 TEST_P(FrameProcessorTest, AppendWindowFilterWithInexactPreroll_2) {
953   InSequence s;
954   AddTestTracks(HAS_AUDIO);
955   if (use_sequence_mode_)
956     frame_processor_->SetSequenceMode(true);
957   SetTimestampOffset(Milliseconds(-10));
958
959   EXPECT_MEDIA_LOG(DroppedFrame("audio", -10000));
960   // Splice trimming checks are done on every audio frame following either a
961   // discontinuity or the beginning of ProcessFrames(), and are also done on
962   // audio frames with PTS not directly continuous with the highest frame end
963   // PTS already processed.
964   if (use_sequence_mode_)
965     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(-10)));
966   else
967     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(0)));
968   EXPECT_TRUE(ProcessFrames("0K", ""));
969
970   EXPECT_CALL(callbacks_, PossibleDurationIncrease(base::Microseconds(10250)));
971   EXPECT_TRUE(ProcessFrames("10.25K", ""));
972
973   EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(10000, 250));
974   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
975   EXPECT_TRUE(ProcessFrames("20K", ""));
976
977   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
978   CheckReadsThenReadStalls(audio_.get(), "0P 0:10.25 10:20");
979 }
980
981 TEST_P(FrameProcessorTest, AllowNegativeFramePTSAndDTSBeforeOffsetAdjustment) {
982   InSequence s;
983   AddTestTracks(HAS_AUDIO);
984   if (use_sequence_mode_) {
985     frame_processor_->SetSequenceMode(true);
986     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(30)));
987   } else {
988     EXPECT_MEDIA_LOG(TruncatedFrame(-5000, 5000, "start", 0));
989     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(25)));
990   }
991
992   EXPECT_TRUE(ProcessFrames("-5K 5K 15K", ""));
993
994   if (use_sequence_mode_) {
995     EXPECT_EQ(Milliseconds(5), timestamp_offset_);
996     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,30) }");
997     CheckReadsThenReadStalls(audio_.get(), "0:-5 10:5 20:15");
998   } else {
999     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1000     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,25) }");
1001     CheckReadsThenReadStalls(audio_.get(), "0:-5 5 15");
1002   }
1003 }
1004
1005 TEST_P(FrameProcessorTest, PartialAppendWindowFilterNoDiscontinuity) {
1006   // Tests that spurious discontinuity is not introduced by a partially
1007   // trimmed frame.
1008   append_window_start_ = Milliseconds(7);
1009
1010   InSequence s;
1011   AddTestTracks(HAS_AUDIO);
1012   if (use_sequence_mode_)
1013     frame_processor_->SetSequenceMode(true);
1014   EXPECT_MEDIA_LOG(TruncatedFrame(0, 10000, "start", 7000));
1015   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(29)));
1016
1017   EXPECT_TRUE(ProcessFrames("0K 19K", ""));
1018
1019   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1020   CheckExpectedRangesByTimestamp(audio_.get(), "{ [7,29) }");
1021   CheckReadsThenReadStalls(audio_.get(), "7:0 19");
1022 }
1023
1024 TEST_P(FrameProcessorTest,
1025        PartialAppendWindowFilterNoDiscontinuity_DtsAfterPts) {
1026   // Tests that spurious discontinuity is not introduced by a partially trimmed
1027   // frame that originally had DTS > PTS.
1028   InSequence s;
1029   AddTestTracks(HAS_AUDIO);
1030
1031   if (use_sequence_mode_) {
1032     frame_processor_->SetSequenceMode(true);
1033     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
1034   } else {
1035     EXPECT_MEDIA_LOG(TruncatedFrame(-7000, 3000, "start", 0));
1036     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(13)));
1037   }
1038
1039   // Process a sequence of two audio frames:
1040   // A: PTS -7ms, DTS 10ms, duration 10ms, keyframe
1041   // B: PTS  3ms, DTS 20ms, duration 10ms, keyframe
1042   EXPECT_TRUE(ProcessFrames("-7|10K 3|20K", ""));
1043
1044   if (use_sequence_mode_) {
1045     // Sequence mode detected that frame A needs to be relocated 7ms into the
1046     // future to begin the sequence at time 0. There is no append window
1047     // filtering because the PTS result of the relocation is within the append
1048     // window of [0,+Infinity).
1049     // Frame A is relocated by 7 to PTS 0, DTS 17, duration 10.
1050     // Frame B is relocated by 7 to PTS 10, DTS 27, duration 10.
1051     EXPECT_EQ(Milliseconds(7), timestamp_offset_);
1052
1053     // Start of frame A (0) through end of frame B (10+10).
1054     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
1055
1056     // Frame A is now at PTS 0 (originally at PTS -7)
1057     // Frame B is now at PTS 10 (originally at PTS 3)
1058     CheckReadsThenReadStalls(audio_.get(), "0:-7 10:3");
1059   } else {
1060     // Segments mode does not update timestampOffset automatically, so it
1061     // remained 0 and neither frame was relocated by timestampOffset.
1062     // Frame A's start *was* relocated by append window partial audio cropping:
1063     // Append window filtering (done by PTS, regardless of range buffering API)
1064     // did a partial crop of the first 7ms of frame A which was before
1065     // the default append window start time 0, and moved both the PTS and DTS of
1066     // frame A forward by 7 and reduced its duration by 7. Frame B was fully
1067     // inside the append window and remained uncropped and unrelocated.
1068     // Frame A is buffered at PTS -7+7=0, DTS 10+7=17, duration 10-7=3.
1069     // Frame B is buffered at PTS 3, DTS 20, duration 10.
1070     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1071
1072     // Start of frame A (0) through end of frame B (3+10).
1073     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,13) }");
1074
1075     // Frame A is now at PTS 0 (originally at PTS -7)
1076     // Frame B is now at PTS 3 (same as it was originally)
1077     CheckReadsThenReadStalls(audio_.get(), "0:-7 3");
1078   }
1079 }
1080
1081 TEST_P(FrameProcessorTest, PartialAppendWindowFilterNoNewMediaSegment) {
1082   // Tests that a new media segment is not forcibly signalled for audio frame
1083   // partial front trim, to prevent incorrect introduction of a discontinuity
1084   // and potentially a non-keyframe video frame to be processed next after the
1085   // discontinuity.
1086   InSequence s;
1087   AddTestTracks(HAS_AUDIO | HAS_VIDEO);
1088   frame_processor_->SetSequenceMode(use_sequence_mode_);
1089   if (use_sequence_mode_) {
1090     EXPECT_CALL(callbacks_,
1091                 OnParseWarning(SourceBufferParseWarning::kMuxedSequenceMode));
1092     EXPECT_MEDIA_LOG(MuxedSequenceModeWarning());
1093   }
1094   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
1095   EXPECT_TRUE(ProcessFrames("", "0K"));
1096   EXPECT_MEDIA_LOG(TruncatedFrame(-5000, 5000, "start", 0));
1097   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
1098   EXPECT_TRUE(ProcessFrames("-5K", ""));
1099   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
1100   EXPECT_TRUE(ProcessFrames("", "10"));
1101
1102   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1103   EXPECT_TRUE(in_coded_frame_group());
1104   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,5) }");
1105   CheckExpectedRangesByTimestamp(video_.get(), "{ [0,20) }");
1106   CheckReadsThenReadStalls(audio_.get(), "0:-5");
1107   CheckReadsThenReadStalls(video_.get(), "0 10");
1108 }
1109
1110 TEST_P(FrameProcessorTest, AudioOnly_SequenceModeContinuityAcrossReset) {
1111   if (!use_sequence_mode_) {
1112     DVLOG(1) << "Skipping segments mode variant; inapplicable to this case.";
1113     return;
1114   }
1115
1116   InSequence s;
1117   AddTestTracks(HAS_AUDIO);
1118   frame_processor_->SetSequenceMode(true);
1119   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
1120   EXPECT_TRUE(ProcessFrames("0K", ""));
1121   frame_processor_->Reset();
1122   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
1123   EXPECT_TRUE(ProcessFrames("100K", ""));
1124
1125   EXPECT_EQ(Milliseconds(-90), timestamp_offset_);
1126   EXPECT_TRUE(in_coded_frame_group());
1127   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,20) }");
1128   CheckReadsThenReadStalls(audio_.get(), "0 10:100");
1129 }
1130
1131 TEST_P(FrameProcessorTest, PartialAppendWindowZeroDurationPreroll) {
1132   InSequence s;
1133   AddTestTracks(HAS_AUDIO);
1134   frame_processor_->SetSequenceMode(use_sequence_mode_);
1135
1136   append_window_start_ = Milliseconds(5);
1137
1138   EXPECT_MEDIA_LOG(DroppedFrame("audio", use_sequence_mode_ ? 0 : 4000));
1139   // Append a 0 duration frame that falls just before the append window.
1140   frame_duration_ = Milliseconds(0);
1141   EXPECT_FALSE(in_coded_frame_group());
1142   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(0)));
1143   EXPECT_TRUE(ProcessFrames("4K", ""));
1144   // Verify buffer is not part of ranges. It should be silently saved for
1145   // preroll for future append.
1146   CheckExpectedRangesByTimestamp(audio_.get(), "{ }");
1147   CheckReadsThenReadStalls(audio_.get(), "");
1148   EXPECT_FALSE(in_coded_frame_group());
1149
1150   // Abort the reads from last stall. We don't want those reads to "complete"
1151   // when we append below. We will initiate new reads to confirm the buffer
1152   // looks as we expect.
1153   SeekStream(audio_.get(), Milliseconds(0));
1154
1155   if (use_sequence_mode_) {
1156     EXPECT_MEDIA_LOG(TruncatedFrame(0, 10000, "start", 5000));
1157   } else {
1158     EXPECT_MEDIA_LOG(TruncatedFrame(4000, 14000, "start", 5000));
1159   }
1160   // Append a frame with 10ms duration, with 9ms falling after the window start.
1161   EXPECT_CALL(callbacks_, PossibleDurationIncrease(
1162                               Milliseconds(use_sequence_mode_ ? 10 : 14)));
1163   frame_duration_ = Milliseconds(10);
1164   EXPECT_TRUE(ProcessFrames("4K", ""));
1165   EXPECT_TRUE(in_coded_frame_group());
1166
1167   // Verify range updated to reflect last append was processed and trimmed, and
1168   // also that zero duration buffer was saved and attached as preroll.
1169   if (use_sequence_mode_) {
1170     // For sequence mode, append window trimming is applied after the append
1171     // is adjusted for timestampOffset. Basically, everything gets rebased to 0
1172     // and trimming then removes 5 seconds from the front.
1173     CheckExpectedRangesByTimestamp(audio_.get(), "{ [5,10) }");
1174     CheckReadsThenReadStalls(audio_.get(), "5:4P 5:4");
1175   } else {  // segments mode
1176     CheckExpectedRangesByTimestamp(audio_.get(), "{ [5,14) }");
1177     CheckReadsThenReadStalls(audio_.get(), "5:4P 5:4");
1178   }
1179
1180   // Verify the preroll buffer still has zero duration.
1181   StreamParserBuffer* last_read_parser_buffer =
1182       static_cast<StreamParserBuffer*>(last_read_buffer_.get());
1183   ASSERT_EQ(Milliseconds(0),
1184             last_read_parser_buffer->preroll_buffer()->duration());
1185 }
1186
1187 TEST_P(FrameProcessorTest,
1188        OOOKeyframePrecededByDependantNonKeyframeShouldWarn) {
1189   InSequence s;
1190   AddTestTracks(HAS_VIDEO);
1191   frame_processor_->SetSequenceMode(use_sequence_mode_);
1192
1193   if (use_sequence_mode_) {
1194     // Allow room in the timeline for the last video append (40|70, below) in
1195     // this test to remain within default append window [0, +Infinity]. Moving
1196     // the sequence mode appends to begin at time 50ms, the same time as the
1197     // first append, below, also results in identical expectation checks for
1198     // buffered ranges and buffer reads for both segments and sequence modes.
1199     SetTimestampOffset(Milliseconds(50));
1200   }
1201
1202   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(70)));
1203   EXPECT_TRUE(ProcessFrames("", "50K 60"));
1204
1205   CheckExpectedRangesByTimestamp(video_.get(), "{ [50,70) }");
1206
1207   EXPECT_CALL(callbacks_,
1208               OnParseWarning(
1209                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1210   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.05", "0.04"));
1211   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(70)));
1212   EXPECT_TRUE(ProcessFrames("", "40|70"));  // PTS=40, DTS=70
1213
1214   // This reflects the expectation that PTS start is not "pulled backward" for
1215   // the new frame at PTS=40 because current spec doesn't support SAP Type 2; it
1216   // has no steps in the coded frame processing algorithm that would do that
1217   // "pulling backward". See https://github.com/w3c/media-source/issues/187.
1218   CheckExpectedRangesByTimestamp(video_.get(), "{ [50,70) }");
1219
1220   SeekStream(video_.get(), Milliseconds(0));
1221   CheckReadsThenReadStalls(video_.get(), "50 60 40");
1222 }
1223
1224 TEST_P(FrameProcessorTest, OOOKeyframePts_1) {
1225   InSequence s;
1226   AddTestTracks(HAS_AUDIO);
1227   frame_processor_->SetSequenceMode(use_sequence_mode_);
1228
1229   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1010)));
1230   // Note that the following does not contain a DTS continuity, but *does*
1231   // contain a PTS discontinuity (keyframe at 0.1s after keyframe at 1s).
1232   EXPECT_TRUE(ProcessFrames("0K 1000|10K 100|20K", ""));
1233
1234   // Force sequence mode to place the next frames where segments mode would put
1235   // them, to simplify this test case.
1236   if (use_sequence_mode_)
1237     SetTimestampOffset(Milliseconds(500));
1238
1239   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(510)));
1240   EXPECT_TRUE(ProcessFrames("500|100K", ""));
1241   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1242
1243   // Note that the PTS discontinuity (100ms) in the first ProcessFrames() call,
1244   // above, overlaps the previously buffered range [0,1010), so the frame at
1245   // 100ms is processed with an adjusted coded frame group start to be 0.001ms,
1246   // which is just after the highest timestamp before it in the overlapped
1247   // range. This enables it to be continuous with the frame before it. The
1248   // remainder of the overlapped range (the buffer at [1000,1010)) is adjusted
1249   // to have a range start time at the split point (110), and is within fudge
1250   // room and merged into [0,110). The same happens with the buffer appended
1251   // [500,510).
1252   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,1010) }");
1253   CheckReadsThenReadStalls(audio_.get(), "0 100 500 1000");
1254 }
1255
1256 TEST_P(FrameProcessorTest, OOOKeyframePts_2) {
1257   InSequence s;
1258   AddTestTracks(HAS_AUDIO);
1259   frame_processor_->SetSequenceMode(use_sequence_mode_);
1260
1261   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1010)));
1262   EXPECT_TRUE(ProcessFrames("0K 1000|10K", ""));
1263
1264   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1010)));
1265   EXPECT_TRUE(ProcessFrames("100|20K", ""));
1266
1267   // Note that the PTS discontinuity (100ms) in the first ProcessFrames() call,
1268   // above, overlaps the previously buffered range [0,1010), so the frame at
1269   // 100ms is processed with an adjusted coded frame group start to be 0.001ms,
1270   // which is just after the highest timestamp before it in the overlapped
1271   // range. This enables it to be continuous with the frame before it. The
1272   // remainder of the overlapped range (the buffer at [1000,1010)) is adjusted
1273   // to have a range start time at the split point (110), and is within fudge
1274   // room and merged into [0,110).
1275   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,1010) }");
1276   CheckReadsThenReadStalls(audio_.get(), "0 100 1000");
1277 }
1278
1279 TEST_P(FrameProcessorTest, AudioNonKeyframeChangedToKeyframe) {
1280   // Verifies that an audio non-keyframe is changed to a keyframe with a media
1281   // log warning. An exact overlap append of the preceding keyframe is also done
1282   // to ensure that the (original non-keyframe) survives (because it was changed
1283   // to a keyframe, so no longer depends on the original preceding keyframe).
1284   // The sequence mode test version uses SetTimestampOffset to make it behave
1285   // like segments mode to simplify the tests.
1286   // Note, see the NonkeyframeAudioBuffering tests to verify buffering of audio
1287   // nonkeyframes for codec(s) that use nonkeyframes.
1288   InSequence s;
1289   AddTestTracks(HAS_AUDIO);
1290   frame_processor_->SetSequenceMode(use_sequence_mode_);
1291
1292   EXPECT_MEDIA_LOG(AudioNonKeyframe(10000, 10000));
1293   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(30)));
1294   EXPECT_TRUE(ProcessFrames("0K 10 20K", ""));
1295
1296   if (use_sequence_mode_)
1297     SetTimestampOffset(Milliseconds(0));
1298
1299   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
1300   EXPECT_TRUE(ProcessFrames("0K", ""));
1301
1302   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,30) }");
1303   SeekStream(audio_.get(), Milliseconds(0));
1304   CheckReadsThenReadStalls(audio_.get(), "0 10 20");
1305 }
1306
1307 TEST_P(FrameProcessorTest, TimestampOffsetNegativeDts) {
1308   // Shift a GOP earlier using timestampOffset such that the GOP
1309   // starts with negative DTS, but PTS 0.
1310   InSequence s;
1311   AddTestTracks(HAS_VIDEO);
1312   frame_processor_->SetSequenceMode(use_sequence_mode_);
1313
1314   if (!use_sequence_mode_) {
1315     // Simulate the offset that sequence mode would apply, to make the results
1316     // the same regardless of sequence vs segments mode.
1317     SetTimestampOffset(Milliseconds(-100));
1318   }
1319
1320   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(40)));
1321   EXPECT_TRUE(ProcessFrames("", "100|70K 130|80"));
1322   EXPECT_EQ(Milliseconds(-100), timestamp_offset_);
1323   CheckExpectedRangesByTimestamp(video_.get(), "{ [0,40) }");
1324   SeekStream(video_.get(), Milliseconds(0));
1325   CheckReadsThenReadStalls(video_.get(), "0:100 30:130");
1326 }
1327
1328 TEST_P(FrameProcessorTest, LargeTimestampOffsetJumpForward) {
1329   // Verifies that jumps forward in buffers emitted from the coded frame
1330   // processing algorithm can create discontinuous buffered ranges if those
1331   // jumps are large enough, in both kinds of AppendMode.
1332   InSequence s;
1333   AddTestTracks(HAS_AUDIO);
1334   frame_processor_->SetSequenceMode(use_sequence_mode_);
1335
1336   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
1337   EXPECT_TRUE(ProcessFrames("0K", ""));
1338
1339   SetTimestampOffset(Milliseconds(5000));
1340
1341   // Along with the new timestampOffset set above, this should cause a large
1342   // jump forward in both PTS and DTS for both sequence and segments append
1343   // modes.
1344   if (use_sequence_mode_) {
1345     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(5010)));
1346   } else {
1347     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10010)));
1348   }
1349   EXPECT_TRUE(ProcessFrames("5000|100K", ""));
1350   if (use_sequence_mode_) {
1351     EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1352   } else {
1353     EXPECT_EQ(Milliseconds(5000), timestamp_offset_);
1354   }
1355
1356   if (use_sequence_mode_) {
1357     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,10) [5000,5010) }");
1358     CheckReadsThenReadStalls(audio_.get(), "0");
1359     SeekStream(audio_.get(), Milliseconds(5000));
1360     CheckReadsThenReadStalls(audio_.get(), "5000");
1361   } else {
1362     CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,10) [10000,10010) }");
1363     CheckReadsThenReadStalls(audio_.get(), "0");
1364     SeekStream(audio_.get(), Milliseconds(10000));
1365     CheckReadsThenReadStalls(audio_.get(), "10000:5000");
1366   }
1367 }
1368
1369 TEST_P(FrameProcessorTest, ContinuousDts_SapType2_and_PtsJumpForward) {
1370   InSequence s;
1371   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1372   frame_processor_->SetSequenceMode(use_sequence_mode_);
1373
1374   // Make the sequence mode buffering appear just like segments mode to simplify
1375   // this test case.
1376   if (use_sequence_mode_)
1377     SetTimestampOffset(Milliseconds(1060));
1378
1379   // Note that the PTS of GOP non-keyframes earlier than the keyframe doesn't
1380   // modify the GOP start of the buffered range here. This may change if we
1381   // decide to improve spec for SAP Type 2 GOPs that begin a coded frame group.
1382   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1383                                        Milliseconds(1060)));
1384   EXPECT_CALL(callbacks_,
1385               OnParseWarning(
1386                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1387   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("1.06", "1"));
1388   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1389   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1390   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1070)));
1391   EXPECT_TRUE(ProcessFrames(
1392       "", "1060|0K 1000|10 1050|20 1010|30 1040|40 1020|50 1030|60"));
1393   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1394   CheckExpectedRangesByTimestamp(video_.get(), "{ [1060,1070) }");
1395
1396   // Process just the keyframe of the next SAP Type 2 GOP in decode continuity
1397   // with the previous one.
1398   // Note that this second GOP is buffered continuous with the first because
1399   // there is no decode discontinuity detected. This results in inclusion of
1400   // the significant PTS jump forward in the same continuous range.
1401   EXPECT_CALL(
1402       callbacks_,
1403       OnGroupStart(DemuxerStream::VIDEO,
1404                    DecodeTimestamp::FromPresentationTime(Milliseconds(60)),
1405                    Milliseconds(1070)));
1406   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1407   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1140)));
1408   EXPECT_TRUE(ProcessFrames("", "1130|70K"));
1409   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1410   CheckExpectedRangesByTimestamp(video_.get(), "{ [1060,1140) }");
1411
1412   // Process the remainder of the second GOP.
1413   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1414   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1140)));
1415   EXPECT_TRUE(
1416       ProcessFrames("", "1070|80 1120|90 1080|100 1110|110 1090|120 1100|130"));
1417   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1418   CheckExpectedRangesByTimestamp(video_.get(), "{ [1060,1140) }");
1419
1420   // [1060,1140) should demux continuously without read stall in the middle.
1421   SeekStream(video_.get(), Milliseconds(1060));
1422   CheckReadsThenReadStalls(
1423       video_.get(),
1424       "1060 1000 1050 1010 1040 1020 1030 1130 1070 1120 1080 1110 1090 1100");
1425   // Verify that seek and read of the second GOP is correct.
1426   SeekStream(video_.get(), Milliseconds(1130));
1427   CheckReadsThenReadStalls(video_.get(), "1130 1070 1120 1080 1110 1090 1100");
1428 }
1429
1430 TEST_P(FrameProcessorTest, ContinuousDts_NewGopEndOverlapsLastGop_1) {
1431   // API user might craft a continuous-in-DTS-with-previous-append GOP that has
1432   // PTS interval overlapping the previous append.
1433   // Tests SAP-Type-1 GOPs, where newly appended GOP overlaps a nonkeyframe of
1434   // the last GOP appended.
1435   InSequence s;
1436   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1437   frame_processor_->SetSequenceMode(use_sequence_mode_);
1438
1439   // Make the sequence mode buffering appear just like segments mode to simplify
1440   // this test case.
1441   if (use_sequence_mode_)
1442     SetTimestampOffset(Milliseconds(100));
1443
1444   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1445                                        Milliseconds(100)));
1446   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1447   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
1448   EXPECT_TRUE(ProcessFrames("", "100|0K 110|10 120|20 130|30"));
1449   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1450
1451   EXPECT_CALL(
1452       callbacks_,
1453       OnGroupStart(DemuxerStream::VIDEO,
1454                    DecodeTimestamp::FromPresentationTime(Milliseconds(30)),
1455                    Milliseconds(125)));
1456   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1457   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(165)));
1458   EXPECT_TRUE(ProcessFrames("", "125|40K 135|50 145|60 155|70"));
1459   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1460
1461   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,165) }");
1462   CheckReadsThenReadStalls(video_.get(), "100 110 120 125 135 145 155");
1463 }
1464
1465 TEST_P(FrameProcessorTest, ContinuousDts_NewGopEndOverlapsLastGop_2) {
1466   // API user might craft a continuous-in-DTS-with-previous-append GOP that has
1467   // PTS interval overlapping the previous append.
1468   // Tests SAP-Type 1 GOPs, where newly appended GOP overlaps the keyframe of
1469   // the last GOP appended.
1470   InSequence s;
1471   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1472   frame_processor_->SetSequenceMode(use_sequence_mode_);
1473
1474   // Make the sequence mode buffering appear just like segments mode to simplify
1475   // this test case.
1476   if (use_sequence_mode_)
1477     SetTimestampOffset(Milliseconds(100));
1478
1479   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1480                                        Milliseconds(100)));
1481   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1482   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
1483   EXPECT_TRUE(ProcessFrames("", "100|0K 110|10 120|20K 130|30"));
1484   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1485
1486   EXPECT_CALL(
1487       callbacks_,
1488       OnGroupStart(DemuxerStream::VIDEO,
1489                    DecodeTimestamp::FromPresentationTime(Milliseconds(30)),
1490                    Milliseconds(115)));
1491   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1492   // TODO(wolenetz): Duration shouldn't be allowed to possibly increase to 140ms
1493   // here. See https://crbug.com/763620.
1494   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
1495   EXPECT_TRUE(ProcessFrames("", "115|40K 125|50"));
1496   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1497
1498   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,135) }");
1499   CheckReadsThenReadStalls(video_.get(), "100 110 115 125");
1500 }
1501
1502 TEST_P(FrameProcessorTest, ContinuousDts_NewSap2GopEndOverlapsLastGop_1) {
1503   // API user might craft a continuous-in-DTS-with-previous-append GOP that has
1504   // PTS interval overlapping the previous append, using SAP Type 2 GOPs.
1505   // Tests SAP-Type 2 GOPs, where newly appended GOP overlaps nonkeyframes of
1506   // the last GOP appended.
1507   InSequence s;
1508   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1509   frame_processor_->SetSequenceMode(use_sequence_mode_);
1510
1511   // Make the sequence mode buffering appear just like segments mode to simplify
1512   // this test case.
1513   if (use_sequence_mode_)
1514     SetTimestampOffset(Milliseconds(120));
1515
1516   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1517                                        Milliseconds(120)));
1518   EXPECT_CALL(callbacks_,
1519               OnParseWarning(
1520                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1521   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.12", "0.1"));
1522   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1523   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1524   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
1525   EXPECT_TRUE(ProcessFrames("", "120|0K 100|10 130|20 110|30"));
1526   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1527
1528   // Note, we *don't* expect another OnGroupStart during the next ProcessFrames,
1529   // since the next GOP's keyframe PTS is after the first GOP and close enough
1530   // to be assured adjacent.
1531   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1532   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1533   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(165)));
1534   EXPECT_TRUE(ProcessFrames("", "145|40K 125|50 155|60 135|70"));
1535   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1536
1537   CheckExpectedRangesByTimestamp(video_.get(), "{ [120,165) }");
1538   // [120,165) should demux continuously without read stall in the middle.
1539   CheckReadsThenReadStalls(video_.get(), "120 100 130 110 145 125 155 135");
1540   // Verify that seek and read of the second GOP is correct.
1541   SeekStream(video_.get(), Milliseconds(145));
1542   CheckReadsThenReadStalls(video_.get(), "145 125 155 135");
1543 }
1544
1545 TEST_P(FrameProcessorTest, ContinuousDts_NewSap2GopEndOverlapsLastGop_2) {
1546   // API user might craft a continuous-in-DTS-with-previous-append GOP that has
1547   // PTS interval overlapping the previous append, using SAP Type 2 GOPs.
1548   // Tests SAP-Type 2 GOPs, where newly appended GOP overlaps the keyframe of
1549   // last GOP appended.
1550   InSequence s;
1551   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1552   frame_processor_->SetSequenceMode(use_sequence_mode_);
1553
1554   // Make the sequence mode buffering appear just like segments mode to simplify
1555   // this test case.
1556   if (use_sequence_mode_)
1557     SetTimestampOffset(Milliseconds(120));
1558
1559   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1560                                        Milliseconds(120)));
1561   EXPECT_CALL(callbacks_,
1562               OnParseWarning(
1563                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1564   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.12", "0.1"));
1565   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1566   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1567   // There is a second GOP that is SAP-Type-2 within this first ProcessFrames,
1568   // with PTS jumping forward far enough to trigger group start signalling and a
1569   // flush.
1570   EXPECT_CALL(
1571       callbacks_,
1572       OnGroupStart(DemuxerStream::VIDEO,
1573                    DecodeTimestamp::FromPresentationTime(Milliseconds(30)),
1574                    Milliseconds(140)));
1575   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1576   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(180)));
1577   EXPECT_TRUE(ProcessFrames(
1578       "", "120|0K 100|10 130|20 110|30 160|40K 140|50 170|60 150|70"));
1579   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1580
1581   EXPECT_CALL(
1582       callbacks_,
1583       OnGroupStart(DemuxerStream::VIDEO,
1584                    DecodeTimestamp::FromPresentationTime(Milliseconds(70)),
1585                    Milliseconds(155)));
1586   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1587   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1588   // TODO(wolenetz): Duration shouldn't be allowed to possibly increase to 180ms
1589   // here. See https://crbug.com/763620.
1590   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(180)));
1591   EXPECT_TRUE(ProcessFrames("", "155|80K 145|90"));
1592   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1593
1594   CheckExpectedRangesByTimestamp(video_.get(), "{ [120,165) }");
1595   // [120,165) should demux continuously without read stall in the middle.
1596   CheckReadsThenReadStalls(video_.get(), "120 100 130 110 155 145");
1597   // Verify seek and read of the second GOP is correct.
1598   SeekStream(video_.get(), Milliseconds(155));
1599   CheckReadsThenReadStalls(video_.get(), "155 145");
1600 }
1601
1602 TEST_P(FrameProcessorTest,
1603        ContinuousDts_NewSap2GopEndOverlapsLastGop_3_GopByGop) {
1604   // API user might craft a continuous-in-DTS-with-previous-append GOP that has
1605   // PTS interval overlapping the previous append, using SAP Type 2 GOPs.  Tests
1606   // SAP-Type 2 GOPs, where newly appended GOP overlaps enough nonkeyframes of
1607   // the previous GOP such that dropped decode dependencies might cause problems
1608   // if the first nonkeyframe with PTS prior to the GOP's keyframe PTS is
1609   // flushed at the same time as its keyframe, but the second GOP's keyframe PTS
1610   // is close enough to the end of the first GOP's presentation interval to not
1611   // signal a new coded frame group start.
1612   InSequence s;
1613   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1614   frame_processor_->SetSequenceMode(use_sequence_mode_);
1615
1616   // Make the sequence mode buffering appear just like segments mode to simplify
1617   // this test case.
1618   if (use_sequence_mode_)
1619     SetTimestampOffset(Milliseconds(500));
1620
1621   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1622                                        Milliseconds(500)));
1623   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1624   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
1625   EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
1626   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
1627
1628   EXPECT_CALL(callbacks_,
1629               OnParseWarning(
1630                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1631   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.54", "0.52"));
1632   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1633   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1634   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
1635   EXPECT_TRUE(ProcessFrames("", "540|30K 520|40 530|50"));
1636
1637   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,550) }");
1638   SeekStream(video_.get(), Milliseconds(500));
1639   CheckReadsThenReadStalls(video_.get(), "500 520 510 540 520 530");
1640 }
1641
1642 TEST_P(FrameProcessorTest,
1643        ContinuousDts_NewSap2GopEndOverlapsLastGop_3_FrameByFrame) {
1644   // Tests that the buffered range results match the previous GopByGop test if
1645   // each frame of the second GOP is explicitly appended by the app
1646   // one-at-a-time.
1647   InSequence s;
1648   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1649   frame_processor_->SetSequenceMode(use_sequence_mode_);
1650
1651   // Make the sequence mode buffering appear just like segments mode to simplify
1652   // this test case.
1653   if (use_sequence_mode_)
1654     SetTimestampOffset(Milliseconds(500));
1655
1656   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1657                                        Milliseconds(500)));
1658   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1659   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
1660   EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
1661   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
1662
1663   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1664   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
1665   EXPECT_TRUE(ProcessFrames("", "540|30K"));
1666
1667   EXPECT_CALL(callbacks_,
1668               OnParseWarning(
1669                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1670   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.54", "0.52"));
1671   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1672   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
1673   EXPECT_TRUE(ProcessFrames("", "520|40"));
1674
1675   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1676   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
1677   EXPECT_TRUE(ProcessFrames("", "530|50"));
1678
1679   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,550) }");
1680   SeekStream(video_.get(), Milliseconds(500));
1681   CheckReadsThenReadStalls(video_.get(), "500 520 510 540 520 530");
1682 }
1683
1684 TEST_P(FrameProcessorTest,
1685        ContinuousDts_NewSap2GopEndOverlapsLastGop_4_GopByGop) {
1686   // API user might craft a continuous-in-DTS-with-previous-append GOP that has
1687   // PTS interval overlapping the previous append, using SAP Type 2 GOPs.  Tests
1688   // SAP-Type 2 GOPs, where newly appended GOP overlaps enough nonkeyframes of
1689   // the previous GOP such that dropped decode dependencies might cause problems
1690   // if the first nonkeyframe with PTS prior to the GOP's keyframe PTS is
1691   // flushed at the same time as its keyframe.
1692   InSequence s;
1693   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1694   frame_processor_->SetSequenceMode(use_sequence_mode_);
1695
1696   // Make the sequence mode buffering appear just like segments mode to simplify
1697   // this test case.
1698   if (use_sequence_mode_)
1699     SetTimestampOffset(Milliseconds(500));
1700
1701   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1702                                        Milliseconds(500)));
1703   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1704   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
1705   EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
1706   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
1707
1708   EXPECT_CALL(
1709       callbacks_,
1710       OnGroupStart(DemuxerStream::VIDEO,
1711                    DecodeTimestamp::FromPresentationTime(Milliseconds(20)),
1712                    Milliseconds(530)));
1713   EXPECT_CALL(callbacks_,
1714               OnParseWarning(
1715                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1716   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.55", "0.52"));
1717   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1718   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1719   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
1720   EXPECT_TRUE(ProcessFrames("", "550|30K 520|40 530|50 540|60"));
1721
1722   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,560) }");
1723   SeekStream(video_.get(), Milliseconds(500));
1724   CheckReadsThenReadStalls(video_.get(), "500 520 510 550 520 530 540");
1725 }
1726
1727 TEST_P(FrameProcessorTest,
1728        ContinuousDts_NewSap2GopEndOverlapsLastGop_4_FrameByFrame) {
1729   // Tests that the buffered range results match the previous GopByGop test if
1730   // each frame of the second GOP is explicitly appended by the app
1731   // one-at-a-time.
1732   InSequence s;
1733   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1734   frame_processor_->SetSequenceMode(use_sequence_mode_);
1735
1736   // Make the sequence mode buffering appear just like segments mode to simplify
1737   // this test case.
1738   if (use_sequence_mode_)
1739     SetTimestampOffset(Milliseconds(500));
1740
1741   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1742                                        Milliseconds(500)));
1743   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1744   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
1745   EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
1746   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
1747
1748   EXPECT_CALL(
1749       callbacks_,
1750       OnGroupStart(DemuxerStream::VIDEO,
1751                    DecodeTimestamp::FromPresentationTime(Milliseconds(20)),
1752                    Milliseconds(530)));
1753   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1754   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
1755   EXPECT_TRUE(ProcessFrames("", "550|30K"));
1756
1757   EXPECT_CALL(callbacks_,
1758               OnParseWarning(
1759                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
1760   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.55", "0.52"));
1761   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1762   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
1763   EXPECT_TRUE(ProcessFrames("", "520|40"));
1764
1765   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1766   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
1767   EXPECT_TRUE(ProcessFrames("", "530|50"));
1768
1769   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1770   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
1771   EXPECT_TRUE(ProcessFrames("", "540|60"));
1772
1773   CheckExpectedRangesByTimestamp(video_.get(), "{ [500,560) }");
1774   SeekStream(video_.get(), Milliseconds(500));
1775   CheckReadsThenReadStalls(video_.get(), "500 520 510 550 520 530 540");
1776 }
1777
1778 TEST_P(FrameProcessorTest, ContinuousDts_GopKeyframePtsOrder_2_1_3) {
1779   // White-box test, demonstrating expected behavior for a specially crafted
1780   // sequence that "should" be unusual, but gracefully handled:
1781   // SAP-Type 1 GOPs for simplicity of test. First appended GOP is highest in
1782   // timeline. Second appended GOP is earliest in timeline. Third appended GOP
1783   // is continuous in time with highest end time of first appended GOP. The
1784   // result should be a single continuous range containing just the second and
1785   // third appended GOPs (since the first-appended GOP was overlap-removed from
1786   // the timeline due to being in the gap between the second and third appended
1787   // GOPs). Note that MseTrackBuffer::ResetHighestPresentationTimestamp() done
1788   // at the beginning of the second appended GOP is the key to gracefully
1789   // handling the third appended GOP.
1790   InSequence s;
1791   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1792   frame_processor_->SetSequenceMode(use_sequence_mode_);
1793
1794   // Make the sequence mode buffering appear just like segments mode to simplify
1795   // this test case.
1796   if (use_sequence_mode_)
1797     SetTimestampOffset(Milliseconds(200));
1798
1799   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
1800                                        Milliseconds(200)));
1801   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1802   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(240)));
1803   EXPECT_TRUE(ProcessFrames("", "200|0K 210|10 220|20 230|30"));
1804   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1805   CheckExpectedRangesByTimestamp(video_.get(), "{ [200,240) }");
1806
1807   EXPECT_CALL(
1808       callbacks_,
1809       OnGroupStart(DemuxerStream::VIDEO,
1810                    DecodeTimestamp::FromPresentationTime(Milliseconds(30)),
1811                    Milliseconds(100)));
1812   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1813   // TODO(wolenetz): Duration shouldn't be allowed to possibly increase to 240ms
1814   // here. See https://crbug.com/763620.
1815   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(240)));
1816   EXPECT_TRUE(ProcessFrames("", "100|40K 110|50 120|60 130|70"));
1817   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1818   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [200,240) }");
1819
1820   EXPECT_CALL(
1821       callbacks_,
1822       OnGroupStart(DemuxerStream::VIDEO,
1823                    DecodeTimestamp::FromPresentationTime(Milliseconds(70)),
1824                    Milliseconds(140)));
1825   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1826   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(260)));
1827   EXPECT_TRUE(ProcessFrames("", "240|80K 250|90"));
1828   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1829   CheckExpectedRangesByTimestamp(video_.get(), "{ [100,260) }");
1830
1831   SeekStream(video_.get(), Milliseconds(100));
1832   CheckReadsThenReadStalls(video_.get(), "100 110 120 130 240 250");
1833 }
1834
1835 TEST_P(FrameProcessorTest, ContinuousPts_DiscontinuousDts_AcrossGops) {
1836   // GOPs which overlap in DTS, but are continuous in PTS should be buffered
1837   // correctly. In particular, monotonic increase of DTS in continuous-in-PTS
1838   // append sequences is not required across GOPs (just within GOPs).
1839   InSequence s;
1840   AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1841   frame_processor_->SetSequenceMode(use_sequence_mode_);
1842
1843   // Make the sequence mode buffering appear just like segments mode to simplify
1844   // this test case.
1845   if (use_sequence_mode_)
1846     SetTimestampOffset(Milliseconds(200));
1847
1848   EXPECT_CALL(
1849       callbacks_,
1850       OnGroupStart(DemuxerStream::VIDEO,
1851                    DecodeTimestamp::FromPresentationTime(Milliseconds(200)),
1852                    Milliseconds(200)));
1853   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1854   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(240)));
1855   EXPECT_TRUE(ProcessFrames("", "200K 210 220 230"));
1856   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1857   CheckExpectedRangesByTimestamp(video_.get(), "{ [200,240) }");
1858
1859   EXPECT_CALL(
1860       callbacks_,
1861       OnGroupStart(DemuxerStream::VIDEO,
1862                    DecodeTimestamp::FromPresentationTime(Milliseconds(225)),
1863                    Milliseconds(240)));
1864   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
1865   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(280)));
1866   // Append a second GOP whose first DTS is below the last DTS of the first GOP,
1867   // but whose PTS interval is continuous with the end of the first GOP.
1868   EXPECT_TRUE(ProcessFrames("", "240|225K 250|235 260|245 270|255"));
1869   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1870   SeekStream(video_.get(), Milliseconds(200));
1871
1872   CheckExpectedRangesByTimestamp(video_.get(), "{ [200,280) }");
1873   CheckReadsThenReadStalls(video_.get(), "200 210 220 230 240 250 260 270");
1874 }
1875
1876 TEST_P(FrameProcessorTest, OnlyKeyframes_ContinuousDts_ContinousPts_1) {
1877   // Verifies that precisely one group start and one stream append occurs for a
1878   // single continuous set of frames.
1879   InSequence s;
1880   AddTestTracks(HAS_AUDIO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1881   if (use_sequence_mode_)
1882     frame_processor_->SetSequenceMode(true);
1883
1884   // Default test frame duration is 10 milliseconds.
1885
1886   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::AUDIO, DecodeTimestamp(),
1887                                        base::TimeDelta()));
1888   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::AUDIO, _));
1889   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(40)));
1890   EXPECT_TRUE(ProcessFrames("0K 10K 20K 30K", ""));
1891   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1892
1893   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,40) }");
1894   CheckReadsThenReadStalls(audio_.get(), "0 10 20 30");
1895 }
1896
1897 TEST_P(FrameProcessorTest, OnlyKeyframes_ContinuousDts_ContinuousPts_2) {
1898   // Verifies that precisely one group start and one stream append occurs while
1899   // processing a single continuous set of frames that uses fudge room to just
1900   // barely remain adjacent.
1901   InSequence s;
1902   AddTestTracks(HAS_AUDIO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1903   if (use_sequence_mode_)
1904     frame_processor_->SetSequenceMode(true);
1905
1906   frame_duration_ = Milliseconds(5);
1907
1908   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::AUDIO, DecodeTimestamp(),
1909                                        base::TimeDelta()));
1910   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::AUDIO, _));
1911   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(35)));
1912   EXPECT_TRUE(ProcessFrames("0K 10K 20K 30K", ""));
1913   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1914
1915   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,35) }");
1916   CheckReadsThenReadStalls(audio_.get(), "0 10 20 30");
1917 }
1918
1919 TEST_P(FrameProcessorTest,
1920        OnlyKeyframes_ContinuousDts_DiscontinuousPtsJustBeyondFudgeRoom) {
1921   // Verifies that multiple group starts and distinct appends occur
1922   // when processing a single DTS-continuous set of frames with PTS deltas that
1923   // just barely exceed the adjacency assumption in FrameProcessor.
1924   InSequence s;
1925   AddTestTracks(HAS_AUDIO | OBSERVE_APPENDS_AND_GROUP_STARTS);
1926   if (use_sequence_mode_)
1927     frame_processor_->SetSequenceMode(true);
1928
1929   frame_duration_ = base::Microseconds(4999);
1930
1931   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::AUDIO, DecodeTimestamp(),
1932                                        base::TimeDelta()));
1933   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::AUDIO, _));
1934   // Frame "10|5K" following "0K" triggers start of new group and eventual
1935   // append.
1936   EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::AUDIO, DecodeTimestamp(),
1937                                        frame_duration_));
1938   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::AUDIO, _));
1939
1940   // Frame "20|10K" following "10|5K" triggers start of new group and eventual
1941   // append.
1942   EXPECT_CALL(
1943       callbacks_,
1944       OnGroupStart(DemuxerStream::AUDIO,
1945                    DecodeTimestamp::FromPresentationTime(Milliseconds(5)),
1946                    Milliseconds(10) + frame_duration_));
1947   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::AUDIO, _));
1948
1949   // Frame "30|15K" following "20|10K" triggers start of new group and
1950   // eventual append.
1951   EXPECT_CALL(
1952       callbacks_,
1953       OnGroupStart(DemuxerStream::AUDIO,
1954                    DecodeTimestamp::FromPresentationTime(Milliseconds(10)),
1955                    Milliseconds(20) + frame_duration_));
1956   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::AUDIO, _));
1957
1958   EXPECT_CALL(callbacks_, PossibleDurationIncrease(base::Microseconds(34999)));
1959   EXPECT_TRUE(ProcessFrames("0K 10|5K 20|10K 30|15K", ""));
1960   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1961
1962   // Note that the result is still buffered continuous since DTS was continuous
1963   // and PTS was monotonically increasing (such that each group start was
1964   // signalled by FrameProcessor to be continuous with the end of the previous
1965   // group, if any.)
1966   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,34) }");
1967   CheckReadsThenReadStalls(audio_.get(), "0 10 20 30");
1968 }
1969
1970 TEST_P(FrameProcessorTest,
1971        GroupEndTimestampDecreaseWithinMediaSegmentShouldWarn) {
1972   // This parse warning requires:
1973   // 1) a decode time discontinuity within the set of frames being processed,
1974   // 2) the highest frame end time of any frame successfully processed
1975   //    before that discontinuity is higher than the highest frame end time of
1976   //    all frames processed after that discontinuity.
1977   // TODO(wolenetz): Adjust this case once direction on spec is informed by
1978   // data. See https://crbug.com/920853 and
1979   // https://github.com/w3c/media-source/issues/203.
1980   if (use_sequence_mode_) {
1981     // Sequence mode modifies the presentation timestamps following a decode
1982     // discontinuity such that this scenario should not repro with that mode.
1983     DVLOG(1) << "Skipping segments mode variant; inapplicable to this case.";
1984     return;
1985   }
1986
1987   InSequence s;
1988   AddTestTracks(HAS_VIDEO);
1989
1990   EXPECT_CALL(callbacks_,
1991               OnParseWarning(SourceBufferParseWarning::
1992                                  kGroupEndTimestampDecreaseWithinMediaSegment));
1993
1994   frame_duration_ = Milliseconds(10);
1995   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(15)));
1996   EXPECT_TRUE(ProcessFrames("", "0K 10K 5|40K"));
1997   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
1998
1999   CheckExpectedRangesByTimestamp(video_.get(), "{ [0,15) }");
2000   CheckReadsThenReadStalls(video_.get(), "0 5");
2001 }
2002
2003 TEST_P(FrameProcessorTest, NonkeyframeAudioBuffering_BasicOperation) {
2004   // With the support for audio nonkeyframe buffering enabled, buffer a couple
2005   // continuous groups of audio key and nonkey frames.
2006   // Note, see the AudioNonKeyframeChangedToKeyframe test that tests where
2007   // nonkeyframe audio buffering is not supported, and instead takes a
2008   // workaround that forces all audio to be keyframe.
2009   InSequence s;
2010   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2011   if (use_sequence_mode_)
2012     frame_processor_->SetSequenceMode(true);
2013
2014   // Default test frame duration is 10 milliseconds.
2015   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(80)));
2016   EXPECT_TRUE(ProcessFrames("0K 10 20 30 40K 50 60 70", ""));
2017   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2018
2019   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,80) }");
2020   CheckReadsAndKeyframenessThenReadStalls(audio_.get(),
2021                                           "0K 10N 20N 30N 40K 50N 60N 70N");
2022 }
2023
2024 TEST_P(FrameProcessorTest, NonkeyframeAudioBuffering_BasicOverlaps) {
2025   // With the support for audio nonkeyframe buffering enabled, buffer a few
2026   // groups of audio key and nonkey frames which overlap each other.
2027   // For sequence mode versions, timestampOffset is adjusted to make it act like
2028   // segments mode.
2029   InSequence s;
2030   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2031   if (use_sequence_mode_) {
2032     frame_processor_->SetSequenceMode(true);
2033     SetTimestampOffset(Milliseconds(10));
2034   }
2035
2036   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(60)));
2037   EXPECT_TRUE(ProcessFrames("10K 20 30 40 50", ""));
2038   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2039   CheckExpectedRangesByTimestamp(audio_.get(), "{ [10,60) }");
2040
2041   // End-overlap the last nonkeyframe appended with a keyframe.
2042
2043   if (use_sequence_mode_)
2044     SetTimestampOffset(Milliseconds(50));
2045
2046   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(70)));
2047   EXPECT_TRUE(ProcessFrames("50K 60", ""));
2048   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2049   CheckExpectedRangesByTimestamp(audio_.get(), "{ [10,70) }");
2050
2051   // Front-overlap the original group of frames.
2052
2053   if (use_sequence_mode_)
2054     SetTimestampOffset(Milliseconds(0));
2055
2056   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
2057   EXPECT_TRUE(ProcessFrames("0K 10", ""));
2058   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2059   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,70) }");
2060
2061   SeekStream(audio_.get(), Milliseconds(0));
2062   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "0K 10N 50K 60N");
2063 }
2064
2065 TEST_P(FrameProcessorTest,
2066        NonkeyframeAudioBuffering_InitialNonkeyframesNotBuffered) {
2067   // With the support for audio nonkeyframe buffering enabled, try to buffer
2068   // some frames beginning with a nonkeyframe and observe initial nonkeyframe(s)
2069   // are not buffered.
2070   InSequence s;
2071   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2072   if (use_sequence_mode_)
2073     frame_processor_->SetSequenceMode(true);
2074
2075   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(60)));
2076   EXPECT_TRUE(ProcessFrames("0 10 20K 30 40 50", ""));
2077   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2078   CheckExpectedRangesByTimestamp(audio_.get(), "{ [20,60) }");
2079   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "20K 30N 40N 50N");
2080 }
2081
2082 TEST_P(FrameProcessorTest,
2083        NonkeyframeAudioBuffering_InvalidDecreasingNonkeyframePts) {
2084   // With the support for audio nonkeyframe buffering enabled, try to buffer an
2085   // invalid sequence of nonkeyframes: decreasing presentation timestamps are
2086   // not supported for audio nonkeyframes. For sequence mode versions,
2087   // timestampOffset is adjusted to make it act like segments mode.
2088   InSequence s;
2089   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2090   if (use_sequence_mode_) {
2091     frame_processor_->SetSequenceMode(true);
2092     SetTimestampOffset(Milliseconds(100));
2093   }
2094
2095   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(110)));
2096   EXPECT_TRUE(ProcessFrames("100K", ""));
2097   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2098   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,110) }");
2099
2100   // Processing an audio nonkeyframe with lower PTS than the previous frame
2101   // should fail.
2102   EXPECT_MEDIA_LOG(AudioNonKeyframeOutOfOrder());
2103   EXPECT_FALSE(ProcessFrames("90|110", ""));
2104 }
2105
2106 TEST_P(FrameProcessorTest,
2107        NonkeyframeAudioBuffering_ValidDecreasingKeyframePts) {
2108   // With the support for audio nonkeyframe buffering enabled, try to buffer a
2109   // valid sequence of key and nonkeyframes: decreasing presentation timestamps
2110   // are supported for keyframes. For sequence mode versions, timestampOffset is
2111   // adjusted to make it act like segments mode.
2112   InSequence s;
2113   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2114   if (use_sequence_mode_) {
2115     frame_processor_->SetSequenceMode(true);
2116     SetTimestampOffset(Milliseconds(100));
2117   }
2118
2119   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(130)));
2120   EXPECT_TRUE(ProcessFrames("100K 110 120", ""));
2121   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2122   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }");
2123
2124   // Processing an audio keyframe with lower PTS than the previous frame
2125   // should succeed, since it is a keyframe. Here, we use continuous DTS to
2126   // ensure we precisely target the nonkeyframe monotonicity check when a
2127   // keyframe is not required by the track buffer currently (and to make
2128   // sequence mode versions act like segments mode without further manual
2129   // adjustment of timestamp offset.) The original nonkeyframe at PTS 110 should
2130   // be overlap-removed, and the one at PTS 120 should have be removed as a
2131   // result of depending on that removed PTS 110 nonkeyframe.
2132   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(130)));
2133   EXPECT_TRUE(ProcessFrames("110|130K", ""));
2134   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2135   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,120) }");
2136   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "100K 110K");
2137 }
2138
2139 TEST_P(FrameProcessorTest,
2140        NonkeyframeAudioBuffering_ValidSameNonKeyframePts_1) {
2141   // With the support for audio nonkeyframe buffering enabled, try to buffer a
2142   // valid sequence of a keyframe and a nonkeyframe: non-increasing presentation
2143   // timestamps are supported for audio nonkeyframes, so long as they don't
2144   // decrease. For sequence mode versions, timestampOffset is adjusted to make
2145   // it act like segments mode.
2146   InSequence s;
2147   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2148   if (use_sequence_mode_) {
2149     frame_processor_->SetSequenceMode(true);
2150     SetTimestampOffset(Milliseconds(100));
2151   }
2152
2153   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(110)));
2154   EXPECT_TRUE(ProcessFrames("100K", ""));
2155   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2156   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,110) }");
2157
2158   // Processing an audio nonkeyframe with same PTS as the previous frame should
2159   // succeed, though there is presentation interval overlap causing removal of
2160   // the previous frame (in this case, a keyframe), and hence the new dependent
2161   // nonkeyframe is not buffered.
2162   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(110)));
2163   EXPECT_TRUE(ProcessFrames("100|110", ""));
2164   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2165   CheckExpectedRangesByTimestamp(audio_.get(), "{ }");
2166   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "");
2167 }
2168
2169 TEST_P(FrameProcessorTest,
2170        NonkeyframeAudioBuffering_ValidSameNonKeyframePts_2) {
2171   // With the support for audio nonkeyframe buffering enabled, try to buffer a
2172   // valid sequence of nonkeyframes: non-increasing presentation timestamps are
2173   // supported for audio nonkeyframes, so long as they don't decrease. For
2174   // sequence mode versions, timestampOffset is adjusted to make it act like
2175   // segments mode.
2176   InSequence s;
2177   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2178   if (use_sequence_mode_) {
2179     frame_processor_->SetSequenceMode(true);
2180     SetTimestampOffset(Milliseconds(100));
2181   }
2182
2183   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(120)));
2184   EXPECT_TRUE(ProcessFrames("100K 110", ""));
2185   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2186   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,120) }");
2187
2188   // Processing an audio nonkeyframe with same PTS as the previous frame should
2189   // succeed, though there is presentation interval overlap causing removal of
2190   // the previous nonkeyframe, and hence the new dependent nonkeyframe is not
2191   // buffered.
2192   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(120)));
2193   EXPECT_TRUE(ProcessFrames("110|120", ""));
2194   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
2195   CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,110) }");
2196   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "100K");
2197 }
2198
2199 TEST_P(FrameProcessorTest,
2200        NonkeyframeAudioBuffering_AppendWindowFilterDroppedPrerollKeyframe) {
2201   // For simplicity currently, if the preroll (keyframe) buffer was entirely
2202   // prior to the append window and dropped, an approximately continuous
2203   // keyframe is still required to use that dropped frame as preroll (for
2204   // simplicity). This may change in future if append window trimming of
2205   // nonkeyframes with a fully excluded preroll keyframe is commonly needed to
2206   // be supported.
2207   InSequence s;
2208   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2209   if (use_sequence_mode_)
2210     frame_processor_->SetSequenceMode(true);
2211   SetTimestampOffset(Milliseconds(-10));
2212
2213   EXPECT_MEDIA_LOG(DroppedFrame("audio", -10000));
2214   if (use_sequence_mode_)
2215     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(-10)));
2216   else
2217     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(0)));
2218   EXPECT_TRUE(ProcessFrames("0K", ""));
2219
2220   // This nonkeyframe is dropped for simplicity since it depends on a preroll
2221   // keyframe which was entirely outside the append window.
2222   if (use_sequence_mode_)
2223     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(-10)));
2224   else
2225     EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(0)));
2226   EXPECT_TRUE(ProcessFrames("10", ""));
2227
2228   // Only the following keyframe should buffer successfully, with no preroll.
2229   EXPECT_MEDIA_LOG(DroppedAppendWindowUnusedPreroll(-10000, -10000, 10000));
2230   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(20)));
2231   EXPECT_TRUE(ProcessFrames("20K", ""));
2232
2233   CheckExpectedRangesByTimestamp(audio_.get(), "{ [10,20) }");
2234   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "10:20K");
2235 }
2236
2237 TEST_P(FrameProcessorTest,
2238        NonkeyframeAudioBuffering_AppendWindowFilter_TrimFront) {
2239   InSequence s;
2240   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2241   if (use_sequence_mode_)
2242     frame_processor_->SetSequenceMode(true);
2243   SetTimestampOffset(Milliseconds(-4));
2244   EXPECT_MEDIA_LOG(TruncatedFrame(-4000, 6000, "start", 0));
2245   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(26)));
2246   EXPECT_TRUE(ProcessFrames("0K 10 20", ""));
2247   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,26) }");
2248   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "0K 6:10N 16:20N");
2249 }
2250
2251 TEST_P(FrameProcessorTest,
2252        NonkeyframeAudioBuffering_AppendWindowFilter_TrimEnd) {
2253   InSequence s;
2254   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2255   if (use_sequence_mode_)
2256     frame_processor_->SetSequenceMode(true);
2257
2258   append_window_end_ = Milliseconds(26);
2259
2260   EXPECT_MEDIA_LOG(TruncatedFrame(20000, 30000, "end", 26000));
2261   EXPECT_MEDIA_LOG(DroppedFrameCheckAppendWindow("audio", 0, 26000));
2262   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(26)));
2263   EXPECT_TRUE(ProcessFrames("0K 10 20 30", ""));
2264   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,26) }");
2265   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "0K 10N 20N");
2266 }
2267
2268 TEST_P(FrameProcessorTest, NonkeyframeAudioBuffering_TrimSpliceOverlap) {
2269   // White-box test which focuses on the behavior of underlying
2270   // SourceBufferStream::TrimSpliceOverlap() for frame sequences involving
2271   // nonkeyframes appended by the FrameProcessor. That method detects and
2272   // performs splice trimming on every audio frame following either a
2273   // discontinuity or the beginning of ProcessFrames(), and also on audio frames
2274   // with PTS not directly continuous with the highest frame end PTS already
2275   // processed. We vary |frame_duration_| in this test to avoid confusing
2276   // int:decimal pairs in the eventual CheckReads* call.
2277   InSequence s;
2278   AddTestTracks(HAS_AUDIO | USE_AUDIO_CODEC_SUPPORTING_NONKEYFRAMES);
2279   if (use_sequence_mode_)
2280     frame_processor_->SetSequenceMode(true);
2281
2282   frame_duration_ = base::Microseconds(9750);
2283   EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_));
2284   EXPECT_TRUE(ProcessFrames("0K", ""));
2285
2286   // As with all-keyframe streams, a slight jump forward should not trigger any
2287   // splicing logic, though accumulations of these may result in loss of A/V
2288   // sync.
2289   frame_duration_ = base::Microseconds(10250);
2290   EXPECT_CALL(callbacks_,
2291               PossibleDurationIncrease(Milliseconds(10) + frame_duration_));
2292   EXPECT_TRUE(ProcessFrames("10", ""));
2293
2294   // As with all-keyframe streams, a slightly end-overlapping nonkeyframe should
2295   // not trigger any splicing logic, though accumulations of these may result in
2296   // loss of A/V sync. The difference here is there isn't even any emission of a
2297   // "too little splice overlap" media log, since the new frame is a
2298   // nonkeyframe.
2299   frame_duration_ = Milliseconds(10);
2300   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(30)));
2301   EXPECT_TRUE(ProcessFrames("20", ""));
2302
2303   // A heavily overlapping nonkeyframe should not trigger any splicing logic,
2304   // so long as it isn't completely discontinuous. This is unlike all-keyframe
2305   // audio streams, where such a heavy overlap would end-trim the overlapped
2306   // frame. Accumulations of these could rapidly lead to loss of A/V sync.
2307   // Nonkeyframe timestamp & duration metadata sequences need to be correctly
2308   // muxed to avoid this.
2309   frame_duration_ = base::Microseconds(10250);
2310   EXPECT_CALL(callbacks_,
2311               PossibleDurationIncrease(Milliseconds(22) + frame_duration_));
2312   EXPECT_TRUE(ProcessFrames("22", ""));
2313
2314   // A keyframe that end-overlaps a nonkeyframe will trigger splicing logic.
2315   // Here, we test a "too little splice overlap" case.
2316   frame_duration_ = Milliseconds(10);
2317   EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(32000, 250));
2318   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(42)));
2319   EXPECT_TRUE(ProcessFrames("32K", ""));
2320
2321   // And a keyframe that significantly end-overlaps a nonkeyframe will trigger
2322   // splicing logic that can perform end-trimming of the overlapped frame.
2323   // First, we buffer another nonkeyframe.
2324   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(52)));
2325   EXPECT_TRUE(ProcessFrames("42", ""));
2326   // Verify correct splice behavior on significant overlap of the nonkeyframe by
2327   // a new keyframe.
2328   EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(45000, 42000, 7000));
2329   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(55)));
2330   EXPECT_TRUE(ProcessFrames("45K", ""));
2331
2332   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,55) }");
2333   CheckReadsAndKeyframenessThenReadStalls(audio_.get(),
2334                                           "0K 10N 20N 22N 32K 42N 45K");
2335 }
2336
2337 TEST_P(FrameProcessorTest, FrameDuration_kNoTimestamp_Fails) {
2338   InSequence s;
2339   AddTestTracks(HAS_AUDIO);
2340   frame_processor_->SetSequenceMode(use_sequence_mode_);
2341
2342   frame_duration_ = kNoTimestamp;
2343   EXPECT_MEDIA_LOG(FrameDurationUnknown("audio", 1000));
2344   EXPECT_FALSE(ProcessFrames("1K", ""));
2345 }
2346
2347 TEST_P(FrameProcessorTest,
2348        Pts_BeforeTimestampOffsetApplied_kNoTimestamp_Fails) {
2349   InSequence s;
2350   AddTestTracks(HAS_AUDIO);
2351   frame_processor_->SetSequenceMode(use_sequence_mode_);
2352
2353   EXPECT_MEDIA_LOG(PtsUnknown("audio"));
2354   EXPECT_FALSE(ProcessFrames("MinK", ""));
2355 }
2356
2357 TEST_P(FrameProcessorTest,
2358        Pts_BeforeTimestampOffsetApplied_kInfiniteDuration_Fails) {
2359   InSequence s;
2360   AddTestTracks(HAS_AUDIO);
2361   frame_processor_->SetSequenceMode(use_sequence_mode_);
2362
2363   EXPECT_MEDIA_LOG(FrameTimeOutOfRange("Before adjusting by timestampOffset",
2364                                        "PTS", "audio"));
2365   EXPECT_FALSE(ProcessFrames("MaxK", ""));
2366 }
2367
2368 TEST_P(FrameProcessorTest,
2369        Dts_BeforeTimestampOffsetApplied_kNoDecodeTimestamp_UsesPtsIfValid) {
2370   InSequence s;
2371   AddTestTracks(HAS_AUDIO);
2372   frame_processor_->SetSequenceMode(use_sequence_mode_);
2373
2374   // When PTS is valid, but DTS is kNoDecodeTimestamp, then
2375   // StreamParserBuffer::GetDecodeTimestamp() just returns the frame's PTS.
2376   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10)));
2377   EXPECT_TRUE(ProcessFrames("0|MinK", ""));
2378
2379   CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,10) }");
2380   CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "0K");
2381 }
2382
2383 TEST_P(FrameProcessorTest,
2384        Dts_BeforeTimestampOffsetApplied_kMaxDecodeTimestamp_Fails) {
2385   InSequence s;
2386   AddTestTracks(HAS_AUDIO);
2387   frame_processor_->SetSequenceMode(use_sequence_mode_);
2388
2389   EXPECT_MEDIA_LOG(FrameTimeOutOfRange("Before adjusting by timestampOffset",
2390                                        "DTS", "audio"));
2391   EXPECT_FALSE(ProcessFrames("0|MaxK", ""));
2392 }
2393
2394 TEST_P(FrameProcessorTest, After_Sequence_OffsetUpdate_kNoTimestamp_Fails) {
2395   if (!use_sequence_mode_) {
2396     DVLOG(1) << "Skipping segments mode variant; inapplicable to this case.";
2397     return;
2398   }
2399   InSequence s;
2400
2401   AddTestTracks(HAS_AUDIO);
2402   frame_processor_->SetSequenceMode(use_sequence_mode_);
2403
2404   // (-Infinity + 5)ms minus 10ms saturates to (-Infinity)ms.
2405   SetTimestampOffset(kNoTimestamp + Milliseconds(5));
2406   EXPECT_MEDIA_LOG(SequenceOffsetUpdateOutOfRange());
2407   EXPECT_FALSE(ProcessFrames("10K", ""));
2408 }
2409
2410 TEST_P(FrameProcessorTest,
2411        After_Sequence_OffsetUpdate_kInfiniteDuration_Fails) {
2412   if (!use_sequence_mode_) {
2413     DVLOG(1) << "Skipping segments mode variant; inapplicable to this case.";
2414     return;
2415   }
2416   InSequence s;
2417
2418   AddTestTracks(HAS_AUDIO);
2419   frame_processor_->SetSequenceMode(use_sequence_mode_);
2420
2421   // (+Infinity - 5)ms minus -10ms saturates to (+Infinity)ms.
2422   SetTimestampOffset(kInfiniteDuration - Milliseconds(5));
2423   EXPECT_MEDIA_LOG(SequenceOffsetUpdateOutOfRange());
2424   EXPECT_FALSE(ProcessFrames("-10K", ""));
2425 }
2426
2427 TEST_P(FrameProcessorTest,
2428        Before_Sequence_OffsetUpdate_kInfiniteDuration_Fails) {
2429   if (!use_sequence_mode_) {
2430     DVLOG(1) << "Skipping segments mode variant; inapplicable to this case.";
2431     return;
2432   }
2433   InSequence s;
2434
2435   AddTestTracks(HAS_AUDIO);
2436   frame_processor_->SetSequenceMode(use_sequence_mode_);
2437
2438   // Effectively sets group start timestamp to +Infinity.
2439   SetTimestampOffset(kInfiniteDuration);
2440   EXPECT_MEDIA_LOG(
2441       SequenceOffsetUpdatePreventedByOutOfRangeGroupStartTimestamp());
2442
2443   // That infinite value fails precondition of finite value for group start
2444   // timestamp when about to update timestampOffset based upon it.
2445   EXPECT_FALSE(ProcessFrames("0K", ""));
2446 }
2447
2448 TEST_P(FrameProcessorTest, Segments_InfiniteTimestampOffset_Fails) {
2449   if (use_sequence_mode_) {
2450     DVLOG(1) << "Skipping sequence mode variant; inapplicable to this case.";
2451     return;
2452   }
2453   InSequence s;
2454
2455   AddTestTracks(HAS_AUDIO);
2456   frame_processor_->SetSequenceMode(use_sequence_mode_);
2457
2458   SetTimestampOffset(kInfiniteDuration);
2459   EXPECT_MEDIA_LOG(OffsetOutOfRange());
2460   EXPECT_FALSE(ProcessFrames("0K", ""));
2461 }
2462
2463 TEST_P(FrameProcessorTest, Pts_AfterTimestampOffsetApplied_kNoTimestamp_Fails) {
2464   InSequence s;
2465   AddTestTracks(HAS_VIDEO);
2466   frame_processor_->SetSequenceMode(use_sequence_mode_);
2467
2468   // Note, SetTimestampOffset(kNoTimestamp) hits DCHECK. This test instead
2469   // checks that the result of offset application to PTS gives parse error if
2470   // the result is <= kNoTimestamp. Getting such a result requires different
2471   // test logic for segments vs sequence append modes.
2472   if (use_sequence_mode_) {
2473     // Use an extremely out-of-order DTS/PTS GOP to get the resulting
2474     // timestampOffset needed for application to a nonkeyframe PTS (continuous
2475     // in DTS time with its GOP's keyframe), resulting with kNoTimestamp PTS.
2476     // First, calculate (-kNoTimestamp - 10ms), truncated down to nearest
2477     // millisecond, for use as keyframe PTS and DTS.
2478     frame_duration_ = Milliseconds(1);
2479     base::TimeDelta ts =
2480         Milliseconds(((kNoTimestamp + Milliseconds(10)) * -1).InMilliseconds());
2481     std::string ts_str = base::NumberToString(ts.InMilliseconds());
2482
2483     // Append the keyframe and expect success for this step.
2484     EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_));
2485     EXPECT_TRUE(ProcessFrames("", ts_str + "|" + ts_str + "K"));
2486     EXPECT_EQ(timestamp_offset_.InMicroseconds(), (-1 * ts).InMicroseconds());
2487
2488     // A nonkeyframe with the same DTS as previous frame does not cause any
2489     // discontinuity. Append such a frame, with PTS before offset applied that
2490     // saturates to kNoTimestamp when the offset is applied.
2491     EXPECT_MEDIA_LOG(FrameTimeOutOfRange("After adjusting by timestampOffset",
2492                                          "PTS", "video"));
2493     EXPECT_FALSE(ProcessFrames("", "-20|" + ts_str));
2494   } else {
2495     // Set the offset to be just above kNoTimestamp, and append a frame with a
2496     // PTS that is negative by at least that small amount. The result should
2497     // saturate to kNoTimestamp for PTS.
2498     SetTimestampOffset(kNoTimestamp + Milliseconds(1));
2499     EXPECT_MEDIA_LOG(FrameTimeOutOfRange("After adjusting by timestampOffset",
2500                                          "PTS", "video"));
2501     EXPECT_FALSE(ProcessFrames("", "-2K"));
2502   }
2503 }
2504
2505 TEST_P(FrameProcessorTest,
2506        Pts_AfterTimestampOffsetApplied_kInfiniteDuration_Fails) {
2507   InSequence s;
2508
2509   AddTestTracks(HAS_VIDEO);
2510   frame_processor_->SetSequenceMode(use_sequence_mode_);
2511
2512   // Use a video GOP with a nonkeyframe PTS that jumps forward far enough to
2513   // saturate to kInfiniteDuration after timestampOffset is applied. Take care
2514   // to avoid saturating the (earlier) keyframe's frame_end_timestamp to
2515   // kInfiniteDuration, avoiding a different parse error case.
2516   // First, calculate (kInfiniteDuration - 2ms), truncated down to nearest
2517   // millisecond for use as keyframe PTS (after timestamp offset application).
2518   // It's also used for start of DTS sequence.
2519   frame_duration_ = Milliseconds(1);
2520   base::TimeDelta ts =
2521       Milliseconds((kInfiniteDuration - Milliseconds(2)).InMilliseconds());
2522
2523   // Append the keyframe and expect success for this step.
2524   SetTimestampOffset(ts);
2525   EXPECT_CALL(callbacks_, PossibleDurationIncrease(ts + frame_duration_));
2526   EXPECT_TRUE(ProcessFrames("", "0K"));
2527
2528   // Sequence mode might adjust the offset. This test's logic should ensure the
2529   // offset is the same as in segments mode at this point.
2530   EXPECT_EQ(timestamp_offset_.InMicroseconds(), ts.InMicroseconds());
2531
2532   // A nonkeyframe with same DTS as previous frame does not cause any
2533   // discontinuity. Append such a frame, with PTS jumped 3ms forwards such that
2534   // it saturates to kInfiniteDuration when offset is applied.
2535   EXPECT_MEDIA_LOG(FrameTimeOutOfRange("After adjusting by timestampOffset",
2536                                        "PTS", "video"));
2537   EXPECT_FALSE(ProcessFrames("", "3|0"));
2538 }
2539
2540 TEST_P(FrameProcessorTest,
2541        Dts_AfterTimestampOffsetApplied_kNoDecodeTimestamp_Fails) {
2542   InSequence s;
2543
2544   AddTestTracks(HAS_AUDIO);
2545   frame_processor_->SetSequenceMode(use_sequence_mode_);
2546
2547   SetTimestampOffset(kNoTimestamp + Milliseconds(5));
2548   EXPECT_MEDIA_LOG(FrameTimeOutOfRange("After adjusting by timestampOffset",
2549                                        "DTS", "audio"));
2550   EXPECT_FALSE(ProcessFrames("0|-10K", ""));
2551 }
2552
2553 TEST_P(FrameProcessorTest,
2554        Dts_AfterTimestampOffsetApplied_kMaxDecodeTimestamp_Fails) {
2555   InSequence s;
2556
2557   AddTestTracks(HAS_AUDIO);
2558   frame_processor_->SetSequenceMode(use_sequence_mode_);
2559
2560   SetTimestampOffset(kInfiniteDuration - Milliseconds(5));
2561   EXPECT_MEDIA_LOG(FrameTimeOutOfRange("After adjusting by timestampOffset",
2562                                        "DTS", "audio"));
2563   EXPECT_FALSE(ProcessFrames("0|10K", ""));
2564 }
2565
2566 TEST_P(FrameProcessorTest, FrameEndTimestamp_kInfiniteDuration_Fails) {
2567   InSequence s;
2568
2569   AddTestTracks(HAS_AUDIO);
2570   frame_processor_->SetSequenceMode(use_sequence_mode_);
2571
2572   frame_duration_ = Milliseconds(10);
2573   SetTimestampOffset(kInfiniteDuration - Milliseconds(5));
2574   EXPECT_MEDIA_LOG(FrameEndTimestampOutOfRange("audio"));
2575   EXPECT_FALSE(ProcessFrames("0|0K", ""));
2576 }
2577
2578 INSTANTIATE_TEST_SUITE_P(SequenceMode, FrameProcessorTest, Values(true));
2579 INSTANTIATE_TEST_SUITE_P(SegmentsMode, FrameProcessorTest, Values(false));
2580
2581 }  // namespace media