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

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

Issue 341083004: Introduce the playback time into the MSE garbage collection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: New flow to pass the media time to SourceBufferStream. Created 6 years, 6 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
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/frame_processor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <list> 9 #include <list>
10 10
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 scoped_ptr<StreamParser> stream_parser, 98 scoped_ptr<StreamParser> stream_parser,
99 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb, 99 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb,
100 const CreateDemuxerStreamCB& create_demuxer_stream_cb); 100 const CreateDemuxerStreamCB& create_demuxer_stream_cb);
101 101
102 ~SourceState(); 102 ~SourceState();
103 103
104 void Init(const StreamParser::InitCB& init_cb, 104 void Init(const StreamParser::InitCB& init_cb,
105 bool allow_audio, 105 bool allow_audio,
106 bool allow_video, 106 bool allow_video,
107 const StreamParser::NeedKeyCB& need_key_cb, 107 const StreamParser::NeedKeyCB& need_key_cb,
108 const NewTextTrackCB& new_text_track_cb); 108 const NewTextTrackCB& new_text_track_cb,
109 base::TimeDelta* media_time);
109 110
110 // Appends new data to the StreamParser. 111 // Appends new data to the StreamParser.
111 // Returns true if the data was successfully appended. Returns false if an 112 // Returns true if the data was successfully appended. Returns false if an
112 // error occurred. |*timestamp_offset| is used and possibly updated by the 113 // error occurred. |*timestamp_offset| is used and possibly updated by the
113 // append. |append_window_start| and |append_window_end| correspond to the MSE 114 // append. |append_window_start| and |append_window_end| correspond to the MSE
114 // spec's similarly named source buffer attributes that are used in coded 115 // spec's similarly named source buffer attributes that are used in coded
115 // frame processing. 116 // frame processing.
116 bool Append(const uint8* data, size_t length, 117 bool Append(const uint8* data, size_t length,
117 TimeDelta append_window_start, 118 TimeDelta append_window_start,
118 TimeDelta append_window_end, 119 TimeDelta append_window_end,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 178
178 // Called by the |stream_parser_| at the end of a media segment. 179 // Called by the |stream_parser_| at the end of a media segment.
179 void OnEndOfMediaSegment(); 180 void OnEndOfMediaSegment();
180 181
181 // Called by the |stream_parser_| when new buffers have been parsed. 182 // Called by the |stream_parser_| when new buffers have been parsed.
182 // It processes the new buffers using |frame_processor_|, which includes 183 // It processes the new buffers using |frame_processor_|, which includes
183 // appending the processed frames to associated demuxer streams for each 184 // appending the processed frames to associated demuxer streams for each
184 // frame's track. 185 // frame's track.
185 // Returns true on a successful call. Returns false if an error occurred while 186 // Returns true on a successful call. Returns false if an error occurred while
186 // processing the buffers. 187 // processing the buffers.
187 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, 188 bool OnNewBuffers(base::TimeDelta* media_time,
189 const StreamParser::BufferQueue& audio_buffers,
188 const StreamParser::BufferQueue& video_buffers, 190 const StreamParser::BufferQueue& video_buffers,
189 const StreamParser::TextBufferQueueMap& text_map); 191 const StreamParser::TextBufferQueueMap& text_map);
190 192
191 void OnSourceInitDone(bool success, 193 void OnSourceInitDone(bool success,
192 const StreamParser::InitParameters& params); 194 const StreamParser::InitParameters& params);
193 195
194 CreateDemuxerStreamCB create_demuxer_stream_cb_; 196 CreateDemuxerStreamCB create_demuxer_stream_cb_;
195 NewTextTrackCB new_text_track_cb_; 197 NewTextTrackCB new_text_track_cb_;
196 198
197 // During Append(), if OnNewBuffers() coded frame processing updates the 199 // During Append(), if OnNewBuffers() coded frame processing updates the
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 SourceState::~SourceState() { 264 SourceState::~SourceState() {
263 Shutdown(); 265 Shutdown();
264 266
265 STLDeleteValues(&text_stream_map_); 267 STLDeleteValues(&text_stream_map_);
266 } 268 }
267 269
268 void SourceState::Init(const StreamParser::InitCB& init_cb, 270 void SourceState::Init(const StreamParser::InitCB& init_cb,
269 bool allow_audio, 271 bool allow_audio,
270 bool allow_video, 272 bool allow_video,
271 const StreamParser::NeedKeyCB& need_key_cb, 273 const StreamParser::NeedKeyCB& need_key_cb,
272 const NewTextTrackCB& new_text_track_cb) { 274 const NewTextTrackCB& new_text_track_cb,
275 base::TimeDelta* media_time) {
273 new_text_track_cb_ = new_text_track_cb; 276 new_text_track_cb_ = new_text_track_cb;
274 init_cb_ = init_cb; 277 init_cb_ = init_cb;
275 278
276 stream_parser_->Init( 279 stream_parser_->Init(
277 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)), 280 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)),
278 base::Bind(&SourceState::OnNewConfigs, 281 base::Bind(&SourceState::OnNewConfigs,
279 base::Unretained(this), 282 base::Unretained(this),
280 allow_audio, 283 allow_audio,
281 allow_video), 284 allow_video),
282 base::Bind(&SourceState::OnNewBuffers, base::Unretained(this)), 285 base::Bind(&SourceState::OnNewBuffers,
286 base::Unretained(this),
287 media_time),
283 new_text_track_cb_.is_null(), 288 new_text_track_cb_.is_null(),
284 need_key_cb, 289 need_key_cb,
285 base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this)), 290 base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this)),
286 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)), 291 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)),
287 log_cb_); 292 log_cb_);
288 } 293 }
289 294
290 void SourceState::SetSequenceMode(bool sequence_mode) { 295 void SourceState::SetSequenceMode(bool sequence_mode) {
291 DCHECK(!parsing_media_segment_); 296 DCHECK(!parsing_media_segment_);
292 297
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 new_media_segment_ = true; 679 new_media_segment_ = true;
675 } 680 }
676 681
677 void SourceState::OnEndOfMediaSegment() { 682 void SourceState::OnEndOfMediaSegment() {
678 DVLOG(2) << "OnEndOfMediaSegment()"; 683 DVLOG(2) << "OnEndOfMediaSegment()";
679 parsing_media_segment_ = false; 684 parsing_media_segment_ = false;
680 new_media_segment_ = false; 685 new_media_segment_ = false;
681 } 686 }
682 687
683 bool SourceState::OnNewBuffers( 688 bool SourceState::OnNewBuffers(
689 base::TimeDelta* media_time,
684 const StreamParser::BufferQueue& audio_buffers, 690 const StreamParser::BufferQueue& audio_buffers,
685 const StreamParser::BufferQueue& video_buffers, 691 const StreamParser::BufferQueue& video_buffers,
686 const StreamParser::TextBufferQueueMap& text_map) { 692 const StreamParser::TextBufferQueueMap& text_map) {
687 DVLOG(2) << "OnNewBuffers()"; 693 DVLOG(2) << "OnNewBuffers()";
688 DCHECK(timestamp_offset_during_append_); 694 DCHECK(timestamp_offset_during_append_);
689 DCHECK(parsing_media_segment_); 695 DCHECK(parsing_media_segment_);
690 696
691 const TimeDelta timestamp_offset_before_processing = 697 const TimeDelta timestamp_offset_before_processing =
692 *timestamp_offset_during_append_; 698 *timestamp_offset_during_append_;
693 699
(...skipping 12 matching lines...) Expand all
706 new_timestamp_offset += EndTimestamp(video_buffers); 712 new_timestamp_offset += EndTimestamp(video_buffers);
707 } 713 }
708 } 714 }
709 715
710 if (!frame_processor_->ProcessFrames(audio_buffers, 716 if (!frame_processor_->ProcessFrames(audio_buffers,
711 video_buffers, 717 video_buffers,
712 text_map, 718 text_map,
713 append_window_start_during_append_, 719 append_window_start_during_append_,
714 append_window_end_during_append_, 720 append_window_end_during_append_,
715 &new_media_segment_, 721 &new_media_segment_,
716 timestamp_offset_during_append_)) { 722 timestamp_offset_during_append_,
723 *media_time)) {
717 return false; 724 return false;
718 } 725 }
719 726
720 // Only update the timestamp offset if the frame processor hasn't already. 727 // Only update the timestamp offset if the frame processor hasn't already.
721 if (auto_update_timestamp_offset_ && 728 if (auto_update_timestamp_offset_ &&
722 timestamp_offset_before_processing == *timestamp_offset_during_append_) { 729 timestamp_offset_before_processing == *timestamp_offset_during_append_) {
723 *timestamp_offset_during_append_ = new_timestamp_offset; 730 *timestamp_offset_during_append_ = new_timestamp_offset;
724 } 731 }
725 732
726 return true; 733 return true;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 void ChunkDemuxerStream::Seek(TimeDelta time) { 795 void ChunkDemuxerStream::Seek(TimeDelta time) {
789 DVLOG(1) << "ChunkDemuxerStream::Seek(" << time.InSecondsF() << ")"; 796 DVLOG(1) << "ChunkDemuxerStream::Seek(" << time.InSecondsF() << ")";
790 base::AutoLock auto_lock(lock_); 797 base::AutoLock auto_lock(lock_);
791 DCHECK(read_cb_.is_null()); 798 DCHECK(read_cb_.is_null());
792 DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS) 799 DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS)
793 << state_; 800 << state_;
794 801
795 stream_->Seek(time); 802 stream_->Seek(time);
796 } 803 }
797 804
798 bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { 805 bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers,
806 base::TimeDelta media_time) {
799 if (buffers.empty()) 807 if (buffers.empty())
800 return false; 808 return false;
801 809
802 base::AutoLock auto_lock(lock_); 810 base::AutoLock auto_lock(lock_);
803 DCHECK_NE(state_, SHUTDOWN); 811 DCHECK_NE(state_, SHUTDOWN);
804 if (!stream_->Append(buffers)) { 812 if (!stream_->Append(buffers, media_time)) {
805 DVLOG(1) << "ChunkDemuxerStream::Append() : stream append failed"; 813 DVLOG(1) << "ChunkDemuxerStream::Append() : stream append failed";
806 return false; 814 return false;
807 } 815 }
808 816
809 if (!read_cb_.is_null()) 817 if (!read_cb_.is_null())
810 CompletePendingReadIfPossible_Locked(); 818 CompletePendingReadIfPossible_Locked();
811 819
812 return true; 820 return true;
813 } 821 }
814 822
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 const LogCB& log_cb, 1025 const LogCB& log_cb,
1018 bool splice_frames_enabled) 1026 bool splice_frames_enabled)
1019 : state_(WAITING_FOR_INIT), 1027 : state_(WAITING_FOR_INIT),
1020 cancel_next_seek_(false), 1028 cancel_next_seek_(false),
1021 host_(NULL), 1029 host_(NULL),
1022 open_cb_(open_cb), 1030 open_cb_(open_cb),
1023 need_key_cb_(need_key_cb), 1031 need_key_cb_(need_key_cb),
1024 enable_text_(false), 1032 enable_text_(false),
1025 log_cb_(log_cb), 1033 log_cb_(log_cb),
1026 duration_(kNoTimestamp()), 1034 duration_(kNoTimestamp()),
1035 media_time_(kNoTimestamp()),
1027 user_specified_duration_(-1), 1036 user_specified_duration_(-1),
1028 liveness_(LIVENESS_UNKNOWN), 1037 liveness_(LIVENESS_UNKNOWN),
1029 splice_frames_enabled_(splice_frames_enabled) { 1038 splice_frames_enabled_(splice_frames_enabled) {
1030 DCHECK(!open_cb_.is_null()); 1039 DCHECK(!open_cb_.is_null());
1031 DCHECK(!need_key_cb_.is_null()); 1040 DCHECK(!need_key_cb_.is_null());
1032 } 1041 }
1033 1042
1034 void ChunkDemuxer::Initialize( 1043 void ChunkDemuxer::Initialize(
1035 DemuxerHost* host, 1044 DemuxerHost* host,
1036 const PipelineStatusCB& cb, 1045 const PipelineStatusCB& cb,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 Demuxer::Liveness ChunkDemuxer::GetLiveness() const { 1118 Demuxer::Liveness ChunkDemuxer::GetLiveness() const {
1110 return liveness_; 1119 return liveness_;
1111 } 1120 }
1112 1121
1113 void ChunkDemuxer::StartWaitingForSeek(TimeDelta seek_time) { 1122 void ChunkDemuxer::StartWaitingForSeek(TimeDelta seek_time) {
1114 DVLOG(1) << "StartWaitingForSeek()"; 1123 DVLOG(1) << "StartWaitingForSeek()";
1115 base::AutoLock auto_lock(lock_); 1124 base::AutoLock auto_lock(lock_);
1116 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN || 1125 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN ||
1117 state_ == PARSE_ERROR) << state_; 1126 state_ == PARSE_ERROR) << state_;
1118 DCHECK(seek_cb_.is_null()); 1127 DCHECK(seek_cb_.is_null());
1128 media_time_ = seek_time;
1119 1129
1120 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 1130 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
1121 return; 1131 return;
1122 1132
1123 AbortPendingReads(); 1133 AbortPendingReads();
1124 SeekAllSources(seek_time); 1134 SeekAllSources(seek_time);
1125 1135
1126 // Cancel state set in CancelPendingSeek() since we want to 1136 // Cancel state set in CancelPendingSeek() since we want to
1127 // accept the next Seek(). 1137 // accept the next Seek().
1128 cancel_next_seek_ = false; 1138 cancel_next_seek_ = false;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 if (enable_text_) { 1208 if (enable_text_) {
1199 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, 1209 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack,
1200 base::Unretained(this)); 1210 base::Unretained(this));
1201 } 1211 }
1202 1212
1203 source_state->Init( 1213 source_state->Init(
1204 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), 1214 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
1205 has_audio, 1215 has_audio,
1206 has_video, 1216 has_video,
1207 need_key_cb_, 1217 need_key_cb_,
1208 new_text_track_cb); 1218 new_text_track_cb,
1219 &media_time_);
1209 1220
1210 source_state_map_[id] = source_state.release(); 1221 source_state_map_[id] = source_state.release();
1211 return kOk; 1222 return kOk;
1212 } 1223 }
1213 1224
1214 void ChunkDemuxer::RemoveId(const std::string& id) { 1225 void ChunkDemuxer::RemoveId(const std::string& id) {
1215 base::AutoLock auto_lock(lock_); 1226 base::AutoLock auto_lock(lock_);
1216 CHECK(IsValidId(id)); 1227 CHECK(IsValidId(id));
1217 1228
1218 delete source_state_map_[id]; 1229 delete source_state_map_[id];
(...skipping 21 matching lines...) Expand all
1240 TimeDelta append_window_start, 1251 TimeDelta append_window_start,
1241 TimeDelta append_window_end, 1252 TimeDelta append_window_end,
1242 TimeDelta* timestamp_offset) { 1253 TimeDelta* timestamp_offset) {
1243 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; 1254 DVLOG(1) << "AppendData(" << id << ", " << length << ")";
1244 1255
1245 DCHECK(!id.empty()); 1256 DCHECK(!id.empty());
1246 DCHECK(timestamp_offset); 1257 DCHECK(timestamp_offset);
1247 1258
1248 Ranges<TimeDelta> ranges; 1259 Ranges<TimeDelta> ranges;
1249 1260
1261 // TODO(damienv): Retrieve the current media time outside of any lock.
1262 base::TimeDelta current_media_time = kNoTimestamp();
1263
1250 { 1264 {
1251 base::AutoLock auto_lock(lock_); 1265 base::AutoLock auto_lock(lock_);
1252 DCHECK_NE(state_, ENDED); 1266 DCHECK_NE(state_, ENDED);
1253 1267
1254 // Capture if any of the SourceBuffers are waiting for data before we start 1268 // Capture if any of the SourceBuffers are waiting for data before we start
1255 // parsing. 1269 // parsing.
1256 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); 1270 bool old_waiting_for_data = IsSeekWaitingForData_Locked();
1257 1271
1258 if (length == 0u) 1272 if (length == 0u)
1259 return; 1273 return;
1260 1274
1261 DCHECK(data); 1275 DCHECK(data);
1276 media_time_ = current_media_time;
1262 1277
1263 switch (state_) { 1278 switch (state_) {
1264 case INITIALIZING: 1279 case INITIALIZING:
1265 DCHECK(IsValidId(id)); 1280 DCHECK(IsValidId(id));
1266 if (!source_state_map_[id]->Append(data, length, 1281 if (!source_state_map_[id]->Append(data, length,
1267 append_window_start, 1282 append_window_start,
1268 append_window_end, 1283 append_window_end,
1269 timestamp_offset)) { 1284 timestamp_offset)) {
1270 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1285 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1271 return; 1286 return;
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
1751 } 1766 }
1752 1767
1753 void ChunkDemuxer::ShutdownAllStreams() { 1768 void ChunkDemuxer::ShutdownAllStreams() {
1754 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1769 for (SourceStateMap::iterator itr = source_state_map_.begin();
1755 itr != source_state_map_.end(); ++itr) { 1770 itr != source_state_map_.end(); ++itr) {
1756 itr->second->Shutdown(); 1771 itr->second->Shutdown();
1757 } 1772 }
1758 } 1773 }
1759 1774
1760 } // namespace media 1775 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/frame_processor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698