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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 bool allow_audio, | 104 bool allow_audio, |
105 bool allow_video, | 105 bool allow_video, |
106 const StreamParser::NeedKeyCB& need_key_cb, | 106 const StreamParser::NeedKeyCB& need_key_cb, |
107 const NewTextTrackCB& new_text_track_cb); | 107 const NewTextTrackCB& new_text_track_cb); |
108 | 108 |
109 // Appends new data to the StreamParser. | 109 // Appends new data to the StreamParser. |
110 // 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 |
111 // error occurred. |*timestamp_offset| is used and possibly updated by the | 111 // error occurred. |*timestamp_offset| is used and possibly updated by the |
112 // 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 |
113 // 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 |
114 // frame processing. | 114 // frame processing. |init_segment_received_cb| is run for each new fully |
115 bool Append(const uint8* data, size_t length, | 115 // parsed initialization segment. |
116 TimeDelta append_window_start, | 116 bool Append( |
117 TimeDelta append_window_end, | 117 const uint8* data, |
118 TimeDelta* timestamp_offset); | 118 size_t length, |
119 TimeDelta append_window_start, | |
120 TimeDelta append_window_end, | |
121 TimeDelta* timestamp_offset, | |
122 const ChunkDemuxer::InitSegmentReceivedCB& init_segment_received_cb); | |
acolwell GONE FROM CHROMIUM
2014/09/09 22:36:37
nit: typedef this above so you don't have to menti
wolenetz
2014/09/10 00:43:46
Done.
| |
119 | 123 |
120 // Aborts the current append sequence and resets the parser. | 124 // Aborts the current append sequence and resets the parser. |
121 void Abort(TimeDelta append_window_start, | 125 void Abort(TimeDelta append_window_start, |
122 TimeDelta append_window_end, | 126 TimeDelta append_window_end, |
123 TimeDelta* timestamp_offset); | 127 TimeDelta* timestamp_offset); |
124 | 128 |
125 // Calls Remove(|start|, |end|, |duration|) on all | 129 // Calls Remove(|start|, |end|, |duration|) on all |
126 // ChunkDemuxerStreams managed by this object. | 130 // ChunkDemuxerStreams managed by this object. |
127 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); | 131 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); |
128 | 132 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 | 196 |
193 CreateDemuxerStreamCB create_demuxer_stream_cb_; | 197 CreateDemuxerStreamCB create_demuxer_stream_cb_; |
194 NewTextTrackCB new_text_track_cb_; | 198 NewTextTrackCB new_text_track_cb_; |
195 | 199 |
196 // During Append(), if OnNewBuffers() coded frame processing updates the | 200 // During Append(), if OnNewBuffers() coded frame processing updates the |
197 // timestamp offset then |*timestamp_offset_during_append_| is also updated | 201 // timestamp offset then |*timestamp_offset_during_append_| is also updated |
198 // so Append()'s caller can know the new offset. This pointer is only non-NULL | 202 // so Append()'s caller can know the new offset. This pointer is only non-NULL |
199 // during the lifetime of an Append() call. | 203 // during the lifetime of an Append() call. |
200 TimeDelta* timestamp_offset_during_append_; | 204 TimeDelta* timestamp_offset_during_append_; |
201 | 205 |
206 // During Append(), OnNewConfigs() will trigger the initialization segment | |
207 // received algorithm. This callback is only non-NULL during the lifetime of | |
208 // an Append() call. Note, the MSE spec explicitly disallows this algorithm | |
209 // during an Abort(), since Abort() is allowed only to emit coded frames, and | |
210 // only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment). | |
211 ChunkDemuxer::InitSegmentReceivedCB init_segment_received_cb_during_append_; | |
212 | |
202 // During Append(), coded frame processing triggered by OnNewBuffers() | 213 // During Append(), coded frame processing triggered by OnNewBuffers() |
203 // requires these two attributes. These are only valid during the lifetime of | 214 // requires these two attributes. These are only valid during the lifetime of |
204 // an Append() call. | 215 // an Append() call. |
205 TimeDelta append_window_start_during_append_; | 216 TimeDelta append_window_start_during_append_; |
206 TimeDelta append_window_end_during_append_; | 217 TimeDelta append_window_end_during_append_; |
207 | 218 |
208 // Set to true if the next buffers appended within the append window | 219 // Set to true if the next buffers appended within the append window |
209 // represent the start of a new media segment. This flag being set | 220 // represent the start of a new media segment. This flag being set |
210 // triggers a call to |new_segment_cb_| when the new buffers are | 221 // triggers a call to |new_segment_cb_| when the new buffers are |
211 // appended. The flag is set on actual media segment boundaries and | 222 // appended. The flag is set on actual media segment boundaries and |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
292 frame_processor_->SetSequenceMode(sequence_mode); | 303 frame_processor_->SetSequenceMode(sequence_mode); |
293 } | 304 } |
294 | 305 |
295 void SourceState::SetGroupStartTimestampIfInSequenceMode( | 306 void SourceState::SetGroupStartTimestampIfInSequenceMode( |
296 base::TimeDelta timestamp_offset) { | 307 base::TimeDelta timestamp_offset) { |
297 DCHECK(!parsing_media_segment_); | 308 DCHECK(!parsing_media_segment_); |
298 | 309 |
299 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset); | 310 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset); |
300 } | 311 } |
301 | 312 |
302 bool SourceState::Append(const uint8* data, size_t length, | 313 bool SourceState::Append( |
303 TimeDelta append_window_start, | 314 const uint8* data, |
304 TimeDelta append_window_end, | 315 size_t length, |
305 TimeDelta* timestamp_offset) { | 316 TimeDelta append_window_start, |
317 TimeDelta append_window_end, | |
318 TimeDelta* timestamp_offset, | |
319 const ChunkDemuxer::InitSegmentReceivedCB& init_segment_received_cb) { | |
306 DCHECK(timestamp_offset); | 320 DCHECK(timestamp_offset); |
307 DCHECK(!timestamp_offset_during_append_); | 321 DCHECK(!timestamp_offset_during_append_); |
322 DCHECK(init_segment_received_cb_during_append_.is_null()); | |
323 DCHECK(!init_segment_received_cb.is_null()); | |
308 append_window_start_during_append_ = append_window_start; | 324 append_window_start_during_append_ = append_window_start; |
309 append_window_end_during_append_ = append_window_end; | 325 append_window_end_during_append_ = append_window_end; |
310 timestamp_offset_during_append_ = timestamp_offset; | 326 timestamp_offset_during_append_ = timestamp_offset; |
327 init_segment_received_cb_during_append_ = init_segment_received_cb; | |
311 | 328 |
312 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with | 329 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with |
313 // append window and timestamp offset pointer. See http://crbug.com/351454. | 330 // append window and timestamp offset pointer. See http://crbug.com/351454. |
314 bool err = stream_parser_->Parse(data, length); | 331 bool err = stream_parser_->Parse(data, length); |
315 timestamp_offset_during_append_ = NULL; | 332 timestamp_offset_during_append_ = NULL; |
333 init_segment_received_cb_during_append_.Reset(); | |
316 return err; | 334 return err; |
317 } | 335 } |
318 | 336 |
319 void SourceState::Abort(TimeDelta append_window_start, | 337 void SourceState::Abort(TimeDelta append_window_start, |
320 TimeDelta append_window_end, | 338 TimeDelta append_window_end, |
321 base::TimeDelta* timestamp_offset) { | 339 base::TimeDelta* timestamp_offset) { |
322 DCHECK(timestamp_offset); | 340 DCHECK(timestamp_offset); |
323 DCHECK(!timestamp_offset_during_append_); | 341 DCHECK(!timestamp_offset_during_append_); |
324 timestamp_offset_during_append_ = timestamp_offset; | 342 timestamp_offset_during_append_ = timestamp_offset; |
325 append_window_start_during_append_ = append_window_start; | 343 append_window_start_during_append_ = append_window_start; |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 << " does not match old one."; | 676 << " does not match old one."; |
659 break; | 677 break; |
660 } | 678 } |
661 } | 679 } |
662 } | 680 } |
663 } | 681 } |
664 | 682 |
665 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); | 683 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); |
666 | 684 |
667 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 685 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
686 if (success) { | |
687 // BIG TODO: add parameters to init segment received algo... | |
688 init_segment_received_cb_during_append_.Run(); | |
689 } | |
690 | |
668 return success; | 691 return success; |
669 } | 692 } |
670 | 693 |
671 void SourceState::OnNewMediaSegment() { | 694 void SourceState::OnNewMediaSegment() { |
672 DVLOG(2) << "OnNewMediaSegment()"; | 695 DVLOG(2) << "OnNewMediaSegment()"; |
673 parsing_media_segment_ = true; | 696 parsing_media_segment_ = true; |
674 new_media_segment_ = true; | 697 new_media_segment_ = true; |
675 } | 698 } |
676 | 699 |
677 void SourceState::OnEndOfMediaSegment() { | 700 void SourceState::OnEndOfMediaSegment() { |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1222 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { | 1245 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { |
1223 base::AutoLock auto_lock(lock_); | 1246 base::AutoLock auto_lock(lock_); |
1224 DCHECK(!id.empty()); | 1247 DCHECK(!id.empty()); |
1225 | 1248 |
1226 SourceStateMap::const_iterator itr = source_state_map_.find(id); | 1249 SourceStateMap::const_iterator itr = source_state_map_.find(id); |
1227 | 1250 |
1228 DCHECK(itr != source_state_map_.end()); | 1251 DCHECK(itr != source_state_map_.end()); |
1229 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); | 1252 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); |
1230 } | 1253 } |
1231 | 1254 |
1232 void ChunkDemuxer::AppendData(const std::string& id, | 1255 void ChunkDemuxer::AppendData( |
1233 const uint8* data, size_t length, | 1256 const std::string& id, |
1234 TimeDelta append_window_start, | 1257 const uint8* data, |
1235 TimeDelta append_window_end, | 1258 size_t length, |
1236 TimeDelta* timestamp_offset) { | 1259 TimeDelta append_window_start, |
1260 TimeDelta append_window_end, | |
1261 TimeDelta* timestamp_offset, | |
1262 const InitSegmentReceivedCB& init_segment_received_cb) { | |
1237 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; | 1263 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; |
1238 | 1264 |
1239 DCHECK(!id.empty()); | 1265 DCHECK(!id.empty()); |
1240 DCHECK(timestamp_offset); | 1266 DCHECK(timestamp_offset); |
1267 DCHECK(!init_segment_received_cb.is_null()); | |
1241 | 1268 |
1242 Ranges<TimeDelta> ranges; | 1269 Ranges<TimeDelta> ranges; |
1243 | 1270 |
1244 { | 1271 { |
1245 base::AutoLock auto_lock(lock_); | 1272 base::AutoLock auto_lock(lock_); |
1246 DCHECK_NE(state_, ENDED); | 1273 DCHECK_NE(state_, ENDED); |
1247 | 1274 |
1248 // Capture if any of the SourceBuffers are waiting for data before we start | 1275 // Capture if any of the SourceBuffers are waiting for data before we start |
1249 // parsing. | 1276 // parsing. |
1250 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); | 1277 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); |
1251 | 1278 |
1252 if (length == 0u) | 1279 if (length == 0u) |
1253 return; | 1280 return; |
1254 | 1281 |
1255 DCHECK(data); | 1282 DCHECK(data); |
1256 | 1283 |
1257 switch (state_) { | 1284 switch (state_) { |
1258 case INITIALIZING: | 1285 case INITIALIZING: |
1259 DCHECK(IsValidId(id)); | 1286 DCHECK(IsValidId(id)); |
1260 if (!source_state_map_[id]->Append(data, length, | 1287 if (!source_state_map_[id]->Append(data, length, |
1261 append_window_start, | 1288 append_window_start, |
1262 append_window_end, | 1289 append_window_end, |
1263 timestamp_offset)) { | 1290 timestamp_offset, |
1291 init_segment_received_cb)) { | |
1264 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1292 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1265 return; | 1293 return; |
1266 } | 1294 } |
1267 break; | 1295 break; |
1268 | 1296 |
1269 case INITIALIZED: { | 1297 case INITIALIZED: { |
1270 DCHECK(IsValidId(id)); | 1298 DCHECK(IsValidId(id)); |
1271 if (!source_state_map_[id]->Append(data, length, | 1299 if (!source_state_map_[id]->Append(data, length, |
1272 append_window_start, | 1300 append_window_start, |
1273 append_window_end, | 1301 append_window_end, |
1274 timestamp_offset)) { | 1302 timestamp_offset, |
1303 init_segment_received_cb)) { | |
1275 ReportError_Locked(PIPELINE_ERROR_DECODE); | 1304 ReportError_Locked(PIPELINE_ERROR_DECODE); |
1276 return; | 1305 return; |
1277 } | 1306 } |
1278 } break; | 1307 } break; |
1279 | 1308 |
1280 case PARSE_ERROR: | 1309 case PARSE_ERROR: |
1281 DVLOG(1) << "AppendData(): Ignoring data after a parse error."; | 1310 DVLOG(1) << "AppendData(): Ignoring data after a parse error."; |
1282 return; | 1311 return; |
1283 | 1312 |
1284 case WAITING_FOR_INIT: | 1313 case WAITING_FOR_INIT: |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1752 } | 1781 } |
1753 | 1782 |
1754 void ChunkDemuxer::ShutdownAllStreams() { | 1783 void ChunkDemuxer::ShutdownAllStreams() { |
1755 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1784 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1756 itr != source_state_map_.end(); ++itr) { | 1785 itr != source_state_map_.end(); ++itr) { |
1757 itr->second->Shutdown(); | 1786 itr->second->Shutdown(); |
1758 } | 1787 } |
1759 } | 1788 } |
1760 | 1789 |
1761 } // namespace media | 1790 } // namespace media |
OLD | NEW |