Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / formats / webm / webm_cluster_parser.h
index 749b6bd..ab1d4a1 100644 (file)
@@ -23,18 +23,40 @@ namespace media {
 class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
  public:
   typedef StreamParser::TrackId TrackId;
+  typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
+  typedef std::map<TrackId, const BufferQueue> TextBufferQueueMap;
+
+  // Arbitrarily-chosen numbers to estimate the duration of a buffer if none is
+  // set and there is not enough information to get a better estimate.
+  // TODO(wolenetz/acolwell): Parse audio codebook to determine missing audio
+  // frame durations. See http://crbug.com/351166.
+  enum {
+    kDefaultAudioBufferDurationInMs = 23,  // Common 1k samples @44.1kHz
+    kDefaultVideoBufferDurationInMs = 42  // Low 24fps to reduce stalls
+  };
 
  private:
   // Helper class that manages per-track state.
   class Track {
    public:
-    Track(int track_num, bool is_video, base::TimeDelta default_duration);
+    Track(int track_num,
+          bool is_video,
+          base::TimeDelta default_duration,
+          const LogCB& log_cb);
     ~Track();
 
     int track_num() const { return track_num_; }
-    const std::deque<scoped_refptr<StreamParserBuffer> >& buffers() const {
-      return buffers_;
-    }
+
+    // If a buffer is currently held aside pending duration calculation, returns
+    // its decode timestamp. Otherwise, returns kInfiniteDuration().
+    base::TimeDelta GetReadyUpperBound();
+
+    // Prepares |ready_buffers_| for retrieval. Prior to calling,
+    // |ready_buffers_| must be empty. Moves all |buffers_| with timestamp
+    // before |before_timestamp| to |ready_buffers_|, preserving their order.
+    void ExtractReadyBuffers(const base::TimeDelta before_timestamp);
+
+    const BufferQueue& ready_buffers() const { return ready_buffers_; }
 
     // If |last_added_buffer_missing_duration_| is set, updates its duration
     // relative to |buffer|'s timestamp, and adds it to |buffers_| and unsets
@@ -43,20 +65,21 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
     // otherwise adds |buffer| to |buffers_|.
     bool AddBuffer(const scoped_refptr<StreamParserBuffer>& buffer);
 
-    // If |last_added_buffer_missing_duration_| is set, updates its duration
-    // to be the first non-kNoTimestamp() value of |default_duration_|,
-    // |estimated_next_frame_duration_|, or an arbitrary default, then adds it
-    // to |buffers_| and unsets |last_added_buffer_missing_duration_|. (This
-    // method helps stream parser emit all buffers in a media segment before
-    // signaling end of segment.)
-    void ApplyDurationDefaultOrEstimateIfNeeded();
-
-    // Clears all buffer state, except a possibly held-aside buffer that is
+    // If |last_added_buffer_missing_duration_| is set, updates its duration to
+    // be non-kNoTimestamp() value of |estimated_next_frame_duration_| or an
+    // arbitrary default, then adds it to |buffers_| and unsets
+    // |last_added_buffer_missing_duration_|. (This method helps stream parser
+    // emit all buffers in a media segment before signaling end of segment.)
+    void ApplyDurationEstimateIfNeeded();
+
+    // Clears |ready_buffers_| (use ExtractReadyBuffers() to fill it again).
+    // Leaves as-is |buffers_| and any possibly held-aside buffer that is
     // missing duration.
-    void ClearBuffersButKeepLastIfMissingDuration();
+    void ClearReadyBuffers();
 
     // Clears all buffer state, including any possibly held-aside buffer that
-    // was missing duration.
+    // was missing duration, and all contents of |buffers_| and
+    // |ready_buffers_|.
     void Reset();
 
     // Helper function used to inspect block data to determine if the
@@ -65,6 +88,8 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
     // |size| indicates the number of bytes in |data|.
     bool IsKeyframe(const uint8* data, int size) const;
 
+    base::TimeDelta default_duration() const { return default_duration_; }
+
    private:
     // Helper that sanity-checks |buffer| duration, updates
     // |estimated_next_frame_duration_|, and adds |buffer| to |buffers_|.
@@ -73,28 +98,41 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
     bool QueueBuffer(const scoped_refptr<StreamParserBuffer>& buffer);
 
     // Helper that calculates the buffer duration to use in
-    // ApplyDurationDefaultOrEstimateIfNeeded().
-    base::TimeDelta GetDurationDefaultOrEstimate();
+    // ApplyDurationEstimateIfNeeded().
+    base::TimeDelta GetDurationEstimate();
 
     int track_num_;
-    std::deque<scoped_refptr<StreamParserBuffer> > buffers_;
     bool is_video_;
+
+    // Parsed track buffers, each with duration and in (decode) timestamp order,
+    // that have not yet been extracted into |ready_buffers_|. Note that up to
+    // one additional buffer missing duration may be tracked by
+    // |last_added_buffer_missing_duration_|.
+    BufferQueue buffers_;
     scoped_refptr<StreamParserBuffer> last_added_buffer_missing_duration_;
 
+    // Buffers in (decode) timestamp order that were previously parsed into and
+    // extracted from |buffers_|. Buffers are moved from |buffers_| to
+    // |ready_buffers_| by ExtractReadyBuffers() if they are below a specified
+    // upper bound timestamp. Track users can therefore extract only those
+    // parsed buffers which are "ready" for emission (all before some maximum
+    // timestamp).
+    BufferQueue ready_buffers_;
+
     // If kNoTimestamp(), then |estimated_next_frame_duration_| will be used.
     base::TimeDelta default_duration_;
+
     // If kNoTimestamp(), then a default value will be used. This estimate is
     // the maximum duration seen or derived so far for this track, and is valid
     // only if |default_duration_| is kNoTimestamp().
     base::TimeDelta estimated_next_frame_duration_;
+
+    LogCB log_cb_;
   };
 
   typedef std::map<int, Track> TextTrackMap;
 
  public:
-  typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
-  typedef std::map<TrackId, const BufferQueue> TextBufferQueueMap;
-
   WebMClusterParser(int64 timecode_scale,
                     int audio_track_num,
                     base::TimeDelta audio_default_duration,
@@ -119,17 +157,32 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
 
   base::TimeDelta cluster_start_time() const { return cluster_start_time_; }
 
-  // Get the buffers resulting from Parse().
+  // Get the current ready buffers resulting from Parse().
   // If the parse reached the end of cluster and the last buffer was held aside
   // due to missing duration, the buffer is given an estimated duration and
   // included in the result.
+  // Otherwise, if there are is a buffer held aside due to missing duration for
+  // any of the tracks, no buffers with same or greater (decode) timestamp will
+  // be included in the buffers.
+  // The returned deques are cleared by Parse() or Reset() and updated by the
+  // next calls to Get{Audio,Video}Buffers().
+  // If no Parse() or Reset() has occurred since the last call to Get{Audio,
+  // Video,Text}Buffers(), then the previous BufferQueue& is returned again
+  // without any recalculation.
   const BufferQueue& GetAudioBuffers();
   const BufferQueue& GetVideoBuffers();
 
   // Constructs and returns a subset of |text_track_map_| containing only
-  // tracks with non-empty buffer queues produced by the last Parse().
+  // tracks with non-empty buffer queues produced by the last Parse() and
+  // filtered to exclude any buffers that have (decode) timestamp same or
+  // greater than the lowest (decode) timestamp across all tracks of any buffer
+  // held aside due to missing duration (unless the end of cluster has been
+  // reached).
   // The returned map is cleared by Parse() or Reset() and updated by the next
   // call to GetTextBuffers().
+  // If no Parse() or Reset() has occurred since the last call to
+  // GetTextBuffers(), then the previous TextBufferQueueMap& is returned again
+  // without any recalculation.
   const TextBufferQueueMap& GetTextBuffers();
 
   // Returns true if the last Parse() call stopped at the end of a cluster.
@@ -153,6 +206,22 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
   // Resets the Track objects associated with each text track.
   void ResetTextTracks();
 
+  // Clears the the ready buffers associated with each text track.
+  void ClearTextTrackReadyBuffers();
+
+  // Helper method for Get{Audio,Video,Text}Buffers() that recomputes
+  // |ready_buffer_upper_bound_| and calls ExtractReadyBuffers() on each track.
+  // If |cluster_ended_| is true, first applies duration estimate if needed for
+  // |audio_| and |video_| and sets |ready_buffer_upper_bound_| to
+  // kInfiniteDuration(). Otherwise, sets |ready_buffer_upper_bound_| to the
+  // minimum upper bound across |audio_| and |video_|. (Text tracks can have no
+  // buffers missing duration, so they are not involved in calculating the upper
+  // bound.)
+  // Parse() or Reset() must be called between calls to UpdateReadyBuffers() to
+  // clear each track's ready buffers and to reset |ready_buffer_upper_bound_|
+  // to kNoTimestamp().
+  void UpdateReadyBuffers();
+
   // Search for the indicated track_num among the text tracks.  Returns NULL
   // if that track num is not a text track.
   Track* FindTextTrack(int track_num);
@@ -184,10 +253,18 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
   TextTrackMap text_track_map_;
 
   // Subset of |text_track_map_| maintained by GetTextBuffers(), and cleared by
-  // ResetTextTracks(). Callers of GetTextBuffers() get a const-ref to this
-  // member.
+  // ClearTextTrackReadyBuffers(). Callers of GetTextBuffers() get a const-ref
+  // to this member.
   TextBufferQueueMap text_buffers_map_;
 
+  // Limits the range of buffers returned by Get{Audio,Video,Text}Buffers() to
+  // this exclusive upper bound. Set to kNoTimestamp(), meaning not yet
+  // calculated, by Reset() and Parse(). If kNoTimestamp(), then
+  // Get{Audio,Video,Text}Buffers() will calculate it to be the minimum (decode)
+  // timestamp across all tracks' |last_buffer_missing_duration_|, or
+  // kInfiniteDuration() if no buffers are currently missing duration.
+  base::TimeDelta ready_buffer_upper_bound_;
+
   LogCB log_cb_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(WebMClusterParser);