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_H_
      6 #define MEDIA_FILTERS_FRAME_PROCESSOR_H_
      7 
      8 #include <map>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/callback_forward.h"
     12 #include "base/time/time.h"
     13 #include "media/base/media_export.h"
     14 #include "media/base/stream_parser.h"
     15 #include "media/filters/chunk_demuxer.h"
     16 
     17 namespace media {
     18 
     19 class MseTrackBuffer;
     20 
     21 // Helper class that implements Media Source Extension's coded frame processing
     22 // algorithm.
     23 class MEDIA_EXPORT FrameProcessor {
     24  public:
     25   typedef base::Callback<void(base::TimeDelta)> UpdateDurationCB;
     26 
     27   // TODO(wolenetz/acolwell): Ensure that all TrackIds are coherent and unique
     28   // for each track buffer. For now, special track identifiers are used for each
     29   // of audio and video here, and text TrackIds are assumed to be non-negative.
     30   // See http://crbug.com/341581.
     31   enum {
     32     kAudioTrackId = -2,
     33     kVideoTrackId = -3
     34   };
     35 
     36   explicit FrameProcessor(const UpdateDurationCB& update_duration_cb);
     37   ~FrameProcessor();
     38 
     39   // Get/set the current append mode, which if true means "sequence" and if
     40   // false means "segments".
     41   // See http://www.w3.org/TR/media-source/#widl-SourceBuffer-mode.
     42   bool sequence_mode() { return sequence_mode_; }
     43   void SetSequenceMode(bool sequence_mode);
     44 
     45   // Processes buffers in |audio_buffers|, |video_buffers|, and |text_map|.
     46   // Returns true on success or false on failure which indicates decode error.
     47   // |append_window_start| and |append_window_end| correspond to the MSE spec's
     48   // similarly named source buffer attributes that are used in coded frame
     49   // processing.
     50   // |*new_media_segment| tracks whether the next buffers processed within the
     51   // append window represent the start of a new media segment. This method may
     52   // both use and update this flag.
     53   // Uses |*timestamp_offset| according to the coded frame processing algorithm,
     54   // including updating it as required in 'sequence' mode frame processing.
     55   bool ProcessFrames(const StreamParser::BufferQueue& audio_buffers,
     56                      const StreamParser::BufferQueue& video_buffers,
     57                      const StreamParser::TextBufferQueueMap& text_map,
     58                      base::TimeDelta append_window_start,
     59                      base::TimeDelta append_window_end,
     60                      bool* new_media_segment,
     61                      base::TimeDelta* timestamp_offset);
     62 
     63   // Signals the frame processor to update its group start timestamp to be
     64   // |timestamp_offset| if it is in sequence append mode.
     65   void SetGroupStartTimestampIfInSequenceMode(base::TimeDelta timestamp_offset);
     66 
     67   // Adds a new track with unique track ID |id|.
     68   // If |id| has previously been added, returns false to indicate error.
     69   // Otherwise, returns true, indicating future ProcessFrames() will emit
     70   // frames for the track |id| to |stream|.
     71   bool AddTrack(StreamParser::TrackId id, ChunkDemuxerStream* stream);
     72 
     73   // Updates the internal mapping of TrackId to track buffer for the track
     74   // buffer formerly associated with |old_id| to be associated with |new_id|.
     75   // Returns false to indicate failure due to either no existing track buffer
     76   // for |old_id| or collision with previous track buffer already mapped to
     77   // |new_id|. Otherwise returns true.
     78   bool UpdateTrack(StreamParser::TrackId old_id, StreamParser::TrackId new_id);
     79 
     80   // Sets the need random access point flag on all track buffers to true.
     81   void SetAllTrackBuffersNeedRandomAccessPoint();
     82 
     83   // Resets state for the coded frame processing algorithm as described in steps
     84   // 2-5 of the MSE Reset Parser State algorithm described at
     85   // http://www.w3.org/TR/media-source/#sourcebuffer-reset-parser-state
     86   void Reset();
     87 
     88   // Must be called when the audio config is updated.  Used to manage when
     89   // the preroll buffer is cleared and the allowed "fudge" factor between
     90   // preroll buffers.
     91   void OnPossibleAudioConfigUpdate(const AudioDecoderConfig& config);
     92 
     93  private:
     94   typedef std::map<StreamParser::TrackId, MseTrackBuffer*> TrackBufferMap;
     95 
     96   // If |track_buffers_| contains |id|, returns a pointer to the associated
     97   // MseTrackBuffer. Otherwise, returns NULL.
     98   MseTrackBuffer* FindTrack(StreamParser::TrackId id);
     99 
    100   // Signals all track buffers' streams that a new media segment is starting
    101   // with decode timestamp |segment_timestamp|.
    102   void NotifyNewMediaSegmentStarting(DecodeTimestamp segment_timestamp);
    103 
    104   // Helper that signals each track buffer to append any processed, but not yet
    105   // appended, frames to its stream. Returns true on success, or false if one or
    106   // more of the appends failed.
    107   bool FlushProcessedFrames();
    108 
    109   // Handles partial append window trimming of |buffer|.  Returns true if the
    110   // given |buffer| can be partially trimmed or have preroll added; otherwise,
    111   // returns false.
    112   //
    113   // If |buffer| overlaps |append_window_start|, the portion of |buffer| before
    114   // |append_window_start| will be marked for post-decode discard.  Further, if
    115   // |audio_preroll_buffer_| exists and abuts |buffer|, it will be set as
    116   // preroll on |buffer| and |audio_preroll_buffer_| will be cleared.  If the
    117   // preroll buffer does not abut |buffer|, it will be discarded unused.
    118   //
    119   // Likewise, if |buffer| overlaps |append_window_end|, the portion of |buffer|
    120   // after |append_window_end| will be marked for post-decode discard.
    121   //
    122   // If |buffer| lies entirely before |append_window_start|, and thus would
    123   // normally be discarded, |audio_preroll_buffer_| will be set to |buffer| and
    124   // the method will return false.
    125   bool HandlePartialAppendWindowTrimming(
    126       base::TimeDelta append_window_start,
    127       base::TimeDelta append_window_end,
    128       const scoped_refptr<StreamParserBuffer>& buffer);
    129 
    130   // Helper that processes one frame with the coded frame processing algorithm.
    131   // Returns false on error or true on success.
    132   bool ProcessFrame(const scoped_refptr<StreamParserBuffer>& frame,
    133                     base::TimeDelta append_window_start,
    134                     base::TimeDelta append_window_end,
    135                     base::TimeDelta* timestamp_offset,
    136                     bool* new_media_segment);
    137 
    138   // TrackId-indexed map of each track's stream.
    139   TrackBufferMap track_buffers_;
    140 
    141   // The last audio buffer seen by the frame processor that was removed because
    142   // it was entirely before the start of the append window.
    143   scoped_refptr<StreamParserBuffer> audio_preroll_buffer_;
    144 
    145   // The AudioDecoderConfig associated with buffers handed to ProcessFrames().
    146   AudioDecoderConfig current_audio_config_;
    147   base::TimeDelta sample_duration_;
    148 
    149   // The AppendMode of the associated SourceBuffer.
    150   // See SetSequenceMode() for interpretation of |sequence_mode_|.
    151   // Per http://www.w3.org/TR/media-source/#widl-SourceBuffer-mode:
    152   // Controls how a sequence of media segments are handled. This is initially
    153   // set to false ("segments").
    154   bool sequence_mode_;
    155 
    156   // Tracks the MSE coded frame processing variable of same name.
    157   // Initially kNoTimestamp(), meaning "unset".
    158   base::TimeDelta group_start_timestamp_;
    159 
    160   // Tracks the MSE coded frame processing variable of same name. It stores the
    161   // highest coded frame end timestamp across all coded frames in the current
    162   // coded frame group. It is set to 0 when the SourceBuffer object is created
    163   // and gets updated by ProcessFrames().
    164   base::TimeDelta group_end_timestamp_;
    165 
    166   UpdateDurationCB update_duration_cb_;
    167 
    168   DISALLOW_COPY_AND_ASSIGN(FrameProcessor);
    169 };
    170 
    171 }  // namespace media
    172 
    173 #endif  // MEDIA_FILTERS_FRAME_PROCESSOR_H_
    174