OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "media/filters/chunk_demuxer.h" | 5 #include "media/filters/chunk_demuxer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 30 matching lines...) Expand all Loading... |
41 // Returns true if the data was successfully appended. Returns false if an | 41 // Returns true if the data was successfully appended. Returns false if an |
42 // error occurred. | 42 // error occurred. |
43 bool Append(const uint8* data, size_t length); | 43 bool Append(const uint8* data, size_t length); |
44 | 44 |
45 // Aborts the current append sequence and resets the parser. | 45 // Aborts the current append sequence and resets the parser. |
46 void Abort(); | 46 void Abort(); |
47 | 47 |
48 // Sets |timestamp_offset_| if possible. | 48 // Sets |timestamp_offset_| if possible. |
49 // Returns if the offset was set. Returns false if the offset could not be | 49 // Returns if the offset was set. Returns false if the offset could not be |
50 // updated at this time. | 50 // updated at this time. |
51 bool SetTimestampOffset(TimeDelta timestamp_offset); | 51 bool set_timestampOffset(TimeDelta timestamp_offset); |
52 | 52 |
53 TimeDelta timestamp_offset() const { return timestamp_offset_; } | 53 TimeDelta timestamp_offset() const { return timestamp_offset_; } |
54 | 54 |
55 private: | 55 private: |
56 // Called by the |stream_parser_| at the beginning of a new media segment. | 56 // Called by the |stream_parser_| at the beginning of a new media segment. |
57 // |timestamp| is the timestamp on the first buffer in the segment. | 57 // |timestamp| is the timestamp on the first buffer in the segment. |
58 // It modifies the state of this object and then calls |new_segment_cb| with | 58 // It modifies the state of this object and then calls |new_segment_cb| with |
59 // modified version of |timestamp|. | 59 // modified version of |timestamp|. |
60 void OnNewMediaSegment(const StreamParser::NewMediaSegmentCB& new_segment_cb, | 60 void OnNewMediaSegment(const StreamParser::NewMediaSegmentCB& new_segment_cb, |
61 TimeDelta timestamp); | 61 TimeDelta timestamp); |
(...skipping 27 matching lines...) Expand all Loading... |
89 // Keeps track of whether |timestamp_offset_| can be modified. | 89 // Keeps track of whether |timestamp_offset_| can be modified. |
90 bool can_update_offset_; | 90 bool can_update_offset_; |
91 | 91 |
92 // The object used to parse appended data. | 92 // The object used to parse appended data. |
93 scoped_ptr<StreamParser> stream_parser_; | 93 scoped_ptr<StreamParser> stream_parser_; |
94 | 94 |
95 DISALLOW_COPY_AND_ASSIGN(SourceState); | 95 DISALLOW_COPY_AND_ASSIGN(SourceState); |
96 }; | 96 }; |
97 | 97 |
98 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser) | 98 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser) |
99 : can_update_offset_(true), | 99 : can_update_offset_(true), stream_parser_(stream_parser.release()) {} |
100 stream_parser_(stream_parser.release()) { | |
101 } | |
102 | 100 |
103 void SourceState::Init(const StreamParser::InitCB& init_cb, | 101 void SourceState::Init(const StreamParser::InitCB& init_cb, |
104 const StreamParser::NewConfigCB& config_cb, | 102 const StreamParser::NewConfigCB& config_cb, |
105 const StreamParser::NewBuffersCB& audio_cb, | 103 const StreamParser::NewBuffersCB& audio_cb, |
106 const StreamParser::NewBuffersCB& video_cb, | 104 const StreamParser::NewBuffersCB& video_cb, |
107 const StreamParser::NewTextBuffersCB& text_cb, | 105 const StreamParser::NewTextBuffersCB& text_cb, |
108 const StreamParser::NeedKeyCB& need_key_cb, | 106 const StreamParser::NeedKeyCB& need_key_cb, |
109 const AddTextTrackCB& add_text_track_cb, | 107 const AddTextTrackCB& add_text_track_cb, |
110 const StreamParser::NewMediaSegmentCB& new_segment_cb, | 108 const StreamParser::NewMediaSegmentCB& new_segment_cb, |
111 const LogCB& log_cb) { | 109 const LogCB& log_cb) { |
112 stream_parser_->Init(init_cb, config_cb, | 110 stream_parser_->Init( |
113 base::Bind(&SourceState::OnBuffers, | 111 init_cb, config_cb, |
114 base::Unretained(this), audio_cb), | 112 base::Bind(&SourceState::OnBuffers, base::Unretained(this), audio_cb), |
115 base::Bind(&SourceState::OnBuffers, | 113 base::Bind(&SourceState::OnBuffers, base::Unretained(this), video_cb), |
116 base::Unretained(this), video_cb), | 114 base::Bind(&SourceState::OnTextBuffers, base::Unretained(this), text_cb), |
117 base::Bind(&SourceState::OnTextBuffers, | 115 need_key_cb, add_text_track_cb, |
118 base::Unretained(this), text_cb), | 116 base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this), |
119 need_key_cb, | 117 new_segment_cb), |
120 add_text_track_cb, | 118 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)), |
121 base::Bind(&SourceState::OnNewMediaSegment, | 119 log_cb); |
122 base::Unretained(this), new_segment_cb), | |
123 base::Bind(&SourceState::OnEndOfMediaSegment, | |
124 base::Unretained(this)), | |
125 log_cb); | |
126 } | 120 } |
127 | 121 |
128 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { | 122 bool SourceState::set_timestampOffset(TimeDelta timestamp_offset) { |
129 if (!can_update_offset_) | 123 if (!can_update_offset_) return false; |
130 return false; | |
131 | 124 |
132 timestamp_offset_ = timestamp_offset; | 125 timestamp_offset_ = timestamp_offset; |
133 return true; | 126 return true; |
134 } | 127 } |
135 | 128 |
136 bool SourceState::Append(const uint8* data, size_t length) { | 129 bool SourceState::Append(const uint8* data, size_t length) { |
137 return stream_parser_->Parse(data, length); | 130 return stream_parser_->Parse(data, length); |
138 } | 131 } |
139 | 132 |
140 void SourceState::Abort() { | 133 void SourceState::Abort() { |
141 stream_parser_->Flush(); | 134 stream_parser_->Flush(); |
142 can_update_offset_ = true; | 135 can_update_offset_ = true; |
143 } | 136 } |
144 | 137 |
145 void SourceState::AdjustBufferTimestamps( | 138 void SourceState::AdjustBufferTimestamps( |
146 const StreamParser::BufferQueue& buffers) { | 139 const StreamParser::BufferQueue& buffers) { |
147 if (timestamp_offset_ == TimeDelta()) | 140 if (timestamp_offset_ == TimeDelta()) return; |
148 return; | |
149 | 141 |
150 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); | 142 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); |
151 itr != buffers.end(); ++itr) { | 143 itr != buffers.end(); ++itr) { |
152 (*itr)->SetDecodeTimestamp( | 144 (*itr) |
153 (*itr)->GetDecodeTimestamp() + timestamp_offset_); | 145 ->SetDecodeTimestamp((*itr)->GetDecodeTimestamp() + timestamp_offset_); |
154 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset_); | 146 (*itr)->set_timestamp((*itr)->get_timestamp() + timestamp_offset_); |
155 } | 147 } |
156 } | 148 } |
157 | 149 |
158 void SourceState::OnNewMediaSegment( | 150 void SourceState::OnNewMediaSegment( |
159 const StreamParser::NewMediaSegmentCB& new_segment_cb, | 151 const StreamParser::NewMediaSegmentCB& new_segment_cb, |
160 TimeDelta timestamp) { | 152 TimeDelta timestamp) { |
161 DCHECK(timestamp != kNoTimestamp()); | 153 DCHECK(timestamp != kNoTimestamp()); |
162 DVLOG(2) << "OnNewMediaSegment(" << timestamp.InSecondsF() << ")"; | 154 DVLOG(2) << "OnNewMediaSegment(" << timestamp.InSecondsF() << ")"; |
163 | 155 |
164 can_update_offset_ = false; | 156 can_update_offset_ = false; |
165 new_segment_cb.Run(timestamp + timestamp_offset_); | 157 new_segment_cb.Run(timestamp + timestamp_offset_); |
166 } | 158 } |
167 | 159 |
168 void SourceState::OnEndOfMediaSegment() { | 160 void SourceState::OnEndOfMediaSegment() { |
169 DVLOG(2) << "OnEndOfMediaSegment()"; | 161 DVLOG(2) << "OnEndOfMediaSegment()"; |
170 can_update_offset_ = true; | 162 can_update_offset_ = true; |
171 } | 163 } |
172 | 164 |
173 bool SourceState::OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb, | 165 bool SourceState::OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb, |
174 const StreamParser::BufferQueue& buffers) { | 166 const StreamParser::BufferQueue& buffers) { |
175 if (new_buffers_cb.is_null()) | 167 if (new_buffers_cb.is_null()) return false; |
176 return false; | |
177 | 168 |
178 AdjustBufferTimestamps(buffers); | 169 AdjustBufferTimestamps(buffers); |
179 | 170 |
180 return new_buffers_cb.Run(buffers); | 171 return new_buffers_cb.Run(buffers); |
181 } | 172 } |
182 | 173 |
183 bool SourceState::OnTextBuffers( | 174 bool SourceState::OnTextBuffers( |
184 const StreamParser::NewTextBuffersCB& new_buffers_cb, | 175 const StreamParser::NewTextBuffersCB& new_buffers_cb, TextTrack* text_track, |
185 TextTrack* text_track, | |
186 const StreamParser::BufferQueue& buffers) { | 176 const StreamParser::BufferQueue& buffers) { |
187 if (new_buffers_cb.is_null()) | 177 if (new_buffers_cb.is_null()) return false; |
188 return false; | |
189 | 178 |
190 AdjustBufferTimestamps(buffers); | 179 AdjustBufferTimestamps(buffers); |
191 | 180 |
192 return new_buffers_cb.Run(text_track, buffers); | 181 return new_buffers_cb.Run(text_track, buffers); |
193 } | 182 } |
194 | 183 |
195 class ChunkDemuxerStream : public DemuxerStream { | 184 class ChunkDemuxerStream : public DemuxerStream { |
196 public: | 185 public: |
197 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; | 186 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; |
198 typedef std::deque<ReadCB> ReadCBQueue; | 187 typedef std::deque<ReadCB> ReadCBQueue; |
199 typedef std::deque<base::Closure> ClosureQueue; | 188 typedef std::deque<base::Closure> ClosureQueue; |
200 | 189 |
201 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, | 190 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, |
202 const LogCB& log_cb); | 191 const LogCB& log_cb); |
203 ChunkDemuxerStream(const VideoDecoderConfig& video_config, | 192 ChunkDemuxerStream(const VideoDecoderConfig& video_config, |
204 const LogCB& log_cb); | 193 const LogCB& log_cb); |
205 virtual ~ChunkDemuxerStream(); | 194 virtual ~ChunkDemuxerStream(); |
206 | 195 |
207 void StartWaitingForSeek(); | 196 void StartWaitingForSeek(); |
208 void Seek(TimeDelta time); | 197 void Seek(TimeDelta time); |
209 void CancelPendingSeek(); | 198 void CancelPendingSeek(); |
210 bool IsSeekPending() const; | 199 bool IsSeekPending() const; |
211 | 200 |
212 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, | 201 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
213 // which handle ordering and overlap resolution. | 202 // which handle ordering and overlap resolution. |
214 // Returns true if buffers were successfully added. | 203 // Returns true if buffers were successfully added. |
215 bool Append(const StreamParser::BufferQueue& buffers); | 204 bool Append(const StreamParser::BufferQueue& buffers); |
216 | 205 |
217 // Signal to the stream that duration has changed to |duration|. | 206 // Signal to the stream that duration has changed to |duration|. |
218 void OnSetDuration(base::TimeDelta duration); | 207 void Onset_duration(base::TimeDelta duration); |
219 | 208 |
220 // Returns the range of buffered data in this stream, capped at |duration|. | 209 // Returns the range of buffered data in this stream, capped at |duration|. |
221 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const; | 210 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const; |
222 | 211 |
223 // Signal to the stream that buffers handed in through subsequent calls to | 212 // Signal to the stream that buffers handed in through subsequent calls to |
224 // Append() belong to a media segment that starts at |start_timestamp|. | 213 // Append() belong to a media segment that starts at |start_timestamp|. |
225 void OnNewMediaSegment(TimeDelta start_timestamp); | 214 void OnNewMediaSegment(TimeDelta start_timestamp); |
226 | 215 |
227 // Called when midstream config updates occur. | 216 // Called when midstream config updates occur. |
228 // Returns true if the new config is accepted. | 217 // Returns true if the new config is accepted. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 | 263 |
275 mutable base::Lock lock_; | 264 mutable base::Lock lock_; |
276 State state_; | 265 State state_; |
277 ReadCBQueue read_cbs_; | 266 ReadCBQueue read_cbs_; |
278 | 267 |
279 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 268 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
280 }; | 269 }; |
281 | 270 |
282 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config, | 271 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config, |
283 const LogCB& log_cb) | 272 const LogCB& log_cb) |
284 : type_(AUDIO), | 273 : type_(AUDIO), state_(RETURNING_DATA_FOR_READS) { |
285 state_(RETURNING_DATA_FOR_READS) { | |
286 stream_.reset(new SourceBufferStream(audio_config, log_cb)); | 274 stream_.reset(new SourceBufferStream(audio_config, log_cb)); |
287 } | 275 } |
288 | 276 |
289 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config, | 277 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config, |
290 const LogCB& log_cb) | 278 const LogCB& log_cb) |
291 : type_(VIDEO), | 279 : type_(VIDEO), state_(RETURNING_DATA_FOR_READS) { |
292 state_(RETURNING_DATA_FOR_READS) { | |
293 stream_.reset(new SourceBufferStream(video_config, log_cb)); | 280 stream_.reset(new SourceBufferStream(video_config, log_cb)); |
294 } | 281 } |
295 | 282 |
296 void ChunkDemuxerStream::StartWaitingForSeek() { | 283 void ChunkDemuxerStream::StartWaitingForSeek() { |
297 DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()"; | 284 DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()"; |
298 ReadCBQueue read_cbs; | 285 ReadCBQueue read_cbs; |
299 { | 286 { |
300 base::AutoLock auto_lock(lock_); | 287 base::AutoLock auto_lock(lock_); |
301 ChangeState_Locked(WAITING_FOR_SEEK); | 288 ChangeState_Locked(WAITING_FOR_SEEK); |
302 std::swap(read_cbs_, read_cbs); | 289 std::swap(read_cbs_, read_cbs); |
303 } | 290 } |
304 | 291 |
305 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 292 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
306 it->Run(kAborted, NULL); | 293 it->Run(kAborted, NULL); |
307 } | 294 } |
308 | 295 |
309 void ChunkDemuxerStream::Seek(TimeDelta time) { | 296 void ChunkDemuxerStream::Seek(TimeDelta time) { |
310 base::AutoLock auto_lock(lock_); | 297 base::AutoLock auto_lock(lock_); |
311 | 298 |
312 DCHECK(read_cbs_.empty()); | 299 DCHECK(read_cbs_.empty()); |
313 | 300 |
314 // Ignore seek requests when canceled. | 301 // Ignore seek requests when canceled. |
315 if (state_ == CANCELED) | 302 if (state_ == CANCELED) return; |
316 return; | |
317 | 303 |
318 stream_->Seek(time); | 304 stream_->Seek(time); |
319 | 305 |
320 if (state_ == WAITING_FOR_SEEK) | 306 if (state_ == WAITING_FOR_SEEK) ChangeState_Locked(RETURNING_DATA_FOR_READS); |
321 ChangeState_Locked(RETURNING_DATA_FOR_READS); | |
322 } | 307 } |
323 | 308 |
324 void ChunkDemuxerStream::CancelPendingSeek() { | 309 void ChunkDemuxerStream::CancelPendingSeek() { |
325 DVLOG(1) << "ChunkDemuxerStream::CancelPendingSeek()"; | 310 DVLOG(1) << "ChunkDemuxerStream::CancelPendingSeek()"; |
326 ReadCBQueue read_cbs; | 311 ReadCBQueue read_cbs; |
327 { | 312 { |
328 base::AutoLock auto_lock(lock_); | 313 base::AutoLock auto_lock(lock_); |
329 ChangeState_Locked(CANCELED); | 314 ChangeState_Locked(CANCELED); |
330 std::swap(read_cbs_, read_cbs); | 315 std::swap(read_cbs_, read_cbs); |
331 } | 316 } |
332 | 317 |
333 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 318 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
334 it->Run(kAborted, NULL); | 319 it->Run(kAborted, NULL); |
335 } | 320 } |
336 | 321 |
337 bool ChunkDemuxerStream::IsSeekPending() const { | 322 bool ChunkDemuxerStream::IsSeekPending() const { |
338 base::AutoLock auto_lock(lock_); | 323 base::AutoLock auto_lock(lock_); |
339 return stream_->IsSeekPending(); | 324 return stream_->IsSeekPending(); |
340 } | 325 } |
341 | 326 |
342 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { | 327 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { |
343 base::AutoLock auto_lock(lock_); | 328 base::AutoLock auto_lock(lock_); |
344 stream_->OnNewMediaSegment(start_timestamp); | 329 stream_->OnNewMediaSegment(start_timestamp); |
345 } | 330 } |
346 | 331 |
347 bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { | 332 bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { |
348 if (buffers.empty()) | 333 if (buffers.empty()) return false; |
349 return false; | |
350 | 334 |
351 ClosureQueue closures; | 335 ClosureQueue closures; |
352 { | 336 { |
353 base::AutoLock auto_lock(lock_); | 337 base::AutoLock auto_lock(lock_); |
354 DCHECK_NE(state_, SHUTDOWN); | 338 DCHECK_NE(state_, SHUTDOWN); |
355 if (!stream_->Append(buffers)) { | 339 if (!stream_->Append(buffers)) { |
356 DVLOG(1) << "ChunkDemuxerStream::Append() : stream append failed"; | 340 DVLOG(1) << "ChunkDemuxerStream::Append() : stream append failed"; |
357 return false; | 341 return false; |
358 } | 342 } |
359 CreateReadDoneClosures_Locked(&closures); | 343 CreateReadDoneClosures_Locked(&closures); |
360 } | 344 } |
361 | 345 |
362 for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) | 346 for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) |
363 it->Run(); | 347 it->Run(); |
364 | 348 |
365 return true; | 349 return true; |
366 } | 350 } |
367 | 351 |
368 void ChunkDemuxerStream::OnSetDuration(base::TimeDelta duration) { | 352 void ChunkDemuxerStream::Onset_duration(base::TimeDelta duration) { |
369 base::AutoLock auto_lock(lock_); | 353 base::AutoLock auto_lock(lock_); |
370 stream_->OnSetDuration(duration); | 354 stream_->OnSetDuration(duration); |
371 } | 355 } |
372 | 356 |
373 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges( | 357 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges( |
374 base::TimeDelta duration) const { | 358 base::TimeDelta duration) const { |
375 base::AutoLock auto_lock(lock_); | 359 base::AutoLock auto_lock(lock_); |
376 Ranges<TimeDelta> range = stream_->GetBufferedTime(); | 360 Ranges<TimeDelta> range = stream_->GetBufferedTime(); |
377 | 361 |
378 if (range.size() == 0u) | 362 if (range.size() == 0u) return range; |
379 return range; | |
380 | 363 |
381 // Clamp the end of the stream's buffered ranges to fit within the duration. | 364 // Clamp the end of the stream's buffered ranges to fit within the duration. |
382 // This can be done by intersecting the stream's range with the valid time | 365 // This can be done by intersecting the stream's range with the valid time |
383 // range. | 366 // range. |
384 Ranges<TimeDelta> valid_time_range; | 367 Ranges<TimeDelta> valid_time_range; |
385 valid_time_range.Add(range.start(0), duration); | 368 valid_time_range.Add(range.start(0), duration); |
386 return range.IntersectionWith(valid_time_range); | 369 return range.IntersectionWith(valid_time_range); |
387 } | 370 } |
388 | 371 |
389 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { | 372 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 ReadCBQueue read_cbs; | 404 ReadCBQueue read_cbs; |
422 { | 405 { |
423 base::AutoLock auto_lock(lock_); | 406 base::AutoLock auto_lock(lock_); |
424 ChangeState_Locked(SHUTDOWN); | 407 ChangeState_Locked(SHUTDOWN); |
425 std::swap(read_cbs_, read_cbs); | 408 std::swap(read_cbs_, read_cbs); |
426 } | 409 } |
427 | 410 |
428 // Pass end of stream buffers to all callbacks to signal that no more data | 411 // Pass end of stream buffers to all callbacks to signal that no more data |
429 // will be sent. | 412 // will be sent. |
430 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 413 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
431 it->Run(DemuxerStream::kOk, StreamParserBuffer::CreateEOSBuffer()); | 414 it->Run(DemuxerStream::kOk, StreamParserBuffer::create_eos_buffer()); |
432 } | 415 } |
433 | 416 |
434 // Helper function that makes sure |read_cb| runs on |message_loop_proxy|. | 417 // Helper function that makes sure |read_cb| runs on |message_loop_proxy|. |
435 static void RunOnMessageLoop( | 418 static void RunOnMessageLoop( |
436 const DemuxerStream::ReadCB& read_cb, | 419 const DemuxerStream::ReadCB& read_cb, |
437 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, | 420 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, |
438 DemuxerStream::Status status, | 421 DemuxerStream::Status status, const scoped_refptr<DecoderBuffer>& buffer) { |
439 const scoped_refptr<DecoderBuffer>& buffer) { | |
440 if (!message_loop_proxy->BelongsToCurrentThread()) { | 422 if (!message_loop_proxy->BelongsToCurrentThread()) { |
441 message_loop_proxy->PostTask(FROM_HERE, base::Bind( | 423 message_loop_proxy->PostTask( |
442 &RunOnMessageLoop, read_cb, message_loop_proxy, status, buffer)); | 424 FROM_HERE, base::Bind(&RunOnMessageLoop, read_cb, message_loop_proxy, |
| 425 status, buffer)); |
443 return; | 426 return; |
444 } | 427 } |
445 | 428 |
446 read_cb.Run(status, buffer); | 429 read_cb.Run(status, buffer); |
447 } | 430 } |
448 | 431 |
449 // DemuxerStream methods. | 432 // DemuxerStream methods. |
450 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { | 433 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { |
451 DemuxerStream::Status status = kOk; | 434 DemuxerStream::Status status = kOk; |
452 scoped_refptr<StreamParserBuffer> buffer; | 435 scoped_refptr<StreamParserBuffer> buffer; |
453 { | 436 { |
454 base::AutoLock auto_lock(lock_); | 437 base::AutoLock auto_lock(lock_); |
455 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { | 438 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { |
456 DeferRead_Locked(read_cb); | 439 DeferRead_Locked(read_cb); |
457 return; | 440 return; |
458 } | 441 } |
459 } | 442 } |
460 | 443 |
461 base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( | 444 base::MessageLoopProxy::current()->PostTask( |
462 read_cb, status, buffer)); | 445 FROM_HERE, base::Bind(read_cb, status, buffer)); |
463 } | 446 } |
464 | 447 |
465 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } | 448 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } |
466 | 449 |
467 void ChunkDemuxerStream::EnableBitstreamConverter() {} | 450 void ChunkDemuxerStream::EnableBitstreamConverter() {} |
468 | 451 |
469 AudioDecoderConfig ChunkDemuxerStream::audio_decoder_config() { | 452 AudioDecoderConfig ChunkDemuxerStream::audio_decoder_config() { |
470 CHECK_EQ(type_, AUDIO); | 453 CHECK_EQ(type_, AUDIO); |
471 base::AutoLock auto_lock(lock_); | 454 base::AutoLock auto_lock(lock_); |
472 return stream_->GetCurrentAudioDecoderConfig(); | 455 return stream_->GetCurrentAudioDecoderConfig(); |
473 } | 456 } |
474 | 457 |
475 VideoDecoderConfig ChunkDemuxerStream::video_decoder_config() { | 458 VideoDecoderConfig ChunkDemuxerStream::video_decoder_config() { |
476 CHECK_EQ(type_, VIDEO); | 459 CHECK_EQ(type_, VIDEO); |
477 base::AutoLock auto_lock(lock_); | 460 base::AutoLock auto_lock(lock_); |
478 return stream_->GetCurrentVideoDecoderConfig(); | 461 return stream_->GetCurrentVideoDecoderConfig(); |
479 } | 462 } |
480 | 463 |
481 void ChunkDemuxerStream::ChangeState_Locked(State state) { | 464 void ChunkDemuxerStream::ChangeState_Locked(State state) { |
482 lock_.AssertAcquired(); | 465 lock_.AssertAcquired(); |
483 DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : " | 466 DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : " |
484 << "type " << type_ | 467 << "type " << type_ << " - " << state_ << " -> " << state; |
485 << " - " << state_ << " -> " << state; | |
486 state_ = state; | 468 state_ = state; |
487 } | 469 } |
488 | 470 |
489 ChunkDemuxerStream::~ChunkDemuxerStream() {} | 471 ChunkDemuxerStream::~ChunkDemuxerStream() {} |
490 | 472 |
491 void ChunkDemuxerStream::DeferRead_Locked(const ReadCB& read_cb) { | 473 void ChunkDemuxerStream::DeferRead_Locked(const ReadCB& read_cb) { |
492 lock_.AssertAcquired(); | 474 lock_.AssertAcquired(); |
493 // Wrap & store |read_cb| so that it will | 475 // Wrap & store |read_cb| so that it will |
494 // get called on the current MessageLoop. | 476 // get called on the current MessageLoop. |
495 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, | 477 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, |
496 base::MessageLoopProxy::current())); | 478 base::MessageLoopProxy::current())); |
497 } | 479 } |
498 | 480 |
499 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { | 481 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { |
500 lock_.AssertAcquired(); | 482 lock_.AssertAcquired(); |
501 | 483 |
502 if (state_ != RETURNING_DATA_FOR_READS) | 484 if (state_ != RETURNING_DATA_FOR_READS) return; |
503 return; | |
504 | 485 |
505 DemuxerStream::Status status; | 486 DemuxerStream::Status status; |
506 scoped_refptr<StreamParserBuffer> buffer; | 487 scoped_refptr<StreamParserBuffer> buffer; |
507 while (!read_cbs_.empty()) { | 488 while (!read_cbs_.empty()) { |
508 if (!GetNextBuffer_Locked(&status, &buffer)) | 489 if (!GetNextBuffer_Locked(&status, &buffer)) return; |
509 return; | 490 closures->push_back(base::Bind(read_cbs_.front(), status, buffer)); |
510 closures->push_back(base::Bind(read_cbs_.front(), | |
511 status, buffer)); | |
512 read_cbs_.pop_front(); | 491 read_cbs_.pop_front(); |
513 } | 492 } |
514 } | 493 } |
515 | 494 |
516 bool ChunkDemuxerStream::GetNextBuffer_Locked( | 495 bool ChunkDemuxerStream::GetNextBuffer_Locked( |
517 DemuxerStream::Status* status, | 496 DemuxerStream::Status* status, scoped_refptr<StreamParserBuffer>* buffer) { |
518 scoped_refptr<StreamParserBuffer>* buffer) { | |
519 lock_.AssertAcquired(); | 497 lock_.AssertAcquired(); |
520 | 498 |
521 switch (state_) { | 499 switch (state_) { |
522 case RETURNING_DATA_FOR_READS: | 500 case RETURNING_DATA_FOR_READS: |
523 switch (stream_->GetNextBuffer(buffer)) { | 501 switch (stream_->GetNextBuffer(buffer)) { |
524 case SourceBufferStream::kSuccess: | 502 case SourceBufferStream::kSuccess: |
525 *status = DemuxerStream::kOk; | 503 *status = DemuxerStream::kOk; |
526 return true; | 504 return true; |
527 case SourceBufferStream::kNeedBuffer: | 505 case SourceBufferStream::kNeedBuffer: |
528 return false; | 506 return false; |
529 case SourceBufferStream::kEndOfStream: | 507 case SourceBufferStream::kEndOfStream: |
530 *status = DemuxerStream::kOk; | 508 *status = DemuxerStream::kOk; |
531 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 509 *buffer = StreamParserBuffer::create_eos_buffer(); |
532 return true; | 510 return true; |
533 case SourceBufferStream::kConfigChange: | 511 case SourceBufferStream::kConfigChange: |
534 DVLOG(2) << "Config change reported to ChunkDemuxerStream."; | 512 DVLOG(2) << "Config change reported to ChunkDemuxerStream."; |
535 *status = kConfigChanged; | 513 *status = kConfigChanged; |
536 *buffer = NULL; | 514 *buffer = NULL; |
537 return true; | 515 return true; |
538 } | 516 } |
539 break; | 517 break; |
540 case CANCELED: | 518 case CANCELED: |
541 case WAITING_FOR_SEEK: | 519 case WAITING_FOR_SEEK: |
542 // Null buffers should be returned in this state since we are waiting | 520 // Null buffers should be returned in this state since we are waiting |
543 // for a seek. Any buffers in the SourceBuffer should NOT be returned | 521 // for a seek. Any buffers in the SourceBuffer should NOT be returned |
544 // because they are associated with the seek. | 522 // because they are associated with the seek. |
545 DCHECK(read_cbs_.empty()); | 523 DCHECK(read_cbs_.empty()); |
546 *status = DemuxerStream::kAborted; | 524 *status = DemuxerStream::kAborted; |
547 *buffer = NULL; | 525 *buffer = NULL; |
548 return true; | 526 return true; |
549 case SHUTDOWN: | 527 case SHUTDOWN: |
550 DCHECK(read_cbs_.empty()); | 528 DCHECK(read_cbs_.empty()); |
551 *status = DemuxerStream::kOk; | 529 *status = DemuxerStream::kOk; |
552 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 530 *buffer = StreamParserBuffer::create_eos_buffer(); |
553 return true; | 531 return true; |
554 } | 532 } |
555 | 533 |
556 NOTREACHED(); | 534 NOTREACHED(); |
557 return false; | 535 return false; |
558 } | 536 } |
559 | 537 |
560 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, | 538 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, |
561 const NeedKeyCB& need_key_cb, | 539 const NeedKeyCB& need_key_cb, |
562 const AddTextTrackCB& add_text_track_cb, | 540 const AddTextTrackCB& add_text_track_cb, |
563 const LogCB& log_cb) | 541 const LogCB& log_cb) |
564 : state_(WAITING_FOR_INIT), | 542 : state_(WAITING_FOR_INIT), |
565 host_(NULL), | 543 host_(NULL), |
566 open_cb_(open_cb), | 544 open_cb_(open_cb), |
567 need_key_cb_(need_key_cb), | 545 need_key_cb_(need_key_cb), |
568 add_text_track_cb_(add_text_track_cb), | 546 add_text_track_cb_(add_text_track_cb), |
569 log_cb_(log_cb), | 547 log_cb_(log_cb), |
570 duration_(kNoTimestamp()), | 548 duration_(kNoTimestamp()), |
571 user_specified_duration_(-1) { | 549 user_specified_duration_(-1) { |
572 DCHECK(!open_cb_.is_null()); | 550 DCHECK(!open_cb_.is_null()); |
573 DCHECK(!need_key_cb_.is_null()); | 551 DCHECK(!need_key_cb_.is_null()); |
574 } | 552 } |
575 | 553 |
576 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) { | 554 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) { |
577 DVLOG(1) << "Init()"; | 555 DVLOG(1) << "Init()"; |
578 | 556 |
579 base::AutoLock auto_lock(lock_); | 557 base::AutoLock auto_lock(lock_); |
580 | 558 |
581 if (state_ == SHUTDOWN) { | 559 if (state_ == SHUTDOWN) { |
582 base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( | 560 base::MessageLoopProxy::current()->PostTask( |
583 cb, DEMUXER_ERROR_COULD_NOT_OPEN)); | 561 FROM_HERE, base::Bind(cb, DEMUXER_ERROR_COULD_NOT_OPEN)); |
584 return; | 562 return; |
585 } | 563 } |
586 DCHECK_EQ(state_, WAITING_FOR_INIT); | 564 DCHECK_EQ(state_, WAITING_FOR_INIT); |
587 host_ = host; | 565 host_ = host; |
588 | 566 |
589 ChangeState_Locked(INITIALIZING); | 567 ChangeState_Locked(INITIALIZING); |
590 init_cb_ = cb; | 568 init_cb_ = cb; |
591 | 569 |
592 base::ResetAndReturn(&open_cb_).Run(); | 570 base::ResetAndReturn(&open_cb_).Run(); |
593 } | 571 } |
594 | 572 |
595 void ChunkDemuxer::Stop(const base::Closure& callback) { | 573 void ChunkDemuxer::Stop(const base::Closure& callback) { |
596 DVLOG(1) << "Stop()"; | 574 DVLOG(1) << "Stop()"; |
597 Shutdown(); | 575 Shutdown(); |
598 callback.Run(); | 576 callback.Run(); |
599 } | 577 } |
600 | 578 |
601 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { | 579 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { |
602 DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; | 580 DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; |
603 DCHECK(time >= TimeDelta()); | 581 DCHECK(time >= TimeDelta()); |
604 DCHECK(seek_cb_.is_null()); | 582 DCHECK(seek_cb_.is_null()); |
605 | 583 |
606 PipelineStatus status = PIPELINE_ERROR_INVALID_STATE; | 584 PipelineStatus status = PIPELINE_ERROR_INVALID_STATE; |
607 { | 585 { |
608 base::AutoLock auto_lock(lock_); | 586 base::AutoLock auto_lock(lock_); |
609 | 587 |
610 if (state_ == INITIALIZED || state_ == ENDED) { | 588 if (state_ == INITIALIZED || state_ == ENDED) { |
611 if (audio_) | 589 if (audio_) audio_->Seek(time); |
612 audio_->Seek(time); | |
613 | 590 |
614 if (video_) | 591 if (video_) video_->Seek(time); |
615 video_->Seek(time); | |
616 | 592 |
617 if (IsSeekPending_Locked()) { | 593 if (IsSeekPending_Locked()) { |
618 DVLOG(1) << "Seek() : waiting for more data to arrive."; | 594 DVLOG(1) << "Seek() : waiting for more data to arrive."; |
619 seek_cb_ = cb; | 595 seek_cb_ = cb; |
620 return; | 596 return; |
621 } | 597 } |
622 | 598 |
623 status = PIPELINE_OK; | 599 status = PIPELINE_OK; |
624 } | 600 } |
625 } | 601 } |
626 | 602 |
627 cb.Run(status); | 603 cb.Run(status); |
628 } | 604 } |
629 | 605 |
630 void ChunkDemuxer::OnAudioRendererDisabled() { | 606 void ChunkDemuxer::OnAudioRendererDisabled() { |
631 base::AutoLock auto_lock(lock_); | 607 base::AutoLock auto_lock(lock_); |
632 audio_->Shutdown(); | 608 audio_->Shutdown(); |
633 disabled_audio_ = audio_.Pass(); | 609 disabled_audio_ = audio_.Pass(); |
634 } | 610 } |
635 | 611 |
636 // Demuxer implementation. | 612 // Demuxer implementation. |
637 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { | 613 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { |
638 base::AutoLock auto_lock(lock_); | 614 base::AutoLock auto_lock(lock_); |
639 if (type == DemuxerStream::VIDEO) | 615 if (type == DemuxerStream::VIDEO) return video_.get(); |
640 return video_.get(); | |
641 | 616 |
642 if (type == DemuxerStream::AUDIO) | 617 if (type == DemuxerStream::AUDIO) return audio_.get(); |
643 return audio_.get(); | |
644 | 618 |
645 return NULL; | 619 return NULL; |
646 } | 620 } |
647 | 621 |
648 TimeDelta ChunkDemuxer::GetStartTime() const { | 622 TimeDelta ChunkDemuxer::GetStartTime() const { return TimeDelta(); } |
649 return TimeDelta(); | |
650 } | |
651 | 623 |
652 void ChunkDemuxer::StartWaitingForSeek() { | 624 void ChunkDemuxer::StartWaitingForSeek() { |
653 DVLOG(1) << "StartWaitingForSeek()"; | 625 DVLOG(1) << "StartWaitingForSeek()"; |
654 base::AutoLock auto_lock(lock_); | 626 base::AutoLock auto_lock(lock_); |
655 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN); | 627 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN); |
656 | 628 |
657 if (state_ == SHUTDOWN) | 629 if (state_ == SHUTDOWN) return; |
658 return; | |
659 | 630 |
660 if (audio_) | 631 if (audio_) audio_->StartWaitingForSeek(); |
661 audio_->StartWaitingForSeek(); | |
662 | 632 |
663 if (video_) | 633 if (video_) video_->StartWaitingForSeek(); |
664 video_->StartWaitingForSeek(); | |
665 } | 634 } |
666 | 635 |
667 void ChunkDemuxer::CancelPendingSeek() { | 636 void ChunkDemuxer::CancelPendingSeek() { |
668 PipelineStatusCB cb; | 637 PipelineStatusCB cb; |
669 { | 638 { |
670 base::AutoLock auto_lock(lock_); | 639 base::AutoLock auto_lock(lock_); |
671 if (IsSeekPending_Locked() && !seek_cb_.is_null()) { | 640 if (IsSeekPending_Locked() && !seek_cb_.is_null()) { |
672 std::swap(cb, seek_cb_); | 641 std::swap(cb, seek_cb_); |
673 } | 642 } |
674 if (audio_) | 643 if (audio_) audio_->CancelPendingSeek(); |
675 audio_->CancelPendingSeek(); | |
676 | 644 |
677 if (video_) | 645 if (video_) video_->CancelPendingSeek(); |
678 video_->CancelPendingSeek(); | |
679 } | 646 } |
680 | 647 |
681 if (!cb.is_null()) | 648 if (!cb.is_null()) cb.Run(PIPELINE_OK); |
682 cb.Run(PIPELINE_OK); | |
683 } | 649 } |
684 | 650 |
685 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, | 651 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
686 const std::string& type, | 652 const std::string& type, |
687 std::vector<std::string>& codecs) { | 653 std::vector<std::string>& codecs) { |
688 DCHECK_GT(codecs.size(), 0u); | 654 DCHECK_GT(codecs.size(), 0u); |
689 base::AutoLock auto_lock(lock_); | 655 base::AutoLock auto_lock(lock_); |
690 | 656 |
691 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) | 657 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) |
692 return kReachedIdLimit; | 658 return kReachedIdLimit; |
693 | 659 |
694 bool has_audio = false; | 660 bool has_audio = false; |
695 bool has_video = false; | 661 bool has_video = false; |
696 scoped_ptr<media::StreamParser> stream_parser( | 662 scoped_ptr<media::StreamParser> stream_parser(StreamParserFactory::Create( |
697 StreamParserFactory::Create(type, codecs, log_cb_, | 663 type, codecs, log_cb_, &has_audio, &has_video)); |
698 &has_audio, &has_video)); | |
699 | 664 |
700 if (!stream_parser) | 665 if (!stream_parser) return ChunkDemuxer::kNotSupported; |
701 return ChunkDemuxer::kNotSupported; | |
702 | 666 |
703 if ((has_audio && !source_id_audio_.empty()) || | 667 if ((has_audio && !source_id_audio_.empty()) || |
704 (has_video && !source_id_video_.empty())) | 668 (has_video && !source_id_video_.empty())) |
705 return kReachedIdLimit; | 669 return kReachedIdLimit; |
706 | 670 |
707 StreamParser::NewBuffersCB audio_cb; | 671 StreamParser::NewBuffersCB audio_cb; |
708 StreamParser::NewBuffersCB video_cb; | 672 StreamParser::NewBuffersCB video_cb; |
709 | 673 |
710 if (has_audio) { | 674 if (has_audio) { |
711 source_id_audio_ = id; | 675 source_id_audio_ = id; |
712 audio_cb = base::Bind(&ChunkDemuxer::OnAudioBuffers, | 676 audio_cb = |
713 base::Unretained(this)); | 677 base::Bind(&ChunkDemuxer::OnAudioBuffers, base::Unretained(this)); |
714 } | 678 } |
715 | 679 |
716 if (has_video) { | 680 if (has_video) { |
717 source_id_video_ = id; | 681 source_id_video_ = id; |
718 video_cb = base::Bind(&ChunkDemuxer::OnVideoBuffers, | 682 video_cb = |
719 base::Unretained(this)); | 683 base::Bind(&ChunkDemuxer::OnVideoBuffers, base::Unretained(this)); |
720 } | 684 } |
721 | 685 |
722 scoped_ptr<SourceState> source_state(new SourceState(stream_parser.Pass())); | 686 scoped_ptr<SourceState> source_state(new SourceState(stream_parser.Pass())); |
723 source_state->Init( | 687 source_state->Init( |
724 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), | 688 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), |
725 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), | 689 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), has_audio, |
726 has_audio, has_video), | 690 has_video), |
727 audio_cb, | 691 audio_cb, video_cb, |
728 video_cb, | |
729 base::Bind(&ChunkDemuxer::OnTextBuffers, base::Unretained(this)), | 692 base::Bind(&ChunkDemuxer::OnTextBuffers, base::Unretained(this)), |
730 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)), | 693 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)), |
731 add_text_track_cb_, | 694 add_text_track_cb_, |
732 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id), | 695 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id), |
733 log_cb_); | 696 log_cb_); |
734 | 697 |
735 source_state_map_[id] = source_state.release(); | 698 source_state_map_[id] = source_state.release(); |
736 return kOk; | 699 return kOk; |
737 } | 700 } |
738 | 701 |
739 void ChunkDemuxer::RemoveId(const std::string& id) { | 702 void ChunkDemuxer::RemoveId(const std::string& id) { |
740 base::AutoLock auto_lock(lock_); | 703 base::AutoLock auto_lock(lock_); |
741 CHECK(IsValidId(id)); | 704 CHECK(IsValidId(id)); |
742 | 705 |
743 delete source_state_map_[id]; | 706 delete source_state_map_[id]; |
744 source_state_map_.erase(id); | 707 source_state_map_.erase(id); |
745 | 708 |
746 if (source_id_audio_ == id) { | 709 if (source_id_audio_ == id) { |
747 if (audio_) | 710 if (audio_) audio_->Shutdown(); |
748 audio_->Shutdown(); | |
749 source_id_audio_.clear(); | 711 source_id_audio_.clear(); |
750 } | 712 } |
751 | 713 |
752 if (source_id_video_ == id) { | 714 if (source_id_video_ == id) { |
753 if (video_) | 715 if (video_) video_->Shutdown(); |
754 video_->Shutdown(); | |
755 source_id_video_.clear(); | 716 source_id_video_.clear(); |
756 } | 717 } |
757 } | 718 } |
758 | 719 |
759 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { | 720 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { |
760 base::AutoLock auto_lock(lock_); | 721 base::AutoLock auto_lock(lock_); |
761 DCHECK(!id.empty()); | 722 DCHECK(!id.empty()); |
762 DCHECK(IsValidId(id)); | 723 DCHECK(IsValidId(id)); |
763 DCHECK(id == source_id_audio_ || id == source_id_video_); | 724 DCHECK(id == source_id_audio_ || id == source_id_video_); |
764 | 725 |
765 if (id == source_id_audio_ && id != source_id_video_) { | 726 if (id == source_id_audio_ && id != source_id_video_) { |
766 // Only include ranges that have been buffered in |audio_| | 727 // Only include ranges that have been buffered in |audio_| |
767 return audio_ ? audio_->GetBufferedRanges(duration_) : Ranges<TimeDelta>(); | 728 return audio_ ? audio_->GetBufferedRanges(duration_) : Ranges<TimeDelta>(); |
768 } | 729 } |
769 | 730 |
770 if (id != source_id_audio_ && id == source_id_video_) { | 731 if (id != source_id_audio_ && id == source_id_video_) { |
771 // Only include ranges that have been buffered in |video_| | 732 // Only include ranges that have been buffered in |video_| |
772 return video_ ? video_->GetBufferedRanges(duration_) : Ranges<TimeDelta>(); | 733 return video_ ? video_->GetBufferedRanges(duration_) : Ranges<TimeDelta>(); |
773 } | 734 } |
774 | 735 |
775 return ComputeIntersection(); | 736 return ComputeIntersection(); |
776 } | 737 } |
777 | 738 |
778 Ranges<TimeDelta> ChunkDemuxer::ComputeIntersection() const { | 739 Ranges<TimeDelta> ChunkDemuxer::ComputeIntersection() const { |
779 lock_.AssertAcquired(); | 740 lock_.AssertAcquired(); |
780 | 741 |
781 if (!audio_ || !video_) | 742 if (!audio_ || !video_) return Ranges<TimeDelta>(); |
782 return Ranges<TimeDelta>(); | |
783 | 743 |
784 // Include ranges that have been buffered in both |audio_| and |video_|. | 744 // Include ranges that have been buffered in both |audio_| and |video_|. |
785 Ranges<TimeDelta> audio_ranges = audio_->GetBufferedRanges(duration_); | 745 Ranges<TimeDelta> audio_ranges = audio_->GetBufferedRanges(duration_); |
786 Ranges<TimeDelta> video_ranges = video_->GetBufferedRanges(duration_); | 746 Ranges<TimeDelta> video_ranges = video_->GetBufferedRanges(duration_); |
787 Ranges<TimeDelta> result = audio_ranges.IntersectionWith(video_ranges); | 747 Ranges<TimeDelta> result = audio_ranges.IntersectionWith(video_ranges); |
788 | 748 |
789 if (state_ == ENDED && result.size() > 0) { | 749 if (state_ == ENDED && result.size() > 0) { |
790 // If appending has ended, extend the last intersection range to include the | 750 // If appending has ended, extend the last intersection range to include the |
791 // max end time of the last audio/video range. This allows the buffered | 751 // max end time of the last audio/video range. This allows the buffered |
792 // information to match the actual time range that will get played out if | 752 // information to match the actual time range that will get played out if |
793 // the streams have slightly different lengths. | 753 // the streams have slightly different lengths. |
794 TimeDelta audio_start = audio_ranges.start(audio_ranges.size() - 1); | 754 TimeDelta audio_start = audio_ranges.start(audio_ranges.size() - 1); |
795 TimeDelta audio_end = audio_ranges.end(audio_ranges.size() - 1); | 755 TimeDelta audio_end = audio_ranges.end(audio_ranges.size() - 1); |
796 TimeDelta video_start = video_ranges.start(video_ranges.size() - 1); | 756 TimeDelta video_start = video_ranges.start(video_ranges.size() - 1); |
797 TimeDelta video_end = video_ranges.end(video_ranges.size() - 1); | 757 TimeDelta video_end = video_ranges.end(video_ranges.size() - 1); |
798 | 758 |
799 // Verify the last audio range overlaps with the last video range. | 759 // Verify the last audio range overlaps with the last video range. |
800 // This is enforced by the logic that controls the transition to ENDED. | 760 // This is enforced by the logic that controls the transition to ENDED. |
801 DCHECK((audio_start <= video_start && video_start <= audio_end) || | 761 DCHECK((audio_start <= video_start && video_start <= audio_end) || |
802 (video_start <= audio_start && audio_start <= video_end)); | 762 (video_start <= audio_start && audio_start <= video_end)); |
803 result.Add(result.end(result.size()-1), std::max(audio_end, video_end)); | 763 result.Add(result.end(result.size() - 1), std::max(audio_end, video_end)); |
804 } | 764 } |
805 | 765 |
806 return result; | 766 return result; |
807 } | 767 } |
808 | 768 |
809 void ChunkDemuxer::AppendData(const std::string& id, | 769 void ChunkDemuxer::AppendData(const std::string& id, const uint8* data, |
810 const uint8* data, | |
811 size_t length) { | 770 size_t length) { |
812 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; | 771 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; |
813 | 772 |
814 DCHECK(!id.empty()); | 773 DCHECK(!id.empty()); |
815 | 774 |
816 Ranges<TimeDelta> ranges; | 775 Ranges<TimeDelta> ranges; |
817 | 776 |
818 PipelineStatusCB cb; | 777 PipelineStatusCB cb; |
819 { | 778 { |
820 base::AutoLock auto_lock(lock_); | 779 base::AutoLock auto_lock(lock_); |
821 | 780 |
822 // Capture if the SourceBuffer has a pending seek before we start parsing. | 781 // Capture if the SourceBuffer has a pending seek before we start parsing. |
823 bool old_seek_pending = IsSeekPending_Locked(); | 782 bool old_seek_pending = IsSeekPending_Locked(); |
824 | 783 |
825 if (state_ == ENDED) { | 784 if (state_ == ENDED) { |
826 ChangeState_Locked(INITIALIZED); | 785 ChangeState_Locked(INITIALIZED); |
827 | 786 |
828 if (audio_) | 787 if (audio_) audio_->CancelEndOfStream(); |
829 audio_->CancelEndOfStream(); | |
830 | 788 |
831 if (video_) | 789 if (video_) video_->CancelEndOfStream(); |
832 video_->CancelEndOfStream(); | |
833 } | 790 } |
834 | 791 |
835 if (length == 0u) | 792 if (length == 0u) return; |
836 return; | |
837 | 793 |
838 DCHECK(data); | 794 DCHECK(data); |
839 | 795 |
840 switch (state_) { | 796 switch (state_) { |
841 case INITIALIZING: | 797 case INITIALIZING: |
842 DCHECK(IsValidId(id)); | 798 DCHECK(IsValidId(id)); |
843 if (!source_state_map_[id]->Append(data, length)) { | 799 if (!source_state_map_[id]->Append(data, length)) { |
844 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 800 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
845 return; | 801 return; |
846 } | 802 } |
(...skipping 23 matching lines...) Expand all Loading... |
870 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { | 826 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { |
871 std::swap(cb, seek_cb_); | 827 std::swap(cb, seek_cb_); |
872 } | 828 } |
873 | 829 |
874 ranges = GetBufferedRanges(); | 830 ranges = GetBufferedRanges(); |
875 } | 831 } |
876 | 832 |
877 for (size_t i = 0; i < ranges.size(); ++i) | 833 for (size_t i = 0; i < ranges.size(); ++i) |
878 host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i)); | 834 host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i)); |
879 | 835 |
880 if (!cb.is_null()) | 836 if (!cb.is_null()) cb.Run(PIPELINE_OK); |
881 cb.Run(PIPELINE_OK); | |
882 } | 837 } |
883 | 838 |
884 void ChunkDemuxer::Abort(const std::string& id) { | 839 void ChunkDemuxer::Abort(const std::string& id) { |
885 DVLOG(1) << "Abort(" << id << ")"; | 840 DVLOG(1) << "Abort(" << id << ")"; |
886 base::AutoLock auto_lock(lock_); | 841 base::AutoLock auto_lock(lock_); |
887 DCHECK(!id.empty()); | 842 DCHECK(!id.empty()); |
888 CHECK(IsValidId(id)); | 843 CHECK(IsValidId(id)); |
889 source_state_map_[id]->Abort(); | 844 source_state_map_[id]->Abort(); |
890 } | 845 } |
891 | 846 |
892 double ChunkDemuxer::GetDuration() { | 847 double ChunkDemuxer::GetDuration() { |
893 base::AutoLock auto_lock(lock_); | 848 base::AutoLock auto_lock(lock_); |
894 return GetDuration_Locked(); | 849 return GetDuration_Locked(); |
895 } | 850 } |
896 | 851 |
897 double ChunkDemuxer::GetDuration_Locked() { | 852 double ChunkDemuxer::GetDuration_Locked() { |
898 lock_.AssertAcquired(); | 853 lock_.AssertAcquired(); |
899 if (duration_ == kNoTimestamp()) | 854 if (duration_ == kNoTimestamp()) |
900 return std::numeric_limits<double>::quiet_NaN(); | 855 return std::numeric_limits<double>::quiet_NaN(); |
901 | 856 |
902 // Return positive infinity if the resource is unbounded. | 857 // Return positive infinity if the resource is unbounded. |
903 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-
media-duration | 858 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-
media-duration |
904 if (duration_ == kInfiniteDuration()) | 859 if (duration_ == kInfiniteDuration()) |
905 return std::numeric_limits<double>::infinity(); | 860 return std::numeric_limits<double>::infinity(); |
906 | 861 |
907 if (user_specified_duration_ >= 0) | 862 if (user_specified_duration_ >= 0) return user_specified_duration_; |
908 return user_specified_duration_; | |
909 | 863 |
910 return duration_.InSecondsF(); | 864 return duration_.InSecondsF(); |
911 } | 865 } |
912 | 866 |
913 void ChunkDemuxer::SetDuration(double duration) { | 867 void ChunkDemuxer::SetDuration(double duration) { |
914 base::AutoLock auto_lock(lock_); | 868 base::AutoLock auto_lock(lock_); |
915 DVLOG(1) << "SetDuration(" << duration << ")"; | 869 DVLOG(1) << "set_duration(" << duration << ")"; |
916 DCHECK_GE(duration, 0); | 870 DCHECK_GE(duration, 0); |
917 | 871 |
918 if (duration == GetDuration_Locked()) | 872 if (duration == GetDuration_Locked()) return; |
919 return; | |
920 | 873 |
921 // Compute & bounds check the TimeDelta representation of duration. | 874 // Compute & bounds check the TimeDelta representation of duration. |
922 // This can be different if the value of |duration| doesn't fit the range or | 875 // This can be different if the value of |duration| doesn't fit the range or |
923 // precision of base::TimeDelta. | 876 // precision of base::TimeDelta. |
924 base::TimeDelta min_duration = base::TimeDelta::FromInternalValue(1); | 877 base::TimeDelta min_duration = base::TimeDelta::FromInternalValue(1); |
925 base::TimeDelta max_duration = | 878 base::TimeDelta max_duration = |
926 base::TimeDelta::FromInternalValue(kint64max - 1); | 879 base::TimeDelta::FromInternalValue(kint64max - 1); |
927 double min_duration_in_seconds = min_duration.InSecondsF(); | 880 double min_duration_in_seconds = min_duration.InSecondsF(); |
928 double max_duration_in_seconds = max_duration.InSecondsF(); | 881 double max_duration_in_seconds = max_duration.InSecondsF(); |
929 | 882 |
930 base::TimeDelta duration_td; | 883 base::TimeDelta duration_td; |
931 if (duration == std::numeric_limits<double>::infinity()) { | 884 if (duration == std::numeric_limits<double>::infinity()) { |
932 duration_td = media::kInfiniteDuration(); | 885 duration_td = media::kInfiniteDuration(); |
933 } else if (duration < min_duration_in_seconds) { | 886 } else if (duration < min_duration_in_seconds) { |
934 duration_td = min_duration; | 887 duration_td = min_duration; |
935 } else if (duration > max_duration_in_seconds) { | 888 } else if (duration > max_duration_in_seconds) { |
936 duration_td = max_duration; | 889 duration_td = max_duration; |
937 } else { | 890 } else { |
938 duration_td = base::TimeDelta::FromMicroseconds( | 891 duration_td = base::TimeDelta::FromMicroseconds( |
939 duration * base::Time::kMicrosecondsPerSecond); | 892 duration * base::Time::kMicrosecondsPerSecond); |
940 } | 893 } |
941 | 894 |
942 DCHECK(duration_td > base::TimeDelta()); | 895 DCHECK(duration_td > base::TimeDelta()); |
943 | 896 |
944 user_specified_duration_ = duration; | 897 user_specified_duration_ = duration; |
945 duration_ = duration_td; | 898 duration_ = duration_td; |
946 host_->SetDuration(duration_); | 899 host_->SetDuration(duration_); |
947 | 900 |
948 if (audio_) | 901 if (audio_) audio_->Onset_duration(duration_); |
949 audio_->OnSetDuration(duration_); | |
950 | 902 |
951 if (video_) | 903 if (video_) video_->Onset_duration(duration_); |
952 video_->OnSetDuration(duration_); | |
953 } | 904 } |
954 | 905 |
955 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { | 906 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { |
956 base::AutoLock auto_lock(lock_); | 907 base::AutoLock auto_lock(lock_); |
957 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; | 908 DVLOG(1) << "set_timestampOffset(" << id << ", " << offset.InSecondsF() |
| 909 << ")"; |
958 CHECK(IsValidId(id)); | 910 CHECK(IsValidId(id)); |
959 | 911 |
960 return source_state_map_[id]->SetTimestampOffset(offset); | 912 return source_state_map_[id]->set_timestampOffset(offset); |
961 } | 913 } |
962 | 914 |
963 void ChunkDemuxer::EndOfStream(PipelineStatus status) { | 915 void ChunkDemuxer::EndOfStream(PipelineStatus status) { |
964 DVLOG(1) << "EndOfStream(" << status << ")"; | 916 DVLOG(1) << "EndOfStream(" << status << ")"; |
965 PipelineStatusCB cb; | 917 PipelineStatusCB cb; |
966 { | 918 { |
967 base::AutoLock auto_lock(lock_); | 919 base::AutoLock auto_lock(lock_); |
968 DCHECK_NE(state_, WAITING_FOR_INIT); | 920 DCHECK_NE(state_, WAITING_FOR_INIT); |
969 DCHECK_NE(state_, ENDED); | 921 DCHECK_NE(state_, ENDED); |
970 | 922 |
971 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) | 923 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) return; |
972 return; | |
973 | 924 |
974 if (state_ == INITIALIZING) { | 925 if (state_ == INITIALIZING) { |
975 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 926 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
976 return; | 927 return; |
977 } | 928 } |
978 | 929 |
979 bool old_seek_pending = IsSeekPending_Locked(); | 930 bool old_seek_pending = IsSeekPending_Locked(); |
980 if (audio_) | 931 if (audio_) audio_->EndOfStream(); |
981 audio_->EndOfStream(); | |
982 | 932 |
983 if (video_) | 933 if (video_) video_->EndOfStream(); |
984 video_->EndOfStream(); | |
985 | 934 |
986 // Give a chance to resume the pending seek process. | 935 // Give a chance to resume the pending seek process. |
987 if (status != PIPELINE_OK) { | 936 if (status != PIPELINE_OK) { |
988 ReportError_Locked(status); | 937 ReportError_Locked(status); |
989 return; | 938 return; |
990 } | 939 } |
991 | 940 |
992 ChangeState_Locked(ENDED); | 941 ChangeState_Locked(ENDED); |
993 DecreaseDurationIfNecessary(); | 942 DecreaseDurationIfNecessary(); |
994 | 943 |
995 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) | 944 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) |
996 std::swap(cb, seek_cb_); | 945 std::swap(cb, seek_cb_); |
997 } | 946 } |
998 | 947 |
999 if (!cb.is_null()) | 948 if (!cb.is_null()) cb.Run(PIPELINE_OK); |
1000 cb.Run(PIPELINE_OK); | |
1001 } | 949 } |
1002 | 950 |
1003 void ChunkDemuxer::Shutdown() { | 951 void ChunkDemuxer::Shutdown() { |
1004 DVLOG(1) << "Shutdown()"; | 952 DVLOG(1) << "Shutdown()"; |
1005 PipelineStatusCB cb; | 953 PipelineStatusCB cb; |
1006 { | 954 { |
1007 base::AutoLock auto_lock(lock_); | 955 base::AutoLock auto_lock(lock_); |
1008 | 956 |
1009 if (state_ == SHUTDOWN) | 957 if (state_ == SHUTDOWN) return; |
1010 return; | |
1011 | 958 |
1012 std::swap(cb, seek_cb_); | 959 std::swap(cb, seek_cb_); |
1013 | 960 |
1014 if (audio_) | 961 if (audio_) audio_->Shutdown(); |
1015 audio_->Shutdown(); | |
1016 | 962 |
1017 if (video_) | 963 if (video_) video_->Shutdown(); |
1018 video_->Shutdown(); | |
1019 | 964 |
1020 ChangeState_Locked(SHUTDOWN); | 965 ChangeState_Locked(SHUTDOWN); |
1021 } | 966 } |
1022 | 967 |
1023 if (!cb.is_null()) | 968 if (!cb.is_null()) cb.Run(PIPELINE_ERROR_ABORT); |
1024 cb.Run(PIPELINE_ERROR_ABORT); | |
1025 } | 969 } |
1026 | 970 |
1027 void ChunkDemuxer::ChangeState_Locked(State new_state) { | 971 void ChunkDemuxer::ChangeState_Locked(State new_state) { |
1028 lock_.AssertAcquired(); | 972 lock_.AssertAcquired(); |
1029 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " | 973 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " << state_ << " -> " |
1030 << state_ << " -> " << new_state; | 974 << new_state; |
1031 state_ = new_state; | 975 state_ = new_state; |
1032 } | 976 } |
1033 | 977 |
1034 ChunkDemuxer::~ChunkDemuxer() { | 978 ChunkDemuxer::~ChunkDemuxer() { |
1035 DCHECK_NE(state_, INITIALIZED); | 979 DCHECK_NE(state_, INITIALIZED); |
1036 for (SourceStateMap::iterator it = source_state_map_.begin(); | 980 for (SourceStateMap::iterator it = source_state_map_.begin(); |
1037 it != source_state_map_.end(); ++it) { | 981 it != source_state_map_.end(); ++it) { |
1038 delete it->second; | 982 delete it->second; |
1039 } | 983 } |
1040 source_state_map_.clear(); | 984 source_state_map_.clear(); |
1041 } | 985 } |
1042 | 986 |
1043 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { | 987 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { |
1044 DVLOG(1) << "ReportError_Locked(" << error << ")"; | 988 DVLOG(1) << "ReportError_Locked(" << error << ")"; |
1045 lock_.AssertAcquired(); | 989 lock_.AssertAcquired(); |
1046 DCHECK_NE(error, PIPELINE_OK); | 990 DCHECK_NE(error, PIPELINE_OK); |
1047 | 991 |
1048 ChangeState_Locked(PARSE_ERROR); | 992 ChangeState_Locked(PARSE_ERROR); |
1049 | 993 |
1050 PipelineStatusCB cb; | 994 PipelineStatusCB cb; |
1051 | 995 |
1052 if (!init_cb_.is_null()) { | 996 if (!init_cb_.is_null()) { |
1053 std::swap(cb, init_cb_); | 997 std::swap(cb, init_cb_); |
1054 } else { | 998 } else { |
1055 if (!seek_cb_.is_null()) | 999 if (!seek_cb_.is_null()) std::swap(cb, seek_cb_); |
1056 std::swap(cb, seek_cb_); | |
1057 | 1000 |
1058 if (audio_) | 1001 if (audio_) audio_->Shutdown(); |
1059 audio_->Shutdown(); | |
1060 | 1002 |
1061 if (video_) | 1003 if (video_) video_->Shutdown(); |
1062 video_->Shutdown(); | |
1063 } | 1004 } |
1064 | 1005 |
1065 if (!cb.is_null()) { | 1006 if (!cb.is_null()) { |
1066 base::AutoUnlock auto_unlock(lock_); | 1007 base::AutoUnlock auto_unlock(lock_); |
1067 cb.Run(error); | 1008 cb.Run(error); |
1068 return; | 1009 return; |
1069 } | 1010 } |
1070 | 1011 |
1071 base::AutoUnlock auto_unlock(lock_); | 1012 base::AutoUnlock auto_unlock(lock_); |
1072 host_->OnDemuxerError(error); | 1013 host_->OnDemuxerError(error); |
1073 } | 1014 } |
1074 | 1015 |
1075 bool ChunkDemuxer::IsSeekPending_Locked() const { | 1016 bool ChunkDemuxer::IsSeekPending_Locked() const { |
1076 lock_.AssertAcquired(); | 1017 lock_.AssertAcquired(); |
1077 bool seek_pending = false; | 1018 bool seek_pending = false; |
1078 | 1019 |
1079 if (audio_) | 1020 if (audio_) seek_pending = audio_->IsSeekPending(); |
1080 seek_pending = audio_->IsSeekPending(); | |
1081 | 1021 |
1082 if (!seek_pending && video_) | 1022 if (!seek_pending && video_) seek_pending = video_->IsSeekPending(); |
1083 seek_pending = video_->IsSeekPending(); | |
1084 | 1023 |
1085 return seek_pending; | 1024 return seek_pending; |
1086 } | 1025 } |
1087 | 1026 |
1088 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { | 1027 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { |
1089 DVLOG(1) << "OnSourceInitDone(" << success << ", " | 1028 DVLOG(1) << "OnSourceInitDone(" << success << ", " << duration.InSecondsF() |
1090 << duration.InSecondsF() << ")"; | 1029 << ")"; |
1091 lock_.AssertAcquired(); | 1030 lock_.AssertAcquired(); |
1092 DCHECK_EQ(state_, INITIALIZING); | 1031 DCHECK_EQ(state_, INITIALIZING); |
1093 if (!success || (!audio_ && !video_)) { | 1032 if (!success || (!audio_ && !video_)) { |
1094 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1033 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1095 return; | 1034 return; |
1096 } | 1035 } |
1097 | 1036 |
1098 if (duration != base::TimeDelta() && duration_ == kNoTimestamp()) | 1037 if (duration != base::TimeDelta() && duration_ == kNoTimestamp()) |
1099 UpdateDuration(duration); | 1038 UpdateDuration(duration); |
1100 | 1039 |
1101 // Wait until all streams have initialized. | 1040 // Wait until all streams have initialized. |
1102 if ((!source_id_audio_.empty() && !audio_) || | 1041 if ((!source_id_audio_.empty() && !audio_) || |
1103 (!source_id_video_.empty() && !video_)) | 1042 (!source_id_video_.empty() && !video_)) |
1104 return; | 1043 return; |
1105 | 1044 |
1106 if (audio_) | 1045 if (audio_) audio_->Seek(TimeDelta()); |
1107 audio_->Seek(TimeDelta()); | |
1108 | 1046 |
1109 if (video_) | 1047 if (video_) video_->Seek(TimeDelta()); |
1110 video_->Seek(TimeDelta()); | |
1111 | 1048 |
1112 if (duration_ == kNoTimestamp()) | 1049 if (duration_ == kNoTimestamp()) duration_ = kInfiniteDuration(); |
1113 duration_ = kInfiniteDuration(); | |
1114 | 1050 |
1115 // The demuxer is now initialized after the |start_timestamp_| was set. | 1051 // The demuxer is now initialized after the |start_timestamp_| was set. |
1116 ChangeState_Locked(INITIALIZED); | 1052 ChangeState_Locked(INITIALIZED); |
1117 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1053 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
1118 } | 1054 } |
1119 | 1055 |
1120 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, | 1056 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, |
1121 const AudioDecoderConfig& audio_config, | 1057 const AudioDecoderConfig& audio_config, |
1122 const VideoDecoderConfig& video_config) { | 1058 const VideoDecoderConfig& video_config) { |
1123 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video | 1059 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video << ", " |
1124 << ", " << audio_config.IsValidConfig() | 1060 << audio_config.IsValidConfig() << ", " |
1125 << ", " << video_config.IsValidConfig() << ")"; | 1061 << video_config.IsValidConfig() << ")"; |
1126 lock_.AssertAcquired(); | 1062 lock_.AssertAcquired(); |
1127 | 1063 |
1128 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { | 1064 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { |
1129 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; | 1065 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; |
1130 return false; | 1066 return false; |
1131 } | 1067 } |
1132 | 1068 |
1133 // Signal an error if we get configuration info for stream types that weren't | 1069 // Signal an error if we get configuration info for stream types that weren't |
1134 // specified in AddId() or more configs after a stream is initialized. | 1070 // specified in AddId() or more configs after a stream is initialized. |
1135 // Only allow a single audio config for now. | 1071 // Only allow a single audio config for now. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1172 } | 1108 } |
1173 | 1109 |
1174 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 1110 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
1175 return success; | 1111 return success; |
1176 } | 1112 } |
1177 | 1113 |
1178 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { | 1114 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { |
1179 lock_.AssertAcquired(); | 1115 lock_.AssertAcquired(); |
1180 DCHECK_NE(state_, SHUTDOWN); | 1116 DCHECK_NE(state_, SHUTDOWN); |
1181 | 1117 |
1182 if (!audio_) | 1118 if (!audio_) return false; |
1183 return false; | |
1184 | 1119 |
1185 CHECK(IsValidId(source_id_audio_)); | 1120 CHECK(IsValidId(source_id_audio_)); |
1186 if (!audio_->Append(buffers)) | 1121 if (!audio_->Append(buffers)) return false; |
1187 return false; | |
1188 | 1122 |
1189 IncreaseDurationIfNecessary(buffers, audio_.get()); | 1123 IncreaseDurationIfNecessary(buffers, audio_.get()); |
1190 return true; | 1124 return true; |
1191 } | 1125 } |
1192 | 1126 |
1193 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { | 1127 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { |
1194 lock_.AssertAcquired(); | 1128 lock_.AssertAcquired(); |
1195 DCHECK_NE(state_, SHUTDOWN); | 1129 DCHECK_NE(state_, SHUTDOWN); |
1196 | 1130 |
1197 if (!video_) | 1131 if (!video_) return false; |
1198 return false; | |
1199 | 1132 |
1200 CHECK(IsValidId(source_id_video_)); | 1133 CHECK(IsValidId(source_id_video_)); |
1201 if (!video_->Append(buffers)) | 1134 if (!video_->Append(buffers)) return false; |
1202 return false; | |
1203 | 1135 |
1204 IncreaseDurationIfNecessary(buffers, video_.get()); | 1136 IncreaseDurationIfNecessary(buffers, video_.get()); |
1205 return true; | 1137 return true; |
1206 } | 1138 } |
1207 | 1139 |
1208 bool ChunkDemuxer::OnTextBuffers( | 1140 bool ChunkDemuxer::OnTextBuffers(TextTrack* text_track, |
1209 TextTrack* text_track, | 1141 const StreamParser::BufferQueue& buffers) { |
1210 const StreamParser::BufferQueue& buffers) { | |
1211 lock_.AssertAcquired(); | 1142 lock_.AssertAcquired(); |
1212 DCHECK_NE(state_, SHUTDOWN); | 1143 DCHECK_NE(state_, SHUTDOWN); |
1213 | 1144 |
1214 // TODO(matthewjheaney): IncreaseDurationIfNecessary | 1145 // TODO(matthewjheaney): IncreaseDurationIfNecessary |
1215 | 1146 |
1216 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); | 1147 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); |
1217 itr != buffers.end(); ++itr) { | 1148 itr != buffers.end(); ++itr) { |
1218 const StreamParserBuffer* const buffer = itr->get(); | 1149 const StreamParserBuffer* const buffer = itr->get(); |
1219 const base::TimeDelta start = buffer->GetTimestamp(); | 1150 const base::TimeDelta start = buffer->get_timestamp(); |
1220 const base::TimeDelta end = start + buffer->GetDuration(); | 1151 const base::TimeDelta end = start + buffer->get_duration(); |
1221 | 1152 |
1222 std::string id, settings, content; | 1153 std::string id, settings, content; |
1223 | 1154 |
1224 WebMWebVTTParser::Parse(buffer->GetData(), | 1155 WebMWebVTTParser::Parse(buffer->get_data(), buffer->get_data_size(), &id, |
1225 buffer->GetDataSize(), | 1156 &settings, &content); |
1226 &id, &settings, &content); | |
1227 | 1157 |
1228 text_track->addWebVTTCue(start, end, id, content, settings); | 1158 text_track->addWebVTTCue(start, end, id, content, settings); |
1229 } | 1159 } |
1230 | 1160 |
1231 return true; | 1161 return true; |
1232 } | 1162 } |
1233 | 1163 |
1234 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that | 1164 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that |
1235 // this method can be removed and need_key_cb_ can be passed directly | 1165 // this method can be removed and need_key_cb_ can be passed directly |
1236 // to the parser. | 1166 // to the parser. |
(...skipping 25 matching lines...) Expand all Loading... |
1262 } | 1192 } |
1263 | 1193 |
1264 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { | 1194 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { |
1265 DCHECK(duration_ != new_duration); | 1195 DCHECK(duration_ != new_duration); |
1266 user_specified_duration_ = -1; | 1196 user_specified_duration_ = -1; |
1267 duration_ = new_duration; | 1197 duration_ = new_duration; |
1268 host_->SetDuration(new_duration); | 1198 host_->SetDuration(new_duration); |
1269 } | 1199 } |
1270 | 1200 |
1271 void ChunkDemuxer::IncreaseDurationIfNecessary( | 1201 void ChunkDemuxer::IncreaseDurationIfNecessary( |
1272 const StreamParser::BufferQueue& buffers, | 1202 const StreamParser::BufferQueue& buffers, ChunkDemuxerStream* stream) { |
1273 ChunkDemuxerStream* stream) { | |
1274 DCHECK(!buffers.empty()); | 1203 DCHECK(!buffers.empty()); |
1275 if (buffers.back()->GetTimestamp() <= duration_) | 1204 if (buffers.back()->get_timestamp() <= duration_) return; |
1276 return; | |
1277 | 1205 |
1278 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); | 1206 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); |
1279 DCHECK_GT(ranges.size(), 0u); | 1207 DCHECK_GT(ranges.size(), 0u); |
1280 | 1208 |
1281 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); | 1209 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
1282 if (last_timestamp_buffered > duration_) | 1210 if (last_timestamp_buffered > duration_) |
1283 UpdateDuration(last_timestamp_buffered); | 1211 UpdateDuration(last_timestamp_buffered); |
1284 } | 1212 } |
1285 | 1213 |
1286 void ChunkDemuxer::DecreaseDurationIfNecessary() { | 1214 void ChunkDemuxer::DecreaseDurationIfNecessary() { |
1287 Ranges<TimeDelta> ranges = GetBufferedRanges(); | 1215 Ranges<TimeDelta> ranges = GetBufferedRanges(); |
1288 if (ranges.size() == 0u) | 1216 if (ranges.size() == 0u) return; |
1289 return; | |
1290 | 1217 |
1291 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); | 1218 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
1292 if (last_timestamp_buffered < duration_) | 1219 if (last_timestamp_buffered < duration_) |
1293 UpdateDuration(last_timestamp_buffered); | 1220 UpdateDuration(last_timestamp_buffered); |
1294 } | 1221 } |
1295 | 1222 |
1296 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1223 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
1297 if (audio_ && !video_) | 1224 if (audio_ && !video_) |
1298 return audio_->GetBufferedRanges(duration_); | 1225 return audio_->GetBufferedRanges(duration_); |
1299 else if (!audio_ && video_) | 1226 else if (!audio_ && video_) |
1300 return video_->GetBufferedRanges(duration_); | 1227 return video_->GetBufferedRanges(duration_); |
1301 return ComputeIntersection(); | 1228 return ComputeIntersection(); |
1302 } | 1229 } |
1303 | 1230 |
1304 } // namespace media | 1231 } // namespace media |
OLD | NEW |