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