Chromium Code Reviews| 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 |