| 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 |