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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 // Contains state belonging to a source id. | 86 // Contains state belonging to a source id. |
87 class SourceState { | 87 class SourceState { |
88 public: | 88 public: |
89 // Callback signature used to create ChunkDemuxerStreams. | 89 // Callback signature used to create ChunkDemuxerStreams. |
90 typedef base::Callback<ChunkDemuxerStream*( | 90 typedef base::Callback<ChunkDemuxerStream*( |
91 DemuxerStream::Type)> CreateDemuxerStreamCB; | 91 DemuxerStream::Type)> CreateDemuxerStreamCB; |
92 | 92 |
93 typedef base::Callback<void( | 93 typedef base::Callback<void( |
94 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; | 94 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; |
95 | 95 |
96 // First parameter - Indicates initialization success. Set to true if | |
97 // initialization was successful. False if an error | |
98 // occurred. | |
99 // Second parameter - Indicates the stream duration. Only contains a valid | |
100 // value if the first parameter is true. | |
101 // Third parameter - Indicates the source Time associated with | |
102 // presentation timestamp 0. A null Time is returned if | |
103 // no mapping to Time exists. Only contains a | |
104 // valid value if the first parameter is true. | |
105 typedef base::Callback<void(bool, TimeDelta, base::Time)> InitCB; | |
106 | |
107 SourceState( | 96 SourceState( |
108 scoped_ptr<StreamParser> stream_parser, | 97 scoped_ptr<StreamParser> stream_parser, |
109 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb, | 98 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb, |
110 const CreateDemuxerStreamCB& create_demuxer_stream_cb); | 99 const CreateDemuxerStreamCB& create_demuxer_stream_cb); |
111 | 100 |
112 ~SourceState(); | 101 ~SourceState(); |
113 | 102 |
114 void Init(const InitCB& init_cb, | 103 void Init(const StreamParser::InitCB& init_cb, |
115 bool allow_audio, | 104 bool allow_audio, |
116 bool allow_video, | 105 bool allow_video, |
117 const StreamParser::NeedKeyCB& need_key_cb, | 106 const StreamParser::NeedKeyCB& need_key_cb, |
118 const NewTextTrackCB& new_text_track_cb); | 107 const NewTextTrackCB& new_text_track_cb); |
119 | 108 |
120 // Appends new data to the StreamParser. | 109 // Appends new data to the StreamParser. |
121 // Returns true if the data was successfully appended. Returns false if an | 110 // Returns true if the data was successfully appended. Returns false if an |
122 // error occurred. |*timestamp_offset| is used and possibly updated by the | 111 // error occurred. |*timestamp_offset| is used and possibly updated by the |
123 // append. |append_window_start| and |append_window_end| correspond to the MSE | 112 // append. |append_window_start| and |append_window_end| correspond to the MSE |
124 // spec's similarly named source buffer attributes that are used in coded | 113 // spec's similarly named source buffer attributes that are used in coded |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 // It processes the new buffers using |frame_processor_|, which includes | 175 // It processes the new buffers using |frame_processor_|, which includes |
187 // appending the processed frames to associated demuxer streams for each | 176 // appending the processed frames to associated demuxer streams for each |
188 // frame's track. | 177 // frame's track. |
189 // Returns true on a successful call. Returns false if an error occurred while | 178 // Returns true on a successful call. Returns false if an error occurred while |
190 // processing the buffers. | 179 // processing the buffers. |
191 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, | 180 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, |
192 const StreamParser::BufferQueue& video_buffers, | 181 const StreamParser::BufferQueue& video_buffers, |
193 const StreamParser::TextBufferQueueMap& text_map); | 182 const StreamParser::TextBufferQueueMap& text_map); |
194 | 183 |
195 void OnSourceInitDone(bool success, | 184 void OnSourceInitDone(bool success, |
196 TimeDelta duration, | 185 const StreamParser::InitParameters& params); |
197 base::Time timeline_offset, | |
198 bool auto_update_timestamp_offset); | |
199 | 186 |
200 CreateDemuxerStreamCB create_demuxer_stream_cb_; | 187 CreateDemuxerStreamCB create_demuxer_stream_cb_; |
201 NewTextTrackCB new_text_track_cb_; | 188 NewTextTrackCB new_text_track_cb_; |
202 | 189 |
203 // During Append(), if OnNewBuffers() coded frame processing updates the | 190 // During Append(), if OnNewBuffers() coded frame processing updates the |
204 // timestamp offset then |*timestamp_offset_during_append_| is also updated | 191 // timestamp offset then |*timestamp_offset_during_append_| is also updated |
205 // so Append()'s caller can know the new offset. This pointer is only non-NULL | 192 // so Append()'s caller can know the new offset. This pointer is only non-NULL |
206 // during the lifetime of an Append() call. | 193 // during the lifetime of an Append() call. |
207 TimeDelta* timestamp_offset_during_append_; | 194 TimeDelta* timestamp_offset_during_append_; |
208 | 195 |
(...skipping 20 matching lines...) Expand all Loading... |
229 scoped_ptr<StreamParser> stream_parser_; | 216 scoped_ptr<StreamParser> stream_parser_; |
230 | 217 |
231 ChunkDemuxerStream* audio_; // Not owned by |this|. | 218 ChunkDemuxerStream* audio_; // Not owned by |this|. |
232 ChunkDemuxerStream* video_; // Not owned by |this|. | 219 ChunkDemuxerStream* video_; // Not owned by |this|. |
233 | 220 |
234 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; | 221 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; |
235 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. | 222 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. |
236 | 223 |
237 scoped_ptr<FrameProcessorBase> frame_processor_; | 224 scoped_ptr<FrameProcessorBase> frame_processor_; |
238 LogCB log_cb_; | 225 LogCB log_cb_; |
239 InitCB init_cb_; | 226 StreamParser::InitCB init_cb_; |
240 | 227 |
241 // Indicates that timestampOffset should be updated automatically during | 228 // Indicates that timestampOffset should be updated automatically during |
242 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. | 229 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. |
243 bool auto_update_timestamp_offset_; | 230 bool auto_update_timestamp_offset_; |
244 | 231 |
245 DISALLOW_COPY_AND_ASSIGN(SourceState); | 232 DISALLOW_COPY_AND_ASSIGN(SourceState); |
246 }; | 233 }; |
247 | 234 |
248 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 235 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
249 scoped_ptr<FrameProcessorBase> frame_processor, | 236 scoped_ptr<FrameProcessorBase> frame_processor, |
(...skipping 12 matching lines...) Expand all Loading... |
262 DCHECK(!create_demuxer_stream_cb_.is_null()); | 249 DCHECK(!create_demuxer_stream_cb_.is_null()); |
263 DCHECK(frame_processor_); | 250 DCHECK(frame_processor_); |
264 } | 251 } |
265 | 252 |
266 SourceState::~SourceState() { | 253 SourceState::~SourceState() { |
267 Shutdown(); | 254 Shutdown(); |
268 | 255 |
269 STLDeleteValues(&text_stream_map_); | 256 STLDeleteValues(&text_stream_map_); |
270 } | 257 } |
271 | 258 |
272 void SourceState::Init(const InitCB& init_cb, | 259 void SourceState::Init(const StreamParser::InitCB& init_cb, |
273 bool allow_audio, | 260 bool allow_audio, |
274 bool allow_video, | 261 bool allow_video, |
275 const StreamParser::NeedKeyCB& need_key_cb, | 262 const StreamParser::NeedKeyCB& need_key_cb, |
276 const NewTextTrackCB& new_text_track_cb) { | 263 const NewTextTrackCB& new_text_track_cb) { |
277 new_text_track_cb_ = new_text_track_cb; | 264 new_text_track_cb_ = new_text_track_cb; |
278 init_cb_ = init_cb; | 265 init_cb_ = init_cb; |
279 | 266 |
280 stream_parser_->Init( | 267 stream_parser_->Init( |
281 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)), | 268 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)), |
282 base::Bind(&SourceState::OnNewConfigs, | 269 base::Bind(&SourceState::OnNewConfigs, |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 // Only update the timestamp offset if the frame processor hasn't already. | 681 // Only update the timestamp offset if the frame processor hasn't already. |
695 if (auto_update_timestamp_offset_ && | 682 if (auto_update_timestamp_offset_ && |
696 timestamp_offset_before_processing == *timestamp_offset_during_append_) { | 683 timestamp_offset_before_processing == *timestamp_offset_during_append_) { |
697 *timestamp_offset_during_append_ = new_timestamp_offset; | 684 *timestamp_offset_during_append_ = new_timestamp_offset; |
698 } | 685 } |
699 | 686 |
700 return true; | 687 return true; |
701 } | 688 } |
702 | 689 |
703 void SourceState::OnSourceInitDone(bool success, | 690 void SourceState::OnSourceInitDone(bool success, |
704 TimeDelta duration, | 691 const StreamParser::InitParameters& params) { |
705 base::Time timeline_offset, | 692 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; |
706 bool auto_update_timestamp_offset) { | 693 base::ResetAndReturn(&init_cb_).Run(success, params); |
707 auto_update_timestamp_offset_ = auto_update_timestamp_offset; | |
708 base::ResetAndReturn(&init_cb_).Run( | |
709 success, duration, timeline_offset); | |
710 } | 694 } |
711 | 695 |
712 ChunkDemuxerStream::ChunkDemuxerStream(Type type, bool splice_frames_enabled) | 696 ChunkDemuxerStream::ChunkDemuxerStream(Type type, bool splice_frames_enabled) |
713 : type_(type), | 697 : type_(type), |
714 state_(UNINITIALIZED), | 698 state_(UNINITIALIZED), |
715 splice_frames_enabled_(splice_frames_enabled) {} | 699 splice_frames_enabled_(splice_frames_enabled) {} |
716 | 700 |
717 void ChunkDemuxerStream::StartReturningData() { | 701 void ChunkDemuxerStream::StartReturningData() { |
718 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; | 702 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; |
719 base::AutoLock auto_lock(lock_); | 703 base::AutoLock auto_lock(lock_); |
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1490 lock_.AssertAcquired(); | 1474 lock_.AssertAcquired(); |
1491 for (SourceStateMap::const_iterator itr = source_state_map_.begin(); | 1475 for (SourceStateMap::const_iterator itr = source_state_map_.begin(); |
1492 itr != source_state_map_.end(); ++itr) { | 1476 itr != source_state_map_.end(); ++itr) { |
1493 if (itr->second->IsSeekWaitingForData()) | 1477 if (itr->second->IsSeekWaitingForData()) |
1494 return true; | 1478 return true; |
1495 } | 1479 } |
1496 | 1480 |
1497 return false; | 1481 return false; |
1498 } | 1482 } |
1499 | 1483 |
1500 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration, | 1484 void ChunkDemuxer::OnSourceInitDone( |
1501 base::Time timeline_offset) { | 1485 bool success, |
| 1486 const StreamParser::InitParameters& params) { |
1502 DVLOG(1) << "OnSourceInitDone(" << success << ", " | 1487 DVLOG(1) << "OnSourceInitDone(" << success << ", " |
1503 << duration.InSecondsF() << ")"; | 1488 << params.duration.InSecondsF() << ")"; |
1504 lock_.AssertAcquired(); | 1489 lock_.AssertAcquired(); |
1505 DCHECK_EQ(state_, INITIALIZING); | 1490 DCHECK_EQ(state_, INITIALIZING); |
1506 if (!success || (!audio_ && !video_)) { | 1491 if (!success || (!audio_ && !video_)) { |
1507 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1492 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1508 return; | 1493 return; |
1509 } | 1494 } |
1510 | 1495 |
1511 if (duration != TimeDelta() && duration_ == kNoTimestamp()) | 1496 if (params.duration != TimeDelta() && duration_ == kNoTimestamp()) |
1512 UpdateDuration(duration); | 1497 UpdateDuration(params.duration); |
1513 | 1498 |
1514 if (!timeline_offset.is_null()) { | 1499 if (!params.timeline_offset.is_null()) { |
1515 if (!timeline_offset_.is_null() && | 1500 if (!timeline_offset_.is_null() && |
1516 timeline_offset != timeline_offset_) { | 1501 params.timeline_offset != timeline_offset_) { |
1517 MEDIA_LOG(log_cb_) | 1502 MEDIA_LOG(log_cb_) |
1518 << "Timeline offset is not the same across all SourceBuffers."; | 1503 << "Timeline offset is not the same across all SourceBuffers."; |
1519 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1504 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1520 return; | 1505 return; |
1521 } | 1506 } |
1522 | 1507 |
1523 timeline_offset_ = timeline_offset; | 1508 timeline_offset_ = params.timeline_offset; |
1524 } | 1509 } |
1525 | 1510 |
1526 // Wait until all streams have initialized. | 1511 // Wait until all streams have initialized. |
1527 if ((!source_id_audio_.empty() && !audio_) || | 1512 if ((!source_id_audio_.empty() && !audio_) || |
1528 (!source_id_video_.empty() && !video_)) | 1513 (!source_id_video_.empty() && !video_)) { |
1529 return; | 1514 return; |
| 1515 } |
1530 | 1516 |
1531 SeekAllSources(GetStartTime()); | 1517 SeekAllSources(GetStartTime()); |
1532 StartReturningData(); | 1518 StartReturningData(); |
1533 | 1519 |
1534 if (duration_ == kNoTimestamp()) | 1520 if (duration_ == kNoTimestamp()) |
1535 duration_ = kInfiniteDuration(); | 1521 duration_ = kInfiniteDuration(); |
1536 | 1522 |
1537 // The demuxer is now initialized after the |start_timestamp_| was set. | 1523 // The demuxer is now initialized after the |start_timestamp_| was set. |
1538 ChangeState_Locked(INITIALIZED); | 1524 ChangeState_Locked(INITIALIZED); |
1539 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1525 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1668 } | 1654 } |
1669 | 1655 |
1670 void ChunkDemuxer::ShutdownAllStreams() { | 1656 void ChunkDemuxer::ShutdownAllStreams() { |
1671 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1657 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1672 itr != source_state_map_.end(); ++itr) { | 1658 itr != source_state_map_.end(); ++itr) { |
1673 itr->second->Shutdown(); | 1659 itr->second->Shutdown(); |
1674 } | 1660 } |
1675 } | 1661 } |
1676 | 1662 |
1677 } // namespace media | 1663 } // namespace media |
OLD | NEW |