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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
516 } | 516 } |
517 | 517 |
518 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) | 518 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) |
519 : state_(WAITING_FOR_INIT), | 519 : state_(WAITING_FOR_INIT), |
520 host_(NULL), | 520 host_(NULL), |
521 client_(client), | 521 client_(client), |
522 start_time_(kNoTimestamp()) { | 522 start_time_(kNoTimestamp()) { |
523 DCHECK(client); | 523 DCHECK(client); |
524 } | 524 } |
525 | 525 |
526 void ChunkDemuxer::Initialize(DemuxerHost* host, | 526 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) { |
527 const PipelineStatusCB& cb) { | |
528 DVLOG(1) << "Init()"; | 527 DVLOG(1) << "Init()"; |
529 { | 528 { |
530 base::AutoLock auto_lock(lock_); | 529 base::AutoLock auto_lock(lock_); |
531 DCHECK_EQ(state_, WAITING_FOR_INIT); | 530 DCHECK_EQ(state_, WAITING_FOR_INIT); |
532 host_ = host; | 531 host_ = host; |
533 | 532 |
534 ChangeState_Locked(INITIALIZING); | 533 ChangeState_Locked(INITIALIZING); |
535 init_cb_ = cb; | 534 init_cb_ = cb; |
536 } | 535 } |
537 | 536 |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 DVLOG(1) << "AppendData(): called in unexpected state " << state_; | 780 DVLOG(1) << "AppendData(): called in unexpected state " << state_; |
782 return false; | 781 return false; |
783 } | 782 } |
784 | 783 |
785 // Check to see if data was appended at the pending seek point. This | 784 // Check to see if data was appended at the pending seek point. This |
786 // indicates we have parsed enough data to complete the seek. | 785 // indicates we have parsed enough data to complete the seek. |
787 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { | 786 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { |
788 std::swap(cb, seek_cb_); | 787 std::swap(cb, seek_cb_); |
789 } | 788 } |
790 | 789 |
791 if (audio_ && !video_) { | 790 ranges = GetBufferedRanges(); |
792 ranges = audio_->GetBufferedRanges(); | |
793 } else if (!audio_ && video_) { | |
794 ranges = video_->GetBufferedRanges(); | |
795 } else { | |
796 ranges = ComputeIntersection(); | |
797 } | |
798 } | 791 } |
799 | 792 |
800 for (size_t i = 0; i < ranges.size(); ++i) | 793 for (size_t i = 0; i < ranges.size(); ++i) |
801 host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i)); | 794 host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i)); |
802 | 795 |
803 if (!cb.is_null()) | 796 if (!cb.is_null()) |
804 cb.Run(PIPELINE_OK); | 797 cb.Run(PIPELINE_OK); |
805 | 798 |
806 return true; | 799 return true; |
807 } | 800 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
961 DVLOG(1) << "OnStreamParserInitDone(" << success << ", " | 954 DVLOG(1) << "OnStreamParserInitDone(" << success << ", " |
962 << duration.InSecondsF() << ")"; | 955 << duration.InSecondsF() << ")"; |
963 lock_.AssertAcquired(); | 956 lock_.AssertAcquired(); |
964 DCHECK_EQ(state_, INITIALIZING); | 957 DCHECK_EQ(state_, INITIALIZING); |
965 if (!success || (!audio_ && !video_)) { | 958 if (!success || (!audio_ && !video_)) { |
966 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 959 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
967 return; | 960 return; |
968 } | 961 } |
969 | 962 |
970 if (duration > duration_) | 963 if (duration > duration_) |
971 duration_ = duration; | 964 UpdateDuration(duration); |
972 | 965 |
973 // Wait until all streams have initialized. | 966 // Wait until all streams have initialized. |
974 if ((!source_id_audio_.empty() && !audio_) || | 967 if ((!source_id_audio_.empty() && !audio_) || |
975 (!source_id_video_.empty() && !video_)) | 968 (!source_id_video_.empty() && !video_)) |
976 return; | 969 return; |
977 | 970 |
978 host_->SetDuration(duration_); | |
979 | |
980 ChangeState_Locked(WAITING_FOR_START_TIME); | 971 ChangeState_Locked(WAITING_FOR_START_TIME); |
981 } | 972 } |
982 | 973 |
983 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, | 974 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, |
984 const AudioDecoderConfig& audio_config, | 975 const AudioDecoderConfig& audio_config, |
985 const VideoDecoderConfig& video_config) { | 976 const VideoDecoderConfig& video_config) { |
986 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video | 977 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video |
987 << ", " << audio_config.IsValidConfig() | 978 << ", " << audio_config.IsValidConfig() |
988 << ", " << video_config.IsValidConfig() << ")"; | 979 << ", " << video_config.IsValidConfig() << ")"; |
989 CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); | 980 CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1028 lock_.AssertAcquired(); | 1019 lock_.AssertAcquired(); |
1029 DCHECK_NE(state_, SHUTDOWN); | 1020 DCHECK_NE(state_, SHUTDOWN); |
1030 | 1021 |
1031 if (!audio_) | 1022 if (!audio_) |
1032 return false; | 1023 return false; |
1033 | 1024 |
1034 CHECK(IsValidId(source_id_audio_)); | 1025 CHECK(IsValidId(source_id_audio_)); |
1035 AdjustBufferTimestamps( | 1026 AdjustBufferTimestamps( |
1036 buffers, source_info_map_[source_id_audio_].timestamp_offset); | 1027 buffers, source_info_map_[source_id_audio_].timestamp_offset); |
1037 | 1028 |
1029 IncreaseDurationIfNecessary(buffers); | |
1030 | |
1038 return audio_->Append(buffers); | 1031 return audio_->Append(buffers); |
1039 } | 1032 } |
1040 | 1033 |
1041 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { | 1034 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { |
1042 lock_.AssertAcquired(); | 1035 lock_.AssertAcquired(); |
1043 DCHECK_NE(state_, SHUTDOWN); | 1036 DCHECK_NE(state_, SHUTDOWN); |
1044 | 1037 |
1045 if (!video_) | 1038 if (!video_) |
1046 return false; | 1039 return false; |
1047 | 1040 |
1048 CHECK(IsValidId(source_id_video_)); | 1041 CHECK(IsValidId(source_id_video_)); |
1049 AdjustBufferTimestamps( | 1042 AdjustBufferTimestamps( |
1050 buffers, source_info_map_[source_id_video_].timestamp_offset); | 1043 buffers, source_info_map_[source_id_video_].timestamp_offset); |
1051 | 1044 |
1045 IncreaseDurationIfNecessary(buffers); | |
1046 | |
1052 return video_->Append(buffers); | 1047 return video_->Append(buffers); |
1053 } | 1048 } |
1054 | 1049 |
1055 bool ChunkDemuxer::OnNeedKey(scoped_array<uint8> init_data, | 1050 bool ChunkDemuxer::OnNeedKey(scoped_array<uint8> init_data, |
1056 int init_data_size) { | 1051 int init_data_size) { |
1057 client_->DemuxerNeedKey(init_data.Pass(), init_data_size); | 1052 client_->DemuxerNeedKey(init_data.Pass(), init_data_size); |
1058 return true; | 1053 return true; |
1059 } | 1054 } |
1060 | 1055 |
1061 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id, | 1056 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id, |
(...skipping 24 matching lines...) Expand all Loading... | |
1086 | 1081 |
1087 if (audio_) { | 1082 if (audio_) { |
1088 audio_->SetStartTime(start_time_); | 1083 audio_->SetStartTime(start_time_); |
1089 audio_->Seek(start_time_); | 1084 audio_->Seek(start_time_); |
1090 } | 1085 } |
1091 if (video_) { | 1086 if (video_) { |
1092 video_->SetStartTime(start_time_); | 1087 video_->SetStartTime(start_time_); |
1093 video_->Seek(start_time_); | 1088 video_->Seek(start_time_); |
1094 } | 1089 } |
1095 | 1090 |
1091 if (start_time_ > duration_) | |
1092 UpdateDuration(start_time_); | |
acolwell GONE FROM CHROMIUM
2012/07/27 00:03:23
nit: Could this be up where start_time_ is initial
vrk (LEFT CHROMIUM)
2012/07/28 01:42:05
Done.
| |
1093 | |
1096 // The demuxer is now initialized after the |start_timestamp_| was set. | 1094 // The demuxer is now initialized after the |start_timestamp_| was set. |
1097 ChangeState_Locked(INITIALIZED); | 1095 ChangeState_Locked(INITIALIZED); |
1098 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1096 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
1099 } | 1097 } |
1100 | 1098 |
1101 void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) { | 1099 void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) { |
1102 DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")"; | 1100 DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")"; |
1103 CHECK(IsValidId(source_id)); | 1101 CHECK(IsValidId(source_id)); |
1104 source_info_map_[source_id].can_update_offset = true; | 1102 source_info_map_[source_id].can_update_offset = true; |
1105 } | 1103 } |
(...skipping 10 matching lines...) Expand all Loading... | |
1116 (*itr)->GetDecodeTimestamp() + timestamp_offset); | 1114 (*itr)->GetDecodeTimestamp() + timestamp_offset); |
1117 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset); | 1115 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset); |
1118 } | 1116 } |
1119 } | 1117 } |
1120 | 1118 |
1121 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { | 1119 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { |
1122 return source_info_map_.count(source_id) > 0u && | 1120 return source_info_map_.count(source_id) > 0u && |
1123 stream_parser_map_.count(source_id) > 0u; | 1121 stream_parser_map_.count(source_id) > 0u; |
1124 } | 1122 } |
1125 | 1123 |
1124 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { | |
1125 duration_ = new_duration; | |
acolwell GONE FROM CHROMIUM
2012/07/27 00:03:23
DCHECK(duration_ != new_duration) to make sure cod
vrk (LEFT CHROMIUM)
2012/07/28 01:42:05
Done.
| |
1126 host_->SetDuration(new_duration); | |
acolwell GONE FROM CHROMIUM
2012/07/27 00:03:23
Does this cause double duration notifications on m
vrk (LEFT CHROMIUM)
2012/07/28 01:42:05
Yes this happens!
| |
1127 } | |
1128 | |
1129 void ChunkDemuxer::IncreaseDurationIfNecessary( | |
1130 const StreamParser::BufferQueue& buffers) { | |
1131 DCHECK(!buffers.empty()); | |
1132 if (buffers.back()->GetTimestamp() <= duration_) | |
1133 return; | |
1134 | |
1135 Ranges<TimeDelta> ranges = GetBufferedRanges(); | |
1136 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); | |
1137 DCHECK(last_timestamp_buffered > duration_); | |
acolwell GONE FROM CHROMIUM
2012/07/27 00:03:23
I don't think this is right. The buffers aren't ap
vrk (LEFT CHROMIUM)
2012/07/28 01:42:05
AHH you are right! I must have fiddled with this b
| |
1138 UpdateDuration(last_timestamp_buffered); | |
1139 } | |
1140 | |
1141 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | |
1142 lock_.AssertAcquired(); | |
1143 | |
1144 if (audio_ && !video_) | |
1145 return audio_->GetBufferedRanges(); | |
1146 else if (!audio_ && video_) | |
1147 return video_->GetBufferedRanges(); | |
1148 | |
1149 return ComputeIntersection(); | |
1150 } | |
1151 | |
1126 } // namespace media | 1152 } // namespace media |
OLD | NEW |