OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // Implements a Demuxer that can switch among different data sources mid-stream. | 5 // Implements a Demuxer that can switch among different data sources mid-stream. |
6 // Uses FFmpegDemuxer under the covers, so see the caveats at the top of | 6 // Uses FFmpegDemuxer under the covers, so see the caveats at the top of |
7 // ffmpeg_demuxer.h. | 7 // ffmpeg_demuxer.h. |
8 | 8 |
9 #ifndef MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ | 9 #ifndef MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ |
10 #define MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ | 10 #define MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ |
11 | 11 |
12 #include <deque> | 12 #include <deque> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/callback.h" | 15 #include "base/callback.h" |
16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
17 #include "media/base/buffers.h" | 17 #include "media/base/buffers.h" |
18 #include "media/base/filter_factories.h" | 18 #include "media/base/filter_factories.h" |
19 #include "media/base/filters.h" | 19 #include "media/base/filters.h" |
20 #include "media/base/pipeline.h" | 20 #include "media/base/pipeline.h" |
21 #include "media/base/media_format.h" | 21 #include "media/base/media_format.h" |
22 | 22 |
23 namespace media { | 23 namespace media { |
24 | 24 |
25 class AdaptiveDemuxer; | 25 class AdaptiveDemuxer; |
26 class StreamSwitchManager; | |
26 | 27 |
27 class AdaptiveDemuxerStream : public DemuxerStream { | 28 class AdaptiveDemuxerStream : public DemuxerStream { |
28 public: | 29 public: |
29 typedef std::vector<scoped_refptr<DemuxerStream> > StreamVector; | 30 typedef std::vector<scoped_refptr<DemuxerStream> > StreamVector; |
31 typedef std::deque<ReadCallback> ReadCBQueue; | |
32 | |
33 // Typedefs used by the stream switching code to seek a stream to a desired | |
34 // location. The AdaptiveDemuxer constructs a SeekFunction for the stream | |
35 // being switched to and passes this function to | |
36 // AdaptiveDemuxerStream::ChangeCurrentStream(). | |
Ami GONE FROM CHROMIUM
2011/05/24 06:14:12
Add a pointer to the ascii art below?
acolwell GONE FROM CHROMIUM
2011/05/24 23:45:16
Done.
| |
37 // | |
38 // Callback for SeekFunction. The PipelineStatus parameter indicates whether | |
39 // the seek was successful or not. The base::TimeDelta parameter indicates the | |
40 // time we actually seeked to. If the seek was successful this should be >= | |
41 // than the requested time. | |
42 typedef base::Callback<void(PipelineStatus, base::TimeDelta)> SeekFunctionCB; | |
43 | |
44 // Wraps a function that performs a seek on a specified stream. The | |
45 // base::TimeDelta parameter indicates what time to seek to. The | |
46 // SeekFunctionCBparameter specifies the callback we want called when the seek | |
47 // completes. | |
48 typedef base::Callback<void(base::TimeDelta, SeekFunctionCB)> SeekFunction; | |
30 | 49 |
31 // Keeps references to the passed-in streams. |streams| must be non-empty and | 50 // Keeps references to the passed-in streams. |streams| must be non-empty and |
32 // all the streams in it must agree on type and media_format (or be NULL). | 51 // all the streams in it must agree on type and media_format (or be NULL). |
33 // |initial_stream| must be a valid index into |streams| and specifies the | 52 // |initial_stream| must be a valid index into |streams| and specifies the |
34 // current stream on construction. | 53 // current stream on construction. |
35 AdaptiveDemuxerStream(StreamVector const& streams, int initial_stream); | 54 AdaptiveDemuxerStream(StreamVector const& streams, int initial_stream); |
36 virtual ~AdaptiveDemuxerStream(); | 55 virtual ~AdaptiveDemuxerStream(); |
37 | 56 |
57 // Notifies this stream that a Seek() was requested on the demuxer. | |
58 void OnAdaptiveDemuxerSeek(); | |
59 | |
38 // Change the stream to satisfy subsequent Read() requests from. The | 60 // Change the stream to satisfy subsequent Read() requests from. The |
39 // referenced pointer must not be NULL. | 61 // referenced pointer must not be NULL. The SeekFunction parameter |
40 void ChangeCurrentStream(int index); | 62 // provides a way to seek |streams_[index]| to a specific time. |
63 void ChangeCurrentStream(int index, const SeekFunction& seek_function, | |
64 const PipelineStatusCB& cb); | |
41 | 65 |
42 // DemuxerStream methods. | 66 // DemuxerStream methods. |
43 virtual void Read(const ReadCallback& read_callback); | 67 virtual void Read(const ReadCallback& read_callback); |
44 virtual Type type(); | 68 virtual Type type(); |
45 virtual const MediaFormat& media_format(); | 69 virtual const MediaFormat& media_format(); |
46 virtual void EnableBitstreamConverter(); | 70 virtual void EnableBitstreamConverter(); |
47 virtual AVStream* GetAVStream(); | 71 virtual AVStream* GetAVStream(); |
48 | 72 |
49 private: | 73 private: |
50 // Returns a pointer to the current stream. | 74 // Returns a pointer to the current stream. |
51 DemuxerStream* current_stream(); | 75 DemuxerStream* current_stream(); |
52 | 76 |
53 // DEBUG_MODE-only CHECK that the data members are in a reasonable state. | 77 // DEBUG_MODE-only CHECK that the data members are in a reasonable state. |
54 void DCheckSanity(); | 78 void DCheckSanity(); |
55 | 79 |
80 void OnReadDone(Buffer* buffer); | |
81 | |
82 bool IsSwitchPending_Locked() const; | |
83 bool CanStartSwitch_Locked() const; | |
84 | |
85 // Starts the stream switch. This method expects that no Read()s are | |
86 // outstanding on |streams_[current_stream_index_]|. | |
87 void StartSwitch(); | |
88 | |
89 // Called by the SeekFunction when it has completed the seek on | |
90 // |streams_[switch_index_]|. | |
91 void OnSwitchSeekDone(PipelineStatus status, | |
92 base::TimeDelta seek_time); | |
93 | |
56 StreamVector streams_; | 94 StreamVector streams_; |
57 // Guards the members below. Only held for simple variable reads/writes, not | 95 // Guards the members below. Only held for simple variable reads/writes, not |
58 // during async operation. | 96 // during async operation. |
59 base::Lock lock_; | 97 base::Lock lock_; |
60 int current_stream_index_; | 98 int current_stream_index_; |
61 bool bitstream_converter_enabled_; | 99 bool bitstream_converter_enabled_; |
62 | 100 |
101 // The number of outstanding Read()'s on |streams_[current_stream_index_]|. | |
102 int pending_reads_; | |
103 | |
104 // A queue of callback objects passed to Read(). | |
105 ReadCBQueue read_cb_queue_; | |
106 | |
107 // Callback passed to ChangeCurrentStream(). This is called & reset when the | |
108 // stream switch has completed. Callback object is null when a stream switch | |
109 // is not in progress. | |
110 PipelineStatusCB switch_cb_; | |
111 | |
112 // The index of the stream we are switching to. During a stream switch | |
113 // 0 <= |switch_index_| < |streams_.size()| and | |
114 // |streams_[switch_index]| MUST NOT be null. |switch_index_| is set to -1 if | |
115 // a stream switch is not in progress. | |
116 int switch_index_; | |
117 | |
118 // Function used to seek |streams_[switch_index_]| to a specific time. The | |
119 // callback is null if a switch is not pending. | |
120 SeekFunction switch_seek_function_; | |
121 | |
122 // The timestamp of the last buffer returned via a Read() callback. | |
123 base::TimeDelta last_buffer_timestamp_; | |
124 | |
63 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerStream); | 125 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerStream); |
64 }; | 126 }; |
65 | 127 |
66 class AdaptiveDemuxer : public Demuxer { | 128 class AdaptiveDemuxer : public Demuxer { |
67 public: | 129 public: |
68 typedef std::vector<scoped_refptr<Demuxer> > DemuxerVector; | 130 typedef std::vector<scoped_refptr<Demuxer> > DemuxerVector; |
131 typedef std::vector<int> StreamIdVector; | |
69 | 132 |
70 // |demuxers| must be non-empty, and the index arguments must be valid indexes | 133 // |demuxers| must be non-empty, and the index arguments must be valid indexes |
71 // into |demuxers|, or -1 to indicate no demuxer is serving that type. | 134 // into |demuxers|, or -1 to indicate no demuxer is serving that type. |
72 AdaptiveDemuxer(DemuxerVector const& demuxers, | 135 AdaptiveDemuxer(DemuxerVector const& demuxers, |
73 int initial_audio_demuxer_index, | 136 int initial_audio_demuxer_index, |
74 int initial_video_demuxer_index); | 137 int initial_video_demuxer_index); |
75 virtual ~AdaptiveDemuxer(); | 138 virtual ~AdaptiveDemuxer(); |
76 | 139 |
77 // Change which demuxers the streams will use. | 140 // Change to a different video stream. |
78 void ChangeCurrentDemuxer(int audio_index, int video_index); | 141 void ChangeVideoStream(int video_id, const PipelineStatusCB& done_cb); |
142 | |
143 // Get the ID of the current video stream. | |
144 int GetCurrentVideoId() const; | |
145 | |
146 // Get all of the video stream IDs. | |
147 StreamIdVector GetVideoIds() const; | |
79 | 148 |
80 // Filter implementation. | 149 // Filter implementation. |
81 virtual void Stop(FilterCallback* callback); | 150 virtual void Stop(FilterCallback* callback); |
82 virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb); | 151 virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb); |
83 virtual void OnAudioRendererDisabled(); | 152 virtual void OnAudioRendererDisabled(); |
84 virtual void set_host(FilterHost* filter_host); | 153 virtual void set_host(FilterHost* filter_host); |
85 virtual void SetPlaybackRate(float playback_rate); | 154 virtual void SetPlaybackRate(float playback_rate); |
86 virtual void SetPreload(Preload preload); | 155 virtual void SetPreload(Preload preload); |
87 | 156 |
88 // Demuxer implementation. | 157 // Demuxer implementation. |
89 virtual scoped_refptr<DemuxerStream> GetStream(DemuxerStream::Type type); | 158 virtual scoped_refptr<DemuxerStream> GetStream(DemuxerStream::Type type); |
90 | 159 |
91 private: | 160 private: |
92 // Returns a pointer to the currently active demuxer of the given type. | 161 // Returns a pointer to the currently active demuxer of the given type. |
93 Demuxer* current_demuxer(DemuxerStream::Type type); | 162 Demuxer* current_demuxer(DemuxerStream::Type type); |
94 | 163 |
164 // Called when the AdaptiveDemuxerStream completes a stream switch. | |
165 void ChangeVideoStreamDone(int new_stream_index, | |
166 const PipelineStatusCB& done_cb, | |
167 PipelineStatus status); | |
168 | |
169 // Methods for SeekFunction. | |
170 // | |
171 // Seeking on a stream follows the flow below. | |
172 // | |
173 // SeekFunction.Run() -> StartStreamSwitchSeek() | |
174 // | | |
175 // \|/ | |
176 // +--------------+ | |
177 // | Found Switch | | |
178 // | Point in | No (Seeking to get more index data.) | |
179 // | Index Data? |---> |demuxers_[stream_index]->Seek()| | |
180 // +--------------+ | | |
181 // |Yes \|/ | |
182 // | OnIndexSeekDone() | |
183 // | | | |
184 // \|/ \|/ | |
185 // (Seeking stream to switch point.) Yes +--------------+ | |
186 // |demuxers_[stream_index]->Seek()| <------| Found Switch | | |
187 // | | Point in | | |
188 // | | Index Data? | | |
189 // | +--------------+ | |
190 // | | No | |
191 // \|/ \|/ | |
192 // OnStreamSeekDone() seek_cb(ERROR) | |
193 // | | |
194 // \|/ | |
195 // seek_cb(OK | ERROR) | |
196 // | |
197 // When AdaptiveDemuxer creates a SeekFunction object it points to this | |
198 // method. | |
199 void StartStreamSwitchSeek( | |
200 DemuxerStream::Type type, | |
201 int stream_index, | |
202 base::TimeDelta seek_time, | |
203 const AdaptiveDemuxerStream::SeekFunctionCB& seek_cb); | |
204 | |
205 // Called when the seek for index data initiated by StartStreamSwitchSeek() | |
206 // completes. | |
207 void OnIndexSeekDone(DemuxerStream::Type type, | |
208 int stream_index, | |
209 base::TimeDelta seek_time, | |
210 const AdaptiveDemuxerStream::SeekFunctionCB& seek_cb, | |
211 PipelineStatus status); | |
212 | |
213 // Called when the stream seek initiated by StartStreamSwitchSeek() or | |
214 // OnIndexSeekDone() completes. | |
215 void OnStreamSeekDone(base::TimeDelta seek_point, | |
216 const AdaptiveDemuxerStream::SeekFunctionCB& seek_cb, | |
217 PipelineStatus status); | |
218 | |
95 DemuxerVector demuxers_; | 219 DemuxerVector demuxers_; |
96 scoped_refptr<AdaptiveDemuxerStream> audio_stream_; | 220 scoped_refptr<AdaptiveDemuxerStream> audio_stream_; |
97 scoped_refptr<AdaptiveDemuxerStream> video_stream_; | 221 scoped_refptr<AdaptiveDemuxerStream> video_stream_; |
98 // Guards the members below. Only held for simple variable reads/writes, not | 222 // Guards the members below. Only held for simple variable reads/writes, not |
99 // during async operation. | 223 // during async operation. |
100 base::Lock lock_; | 224 mutable base::Lock lock_; |
101 int current_audio_demuxer_index_; | 225 int current_audio_demuxer_index_; |
102 int current_video_demuxer_index_; | 226 int current_video_demuxer_index_; |
227 float playback_rate_; | |
228 bool switch_pending_; | |
229 scoped_refptr<StreamSwitchManager> stream_switch_manager_; | |
103 | 230 |
104 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxer); | 231 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxer); |
105 }; | 232 }; |
106 | 233 |
107 // AdaptiveDemuxerFactory wraps an underlying DemuxerFactory that knows how to | 234 // AdaptiveDemuxerFactory wraps an underlying DemuxerFactory that knows how to |
108 // build demuxers for a single URL, and implements a primitive (for now) version | 235 // build demuxers for a single URL, and implements a primitive (for now) version |
109 // of multi-file manifests. The manifest is encoded in the |url| parameter to | 236 // of multi-file manifests. The manifest is encoded in the |url| parameter to |
110 // Build() as: | 237 // Build() as: |
111 // x-adaptive:<initial_audio_index>:<initial_video_index>:<URL>[^<URL>]* where | 238 // x-adaptive:<initial_audio_index>:<initial_video_index>:<URL>[^<URL>]* where |
112 // <URL>'s are "real" media URLs which are passed to the underlying | 239 // <URL>'s are "real" media URLs which are passed to the underlying |
(...skipping 14 matching lines...) Expand all Loading... | |
127 | 254 |
128 private: | 255 private: |
129 scoped_ptr<DemuxerFactory> delegate_factory_; | 256 scoped_ptr<DemuxerFactory> delegate_factory_; |
130 | 257 |
131 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerFactory); | 258 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerFactory); |
132 }; | 259 }; |
133 | 260 |
134 } // namespace media | 261 } // namespace media |
135 | 262 |
136 #endif // MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ | 263 #endif // MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ |
OLD | NEW |