Chromium Code Reviews| 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 |