- add sources.
[platform/framework/web/crosswalk.git] / src / media / filters / chunk_demuxer.h
1 // Copyright (c) 2012 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_CHUNK_DEMUXER_H_
6 #define MEDIA_FILTERS_CHUNK_DEMUXER_H_
7
8 #include <map>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/synchronization/lock.h"
14 #include "media/base/byte_queue.h"
15 #include "media/base/demuxer.h"
16 #include "media/base/ranges.h"
17 #include "media/base/stream_parser.h"
18 #include "media/base/text_track.h"
19 #include "media/filters/source_buffer_stream.h"
20
21 namespace media {
22
23 class ChunkDemuxerStream;
24 class FFmpegURLProtocol;
25 class SourceState;
26
27 // Demuxer implementation that allows chunks of media data to be passed
28 // from JavaScript to the media stack.
29 class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
30  public:
31   enum Status {
32     kOk,              // ID added w/o error.
33     kNotSupported,    // Type specified is not supported.
34     kReachedIdLimit,  // Reached ID limit. We can't handle any more IDs.
35   };
36
37   // |open_cb| Run when Initialize() is called to signal that the demuxer
38   //   is ready to receive media data via AppenData().
39   // |need_key_cb| Run when the demuxer determines that an encryption key is
40   //   needed to decrypt the content.
41   // |add_text_track_cb| Run when demuxer detects the presence of an inband
42   //   text track.
43   // |log_cb| Run when parsing error messages need to be logged to the error
44   //   console.
45   ChunkDemuxer(const base::Closure& open_cb,
46                const NeedKeyCB& need_key_cb,
47                const AddTextTrackCB& add_text_track_cb,
48                const LogCB& log_cb);
49   virtual ~ChunkDemuxer();
50
51   // Demuxer implementation.
52   virtual void Initialize(DemuxerHost* host,
53                           const PipelineStatusCB& cb) OVERRIDE;
54   virtual void Stop(const base::Closure& callback) OVERRIDE;
55   virtual void Seek(base::TimeDelta time, const PipelineStatusCB&  cb) OVERRIDE;
56   virtual void OnAudioRendererDisabled() OVERRIDE;
57   virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE;
58   virtual base::TimeDelta GetStartTime() const OVERRIDE;
59
60   // Methods used by an external object to control this demuxer.
61   //
62   // Indicates that a new Seek() call is on its way. Any pending Reads on the
63   // DemuxerStream objects should be aborted immediately inside this call and
64   // future Read calls should return kAborted until the Seek() call occurs.
65   // This method MUST ALWAYS be called before Seek() is called to signal that
66   // the next Seek() call represents the seek point we actually want to return
67   // data for.
68   // |seek_time| - The presentation timestamp for the seek that triggered this
69   // call. It represents the most recent position the caller is trying to seek
70   // to.
71   void StartWaitingForSeek(base::TimeDelta seek_time);
72
73   // Indicates that a Seek() call is on its way, but another seek has been
74   // requested that will override the impending Seek() call. Any pending Reads
75   // on the DemuxerStream objects should be aborted immediately inside this call
76   // and future Read calls should return kAborted until the next
77   // StartWaitingForSeek() call. This method also arranges for the next Seek()
78   // call received before a StartWaitingForSeek() call to immediately call its
79   // callback without waiting for any data.
80   // |seek_time| - The presentation timestamp for the seek request that
81   // triggered this call. It represents the most recent position the caller is
82   // trying to seek to.
83   void CancelPendingSeek(base::TimeDelta seek_time);
84
85   // Registers a new |id| to use for AppendData() calls. |type| indicates
86   // the MIME type for the data that we intend to append for this ID.
87   // kOk is returned if the demuxer has enough resources to support another ID
88   //    and supports the format indicated by |type|.
89   // kNotSupported is returned if |type| is not a supported format.
90   // kReachedIdLimit is returned if the demuxer cannot handle another ID right
91   //    now.
92   Status AddId(const std::string& id, const std::string& type,
93                std::vector<std::string>& codecs);
94
95   // Removed an ID & associated resources that were previously added with
96   // AddId().
97   void RemoveId(const std::string& id);
98
99   // Gets the currently buffered ranges for the specified ID.
100   Ranges<base::TimeDelta> GetBufferedRanges(const std::string& id) const;
101
102   // Appends media data to the source buffer associated with |id|.
103   void AppendData(const std::string& id, const uint8* data, size_t length);
104
105   // Aborts parsing the current segment and reset the parser to a state where
106   // it can accept a new segment.
107   void Abort(const std::string& id);
108
109   // Remove buffers between |start| and |end| for the source buffer
110   // associated with |id|.
111   void Remove(const std::string& id, base::TimeDelta start,
112               base::TimeDelta end);
113
114   // Returns the current presentation duration.
115   double GetDuration();
116   double GetDuration_Locked();
117
118   // Notifies the demuxer that the duration of the media has changed to
119   // |duration|.
120   void SetDuration(double duration);
121
122   // Sets a time |offset| to be applied to subsequent buffers appended to the
123   // source buffer associated with |id|. Returns true if the offset is set
124   // properly, false if the offset cannot be applied because we're in the
125   // middle of parsing a media segment.
126   bool SetTimestampOffset(const std::string& id, base::TimeDelta offset);
127
128   // Called to signal changes in the "end of stream"
129   // state. UnmarkEndOfStream() must not be called if a matching
130   // MarkEndOfStream() has not come before it.
131   void MarkEndOfStream(PipelineStatus status);
132   void UnmarkEndOfStream();
133
134   // Set the append window start and end values for the source buffer
135   // associated with |id|.
136   void SetAppendWindowStart(const std::string& id, base::TimeDelta start);
137   void SetAppendWindowEnd(const std::string& id, base::TimeDelta end);
138
139   void Shutdown();
140
141   void SetMemoryLimitsForTesting(int memory_limit);
142
143   // Returns the ranges representing the buffered data in the demuxer.
144   // TODO(wolenetz): Remove this method once MediaSourceDelegate no longer
145   // requires it for doing hack browser seeks to I-frame on Android. See
146   // http://crbug.com/304234.
147   Ranges<base::TimeDelta> GetBufferedRanges() const;
148
149  private:
150   enum State {
151     WAITING_FOR_INIT,
152     INITIALIZING,
153     INITIALIZED,
154     ENDED,
155     PARSE_ERROR,
156     SHUTDOWN,
157   };
158
159   void ChangeState_Locked(State new_state);
160
161   // Reports an error and puts the demuxer in a state where it won't accept more
162   // data.
163   void ReportError_Locked(PipelineStatus error);
164
165   // Returns true if any stream has seeked to a time without buffered data.
166   bool IsSeekWaitingForData_Locked() const;
167
168   // Returns true if all streams can successfully call EndOfStream,
169   // false if any can not.
170   bool CanEndOfStream_Locked() const;
171
172   // SourceState callbacks.
173   void OnSourceInitDone(bool success, base::TimeDelta duration);
174
175   // Creates a DemuxerStream for the specified |type|.
176   // Returns a new ChunkDemuxerStream instance if a stream of this type
177   // has not been created before. Returns NULL otherwise.
178   ChunkDemuxerStream* CreateDemuxerStream(DemuxerStream::Type type);
179
180   bool OnTextBuffers(TextTrack* text_track,
181                      const StreamParser::BufferQueue& buffers);
182   void OnNewMediaSegment(const std::string& source_id,
183                          base::TimeDelta start_timestamp);
184
185   // Computes the intersection between the video & audio
186   // buffered ranges.
187   Ranges<base::TimeDelta> ComputeIntersection() const;
188
189   // Applies |time_offset| to the timestamps of |buffers|.
190   void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers,
191                               base::TimeDelta timestamp_offset);
192
193   // Returns true if |source_id| is valid, false otherwise.
194   bool IsValidId(const std::string& source_id) const;
195
196   // Increases |duration_| if |last_appended_buffer_timestamp| exceeds the
197   // current  |duration_|. The |duration_| is set to the end buffered timestamp
198   // of |stream|.
199   void IncreaseDurationIfNecessary(
200       base::TimeDelta last_appended_buffer_timestamp,
201       ChunkDemuxerStream* stream);
202
203   // Decreases |duration_| if the buffered region is less than |duration_| when
204   // EndOfStream() is called.
205   void DecreaseDurationIfNecessary();
206
207   // Sets |duration_| to |new_duration|, sets |user_specified_duration_| to -1
208   // and notifies |host_|.
209   void UpdateDuration(base::TimeDelta new_duration);
210
211   // Returns the ranges representing the buffered data in the demuxer.
212   Ranges<base::TimeDelta> GetBufferedRanges_Locked() const;
213
214   // Start returning data on all DemuxerStreams.
215   void StartReturningData();
216
217   // Aborts pending reads on all DemuxerStreams.
218   void AbortPendingReads();
219
220   // Completes any pending reads if it is possible to do so.
221   void CompletePendingReadsIfPossible();
222
223   // Seeks all SourceBufferStreams to |seek_time|.
224   void SeekAllSources(base::TimeDelta seek_time);
225
226   mutable base::Lock lock_;
227   State state_;
228   bool cancel_next_seek_;
229
230   DemuxerHost* host_;
231   base::Closure open_cb_;
232   NeedKeyCB need_key_cb_;
233   AddTextTrackCB add_text_track_cb_;
234   // Callback used to report error strings that can help the web developer
235   // figure out what is wrong with the content.
236   LogCB log_cb_;
237
238   PipelineStatusCB init_cb_;
239   // Callback to execute upon seek completion.
240   // TODO(wolenetz/acolwell): Protect against possible double-locking by first
241   // releasing |lock_| before executing this callback. See
242   // http://crbug.com/308226
243   PipelineStatusCB seek_cb_;
244
245   scoped_ptr<ChunkDemuxerStream> audio_;
246   scoped_ptr<ChunkDemuxerStream> video_;
247
248   // Keeps |audio_| alive when audio has been disabled.
249   scoped_ptr<ChunkDemuxerStream> disabled_audio_;
250
251   base::TimeDelta duration_;
252
253   // The duration passed to the last SetDuration(). If
254   // SetDuration() is never called or an AppendData() call or
255   // a EndOfStream() call changes |duration_|, then this
256   // variable is set to < 0 to indicate that the |duration_| represents
257   // the actual duration instead of a user specified value.
258   double user_specified_duration_;
259
260   typedef std::map<std::string, SourceState*> SourceStateMap;
261   SourceStateMap source_state_map_;
262
263   // Used to ensure that (1) config data matches the type and codec provided in
264   // AddId(), (2) only 1 audio and 1 video sources are added, and (3) ids may be
265   // removed with RemoveID() but can not be re-added (yet).
266   std::string source_id_audio_;
267   std::string source_id_video_;
268
269   DISALLOW_COPY_AND_ASSIGN(ChunkDemuxer);
270 };
271
272 }  // namespace media
273
274 #endif  // MEDIA_FILTERS_CHUNK_DEMUXER_H_