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 #include <list> | 10 #include <list> |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 const NewTextTrackCB& new_text_track_cb); | 107 const NewTextTrackCB& new_text_track_cb); |
108 | 108 |
109 // Appends new data to the StreamParser. | 109 // Appends new data to the StreamParser. |
110 // Returns true if the data was successfully appended. Returns false if an | 110 // Returns true if the data was successfully appended. Returns false if an |
111 // error occurred. | 111 // error occurred. |
112 bool Append(const uint8* data, size_t length); | 112 bool Append(const uint8* data, size_t length); |
113 | 113 |
114 // Aborts the current append sequence and resets the parser. | 114 // Aborts the current append sequence and resets the parser. |
115 void Abort(); | 115 void Abort(); |
116 | 116 |
117 // Calls Remove(|start|, |end|, |duration|) on all | |
118 // ChunkDemuxerStreams managed by this object. | |
119 void Remove(base::TimeDelta start, base::TimeDelta end, | |
120 base::TimeDelta duration); | |
xhwang
2013/12/28 01:06:03
Here and in this file, pass base::TimeDelta by con
acolwell GONE FROM CHROMIUM
2013/12/28 02:17:10
I've talked with scherkus@ and fischman@ about thi
xhwang
2013/12/30 17:53:38
sg. thanks for the explanation.
| |
121 | |
117 // Sets |timestamp_offset_| if possible. | 122 // Sets |timestamp_offset_| if possible. |
118 // Returns if the offset was set. Returns false if the offset could not be | 123 // Returns if the offset was set. Returns false if the offset could not be |
119 // updated at this time. | 124 // updated at this time. |
120 bool SetTimestampOffset(TimeDelta timestamp_offset); | 125 bool SetTimestampOffset(TimeDelta timestamp_offset); |
121 | 126 |
122 TimeDelta timestamp_offset() const { return timestamp_offset_; } | 127 TimeDelta timestamp_offset() const { return timestamp_offset_; } |
123 | 128 |
124 void set_append_window_start(TimeDelta start) { | 129 void set_append_window_start(TimeDelta start) { |
125 append_window_start_ = start; | 130 append_window_start_ = start; |
126 } | 131 } |
127 void set_append_window_end(TimeDelta end) { append_window_end_ = end; } | 132 void set_append_window_end(TimeDelta end) { append_window_end_ = end; } |
128 | 133 |
129 // Returns the range of buffered data in this source, capped at |duration|. | 134 // Returns the range of buffered data in this source, capped at |duration|. |
130 // |ended| - Set to true if end of stream has been signalled and the special | 135 // |ended| - Set to true if end of stream has been signalled and the special |
131 // end of stream range logic needs to be executed. | 136 // end of stream range logic needs to be executed. |
132 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const; | 137 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const; |
133 | 138 |
139 // Helper methods that call methods with similar names on all the | |
140 // ChunkDemuxerStreams managed by this object. | |
134 void StartReturningData(); | 141 void StartReturningData(); |
135 void AbortReads(); | 142 void AbortReads(); |
136 void Seek(TimeDelta seek_time); | 143 void Seek(TimeDelta seek_time); |
137 void CompletePendingReadIfPossible(); | 144 void CompletePendingReadIfPossible(); |
145 void OnSetDuration(TimeDelta duration); | |
146 void MarkEndOfStream(); | |
147 void UnmarkEndOfStream(); | |
148 void Shutdown(); | |
149 void SetMemoryLimitsForTesting(int memory_limit); | |
xhwang
2013/12/28 01:06:03
Is |memory_limit| in KB or MB?
acolwell GONE FROM CHROMIUM
2014/01/08 02:16:49
It's bytes. I've added a comment clarifying this h
| |
150 bool IsSeekWaitingForData() const; | |
138 | 151 |
139 private: | 152 private: |
140 // Called by the |stream_parser_| when a new initialization segment is | 153 // Called by the |stream_parser_| when a new initialization segment is |
141 // encountered. | 154 // encountered. |
142 // Returns true on a successful call. Returns false if an error occured while | 155 // Returns true on a successful call. Returns false if an error occured while |
143 // processing decoder configurations. | 156 // processing decoder configurations. |
144 bool OnNewConfigs(bool allow_audio, bool allow_video, | 157 bool OnNewConfigs(bool allow_audio, bool allow_video, |
145 const AudioDecoderConfig& audio_config, | 158 const AudioDecoderConfig& audio_config, |
146 const VideoDecoderConfig& video_config, | 159 const VideoDecoderConfig& video_config, |
147 const StreamParser::TextTrackConfigMap& text_configs); | 160 const StreamParser::TextTrackConfigMap& text_configs); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 audio_(NULL), | 345 audio_(NULL), |
333 audio_needs_keyframe_(true), | 346 audio_needs_keyframe_(true), |
334 video_(NULL), | 347 video_(NULL), |
335 video_needs_keyframe_(true), | 348 video_needs_keyframe_(true), |
336 log_cb_(log_cb) { | 349 log_cb_(log_cb) { |
337 DCHECK(!create_demuxer_stream_cb_.is_null()); | 350 DCHECK(!create_demuxer_stream_cb_.is_null()); |
338 DCHECK(!increase_duration_cb_.is_null()); | 351 DCHECK(!increase_duration_cb_.is_null()); |
339 } | 352 } |
340 | 353 |
341 SourceState::~SourceState() { | 354 SourceState::~SourceState() { |
342 if (audio_) | 355 Shutdown(); |
343 audio_->Shutdown(); | |
344 | 356 |
345 if (video_) | 357 STLDeleteValues(&text_stream_map_); |
346 video_->Shutdown(); | |
347 | |
348 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
349 itr != text_stream_map_.end(); ++itr) { | |
350 itr->second->Shutdown(); | |
351 delete itr->second; | |
352 } | |
353 } | 358 } |
354 | 359 |
355 void SourceState::Init(const StreamParser::InitCB& init_cb, | 360 void SourceState::Init(const StreamParser::InitCB& init_cb, |
356 bool allow_audio, | 361 bool allow_audio, |
357 bool allow_video, | 362 bool allow_video, |
358 const StreamParser::NeedKeyCB& need_key_cb, | 363 const StreamParser::NeedKeyCB& need_key_cb, |
359 const NewTextTrackCB& new_text_track_cb) { | 364 const NewTextTrackCB& new_text_track_cb) { |
360 new_text_track_cb_ = new_text_track_cb; | 365 new_text_track_cb_ = new_text_track_cb; |
361 | 366 |
362 StreamParser::NewTextBuffersCB new_text_buffers_cb; | 367 StreamParser::NewTextBuffersCB new_text_buffers_cb; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 return stream_parser_->Parse(data, length); | 399 return stream_parser_->Parse(data, length); |
395 } | 400 } |
396 | 401 |
397 void SourceState::Abort() { | 402 void SourceState::Abort() { |
398 stream_parser_->Flush(); | 403 stream_parser_->Flush(); |
399 audio_needs_keyframe_ = true; | 404 audio_needs_keyframe_ = true; |
400 video_needs_keyframe_ = true; | 405 video_needs_keyframe_ = true; |
401 can_update_offset_ = true; | 406 can_update_offset_ = true; |
402 } | 407 } |
403 | 408 |
409 void SourceState::Remove(base::TimeDelta start, base::TimeDelta end, | |
410 base::TimeDelta duration) { | |
411 if (audio_) | |
412 audio_->Remove(start, end, duration); | |
413 | |
414 if (video_) | |
415 video_->Remove(start, end, duration); | |
416 | |
417 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
418 itr != text_stream_map_.end(); ++itr) { | |
419 itr->second->Remove(start, end, duration); | |
420 } | |
421 } | |
422 | |
404 Ranges<TimeDelta> SourceState::GetBufferedRanges(TimeDelta duration, | 423 Ranges<TimeDelta> SourceState::GetBufferedRanges(TimeDelta duration, |
405 bool ended) const { | 424 bool ended) const { |
406 // TODO(acolwell): When we start allowing disabled tracks we'll need to update | 425 // TODO(acolwell): When we start allowing disabled tracks we'll need to update |
407 // this code to only add ranges from active tracks. | 426 // this code to only add ranges from active tracks. |
408 RangesList ranges_list; | 427 RangesList ranges_list; |
409 if (audio_) | 428 if (audio_) |
410 ranges_list.push_back(audio_->GetBufferedRanges(duration)); | 429 ranges_list.push_back(audio_->GetBufferedRanges(duration)); |
411 | 430 |
412 if (video_) | 431 if (video_) |
413 ranges_list.push_back(video_->GetBufferedRanges(duration)); | 432 ranges_list.push_back(video_->GetBufferedRanges(duration)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 | 485 |
467 if (video_) | 486 if (video_) |
468 video_->CompletePendingReadIfPossible(); | 487 video_->CompletePendingReadIfPossible(); |
469 | 488 |
470 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | 489 for (TextStreamMap::iterator itr = text_stream_map_.begin(); |
471 itr != text_stream_map_.end(); ++itr) { | 490 itr != text_stream_map_.end(); ++itr) { |
472 itr->second->CompletePendingReadIfPossible(); | 491 itr->second->CompletePendingReadIfPossible(); |
473 } | 492 } |
474 } | 493 } |
475 | 494 |
495 void SourceState::OnSetDuration(TimeDelta duration) { | |
496 if (audio_) | |
497 audio_->OnSetDuration(duration); | |
498 | |
499 if (video_) | |
500 video_->OnSetDuration(duration); | |
501 | |
502 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
503 itr != text_stream_map_.end(); ++itr) { | |
504 itr->second->OnSetDuration(duration); | |
505 } | |
506 } | |
507 | |
508 void SourceState::MarkEndOfStream() { | |
509 if (audio_) | |
510 audio_->MarkEndOfStream(); | |
511 | |
512 if (video_) | |
513 video_->MarkEndOfStream(); | |
514 | |
515 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
516 itr != text_stream_map_.end(); ++itr) { | |
517 itr->second->MarkEndOfStream(); | |
518 } | |
519 } | |
520 | |
521 void SourceState::UnmarkEndOfStream() { | |
522 if (audio_) | |
523 audio_->UnmarkEndOfStream(); | |
524 | |
525 if (video_) | |
526 video_->UnmarkEndOfStream(); | |
527 | |
528 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
529 itr != text_stream_map_.end(); ++itr) { | |
530 itr->second->UnmarkEndOfStream(); | |
531 } | |
532 } | |
533 | |
534 void SourceState::Shutdown() { | |
535 if (audio_) | |
536 audio_->Shutdown(); | |
537 | |
538 if (video_) | |
539 video_->Shutdown(); | |
540 | |
541 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
542 itr != text_stream_map_.end(); ++itr) { | |
543 itr->second->Shutdown(); | |
544 } | |
545 } | |
546 | |
547 void SourceState::SetMemoryLimitsForTesting(int memory_limit) { | |
548 if (audio_) | |
549 audio_->set_memory_limit_for_testing(memory_limit); | |
550 | |
551 if (video_) | |
552 video_->set_memory_limit_for_testing(memory_limit); | |
553 | |
554 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | |
555 itr != text_stream_map_.end(); ++itr) { | |
556 itr->second->set_memory_limit_for_testing(memory_limit); | |
557 } | |
558 } | |
559 | |
560 bool SourceState::IsSeekWaitingForData() const { | |
561 if (audio_ && audio_->IsSeekWaitingForData()) | |
562 return true; | |
563 | |
564 if (video_ && video_->IsSeekWaitingForData()) | |
565 return true; | |
566 | |
567 for (TextStreamMap::const_iterator itr = text_stream_map_.begin(); | |
568 itr != text_stream_map_.end(); ++itr) { | |
569 if (itr->second->IsSeekWaitingForData()) | |
570 return true; | |
571 } | |
572 | |
573 return false; | |
574 } | |
575 | |
476 void SourceState::AdjustBufferTimestamps( | 576 void SourceState::AdjustBufferTimestamps( |
477 const StreamParser::BufferQueue& buffers) { | 577 const StreamParser::BufferQueue& buffers) { |
478 if (timestamp_offset_ == TimeDelta()) | 578 if (timestamp_offset_ == TimeDelta()) |
479 return; | 579 return; |
480 | 580 |
481 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); | 581 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); |
482 itr != buffers.end(); ++itr) { | 582 itr != buffers.end(); ++itr) { |
483 (*itr)->SetDecodeTimestamp( | 583 (*itr)->SetDecodeTimestamp( |
484 (*itr)->GetDecodeTimestamp() + timestamp_offset_); | 584 (*itr)->GetDecodeTimestamp() + timestamp_offset_); |
485 (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset_); | 585 (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset_); |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1283 CHECK(IsValidId(id)); | 1383 CHECK(IsValidId(id)); |
1284 source_state_map_[id]->Abort(); | 1384 source_state_map_[id]->Abort(); |
1285 } | 1385 } |
1286 | 1386 |
1287 void ChunkDemuxer::Remove(const std::string& id, base::TimeDelta start, | 1387 void ChunkDemuxer::Remove(const std::string& id, base::TimeDelta start, |
1288 base::TimeDelta end) { | 1388 base::TimeDelta end) { |
1289 DVLOG(1) << "Remove(" << id << ", " << start.InSecondsF() | 1389 DVLOG(1) << "Remove(" << id << ", " << start.InSecondsF() |
1290 << ", " << end.InSecondsF() << ")"; | 1390 << ", " << end.InSecondsF() << ")"; |
1291 base::AutoLock auto_lock(lock_); | 1391 base::AutoLock auto_lock(lock_); |
1292 | 1392 |
1293 if (id == source_id_audio_ && audio_) | 1393 DCHECK(!id.empty()); |
1294 audio_->Remove(start, end, duration_); | 1394 CHECK(IsValidId(id)); |
1295 | 1395 source_state_map_[id]->Remove(start, end, duration_); |
1296 if (id == source_id_video_ && video_) | |
1297 video_->Remove(start, end, duration_); | |
1298 } | 1396 } |
1299 | 1397 |
1300 double ChunkDemuxer::GetDuration() { | 1398 double ChunkDemuxer::GetDuration() { |
1301 base::AutoLock auto_lock(lock_); | 1399 base::AutoLock auto_lock(lock_); |
1302 return GetDuration_Locked(); | 1400 return GetDuration_Locked(); |
1303 } | 1401 } |
1304 | 1402 |
1305 double ChunkDemuxer::GetDuration_Locked() { | 1403 double ChunkDemuxer::GetDuration_Locked() { |
1306 lock_.AssertAcquired(); | 1404 lock_.AssertAcquired(); |
1307 if (duration_ == kNoTimestamp()) | 1405 if (duration_ == kNoTimestamp()) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1345 duration_td = TimeDelta::FromMicroseconds( | 1443 duration_td = TimeDelta::FromMicroseconds( |
1346 duration * base::Time::kMicrosecondsPerSecond); | 1444 duration * base::Time::kMicrosecondsPerSecond); |
1347 } | 1445 } |
1348 | 1446 |
1349 DCHECK(duration_td > TimeDelta()); | 1447 DCHECK(duration_td > TimeDelta()); |
1350 | 1448 |
1351 user_specified_duration_ = duration; | 1449 user_specified_duration_ = duration; |
1352 duration_ = duration_td; | 1450 duration_ = duration_td; |
1353 host_->SetDuration(duration_); | 1451 host_->SetDuration(duration_); |
1354 | 1452 |
1355 if (audio_) | 1453 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1356 audio_->OnSetDuration(duration_); | 1454 itr != source_state_map_.end(); ++itr) { |
1357 | 1455 itr->second->OnSetDuration(duration_); |
1358 if (video_) | 1456 } |
1359 video_->OnSetDuration(duration_); | |
1360 } | 1457 } |
1361 | 1458 |
1362 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { | 1459 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { |
1363 base::AutoLock auto_lock(lock_); | 1460 base::AutoLock auto_lock(lock_); |
1364 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; | 1461 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; |
1365 CHECK(IsValidId(id)); | 1462 CHECK(IsValidId(id)); |
1366 | 1463 |
1367 return source_state_map_[id]->SetTimestampOffset(offset); | 1464 return source_state_map_[id]->SetTimestampOffset(offset); |
1368 } | 1465 } |
1369 | 1466 |
1370 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { | 1467 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { |
1371 DVLOG(1) << "MarkEndOfStream(" << status << ")"; | 1468 DVLOG(1) << "MarkEndOfStream(" << status << ")"; |
1372 base::AutoLock auto_lock(lock_); | 1469 base::AutoLock auto_lock(lock_); |
1373 DCHECK_NE(state_, WAITING_FOR_INIT); | 1470 DCHECK_NE(state_, WAITING_FOR_INIT); |
1374 DCHECK_NE(state_, ENDED); | 1471 DCHECK_NE(state_, ENDED); |
1375 | 1472 |
1376 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) | 1473 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) |
1377 return; | 1474 return; |
1378 | 1475 |
1379 if (state_ == INITIALIZING) { | 1476 if (state_ == INITIALIZING) { |
1380 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1477 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1381 return; | 1478 return; |
1382 } | 1479 } |
1383 | 1480 |
1384 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); | 1481 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); |
1385 if (audio_) | 1482 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1386 audio_->MarkEndOfStream(); | 1483 itr != source_state_map_.end(); ++itr) { |
1387 | 1484 itr->second->MarkEndOfStream(); |
1388 if (video_) | 1485 } |
1389 video_->MarkEndOfStream(); | |
1390 | 1486 |
1391 CompletePendingReadsIfPossible(); | 1487 CompletePendingReadsIfPossible(); |
1392 | 1488 |
1393 // Give a chance to resume the pending seek process. | 1489 // Give a chance to resume the pending seek process. |
1394 if (status != PIPELINE_OK) { | 1490 if (status != PIPELINE_OK) { |
1395 ReportError_Locked(status); | 1491 ReportError_Locked(status); |
1396 return; | 1492 return; |
1397 } | 1493 } |
1398 | 1494 |
1399 ChangeState_Locked(ENDED); | 1495 ChangeState_Locked(ENDED); |
1400 DecreaseDurationIfNecessary(); | 1496 DecreaseDurationIfNecessary(); |
1401 | 1497 |
1402 if (old_waiting_for_data && !IsSeekWaitingForData_Locked() && | 1498 if (old_waiting_for_data && !IsSeekWaitingForData_Locked() && |
1403 !seek_cb_.is_null()) { | 1499 !seek_cb_.is_null()) { |
1404 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | 1500 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
1405 } | 1501 } |
1406 } | 1502 } |
1407 | 1503 |
1408 void ChunkDemuxer::UnmarkEndOfStream() { | 1504 void ChunkDemuxer::UnmarkEndOfStream() { |
1409 DVLOG(1) << "UnmarkEndOfStream()"; | 1505 DVLOG(1) << "UnmarkEndOfStream()"; |
1410 base::AutoLock auto_lock(lock_); | 1506 base::AutoLock auto_lock(lock_); |
1411 DCHECK_EQ(state_, ENDED); | 1507 DCHECK_EQ(state_, ENDED); |
1412 | 1508 |
1413 ChangeState_Locked(INITIALIZED); | 1509 ChangeState_Locked(INITIALIZED); |
1414 | 1510 |
1415 if (audio_) | 1511 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1416 audio_->UnmarkEndOfStream(); | 1512 itr != source_state_map_.end(); ++itr) { |
1417 | 1513 itr->second->UnmarkEndOfStream(); |
1418 if (video_) | 1514 } |
1419 video_->UnmarkEndOfStream(); | |
1420 } | 1515 } |
1421 | 1516 |
1422 void ChunkDemuxer::SetAppendWindowStart(const std::string& id, | 1517 void ChunkDemuxer::SetAppendWindowStart(const std::string& id, |
1423 TimeDelta start) { | 1518 TimeDelta start) { |
1424 base::AutoLock auto_lock(lock_); | 1519 base::AutoLock auto_lock(lock_); |
1425 DVLOG(1) << "SetAppendWindowStart(" << id << ", " | 1520 DVLOG(1) << "SetAppendWindowStart(" << id << ", " |
1426 << start.InSecondsF() << ")"; | 1521 << start.InSecondsF() << ")"; |
1427 CHECK(IsValidId(id)); | 1522 CHECK(IsValidId(id)); |
1428 source_state_map_[id]->set_append_window_start(start); | 1523 source_state_map_[id]->set_append_window_start(start); |
1429 } | 1524 } |
1430 | 1525 |
1431 void ChunkDemuxer::SetAppendWindowEnd(const std::string& id, TimeDelta end) { | 1526 void ChunkDemuxer::SetAppendWindowEnd(const std::string& id, TimeDelta end) { |
1432 base::AutoLock auto_lock(lock_); | 1527 base::AutoLock auto_lock(lock_); |
1433 DVLOG(1) << "SetAppendWindowEnd(" << id << ", " << end.InSecondsF() << ")"; | 1528 DVLOG(1) << "SetAppendWindowEnd(" << id << ", " << end.InSecondsF() << ")"; |
1434 CHECK(IsValidId(id)); | 1529 CHECK(IsValidId(id)); |
1435 source_state_map_[id]->set_append_window_end(end); | 1530 source_state_map_[id]->set_append_window_end(end); |
1436 } | 1531 } |
1437 | 1532 |
1438 void ChunkDemuxer::Shutdown() { | 1533 void ChunkDemuxer::Shutdown() { |
1439 DVLOG(1) << "Shutdown()"; | 1534 DVLOG(1) << "Shutdown()"; |
1440 base::AutoLock auto_lock(lock_); | 1535 base::AutoLock auto_lock(lock_); |
1441 | 1536 |
1442 if (state_ == SHUTDOWN) | 1537 if (state_ == SHUTDOWN) |
1443 return; | 1538 return; |
1444 | 1539 |
1445 if (audio_) | 1540 ShutdownAllStreams(); |
1446 audio_->Shutdown(); | |
1447 | |
1448 if (video_) | |
1449 video_->Shutdown(); | |
1450 | 1541 |
1451 ChangeState_Locked(SHUTDOWN); | 1542 ChangeState_Locked(SHUTDOWN); |
1452 | 1543 |
1453 if(!seek_cb_.is_null()) | 1544 if(!seek_cb_.is_null()) |
1454 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT); | 1545 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT); |
1455 } | 1546 } |
1456 | 1547 |
1457 void ChunkDemuxer::SetMemoryLimitsForTesting(int memory_limit) { | 1548 void ChunkDemuxer::SetMemoryLimitsForTesting(int memory_limit) { |
1458 if (audio_) | 1549 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1459 audio_->set_memory_limit_for_testing(memory_limit); | 1550 itr != source_state_map_.end(); ++itr) { |
1460 | 1551 itr->second->SetMemoryLimitsForTesting(memory_limit); |
1461 if (video_) | 1552 } |
1462 video_->set_memory_limit_for_testing(memory_limit); | |
1463 } | 1553 } |
1464 | 1554 |
1465 void ChunkDemuxer::ChangeState_Locked(State new_state) { | 1555 void ChunkDemuxer::ChangeState_Locked(State new_state) { |
1466 lock_.AssertAcquired(); | 1556 lock_.AssertAcquired(); |
1467 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " | 1557 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " |
1468 << state_ << " -> " << new_state; | 1558 << state_ << " -> " << new_state; |
1469 state_ = new_state; | 1559 state_ = new_state; |
1470 } | 1560 } |
1471 | 1561 |
1472 ChunkDemuxer::~ChunkDemuxer() { | 1562 ChunkDemuxer::~ChunkDemuxer() { |
1473 DCHECK_NE(state_, INITIALIZED); | 1563 DCHECK_NE(state_, INITIALIZED); |
1474 for (SourceStateMap::iterator it = source_state_map_.begin(); | 1564 |
1475 it != source_state_map_.end(); ++it) { | 1565 STLDeleteValues(&source_state_map_); |
1476 delete it->second; | |
1477 } | |
1478 source_state_map_.clear(); | |
1479 } | 1566 } |
1480 | 1567 |
1481 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { | 1568 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { |
1482 DVLOG(1) << "ReportError_Locked(" << error << ")"; | 1569 DVLOG(1) << "ReportError_Locked(" << error << ")"; |
1483 lock_.AssertAcquired(); | 1570 lock_.AssertAcquired(); |
1484 DCHECK_NE(error, PIPELINE_OK); | 1571 DCHECK_NE(error, PIPELINE_OK); |
1485 | 1572 |
1486 ChangeState_Locked(PARSE_ERROR); | 1573 ChangeState_Locked(PARSE_ERROR); |
1487 | 1574 |
1488 PipelineStatusCB cb; | 1575 PipelineStatusCB cb; |
1489 | 1576 |
1490 if (!init_cb_.is_null()) { | 1577 if (!init_cb_.is_null()) { |
1491 std::swap(cb, init_cb_); | 1578 std::swap(cb, init_cb_); |
1492 } else { | 1579 } else { |
1493 if (!seek_cb_.is_null()) | 1580 if (!seek_cb_.is_null()) |
1494 std::swap(cb, seek_cb_); | 1581 std::swap(cb, seek_cb_); |
1495 | 1582 |
1496 if (audio_) | 1583 ShutdownAllStreams(); |
1497 audio_->Shutdown(); | |
1498 | |
1499 if (video_) | |
1500 video_->Shutdown(); | |
1501 } | 1584 } |
1502 | 1585 |
1503 if (!cb.is_null()) { | 1586 if (!cb.is_null()) { |
1504 cb.Run(error); | 1587 cb.Run(error); |
1505 return; | 1588 return; |
1506 } | 1589 } |
1507 | 1590 |
1508 base::AutoUnlock auto_unlock(lock_); | 1591 base::AutoUnlock auto_unlock(lock_); |
1509 host_->OnDemuxerError(error); | 1592 host_->OnDemuxerError(error); |
1510 } | 1593 } |
1511 | 1594 |
1512 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { | 1595 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { |
1513 lock_.AssertAcquired(); | 1596 lock_.AssertAcquired(); |
1514 bool waiting_for_data = false; | |
1515 | 1597 |
1516 if (audio_) | 1598 for (SourceStateMap::const_iterator itr = source_state_map_.begin(); |
1517 waiting_for_data = audio_->IsSeekWaitingForData(); | 1599 itr != source_state_map_.end(); ++itr) { |
1600 if (itr->second->IsSeekWaitingForData()) | |
1601 return true; | |
1602 } | |
1518 | 1603 |
1519 if (!waiting_for_data && video_) | 1604 return false; |
1520 waiting_for_data = video_->IsSeekWaitingForData(); | |
1521 | |
1522 return waiting_for_data; | |
1523 } | 1605 } |
1524 | 1606 |
1525 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { | 1607 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { |
1526 DVLOG(1) << "OnSourceInitDone(" << success << ", " | 1608 DVLOG(1) << "OnSourceInitDone(" << success << ", " |
1527 << duration.InSecondsF() << ")"; | 1609 << duration.InSecondsF() << ")"; |
1528 lock_.AssertAcquired(); | 1610 lock_.AssertAcquired(); |
1529 DCHECK_EQ(state_, INITIALIZING); | 1611 DCHECK_EQ(state_, INITIALIZING); |
1530 if (!success || (!audio_ && !video_)) { | 1612 if (!success || (!audio_ && !video_)) { |
1531 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1613 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1532 return; | 1614 return; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1665 } | 1747 } |
1666 } | 1748 } |
1667 | 1749 |
1668 void ChunkDemuxer::CompletePendingReadsIfPossible() { | 1750 void ChunkDemuxer::CompletePendingReadsIfPossible() { |
1669 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1751 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1670 itr != source_state_map_.end(); ++itr) { | 1752 itr != source_state_map_.end(); ++itr) { |
1671 itr->second->CompletePendingReadIfPossible(); | 1753 itr->second->CompletePendingReadIfPossible(); |
1672 } | 1754 } |
1673 } | 1755 } |
1674 | 1756 |
1757 void ChunkDemuxer::ShutdownAllStreams() { | |
1758 for (SourceStateMap::iterator itr = source_state_map_.begin(); | |
1759 itr != source_state_map_.end(); ++itr) { | |
1760 itr->second->Shutdown(); | |
1761 } | |
1762 } | |
1763 | |
1675 } // namespace media | 1764 } // namespace media |
OLD | NEW |