Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 10800041: Update media duration if data is appended after the previous duration (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 } 492 }
493 493
494 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) 494 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client)
495 : state_(WAITING_FOR_INIT), 495 : state_(WAITING_FOR_INIT),
496 host_(NULL), 496 host_(NULL),
497 client_(client), 497 client_(client),
498 start_time_(kNoTimestamp()) { 498 start_time_(kNoTimestamp()) {
499 DCHECK(client); 499 DCHECK(client);
500 } 500 }
501 501
502 void ChunkDemuxer::Initialize(DemuxerHost* host, 502 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) {
503 const PipelineStatusCB& cb) {
504 DVLOG(1) << "Init()"; 503 DVLOG(1) << "Init()";
505 { 504 {
506 base::AutoLock auto_lock(lock_); 505 base::AutoLock auto_lock(lock_);
507 DCHECK_EQ(state_, WAITING_FOR_INIT); 506 DCHECK_EQ(state_, WAITING_FOR_INIT);
508 host_ = host; 507 host_ = host;
509 508
510 ChangeState_Locked(INITIALIZING); 509 ChangeState_Locked(INITIALIZING);
511 init_cb_ = cb; 510 init_cb_ = cb;
512 } 511 }
513 512
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 void ChunkDemuxer::OnStreamParserInitDone(bool success, TimeDelta duration) { 929 void ChunkDemuxer::OnStreamParserInitDone(bool success, TimeDelta duration) {
931 DVLOG(1) << "OnStreamParserInitDone(" << success << ", " 930 DVLOG(1) << "OnStreamParserInitDone(" << success << ", "
932 << duration.InSecondsF() << ")"; 931 << duration.InSecondsF() << ")";
933 lock_.AssertAcquired(); 932 lock_.AssertAcquired();
934 DCHECK_EQ(state_, INITIALIZING); 933 DCHECK_EQ(state_, INITIALIZING);
935 if (!success || (!audio_ && !video_)) { 934 if (!success || (!audio_ && !video_)) {
936 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 935 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
937 return; 936 return;
938 } 937 }
939 938
940 if (duration > duration_) 939 if (duration > duration_)
acolwell GONE FROM CHROMIUM 2012/07/30 21:37:45 I believe the new spec text specifies that only th
vrk (LEFT CHROMIUM) 2012/07/31 22:39:01 Changed to if (duration != base::TimeDelta() && du
941 duration_ = duration; 940 UpdateDuration(duration);
942 941
943 // Wait until all streams have initialized. 942 // Wait until all streams have initialized.
944 if ((!source_id_audio_.empty() && !audio_) || 943 if ((!source_id_audio_.empty() && !audio_) ||
945 (!source_id_video_.empty() && !video_)) 944 (!source_id_video_.empty() && !video_))
946 return; 945 return;
947 946
948 host_->SetDuration(duration_);
949
950 ChangeState_Locked(WAITING_FOR_START_TIME); 947 ChangeState_Locked(WAITING_FOR_START_TIME);
951 } 948 }
952 949
953 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, 950 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video,
954 const AudioDecoderConfig& audio_config, 951 const AudioDecoderConfig& audio_config,
955 const VideoDecoderConfig& video_config) { 952 const VideoDecoderConfig& video_config) {
956 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video 953 DVLOG(1) << "OnNewConfigs(" << has_audio << ", " << has_video
957 << ", " << audio_config.IsValidConfig() 954 << ", " << audio_config.IsValidConfig()
958 << ", " << video_config.IsValidConfig() << ")"; 955 << ", " << video_config.IsValidConfig() << ")";
959 CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); 956 CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 lock_.AssertAcquired(); 995 lock_.AssertAcquired();
999 DCHECK_NE(state_, SHUTDOWN); 996 DCHECK_NE(state_, SHUTDOWN);
1000 997
1001 if (!audio_) 998 if (!audio_)
1002 return false; 999 return false;
1003 1000
1004 CHECK(IsValidId(source_id_audio_)); 1001 CHECK(IsValidId(source_id_audio_));
1005 AdjustBufferTimestamps( 1002 AdjustBufferTimestamps(
1006 buffers, source_info_map_[source_id_audio_].timestamp_offset); 1003 buffers, source_info_map_[source_id_audio_].timestamp_offset);
1007 1004
1008 return audio_->Append(buffers); 1005 if (!audio_->Append(buffers))
1006 return false;
1007
1008 IncreaseDurationIfNecessary(buffers, audio_);
1009 return true;
1009 } 1010 }
1010 1011
1011 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { 1012 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) {
1012 lock_.AssertAcquired(); 1013 lock_.AssertAcquired();
1013 DCHECK_NE(state_, SHUTDOWN); 1014 DCHECK_NE(state_, SHUTDOWN);
1014 1015
1015 if (!video_) 1016 if (!video_)
1016 return false; 1017 return false;
1017 1018
1018 CHECK(IsValidId(source_id_video_)); 1019 CHECK(IsValidId(source_id_video_));
1019 AdjustBufferTimestamps( 1020 AdjustBufferTimestamps(
1020 buffers, source_info_map_[source_id_video_].timestamp_offset); 1021 buffers, source_info_map_[source_id_video_].timestamp_offset);
1021 1022
1022 return video_->Append(buffers); 1023 if (!video_->Append(buffers))
1024 return false;
1025
1026 IncreaseDurationIfNecessary(buffers, video_);
1027 return true;
1023 } 1028 }
1024 1029
1025 bool ChunkDemuxer::OnNeedKey(scoped_array<uint8> init_data, 1030 bool ChunkDemuxer::OnNeedKey(scoped_array<uint8> init_data,
1026 int init_data_size) { 1031 int init_data_size) {
1027 client_->DemuxerNeedKey(init_data.Pass(), init_data_size); 1032 client_->DemuxerNeedKey(init_data.Pass(), init_data_size);
1028 return true; 1033 return true;
1029 } 1034 }
1030 1035
1031 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id, 1036 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id,
1032 TimeDelta timestamp) { 1037 TimeDelta timestamp) {
1033 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", " 1038 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", "
1034 << timestamp.InSecondsF() << ")"; 1039 << timestamp.InSecondsF() << ")";
1035 lock_.AssertAcquired(); 1040 lock_.AssertAcquired();
1036 1041
1037 CHECK(IsValidId(source_id)); 1042 CHECK(IsValidId(source_id));
1038 source_info_map_[source_id].can_update_offset = false; 1043 source_info_map_[source_id].can_update_offset = false;
1039 base::TimeDelta start_timestamp = 1044 base::TimeDelta start_timestamp =
1040 timestamp + source_info_map_[source_id].timestamp_offset; 1045 timestamp + source_info_map_[source_id].timestamp_offset;
1041 1046
1042 if (start_time_ == kNoTimestamp()) { 1047 if (start_time_ == kNoTimestamp()) {
1043 DCHECK(state_ == INITIALIZING || state_ == WAITING_FOR_START_TIME); 1048 DCHECK(state_ == INITIALIZING || state_ == WAITING_FOR_START_TIME);
1044 // Use the first reported media segment start time as the |start_time_| 1049 // Use the first reported media segment start time as the |start_time_|
1045 // for the demuxer. 1050 // for the demuxer.
1046 start_time_ = start_timestamp; 1051 start_time_ = start_timestamp;
1052
1053 // Ensure |duration_| is never before |start_time_|.
1054 // TODO(vrk): We have to do this because there are places in the code that
1055 // assumes the media duration is the same as the end time of the media
1056 // stream. Fix this once crbug.com/137275 is addressed.
1057 if (start_time_ > duration_)
1058 UpdateDuration(start_time_);
1047 } 1059 }
1048 1060
1049 if (audio_ && source_id == source_id_audio_) 1061 if (audio_ && source_id == source_id_audio_)
1050 audio_->OnNewMediaSegment(start_timestamp); 1062 audio_->OnNewMediaSegment(start_timestamp);
1051 if (video_ && source_id == source_id_video_) 1063 if (video_ && source_id == source_id_video_)
1052 video_->OnNewMediaSegment(start_timestamp); 1064 video_->OnNewMediaSegment(start_timestamp);
1053 1065
1054 if (state_ != WAITING_FOR_START_TIME) 1066 if (state_ != WAITING_FOR_START_TIME)
1055 return; 1067 return;
1056 1068
1057 if (audio_) { 1069 if (audio_) {
1058 audio_->SetStartTime(start_time_); 1070 audio_->SetStartTime(start_time_);
1059 audio_->Seek(start_time_); 1071 audio_->Seek(start_time_);
1060 } 1072 }
1061 if (video_) { 1073 if (video_) {
1062 video_->SetStartTime(start_time_); 1074 video_->SetStartTime(start_time_);
1063 video_->Seek(start_time_); 1075 video_->Seek(start_time_);
1064 } 1076 }
1065 1077
acolwell GONE FROM CHROMIUM 2012/07/30 21:37:45 Based on the spec text, I believe if we reach here
vrk (LEFT CHROMIUM) 2012/07/31 22:39:01 Done.
1066 // The demuxer is now initialized after the |start_timestamp_| was set. 1078 // The demuxer is now initialized after the |start_timestamp_| was set.
1067 ChangeState_Locked(INITIALIZED); 1079 ChangeState_Locked(INITIALIZED);
1068 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 1080 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
1069 } 1081 }
1070 1082
1071 void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) { 1083 void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) {
1072 DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")"; 1084 DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")";
1073 CHECK(IsValidId(source_id)); 1085 CHECK(IsValidId(source_id));
1074 source_info_map_[source_id].can_update_offset = true; 1086 source_info_map_[source_id].can_update_offset = true;
1075 } 1087 }
(...skipping 10 matching lines...) Expand all
1086 (*itr)->GetDecodeTimestamp() + timestamp_offset); 1098 (*itr)->GetDecodeTimestamp() + timestamp_offset);
1087 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset); 1099 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset);
1088 } 1100 }
1089 } 1101 }
1090 1102
1091 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { 1103 bool ChunkDemuxer::IsValidId(const std::string& source_id) const {
1092 return source_info_map_.count(source_id) > 0u && 1104 return source_info_map_.count(source_id) > 0u &&
1093 stream_parser_map_.count(source_id) > 0u; 1105 stream_parser_map_.count(source_id) > 0u;
1094 } 1106 }
1095 1107
1108 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) {
1109 DCHECK(duration_ != new_duration);
1110 duration_ = new_duration;
1111 host_->SetDuration(new_duration);
1112 }
1113
1114 void ChunkDemuxer::IncreaseDurationIfNecessary(
1115 const StreamParser::BufferQueue& buffers,
1116 const scoped_refptr<ChunkDemuxerStream>& stream) {
1117 DCHECK(!buffers.empty());
1118 if (buffers.back()->GetTimestamp() <= duration_)
1119 return;
1120
1121 Ranges<TimeDelta> ranges = stream->GetBufferedRanges();
1122 DCHECK_GT(ranges.size(), 0u);
1123
1124 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1);
1125 if (last_timestamp_buffered > duration_)
1126 UpdateDuration(last_timestamp_buffered);
1127 }
1128
1096 } // namespace media 1129 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698