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 <limits> | 8 #include <limits> |
9 #include <list> | 9 #include <list> |
10 | 10 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |