chunk_demuxer.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/filters/source_buffer_stream.h" 19 20namespace media { 21 22class ChunkDemuxerStream; 23class FFmpegURLProtocol; 24class SourceState; 25 26// Demuxer implementation that allows chunks of media data to be passed 27// from JavaScript to the media stack. 28class MEDIA_EXPORT ChunkDemuxer : public Demuxer { 29 public: 30 enum Status { 31 kOk, // ID added w/o error. 32 kNotSupported, // Type specified is not supported. 33 kReachedIdLimit, // Reached ID limit. We can't handle any more IDs. 34 }; 35 36 typedef base::Callback<void(const std::string& type, 37 scoped_ptr<uint8[]> init_data, 38 int init_data_size)> NeedKeyCB; 39 40 // |open_cb| Run when Initialize() is called to signal that the demuxer 41 // is ready to receive media data via AppenData(). 42 // |need_key_cb| Run when the demuxer determines that an encryption key is 43 // needed to decrypt the content. 44 // |log_cb| Run when parsing error messages need to be logged to the error 45 // console. 46 ChunkDemuxer(const base::Closure& open_cb, const NeedKeyCB& need_key_cb, 47 const LogCB& log_cb); 48 virtual ~ChunkDemuxer(); 49 50 // Demuxer implementation. 51 virtual void Initialize(DemuxerHost* host, 52 const PipelineStatusCB& cb) OVERRIDE; 53 virtual void Stop(const base::Closure& callback) OVERRIDE; 54 virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE; 55 virtual void OnAudioRendererDisabled() OVERRIDE; 56 virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE; 57 virtual base::TimeDelta GetStartTime() const OVERRIDE; 58 59 // Methods used by an external object to control this demuxer. 60 void StartWaitingForSeek(); 61 void CancelPendingSeek(); 62 63 // Registers a new |id| to use for AppendData() calls. |type| indicates 64 // the MIME type for the data that we intend to append for this ID. 65 // kOk is returned if the demuxer has enough resources to support another ID 66 // and supports the format indicated by |type|. 67 // kNotSupported is returned if |type| is not a supported format. 68 // kReachedIdLimit is returned if the demuxer cannot handle another ID right 69 // now. 70 Status AddId(const std::string& id, const std::string& type, 71 std::vector<std::string>& codecs); 72 73 // Removed an ID & associated resources that were previously added with 74 // AddId(). 75 void RemoveId(const std::string& id); 76 77 // Gets the currently buffered ranges for the specified ID. 78 Ranges<base::TimeDelta> GetBufferedRanges(const std::string& id) const; 79 80 // Appends media data to the source buffer associated with |id|. 81 void AppendData(const std::string& id, const uint8* data, size_t length); 82 83 // Aborts parsing the current segment and reset the parser to a state where 84 // it can accept a new segment. 85 void Abort(const std::string& id); 86 87 // Returns the current presentation duration. 88 double GetDuration(); 89 double GetDuration_Locked(); 90 91 // Notifies the demuxer that the duration of the media has changed to 92 // |duration|. 93 void SetDuration(double duration); 94 95 // Sets a time |offset| to be applied to subsequent buffers appended to the 96 // source buffer assicated with |id|. Returns true if the offset is set 97 // properly, false if the offset cannot be applied because we're in the 98 // middle of parsing a media segment. 99 bool SetTimestampOffset(const std::string& id, base::TimeDelta offset); 100 101 // Signals an EndOfStream request. 102 // Returns false if called in an unexpected state or if there is a gap between 103 // the current position and the end of the buffered data. 104 bool EndOfStream(PipelineStatus status); 105 void Shutdown(); 106 107 private: 108 enum State { 109 WAITING_FOR_INIT, 110 INITIALIZING, 111 INITIALIZED, 112 ENDED, 113 PARSE_ERROR, 114 SHUTDOWN, 115 }; 116 117 void ChangeState_Locked(State new_state); 118 119 // Reports an error and puts the demuxer in a state where it won't accept more 120 // data. 121 void ReportError_Locked(PipelineStatus error); 122 123 // Returns true if any stream has seeked to a time without buffered data. 124 bool IsSeekPending_Locked() const; 125 126 // Returns true if all streams can successfully call EndOfStream, 127 // false if any can not. 128 bool CanEndOfStream_Locked() const; 129 130 // SourceState callbacks. 131 void OnSourceInitDone(bool success, base::TimeDelta duration); 132 bool OnNewConfigs(bool has_audio, bool has_video, 133 const AudioDecoderConfig& audio_config, 134 const VideoDecoderConfig& video_config); 135 bool OnAudioBuffers(const StreamParser::BufferQueue& buffers); 136 bool OnVideoBuffers(const StreamParser::BufferQueue& buffers); 137 bool OnNeedKey(const std::string& type, 138 scoped_ptr<uint8[]> init_data, 139 int init_data_size); 140 void OnNewMediaSegment(const std::string& source_id, 141 base::TimeDelta start_timestamp); 142 143 // Computes the intersection between the video & audio 144 // buffered ranges. 145 Ranges<base::TimeDelta> ComputeIntersection() const; 146 147 // Applies |time_offset| to the timestamps of |buffers|. 148 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers, 149 base::TimeDelta timestamp_offset); 150 151 // Returns true if |source_id| is valid, false otherwise. 152 bool IsValidId(const std::string& source_id) const; 153 154 // Increases |duration_| if the newly appended |buffers| exceed the current 155 // |duration_|. The |duration_| is set to the end buffered timestamp of 156 // |stream|. 157 void IncreaseDurationIfNecessary( 158 const StreamParser::BufferQueue& buffers, 159 ChunkDemuxerStream* stream); 160 161 // Decreases |duration_| if the buffered region is less than |duration_| when 162 // EndOfStream() is called. 163 void DecreaseDurationIfNecessary(); 164 165 // Sets |duration_| to |new_duration|, sets |user_specified_duration_| to -1 166 // and notifies |host_|. 167 void UpdateDuration(base::TimeDelta new_duration); 168 169 // Returns the ranges representing the buffered data in the demuxer. 170 Ranges<base::TimeDelta> GetBufferedRanges() const; 171 172 mutable base::Lock lock_; 173 State state_; 174 175 DemuxerHost* host_; 176 base::Closure open_cb_; 177 NeedKeyCB need_key_cb_; 178 // Callback used to report error strings that can help the web developer 179 // figure out what is wrong with the content. 180 LogCB log_cb_; 181 182 PipelineStatusCB init_cb_; 183 PipelineStatusCB seek_cb_; 184 185 scoped_ptr<ChunkDemuxerStream> audio_; 186 scoped_ptr<ChunkDemuxerStream> video_; 187 188 // Keeps |audio_| alive when audio has been disabled. 189 scoped_ptr<ChunkDemuxerStream> disabled_audio_; 190 191 base::TimeDelta duration_; 192 193 // The duration passed to the last SetDuration(). If 194 // SetDuration() is never called or an AppendData() call or 195 // a EndOfStream() call changes |duration_|, then this 196 // variable is set to < 0 to indicate that the |duration_| represents 197 // the actual duration instead of a user specified value. 198 double user_specified_duration_; 199 200 typedef std::map<std::string, SourceState*> SourceStateMap; 201 SourceStateMap source_state_map_; 202 203 // Used to ensure that (1) config data matches the type and codec provided in 204 // AddId(), (2) only 1 audio and 1 video sources are added, and (3) ids may be 205 // removed with RemoveID() but can not be re-added (yet). 206 std::string source_id_audio_; 207 std::string source_id_video_; 208 209 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxer); 210}; 211 212} // namespace media 213 214#endif // MEDIA_FILTERS_CHUNK_DEMUXER_H_ 215