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

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

Issue 10803019: Chrome-side implementation of media source timestamp offset (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix windows Created 8 years, 5 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 // and |has_video| are undefined. 104 // and |has_video| are undefined.
105 static bool IsSupported(const std::string& type, 105 static bool IsSupported(const std::string& type,
106 std::vector<std::string>& codecs, 106 std::vector<std::string>& codecs,
107 ParserFactoryFunction* factory_function, 107 ParserFactoryFunction* factory_function,
108 bool* has_audio, 108 bool* has_audio,
109 bool* has_video) { 109 bool* has_video) {
110 *factory_function = NULL; 110 *factory_function = NULL;
111 *has_audio = false; 111 *has_audio = false;
112 *has_video = false; 112 *has_video = false;
113 113
114 // Search for the SupportedTypeInfo for |type| 114 // Search for the SupportedTypeInfo for |type|.
115 for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) { 115 for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
116 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i]; 116 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
117 if (type == type_info.type) { 117 if (type == type_info.type) {
118 // Make sure all the codecs specified in |codecs| are 118 // Make sure all the codecs specified in |codecs| are
119 // in the supported type info. 119 // in the supported type info.
120 for (size_t j = 0; j < codecs.size(); ++j) { 120 for (size_t j = 0; j < codecs.size(); ++j) {
121 // Search the type info for a match. 121 // Search the type info for a match.
122 bool found_codec = false; 122 bool found_codec = false;
123 DemuxerStream::Type codec_type = DemuxerStream::UNKNOWN; 123 DemuxerStream::Type codec_type = DemuxerStream::UNKNOWN;
124 124
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 scoped_ptr<StreamParser> stream_parser(factory_function(codecs)); 654 scoped_ptr<StreamParser> stream_parser(factory_function(codecs));
655 CHECK(stream_parser.get()); 655 CHECK(stream_parser.get());
656 656
657 stream_parser->Init( 657 stream_parser->Init(
658 base::Bind(&ChunkDemuxer::OnStreamParserInitDone, this), 658 base::Bind(&ChunkDemuxer::OnStreamParserInitDone, this),
659 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), 659 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this),
660 has_audio, has_video), 660 has_audio, has_video),
661 audio_cb, 661 audio_cb,
662 video_cb, 662 video_cb,
663 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)), 663 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)),
664 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id)); 664 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id),
665 base::Bind(&ChunkDemuxer::OnEndOfMediaSegment,
666 base::Unretained(this), id));
665 667
666 stream_parser_map_[id] = stream_parser.release(); 668 stream_parser_map_[id] = stream_parser.release();
669 SourceInfo info = { base::TimeDelta(), true };
670 source_info_map_[id] = info;
667 671
668 return kOk; 672 return kOk;
669 } 673 }
670 674
671 void ChunkDemuxer::RemoveId(const std::string& id) { 675 void ChunkDemuxer::RemoveId(const std::string& id) {
672 CHECK_GT(stream_parser_map_.count(id), 0u); 676 CHECK_GT(stream_parser_map_.count(id), 0u);
673 base::AutoLock auto_lock(lock_); 677 base::AutoLock auto_lock(lock_);
674 678
675 delete stream_parser_map_[id]; 679 delete stream_parser_map_[id];
676 stream_parser_map_.erase(id); 680 stream_parser_map_.erase(id);
681 source_info_map_.erase(id);
677 682
678 if (source_id_audio_ == id && audio_) 683 if (source_id_audio_ == id && audio_)
679 audio_->Shutdown(); 684 audio_->Shutdown();
680 685
681 if (source_id_video_ == id && video_) 686 if (source_id_video_ == id && video_)
682 video_->Shutdown(); 687 video_->Shutdown();
683 } 688 }
684 689
685 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { 690 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
686 DCHECK(!id.empty()); 691 DCHECK(!id.empty());
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } 807 }
803 808
804 void ChunkDemuxer::Abort(const std::string& id) { 809 void ChunkDemuxer::Abort(const std::string& id) {
805 DVLOG(1) << "Abort(" << id << ")"; 810 DVLOG(1) << "Abort(" << id << ")";
806 DCHECK(!id.empty()); 811 DCHECK(!id.empty());
807 DCHECK_GT(stream_parser_map_.count(id), 0u); 812 DCHECK_GT(stream_parser_map_.count(id), 0u);
808 813
809 stream_parser_map_[id]->Flush(); 814 stream_parser_map_[id]->Flush();
810 } 815 }
811 816
817 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, float offset) {
818 DVLOG(1) << "TimestampOffset(" << id << ", " << offset << ")";
acolwell GONE FROM CHROMIUM 2012/07/25 18:22:43 nit: Add Set
vrk (LEFT CHROMIUM) 2012/07/25 22:56:50 Done.
819 DCHECK_GT(stream_parser_map_.count(id), 0u);
820
821 TimeDelta time_offset = TimeDelta::FromMicroseconds(
822 offset * base::Time::kMicrosecondsPerSecond);
823
824 if (!source_info_map_[id].can_update_offset)
acolwell GONE FROM CHROMIUM 2012/07/25 18:22:43 nit: move this above time_offset since we don't ne
vrk (LEFT CHROMIUM) 2012/07/25 22:56:50 Done.
825 return false;
826
827 source_info_map_[id].timestamp_offset = time_offset;
828 return true;
829 }
830
812 bool ChunkDemuxer::EndOfStream(PipelineStatus status) { 831 bool ChunkDemuxer::EndOfStream(PipelineStatus status) {
813 DVLOG(1) << "EndOfStream(" << status << ")"; 832 DVLOG(1) << "EndOfStream(" << status << ")";
814 base::AutoLock auto_lock(lock_); 833 base::AutoLock auto_lock(lock_);
815 DCHECK_NE(state_, WAITING_FOR_INIT); 834 DCHECK_NE(state_, WAITING_FOR_INIT);
816 DCHECK_NE(state_, ENDED); 835 DCHECK_NE(state_, ENDED);
817 836
818 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 837 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
819 return true; 838 return true;
820 839
821 if (state_ == INITIALIZING) { 840 if (state_ == INITIALIZING) {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 return success; 1025 return success;
1007 } 1026 }
1008 1027
1009 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { 1028 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) {
1010 lock_.AssertAcquired(); 1029 lock_.AssertAcquired();
1011 DCHECK_NE(state_, SHUTDOWN); 1030 DCHECK_NE(state_, SHUTDOWN);
1012 1031
1013 if (!audio_) 1032 if (!audio_)
1014 return false; 1033 return false;
1015 1034
1035 CHECK_GT(source_info_map_.count(source_id_audio_), 0u);
1036 AdjustBufferTimestamps(
1037 buffers, source_info_map_[source_id_audio_].timestamp_offset);
1038
1016 return audio_->Append(buffers); 1039 return audio_->Append(buffers);
1017 } 1040 }
1018 1041
1019 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { 1042 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) {
1020 lock_.AssertAcquired(); 1043 lock_.AssertAcquired();
1021 DCHECK_NE(state_, SHUTDOWN); 1044 DCHECK_NE(state_, SHUTDOWN);
1022 1045
1023 if (!video_) 1046 if (!video_)
1024 return false; 1047 return false;
1025 1048
1049 CHECK_GT(source_info_map_.count(source_id_video_), 0u);
1050 AdjustBufferTimestamps(
1051 buffers, source_info_map_[source_id_video_].timestamp_offset);
1052
1026 return video_->Append(buffers); 1053 return video_->Append(buffers);
1027 } 1054 }
1028 1055
1029 bool ChunkDemuxer::OnNeedKey(scoped_array<uint8> init_data, 1056 bool ChunkDemuxer::OnNeedKey(scoped_array<uint8> init_data,
1030 int init_data_size) { 1057 int init_data_size) {
1031 client_->DemuxerNeedKey(init_data.Pass(), init_data_size); 1058 client_->DemuxerNeedKey(init_data.Pass(), init_data_size);
1032 return true; 1059 return true;
1033 } 1060 }
1034 1061
1035 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id, 1062 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id,
1036 TimeDelta start_timestamp) { 1063 TimeDelta timestamp) {
1037 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", " 1064 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", "
1038 << start_timestamp.InSecondsF() << ")"; 1065 << timestamp.InSecondsF() << ")";
1039 lock_.AssertAcquired(); 1066 lock_.AssertAcquired();
1040 1067
1068 CHECK_GT(source_info_map_.count(source_id), 0u);
acolwell GONE FROM CHROMIUM 2012/07/25 18:22:43 nit: Create a bool IsValidId(source_id) helper so
vrk (LEFT CHROMIUM) 2012/07/25 22:56:50 Done.
1069 source_info_map_[source_id].can_update_offset = false;
1070 base::TimeDelta start_timestamp =
1071 timestamp + source_info_map_[source_id].timestamp_offset;
1072
1041 if (start_time_ == kNoTimestamp()) { 1073 if (start_time_ == kNoTimestamp()) {
1042 DCHECK(state_ == INITIALIZING || state_ == WAITING_FOR_START_TIME); 1074 DCHECK(state_ == INITIALIZING || state_ == WAITING_FOR_START_TIME);
1043 // Use the first reported media segment start time as the |start_time_| 1075 // Use the first reported media segment start time as the |start_time_|
1044 // for the demuxer. 1076 // for the demuxer.
1045 start_time_ = start_timestamp; 1077 start_time_ = start_timestamp;
1046 } 1078 }
1047 1079
1048 if (audio_ && source_id == source_id_audio_) 1080 if (audio_ && source_id == source_id_audio_)
1049 audio_->OnNewMediaSegment(start_timestamp); 1081 audio_->OnNewMediaSegment(start_timestamp);
1050 if (video_ && source_id == source_id_video_) 1082 if (video_ && source_id == source_id_video_)
1051 video_->OnNewMediaSegment(start_timestamp); 1083 video_->OnNewMediaSegment(start_timestamp);
1052 1084
1053 if (state_ != WAITING_FOR_START_TIME) 1085 if (state_ != WAITING_FOR_START_TIME)
1054 return; 1086 return;
1055 1087
1056 if (audio_) { 1088 if (audio_) {
1057 audio_->SetStartTime(start_time_); 1089 audio_->SetStartTime(start_time_);
1058 audio_->Seek(start_time_); 1090 audio_->Seek(start_time_);
1059 } 1091 }
1060 if (video_) { 1092 if (video_) {
1061 video_->SetStartTime(start_time_); 1093 video_->SetStartTime(start_time_);
1062 video_->Seek(start_time_); 1094 video_->Seek(start_time_);
1063 } 1095 }
1064 1096
1065 // The demuxer is now initialized after the |start_timestamp_| was set. 1097 // The demuxer is now initialized after the |start_timestamp_| was set.
1066 ChangeState_Locked(INITIALIZED); 1098 ChangeState_Locked(INITIALIZED);
1067 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 1099 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
1068 } 1100 }
1069 1101
1102 void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) {
1103 DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")";
1104 CHECK_GT(source_info_map_.count(source_id), 0u);
1105 source_info_map_[source_id].can_update_offset = true;
1106 }
1107
1108 void ChunkDemuxer::AdjustBufferTimestamps(
1109 const StreamParser::BufferQueue& buffers,
1110 base::TimeDelta timestamp_offset) {
1111 if (timestamp_offset == base::TimeDelta())
1112 return;
1113
1114 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
1115 itr != buffers.end(); ++itr) {
1116 (*itr)->SetDecodeTimestamp(
1117 (*itr)->GetDecodeTimestamp() + timestamp_offset);
1118 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset);
1119 }
1120 }
1121
1070 } // namespace media 1122 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698