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_FRAME_PROCESSOR_BASE_H_
      6 #define MEDIA_FILTERS_FRAME_PROCESSOR_BASE_H_
      7 
      8 #include <map>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/time/time.h"
     12 #include "media/base/media_export.h"
     13 #include "media/base/stream_parser.h"
     14 #include "media/filters/chunk_demuxer.h"
     15 
     16 namespace media {
     17 
     18 // Helper class to capture per-track details needed by a frame processor. Some
     19 // of this information may be duplicated in the short-term in the associated
     20 // ChunkDemuxerStream and SourceBufferStream for a track.
     21 // This parallels the MSE spec each of a SourceBuffer's Track Buffers at
     22 // http://www.w3.org/TR/media-source/#track-buffers.
     23 class MseTrackBuffer {
     24  public:
     25   explicit MseTrackBuffer(ChunkDemuxerStream* stream);
     26   ~MseTrackBuffer();
     27 
     28   // Get/set |last_decode_timestamp_|.
     29   base::TimeDelta last_decode_timestamp() const {
     30     return last_decode_timestamp_;
     31   }
     32   void set_last_decode_timestamp(base::TimeDelta timestamp) {
     33     last_decode_timestamp_ = timestamp;
     34   }
     35 
     36   // Get/set |last_frame_duration_|.
     37   base::TimeDelta last_frame_duration() const {
     38     return last_frame_duration_;
     39   }
     40   void set_last_frame_duration(base::TimeDelta duration) {
     41     last_frame_duration_ = duration;
     42   }
     43 
     44   // Gets |highest_presentation_timestamp_|.
     45   base::TimeDelta highest_presentation_timestamp() const {
     46     return highest_presentation_timestamp_;
     47   }
     48 
     49   // Get/set |needs_random_access_point_|.
     50   bool needs_random_access_point() const {
     51     return needs_random_access_point_;
     52   }
     53   void set_needs_random_access_point(bool needs_random_access_point) {
     54     needs_random_access_point_ = needs_random_access_point;
     55   }
     56 
     57   // Gets a pointer to this track's ChunkDemuxerStream.
     58   ChunkDemuxerStream* stream() const { return stream_; }
     59 
     60   // Unsets |last_decode_timestamp_|, unsets |last_frame_duration_|,
     61   // unsets |highest_presentation_timestamp_|, and sets
     62   // |needs_random_access_point_| to true.
     63   void Reset();
     64 
     65   // If |highest_presentation_timestamp_| is unset or |timestamp| is greater
     66   // than |highest_presentation_timestamp_|, sets
     67   // |highest_presentation_timestamp_| to |timestamp|. Note that bidirectional
     68   // prediction between coded frames can cause |timestamp| to not be
     69   // monotonically increasing even though the decode timestamps are
     70   // monotonically increasing.
     71   void SetHighestPresentationTimestampIfIncreased(base::TimeDelta timestamp);
     72 
     73  private:
     74   // The decode timestamp of the last coded frame appended in the current coded
     75   // frame group. Initially kNoTimestamp(), meaning "unset".
     76   base::TimeDelta last_decode_timestamp_;
     77 
     78   // The coded frame duration of the last coded frame appended in the current
     79   // coded frame group. Initially kNoTimestamp(), meaning "unset".
     80   base::TimeDelta last_frame_duration_;
     81 
     82   // The highest presentation timestamp encountered in a coded frame appended
     83   // in the current coded frame group. Initially kNoTimestamp(), meaning
     84   // "unset".
     85   base::TimeDelta highest_presentation_timestamp_;
     86 
     87   // Keeps track of whether the track buffer is waiting for a random access
     88   // point coded frame. Initially set to true to indicate that a random access
     89   // point coded frame is needed before anything can be added to the track
     90   // buffer.
     91   bool needs_random_access_point_;
     92 
     93   // Pointer to the stream associated with this track. The stream is not owned
     94   // by |this|.
     95   ChunkDemuxerStream* const stream_;
     96 
     97   DISALLOW_COPY_AND_ASSIGN(MseTrackBuffer);
     98 };
     99 
    100 // Abstract interface for helper class implementation of Media Source
    101 // Extension's coded frame processing algorithm.
    102 // TODO(wolenetz): Once the new FrameProcessor implementation stabilizes, remove
    103 // LegacyFrameProcessor and fold this interface into FrameProcessor. See
    104 // http://crbug.com/249422.
    105 class MEDIA_EXPORT FrameProcessorBase {
    106  public:
    107   // TODO(wolenetz/acolwell): Ensure that all TrackIds are coherent and unique
    108   // for each track buffer. For now, special track identifiers are used for each
    109   // of audio and video here, and text TrackIds are assumed to be non-negative.
    110   // See http://crbug.com/341581.
    111   enum {
    112     kAudioTrackId = -2,
    113     kVideoTrackId = -3
    114   };
    115 
    116   virtual ~FrameProcessorBase();
    117 
    118   // Get/set the current append mode, which if true means "sequence" and if
    119   // false means "segments".
    120   // See http://www.w3.org/TR/media-source/#widl-SourceBuffer-mode.
    121   bool sequence_mode() { return sequence_mode_; }
    122   virtual void SetSequenceMode(bool sequence_mode) = 0;
    123 
    124   // Processes buffers in |audio_buffers|, |video_buffers|, and |text_map|.
    125   // Returns true on success or false on failure which indicates decode error.
    126   // |append_window_start| and |append_window_end| correspond to the MSE spec's
    127   // similarly named source buffer attributes that are used in coded frame
    128   // processing.
    129   // |*new_media_segment| tracks whether the next buffers processed within the
    130   // append window represent the start of a new media segment. This method may
    131   // both use and update this flag.
    132   // Uses |*timestamp_offset| according to the coded frame processing algorithm,
    133   // including updating it as required in 'sequence' mode frame processing.
    134   virtual bool ProcessFrames(const StreamParser::BufferQueue& audio_buffers,
    135                              const StreamParser::BufferQueue& video_buffers,
    136                              const StreamParser::TextBufferQueueMap& text_map,
    137                              base::TimeDelta append_window_start,
    138                              base::TimeDelta append_window_end,
    139                              bool* new_media_segment,
    140                              base::TimeDelta* timestamp_offset) = 0;
    141 
    142   // Signals the frame processor to update its group start timestamp to be
    143   // |timestamp_offset| if it is in sequence append mode.
    144   void SetGroupStartTimestampIfInSequenceMode(base::TimeDelta timestamp_offset);
    145 
    146   // Adds a new track with unique track ID |id|.
    147   // If |id| has previously been added, returns false to indicate error.
    148   // Otherwise, returns true, indicating future ProcessFrames() will emit
    149   // frames for the track |id| to |stream|.
    150   bool AddTrack(StreamParser::TrackId id, ChunkDemuxerStream* stream);
    151 
    152   // Updates the internal mapping of TrackId to track buffer for the track
    153   // buffer formerly associated with |old_id| to be associated with |new_id|.
    154   // Returns false to indicate failure due to either no existing track buffer
    155   // for |old_id| or collision with previous track buffer already mapped to
    156   // |new_id|. Otherwise returns true.
    157   bool UpdateTrack(StreamParser::TrackId old_id, StreamParser::TrackId new_id);
    158 
    159   // Sets the need random access point flag on all track buffers to true.
    160   void SetAllTrackBuffersNeedRandomAccessPoint();
    161 
    162   // Resets state for the coded frame processing algorithm as described in steps
    163   // 2-5 of the MSE Reset Parser State algorithm described at
    164   // http://www.w3.org/TR/media-source/#sourcebuffer-reset-parser-state
    165   void Reset();
    166 
    167   // Must be called when the audio config is updated.  Used to manage when
    168   // the preroll buffer is cleared and the allowed "fudge" factor between
    169   // preroll buffers.
    170   void OnPossibleAudioConfigUpdate(const AudioDecoderConfig& config);
    171 
    172  protected:
    173   typedef std::map<StreamParser::TrackId, MseTrackBuffer*> TrackBufferMap;
    174 
    175   FrameProcessorBase();
    176 
    177   // If |track_buffers_| contains |id|, returns a pointer to the associated
    178   // MseTrackBuffer. Otherwise, returns NULL.
    179   MseTrackBuffer* FindTrack(StreamParser::TrackId id);
    180 
    181   // Signals all track buffers' streams that a new media segment is starting
    182   // with timestamp |segment_timestamp|.
    183   void NotifyNewMediaSegmentStarting(base::TimeDelta segment_timestamp);
    184 
    185   // Handles partial append window trimming of |buffer|.  Returns true if the
    186   // given |buffer| can be partially trimmed or have preroll added; otherwise,
    187   // returns false.
    188   //
    189   // If |buffer| overlaps |append_window_start|, the portion of |buffer| before
    190   // |append_window_start| will be marked for post-decode discard.  Further, if
    191   // |audio_preroll_buffer_| exists and abuts |buffer|, it will be set as
    192   // preroll on |buffer| and |audio_preroll_buffer_| will be cleared.  If the
    193   // preroll buffer does not abut |buffer|, it will be discarded, but not used.
    194   //
    195   // If |buffer| lies entirely before |append_window_start|, and thus would
    196   // normally be discarded, |audio_preroll_buffer_| will be set to |buffer| and
    197   // the method will return false.
    198   bool HandlePartialAppendWindowTrimming(
    199       base::TimeDelta append_window_start,
    200       base::TimeDelta append_window_end,
    201       const scoped_refptr<StreamParserBuffer>& buffer);
    202 
    203   // The AppendMode of the associated SourceBuffer.
    204   // See SetSequenceMode() for interpretation of |sequence_mode_|.
    205   // Per http://www.w3.org/TR/media-source/#widl-SourceBuffer-mode:
    206   // Controls how a sequence of media segments are handled. This is initially
    207   // set to false ("segments").
    208   bool sequence_mode_;
    209 
    210   // TrackId-indexed map of each track's stream.
    211   TrackBufferMap track_buffers_;
    212 
    213   // Tracks the MSE coded frame processing variable of same name.
    214   // Initially kNoTimestamp(), meaning "unset".
    215   // Note: LegacyFrameProcessor does not use this member; it's here to reduce
    216   // short-term plumbing of SetGroupStartTimestampIfInSequenceMode() until
    217   // LegacyFrameProcessor is removed.
    218   base::TimeDelta group_start_timestamp_;
    219 
    220  private:
    221   // The last audio buffer seen by the frame processor that was removed because
    222   // it was entirely before the start of the append window.
    223   scoped_refptr<StreamParserBuffer> audio_preroll_buffer_;
    224 
    225   // The AudioDecoderConfig associated with buffers handed to ProcessFrames().
    226   AudioDecoderConfig current_audio_config_;
    227   base::TimeDelta sample_duration_;
    228 
    229   DISALLOW_COPY_AND_ASSIGN(FrameProcessorBase);
    230 };
    231 
    232 }  // namespace media
    233 
    234 #endif  // MEDIA_FILTERS_FRAME_PROCESSOR_BASE_H_
    235