Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: media/filters/adaptive_demuxer.h

Issue 7044008: Initial implementation of stream switching in AdaptiveDemuxer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix TODOs Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698