| 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(). 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 Loading... |
| 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_ |
| OLD | NEW |