Home | History | Annotate | Download | only in filters
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MEDIA_FILTERS_AUDIO_CLOCK_H_
      6 #define MEDIA_FILTERS_AUDIO_CLOCK_H_
      7 
      8 #include <deque>
      9 
     10 #include "base/time/time.h"
     11 #include "media/base/media_export.h"
     12 
     13 namespace media {
     14 
     15 // Models a queue of buffered audio in a playback pipeline for use with
     16 // estimating the amount of delay in wall clock time. Takes changes in playback
     17 // rate into account to handle scenarios where multiple rates may be present in
     18 // a playback pipeline with large delay.
     19 //
     20 //
     21 // USAGE
     22 //
     23 // Prior to starting audio playback, construct an AudioClock with an initial
     24 // media timestamp and a sample rate matching the sample rate the audio device
     25 // was opened at.
     26 //
     27 // Each time the audio rendering callback is executed, call WroteAudio() once
     28 // (and only once!) containing information on what was written:
     29 //   1) How many frames of audio data requested
     30 //   2) How many frames of audio data provided
     31 //   3) The playback rate of the audio data provided
     32 //   4) The current amount of delay
     33 //
     34 // After a call to WroteAudio(), clients can inspect the resulting media
     35 // timestamp. This can be used for UI purposes, synchronizing video, etc...
     36 //
     37 //
     38 // DETAILS
     39 //
     40 // Silence (whether caused by the initial audio delay or failing to write the
     41 // amount of requested frames due to underflow) is also modeled and will cause
     42 // the media timestamp to stop increasing until all known silence has been
     43 // played. AudioClock's model is initialized with silence during the first call
     44 // to WroteAudio() using the delay value.
     45 //
     46 // Playback rates are tracked for translating frame durations into media
     47 // durations. Since silence doesn't affect media timestamps, it also isn't
     48 // affected by playback rates.
     49 class MEDIA_EXPORT AudioClock {
     50  public:
     51   AudioClock(base::TimeDelta start_timestamp, int sample_rate);
     52   ~AudioClock();
     53 
     54   // |frames_written| amount of audio data scaled to |playback_rate| written.
     55   // |frames_requested| amount of audio data requested by hardware.
     56   // |delay_frames| is the current amount of hardware delay.
     57   void WroteAudio(int frames_written,
     58                   int frames_requested,
     59                   int delay_frames,
     60                   float playback_rate);
     61 
     62   // Returns the bounds of media data currently buffered by the audio hardware,
     63   // taking silence and changes in playback rate into account. Buffered audio
     64   // structure and timestamps are updated with every call to WroteAudio().
     65   //
     66   //  start_timestamp = 1000 ms                           sample_rate = 40 Hz
     67   // +-----------------------+-----------------------+-----------------------+
     68   // |   10 frames silence   |   20 frames @ 1.0x    |   20 frames @ 0.5x    |
     69   // |      = 250 ms (wall)  |      = 500 ms (wall)  |      = 500 ms (wall)  |
     70   // |      =   0 ms (media) |      = 500 ms (media) |      = 250 ms (media) |
     71   // +-----------------------+-----------------------+-----------------------+
     72   // ^                                                                       ^
     73   // front_timestamp() is equal to               back_timestamp() is equal to
     74   // |start_timestamp| since no                  amount of media frames tracked
     75   // media data has been played yet.             by AudioClock, which would be
     76   //                                             1000 + 500 + 250 = 1750 ms.
     77   base::TimeDelta front_timestamp() const { return front_timestamp_; }
     78   base::TimeDelta back_timestamp() const { return back_timestamp_; }
     79 
     80   // Clients can provide |time_since_writing| to simulate the passage of time
     81   // since last writing audio to get a more accurate current media timestamp.
     82   //
     83   // The value will be bounded between front_timestamp() and back_timestamp().
     84   base::TimeDelta TimestampSinceWriting(
     85       base::TimeDelta time_since_writing) const;
     86 
     87   // Returns the amount of wall time until |timestamp| will be played by the
     88   // audio hardware.
     89   //
     90   // |timestamp| must be within front_timestamp() and back_timestamp().
     91   base::TimeDelta TimeUntilPlayback(base::TimeDelta timestamp) const;
     92 
     93   // Returns the amount of contiguous media time buffered at the head of the
     94   // audio hardware buffer. Silence introduced into the audio hardware buffer is
     95   // treated as a break in media time.
     96   base::TimeDelta contiguous_audio_data_buffered() const {
     97     return contiguous_audio_data_buffered_;
     98   }
     99 
    100   // Same as above, but also treats changes in playback rate as a break in media
    101   // time.
    102   base::TimeDelta contiguous_audio_data_buffered_at_same_rate() const {
    103     return contiguous_audio_data_buffered_at_same_rate_;
    104   }
    105 
    106  private:
    107   // Even with a ridiculously high sample rate of 256kHz, using 64 bits will
    108   // permit tracking up to 416999965 days worth of time (that's 1141 millenia).
    109   //
    110   // 32 bits on the other hand would top out at measly 2 hours and 20 minutes.
    111   struct AudioData {
    112     AudioData(int64_t frames, float playback_rate);
    113 
    114     int64_t frames;
    115     float playback_rate;
    116   };
    117 
    118   // Helpers for operating on |buffered_|.
    119   void PushBufferedAudioData(int64_t frames, float playback_rate);
    120   void PopBufferedAudioData(int64_t frames);
    121   base::TimeDelta ComputeBufferedMediaTime(int64_t frames) const;
    122 
    123   const base::TimeDelta start_timestamp_;
    124   const int sample_rate_;
    125   const double microseconds_per_frame_;
    126 
    127   std::deque<AudioData> buffered_;
    128   int64_t total_buffered_frames_;
    129 
    130   base::TimeDelta front_timestamp_;
    131   base::TimeDelta back_timestamp_;
    132 
    133   // Cached results of last call to WroteAudio().
    134   base::TimeDelta contiguous_audio_data_buffered_;
    135   base::TimeDelta contiguous_audio_data_buffered_at_same_rate_;
    136 
    137   DISALLOW_COPY_AND_ASSIGN(AudioClock);
    138 };
    139 
    140 }  // namespace media
    141 
    142 #endif  // MEDIA_FILTERS_AUDIO_CLOCK_H_
    143