src/media/audio/audio_core/test/api/audio_renderer_pipeline_test.cc
// If we issue DiscardAllPackets during Playback, PTS should not change.
If we issue DiscardAllPackets during Playback, PTS should not change.
If we issue DiscardAllPackets during Playback PTS should not change .
TEST_F(AudioRendererPipelineTestInt16, DiscardDuringPlayback) {
  auto min_lead_time = renderer_->GetMinLeadTime();
  constexpr auto kSchedulingDelayInPackets = 10;
  const auto min_lead_time_in_packets =
      (min_lead_time / zx::msec(RendererShimImpl::kPacketMs)) + kSchedulingDelayInPackets;
   1. The first step starts writing num_packets to the front of the ring buffer, but
      interrupts and discards after two packets have been written. Because of races,
      it's possible that more than two packets will have been written at the moment
      the remaining packets are discarded.
       +---+---+ ...           +
       | P | P | maybe empty   |
       +---+---+ ...           +
       ^..... num_packets .....^
   2. The second step writes another num_packets, starting at least min_lead_time after
      the second packet:
       +---+---+ ...           +---+ ...               +
       | P | P | maybe empty   | P | ...               |
       +---+---+ ...           +---+ ...               +
               ^ min_lead_time ^
               +kSchedulingDelay
       ^..... num_packets .....^..... num_packets .....^
   Note that 1 PTS == 1 frame.
   To further simplify, all of the above sizes are integer numbers of packets.
  const int64_t first_packet = 0;
  const int64_t restart_packet = 2 + min_lead_time_in_packets;
  const int64_t first_pts = first_packet * kPacketFrames;
  const int64_t restart_pts = restart_packet * kPacketFrames;
  const auto num_packets = NumPacketsPerBatch();
  const size_t num_frames = num_packets * kPacketFrames;
   Load the renderer with lots of packets, but interrupt after two of them.
  auto first_input = GenerateSequentialAudio<ASF::SIGNED_16>(format_, num_frames);
  auto first_packets = renderer_->AppendPackets({&first_input}, first_pts);
  renderer_->PlaySynchronized(this, output_, 0);
  renderer_->WaitForPackets(this, {first_packets[0], first_packets[1]});
  renderer_->renderer()->DiscardAllPackets(AddCallback(
      "DiscardAllPackets", []() { AUDIO_LOG(DEBUG) << "DiscardAllPackets #1 complete"; }));
  ExpectCallback();
   The entire first two packets must have been written. Subsequent packets may have been partially
   written, depending on exactly when the DiscardAllPackets command is received. The remaining
   bytes should be zeros.
  auto ring_buffer = output_->SnapshotRingBuffer();
  CompareAudioBufferOptions opts;
  opts.num_frames_per_packet = kPacketFrames;
  opts.test_label = "first_input, first packet";
  CompareAudioBuffers(AudioBufferSlice(&ring_buffer, 0, 2 * kPacketFrames),
                      AudioBufferSlice(&first_input, 0, 2 * kPacketFrames), opts);
  opts.test_label = "first_input, third packet onwards";
  opts.partial = true;
  CompareAudioBuffers(AudioBufferSlice(&ring_buffer, 2 * kPacketFrames, output_->frame_count()),
                      AudioBufferSlice(&first_input, 2 * kPacketFrames, output_->frame_count()),
                      opts);
  opts.partial = false;
  renderer_->ClearPayload();
   After interrupting the stream without stopping, now play another sequence of packets starting
   at least "min_lead_time" after the last audio frame previously written to the ring buffer.
   Between Left|Right, initial data values were odd|even; these are even|odd, for quick contrast
   when visually inspecting the buffer.
  const int16_t restart_data_value = 0x4000;
  auto second_input =
      GenerateSequentialAudio<ASF::SIGNED_16>(format_, num_frames, restart_data_value);
  auto second_packets = renderer_->AppendPackets({&second_input}, restart_pts);
  renderer_->WaitForPackets(this, second_packets);
   The ring buffer should contain first_input for 10ms (one packet), then partially-written data
   followed by zeros until restart_pts, then second_input (num_packets), then the remaining bytes
   should be zeros.
  ring_buffer = output_->SnapshotRingBuffer();
  opts.test_label = "first packet, after the second write";
  CompareAudioBuffers(AudioBufferSlice(&ring_buffer, 0, 2 * kPacketFrames),
                      AudioBufferSlice(&first_input, 0, 2 * kPacketFrames), opts);
  opts.test_label = "space between the first packet and second_input";
  opts.partial = true;
  CompareAudioBuffers(AudioBufferSlice(&ring_buffer, 2 * kPacketFrames, restart_pts),
                      AudioBufferSlice(&first_input, 2 * kPacketFrames, restart_pts), opts);
  opts.test_label = "second_input";
  opts.partial = false;
  CompareAudioBuffers(AudioBufferSlice(&ring_buffer, restart_pts, restart_pts + num_frames),
                      AudioBufferSlice(&second_input, 0, num_frames), opts);
  opts.test_label = "silence after second_input";
  CompareAudioBuffers(
      AudioBufferSlice(&ring_buffer, restart_pts + num_frames, output_->frame_count()),
      AudioBufferSlice<ASF::SIGNED_16>(), opts);
}
TEST_F ( AudioRendererPipelineTestInt16 , DiscardDuringPlayback ) { auto min_lead_time = renderer_ -> GetMinLeadTime ( ) ; constexpr auto kSchedulingDelayInPackets = 10 ; const auto min_lead_time_in_packets = ( min_lead_time / zx :: msec ( RendererShimImpl :: kPacketMs ) ) + kSchedulingDelayInPackets ; const int64_t first_packet = 0 ; const int64_t restart_packet = 2 + min_lead_time_in_packets ; const int64_t first_pts = first_packet * kPacketFrames ; const int64_t restart_pts = restart_packet * kPacketFrames ; const auto num_packets = NumPacketsPerBatch ( ) ; const size_t num_frames = num_packets * kPacketFrames ; auto first_input = GenerateSequentialAudio < ASF :: SIGNED_16 > ( format_ , num_frames ) ; auto first_packets = renderer_ -> AppendPackets ( { & first_input } , first_pts ) ; renderer_ -> PlaySynchronized ( this , output_ , 0 ) ; renderer_ -> WaitForPackets ( this , { first_packets [ 0 ] , first_packets [ 1 ] } ) ; renderer_ -> renderer ( ) -> DiscardAllPackets ( AddCallback ( " " , [ ] ( ) { AUDIO_LOG ( DEBUG ) << " " ; } ) ) ; ExpectCallback ( ) ; auto ring_buffer = output_ -> SnapshotRingBuffer ( ) ; CompareAudioBufferOptions opts ; opts . num_frames_per_packet = kPacketFrames ; opts . test_label = " " ; CompareAudioBuffers ( AudioBufferSlice ( & ring_buffer , 0 , 2 * kPacketFrames ) , AudioBufferSlice ( & first_input , 0 , 2 * kPacketFrames ) , opts ) ; opts . test_label = " " ; opts . partial = true ; CompareAudioBuffers ( AudioBufferSlice ( & ring_buffer , 2 * kPacketFrames , output_ -> frame_count ( ) ) , AudioBufferSlice ( & first_input , 2 * kPacketFrames , output_ -> frame_count ( ) ) , opts ) ; opts . partial = false ; renderer_ -> ClearPayload ( ) ; const int16_t restart_data_value = 0x4000 ; auto second_input = GenerateSequentialAudio < ASF :: SIGNED_16 > ( format_ , num_frames , restart_data_value ) ; auto second_packets = renderer_ -> AppendPackets ( { & second_input } , restart_pts ) ; renderer_ -> WaitForPackets ( this , second_packets ) ; ring_buffer = output_ -> SnapshotRingBuffer ( ) ; opts . test_label = " " ; CompareAudioBuffers ( AudioBufferSlice ( & ring_buffer , 0 , 2 * kPacketFrames ) , AudioBufferSlice ( & first_input , 0 , 2 * kPacketFrames ) , opts ) ; opts . test_label = " " ; opts . partial = true ; CompareAudioBuffers ( AudioBufferSlice ( & ring_buffer , 2 * kPacketFrames , restart_pts ) , AudioBufferSlice ( & first_input , 2 * kPacketFrames , restart_pts ) , opts ) ; opts . test_label = " " ; opts . partial = false ; CompareAudioBuffers ( AudioBufferSlice ( & ring_buffer , restart_pts , restart_pts + num_frames ) , AudioBufferSlice ( & second_input , 0 , num_frames ) , opts ) ; opts . test_label = " " ; CompareAudioBuffers ( AudioBufferSlice ( & ring_buffer , restart_pts + num_frames , output_ -> frame_count ( ) ) , AudioBufferSlice < ASF :: SIGNED_16 > ( ) , opts ) ; }
If we issue DiscardAllPackets during Playback, PTS should not change.
If we issue DiscardAllPackets during Playback PTS should not change .
// Add extra packets to allow for scheduling delay to reduce flakes in debug mode. See fxb/52410. // This test writes to the ring buffer as follows: // // 1. The first step starts writing num_packets to the front of the ring buffer, but //    interrupts and discards after two packets have been written. Because of races, //    it's possible that more than two packets will have been written at the moment //    the remaining packets are discarded. // //     +---+---+ ...           + //     | P | P | maybe empty   | //     +---+---+ ...           + // //     ^..... num_packets .....^ // // 2. The second step writes another num_packets, starting at least min_lead_time after //    the second packet: // //     +---+---+ ...           +---+ ...               + //     | P | P | maybe empty   | P | ...               | //     +---+---+ ...           +---+ ...               + // //             ^ min_lead_time ^ //             +kSchedulingDelay // //     ^..... num_packets .....^..... num_packets .....^ // // Note that 1 PTS == 1 frame. // To further simplify, all of the above sizes are integer numbers of packets. // Load the renderer with lots of packets, but interrupt after two of them. // The entire first two packets must have been written. Subsequent packets may have been partially // written, depending on exactly when the DiscardAllPackets command is received. The remaining // bytes should be zeros. // After interrupting the stream without stopping, now play another sequence of packets starting // at least "min_lead_time" after the last audio frame previously written to the ring buffer. // Between Left|Right, initial data values were odd|even; these are even|odd, for quick contrast // when visually inspecting the buffer. // The ring buffer should contain first_input for 10ms (one packet), then partially-written data // followed by zeros until restart_pts, then second_input (num_packets), then the remaining bytes // should be zeros.