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

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: Addressing final CR concerns and fixing Lint errors. 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
« no previous file with comments | « media/base/pipeline_status.h ('k') | media/filters/adaptive_demuxer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(). For more information about
37 // how the SeekFunction is implemented, look at the comments for
38 // AdaptiveDemuxer::StartStreamSwitchSeek() below.
39 //
40 // Callback for SeekFunction. The PipelineStatus parameter indicates whether
41 // the seek was successful or not. The base::TimeDelta parameter indicates the
42 // time we actually seeked to. If the seek was successful this should be >=
43 // than the requested time.
44 typedef base::Callback<void(base::TimeDelta, PipelineStatus)> SeekFunctionCB;
45
46 // Wraps a function that performs a seek on a specified stream. The
47 // base::TimeDelta parameter indicates what time to seek to. The
48 // SeekFunctionCBparameter specifies the callback we want called when the seek
49 // completes.
50 typedef base::Callback<void(base::TimeDelta, SeekFunctionCB)> SeekFunction;
30 51
31 // Keeps references to the passed-in streams. |streams| must be non-empty and 52 // 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). 53 // 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 54 // |initial_stream| must be a valid index into |streams| and specifies the
34 // current stream on construction. 55 // current stream on construction.
35 AdaptiveDemuxerStream(StreamVector const& streams, int initial_stream); 56 AdaptiveDemuxerStream(StreamVector const& streams, int initial_stream);
36 virtual ~AdaptiveDemuxerStream(); 57 virtual ~AdaptiveDemuxerStream();
37 58
59 // Notifies this stream that a Seek() was requested on the demuxer.
60 void OnAdaptiveDemuxerSeek(base::TimeDelta seek_time);
61
38 // Change the stream to satisfy subsequent Read() requests from. The 62 // Change the stream to satisfy subsequent Read() requests from. The
39 // referenced pointer must not be NULL. 63 // referenced pointer must not be NULL. The SeekFunction parameter
40 void ChangeCurrentStream(int index); 64 // provides a way to seek |streams_[index]| to a specific time.
65 void ChangeCurrentStream(int index, const SeekFunction& seek_function,
66 const PipelineStatusCB& cb);
41 67
42 // DemuxerStream methods. 68 // DemuxerStream methods.
43 virtual void Read(const ReadCallback& read_callback); 69 virtual void Read(const ReadCallback& read_callback);
44 virtual Type type(); 70 virtual Type type();
45 virtual const MediaFormat& media_format(); 71 virtual const MediaFormat& media_format();
46 virtual void EnableBitstreamConverter(); 72 virtual void EnableBitstreamConverter();
47 virtual AVStream* GetAVStream(); 73 virtual AVStream* GetAVStream();
48 74
49 private: 75 private:
50 // Returns a pointer to the current stream. 76 // Returns a pointer to the current stream.
51 DemuxerStream* current_stream(); 77 DemuxerStream* current_stream();
52 78
53 // DEBUG_MODE-only CHECK that the data members are in a reasonable state. 79 // DEBUG_MODE-only CHECK that the data members are in a reasonable state.
54 void DCheckSanity(); 80 void DCheckSanity();
55 81
82 void OnReadDone(Buffer* buffer);
83
84 bool IsSwitchPending_Locked() const;
85 bool CanStartSwitch_Locked() const;
86
87 // Starts the stream switch. This method expects that no Read()s are
88 // outstanding on |streams_[current_stream_index_]|.
89 void StartSwitch();
90
91 // Called by the SeekFunction when it has completed the seek on
92 // |streams_[switch_index_]|.
93 void OnSwitchSeekDone(base::TimeDelta seek_time, PipelineStatus status);
94
56 StreamVector streams_; 95 StreamVector streams_;
57 // Guards the members below. Only held for simple variable reads/writes, not 96 // Guards the members below. Only held for simple variable reads/writes, not
58 // during async operation. 97 // during async operation.
59 base::Lock lock_; 98 base::Lock lock_;
60 int current_stream_index_; 99 int current_stream_index_;
61 bool bitstream_converter_enabled_; 100 bool bitstream_converter_enabled_;
62 101
102 // The number of outstanding Read()'s on |streams_[current_stream_index_]|.
103 int pending_reads_;
104
105 // A queue of callback objects passed to Read().
106 ReadCBQueue read_cb_queue_;
107
108 // Callback passed to ChangeCurrentStream(). This is called & reset when the
109 // stream switch has completed. Callback object is null when a stream switch
110 // is not in progress.
111 PipelineStatusCB switch_cb_;
112
113 // The index of the stream we are switching to. During a stream switch
114 // 0 <= |switch_index_| < |streams_.size()| and
115 // |streams_[switch_index]| MUST NOT be null. |switch_index_| is set to -1 if
116 // a stream switch is not in progress.
117 int switch_index_;
118
119 // Function used to seek |streams_[switch_index_]| to a specific time. The
120 // callback is null if a switch is not pending.
121 SeekFunction switch_seek_function_;
122
123 // The timestamp of the last buffer returned via a Read() callback.
124 base::TimeDelta last_buffer_timestamp_;
125
63 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerStream); 126 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerStream);
64 }; 127 };
65 128
66 class AdaptiveDemuxer : public Demuxer { 129 class AdaptiveDemuxer : public Demuxer {
67 public: 130 public:
68 typedef std::vector<scoped_refptr<Demuxer> > DemuxerVector; 131 typedef std::vector<scoped_refptr<Demuxer> > DemuxerVector;
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;
79 145
80 // Filter implementation. 146 // Filter implementation.
81 virtual void Stop(FilterCallback* callback); 147 virtual void Stop(FilterCallback* callback);
82 virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb); 148 virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb);
83 virtual void OnAudioRendererDisabled(); 149 virtual void OnAudioRendererDisabled();
84 virtual void set_host(FilterHost* filter_host); 150 virtual void set_host(FilterHost* filter_host);
85 virtual void SetPlaybackRate(float playback_rate); 151 virtual void SetPlaybackRate(float playback_rate);
86 virtual void SetPreload(Preload preload); 152 virtual void SetPreload(Preload preload);
87 153
88 // Demuxer implementation. 154 // Demuxer implementation.
89 virtual scoped_refptr<DemuxerStream> GetStream(DemuxerStream::Type type); 155 virtual scoped_refptr<DemuxerStream> GetStream(DemuxerStream::Type type);
90 156
91 private: 157 private:
92 // Returns a pointer to the currently active demuxer of the given type. 158 // Returns a pointer to the currently active demuxer of the given type.
93 Demuxer* current_demuxer(DemuxerStream::Type type); 159 Demuxer* current_demuxer(DemuxerStream::Type type);
94 160
161 // Called when the AdaptiveDemuxerStream completes a stream switch.
162 void ChangeVideoStreamDone(int new_stream_index,
163 const PipelineStatusCB& done_cb,
164 PipelineStatus status);
165
166 // Methods for SeekFunction.
167 //
168 // Seeking on a stream follows the flow below.
169 //
170 // SeekFunction.Run() -> StartStreamSwitchSeek()
171 // |
172 // V
173 // +--------------+
174 // | Found Switch |
175 // | Point in | No (Seeking to get more index data.)
176 // | Index Data? |---> |demuxers_[stream_index]->Seek()|
177 // +--------------+ |
178 // |Yes V
179 // | OnIndexSeekDone()
180 // | |
181 // V V
182 // (Seeking stream to switch point.) Yes +--------------+
183 // |demuxers_[stream_index]->Seek()| <------| Found Switch |
184 // | | Point in |
185 // | | Index Data? |
186 // | +--------------+
187 // | | No
188 // V V
189 // OnStreamSeekDone() seek_cb(ERROR)
190 // |
191 // V
192 // seek_cb(OK | ERROR)
193 //
194 // When AdaptiveDemuxer creates a SeekFunction object it points to this
195 // method.
196 void StartStreamSwitchSeek(
197 DemuxerStream::Type type,
198 int stream_index,
199 base::TimeDelta seek_time,
200 const AdaptiveDemuxerStream::SeekFunctionCB& seek_cb);
201
202 // Called when the seek for index data initiated by StartStreamSwitchSeek()
203 // completes.
204 void OnIndexSeekDone(DemuxerStream::Type type,
205 int stream_index,
206 base::TimeDelta seek_time,
207 const AdaptiveDemuxerStream::SeekFunctionCB& seek_cb,
208 PipelineStatus status);
209
210 // Called when the stream seek initiated by StartStreamSwitchSeek() or
211 // OnIndexSeekDone() completes.
212 static void OnStreamSeekDone(
213 const AdaptiveDemuxerStream::SeekFunctionCB& seek_cb,
214 base::TimeDelta seek_point,
215 PipelineStatus status);
216
95 DemuxerVector demuxers_; 217 DemuxerVector demuxers_;
96 scoped_refptr<AdaptiveDemuxerStream> audio_stream_; 218 scoped_refptr<AdaptiveDemuxerStream> audio_stream_;
97 scoped_refptr<AdaptiveDemuxerStream> video_stream_; 219 scoped_refptr<AdaptiveDemuxerStream> video_stream_;
98 // Guards the members below. Only held for simple variable reads/writes, not 220 // Guards the members below. Only held for simple variable reads/writes, not
99 // during async operation. 221 // during async operation.
100 base::Lock lock_; 222 mutable base::Lock lock_;
101 int current_audio_demuxer_index_; 223 int current_audio_demuxer_index_;
102 int current_video_demuxer_index_; 224 int current_video_demuxer_index_;
225 float playback_rate_;
226 bool switch_pending_;
227 scoped_refptr<StreamSwitchManager> stream_switch_manager_;
103 228
104 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxer); 229 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxer);
105 }; 230 };
106 231
107 // AdaptiveDemuxerFactory wraps an underlying DemuxerFactory that knows how to 232 // AdaptiveDemuxerFactory wraps an underlying DemuxerFactory that knows how to
108 // build demuxers for a single URL, and implements a primitive (for now) version 233 // 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 234 // of multi-file manifests. The manifest is encoded in the |url| parameter to
110 // Build() as: 235 // Build() as:
111 // x-adaptive:<initial_audio_index>:<initial_video_index>:<URL>[^<URL>]* where 236 // x-adaptive:<initial_audio_index>:<initial_video_index>:<URL>[^<URL>]* where
112 // <URL>'s are "real" media URLs which are passed to the underlying 237 // <URL>'s are "real" media URLs which are passed to the underlying
(...skipping 14 matching lines...) Expand all
127 252
128 private: 253 private:
129 scoped_ptr<DemuxerFactory> delegate_factory_; 254 scoped_ptr<DemuxerFactory> delegate_factory_;
130 255
131 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerFactory); 256 DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveDemuxerFactory);
132 }; 257 };
133 258
134 } // namespace media 259 } // namespace media
135 260
136 #endif // MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_ 261 #endif // MEDIA_FILTERS_ADAPTIVE_DEMUXER_H_
OLDNEW
« no previous file with comments | « media/base/pipeline_status.h ('k') | media/filters/adaptive_demuxer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698