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