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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 // Called by the |stream_parser_| when new buffers have been parsed. | 170 // Called by the |stream_parser_| when new buffers have been parsed. |
| 171 // It processes the new buffers using |frame_processor_|, which includes | 171 // It processes the new buffers using |frame_processor_|, which includes |
| 172 // appending the processed frames to associated demuxer streams for each | 172 // appending the processed frames to associated demuxer streams for each |
| 173 // frame's track. | 173 // frame's track. |
| 174 // Returns true on a successful call. Returns false if an error occurred while | 174 // Returns true on a successful call. Returns false if an error occurred while |
| 175 // processing the buffers. | 175 // processing the buffers. |
| 176 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, | 176 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, |
| 177 const StreamParser::BufferQueue& video_buffers, | 177 const StreamParser::BufferQueue& video_buffers, |
| 178 const StreamParser::TextBufferQueueMap& text_map); | 178 const StreamParser::TextBufferQueueMap& text_map); |
| 179 | 179 |
| 180 void OnSourceInitDone(bool success, | |
| 181 TimeDelta duration, | |
| 182 bool auto_update_timestamp_offset); | |
| 183 | |
| 180 CreateDemuxerStreamCB create_demuxer_stream_cb_; | 184 CreateDemuxerStreamCB create_demuxer_stream_cb_; |
| 181 NewTextTrackCB new_text_track_cb_; | 185 NewTextTrackCB new_text_track_cb_; |
| 182 | 186 |
| 183 // During Append(), if OnNewBuffers() coded frame processing updates the | 187 // During Append(), if OnNewBuffers() coded frame processing updates the |
| 184 // timestamp offset then |*timestamp_offset_during_append_| is also updated | 188 // timestamp offset then |*timestamp_offset_during_append_| is also updated |
| 185 // so Append()'s caller can know the new offset. This pointer is only non-NULL | 189 // so Append()'s caller can know the new offset. This pointer is only non-NULL |
| 186 // during the lifetime of an Append() call. | 190 // during the lifetime of an Append() call. |
| 187 TimeDelta* timestamp_offset_during_append_; | 191 TimeDelta* timestamp_offset_during_append_; |
| 188 | 192 |
| 189 // During Append(), coded frame processing triggered by OnNewBuffers() | 193 // During Append(), coded frame processing triggered by OnNewBuffers() |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 209 scoped_ptr<StreamParser> stream_parser_; | 213 scoped_ptr<StreamParser> stream_parser_; |
| 210 | 214 |
| 211 ChunkDemuxerStream* audio_; // Not owned by |this|. | 215 ChunkDemuxerStream* audio_; // Not owned by |this|. |
| 212 ChunkDemuxerStream* video_; // Not owned by |this|. | 216 ChunkDemuxerStream* video_; // Not owned by |this|. |
| 213 | 217 |
| 214 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; | 218 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; |
| 215 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. | 219 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. |
| 216 | 220 |
| 217 scoped_ptr<FrameProcessorBase> frame_processor_; | 221 scoped_ptr<FrameProcessorBase> frame_processor_; |
| 218 LogCB log_cb_; | 222 LogCB log_cb_; |
| 223 StreamParser::InitCB init_cb_; | |
| 224 | |
| 225 // Indicates that timestampOffset should be updated automatically during | |
| 226 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. | |
| 227 bool auto_update_timestamp_offset_; | |
| 219 | 228 |
| 220 DISALLOW_COPY_AND_ASSIGN(SourceState); | 229 DISALLOW_COPY_AND_ASSIGN(SourceState); |
| 221 }; | 230 }; |
| 222 | 231 |
| 223 SourceState::SourceState( | 232 SourceState::SourceState( |
| 224 scoped_ptr<StreamParser> stream_parser, | 233 scoped_ptr<StreamParser> stream_parser, |
| 225 scoped_ptr<FrameProcessorBase> frame_processor, | 234 scoped_ptr<FrameProcessorBase> frame_processor, |
| 226 const LogCB& log_cb, | 235 const LogCB& log_cb, |
| 227 const CreateDemuxerStreamCB& create_demuxer_stream_cb) | 236 const CreateDemuxerStreamCB& create_demuxer_stream_cb) |
| 228 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 237 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
| 229 timestamp_offset_during_append_(NULL), | 238 timestamp_offset_during_append_(NULL), |
| 230 new_media_segment_(false), | 239 new_media_segment_(false), |
| 231 parsing_media_segment_(false), | 240 parsing_media_segment_(false), |
| 232 stream_parser_(stream_parser.release()), | 241 stream_parser_(stream_parser.release()), |
| 233 audio_(NULL), | 242 audio_(NULL), |
| 234 video_(NULL), | 243 video_(NULL), |
| 235 frame_processor_(frame_processor.release()), | 244 frame_processor_(frame_processor.release()), |
| 236 log_cb_(log_cb) { | 245 log_cb_(log_cb), |
| 246 auto_update_timestamp_offset_(false) { | |
| 237 DCHECK(!create_demuxer_stream_cb_.is_null()); | 247 DCHECK(!create_demuxer_stream_cb_.is_null()); |
| 238 DCHECK(frame_processor_); | 248 DCHECK(frame_processor_); |
| 239 } | 249 } |
| 240 | 250 |
| 241 SourceState::~SourceState() { | 251 SourceState::~SourceState() { |
| 242 Shutdown(); | 252 Shutdown(); |
| 243 | 253 |
| 244 STLDeleteValues(&text_stream_map_); | 254 STLDeleteValues(&text_stream_map_); |
| 245 } | 255 } |
| 246 | 256 |
| 247 void SourceState::Init(const StreamParser::InitCB& init_cb, | 257 void SourceState::Init(const StreamParser::InitCB& init_cb, |
| 248 bool allow_audio, | 258 bool allow_audio, |
| 249 bool allow_video, | 259 bool allow_video, |
| 250 const StreamParser::NeedKeyCB& need_key_cb, | 260 const StreamParser::NeedKeyCB& need_key_cb, |
| 251 const NewTextTrackCB& new_text_track_cb) { | 261 const NewTextTrackCB& new_text_track_cb) { |
| 252 new_text_track_cb_ = new_text_track_cb; | 262 new_text_track_cb_ = new_text_track_cb; |
| 263 init_cb_ = init_cb; | |
| 253 | 264 |
| 254 stream_parser_->Init(init_cb, | 265 stream_parser_->Init(base::Bind(&SourceState::OnSourceInitDone, |
| 266 base::Unretained(this)), | |
| 255 base::Bind(&SourceState::OnNewConfigs, | 267 base::Bind(&SourceState::OnNewConfigs, |
| 256 base::Unretained(this), | 268 base::Unretained(this), |
| 257 allow_audio, | 269 allow_audio, |
| 258 allow_video), | 270 allow_video), |
| 259 base::Bind(&SourceState::OnNewBuffers, | 271 base::Bind(&SourceState::OnNewBuffers, |
| 260 base::Unretained(this)), | 272 base::Unretained(this)), |
| 261 new_text_track_cb_.is_null(), | 273 new_text_track_cb_.is_null(), |
| 262 need_key_cb, | 274 need_key_cb, |
| 263 base::Bind(&SourceState::OnNewMediaSegment, | 275 base::Bind(&SourceState::OnNewMediaSegment, |
| 264 base::Unretained(this)), | 276 base::Unretained(this)), |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 631 new_media_segment_ = false; | 643 new_media_segment_ = false; |
| 632 } | 644 } |
| 633 | 645 |
| 634 bool SourceState::OnNewBuffers( | 646 bool SourceState::OnNewBuffers( |
| 635 const StreamParser::BufferQueue& audio_buffers, | 647 const StreamParser::BufferQueue& audio_buffers, |
| 636 const StreamParser::BufferQueue& video_buffers, | 648 const StreamParser::BufferQueue& video_buffers, |
| 637 const StreamParser::TextBufferQueueMap& text_map) { | 649 const StreamParser::TextBufferQueueMap& text_map) { |
| 638 DVLOG(2) << "OnNewBuffers()"; | 650 DVLOG(2) << "OnNewBuffers()"; |
| 639 DCHECK(timestamp_offset_during_append_); | 651 DCHECK(timestamp_offset_during_append_); |
| 640 | 652 |
| 641 return frame_processor_->ProcessFrames( | 653 const bool success = |
| 642 audio_buffers, video_buffers, text_map, | 654 frame_processor_->ProcessFrames(audio_buffers, |
| 643 append_window_start_during_append_, append_window_end_during_append_, | 655 video_buffers, |
| 644 &new_media_segment_, timestamp_offset_during_append_); | 656 text_map, |
| 657 append_window_start_during_append_, | |
| 658 append_window_end_during_append_, | |
| 659 &new_media_segment_, | |
| 660 timestamp_offset_during_append_); | |
| 661 | |
| 662 if (auto_update_timestamp_offset_) { | |
| 663 const bool have_video_buffers = !video_buffers.empty(); | |
| 664 base::TimeDelta new_timestamp_offset = | |
|
acolwell GONE FROM CHROMIUM
2014/03/17 22:52:17
nit: Drop base:: since we've got a using directive
DaleCurtis
2014/03/18 00:14:02
Done.
| |
| 665 have_video_buffers ? video_buffers.back()->timestamp() + | |
| 666 video_buffers.back()->duration() | |
| 667 : audio_buffers.back()->timestamp() + | |
|
acolwell GONE FROM CHROMIUM
2014/03/17 22:52:17
You need an empty guard here if we only happened t
DaleCurtis
2014/03/18 00:14:02
Reflowed to a multi-if statement + helper function
| |
| 668 audio_buffers.back()->duration(); | |
| 669 if (have_video_buffers && !audio_buffers.empty()) { | |
| 670 new_timestamp_offset = std::min( | |
| 671 new_timestamp_offset, | |
| 672 audio_buffers.back()->timestamp() + audio_buffers.back()->duration()); | |
| 673 } | |
| 674 | |
| 675 *timestamp_offset_during_append_ = new_timestamp_offset; | |
|
acolwell GONE FROM CHROMIUM
2014/03/17 22:52:17
You might need to snapshot *timestamp_offset_durin
DaleCurtis
2014/03/18 00:14:02
+wolenetz, what do you think? Probably we both sho
| |
| 676 } | |
| 677 | |
| 678 return success; | |
| 679 } | |
| 680 | |
| 681 void SourceState::OnSourceInitDone(bool success, | |
| 682 TimeDelta duration, | |
| 683 bool auto_update_timestamp_offset) { | |
| 684 auto_update_timestamp_offset_ = auto_update_timestamp_offset; | |
| 685 init_cb_.Run(success, duration, auto_update_timestamp_offset); | |
| 645 } | 686 } |
| 646 | 687 |
| 647 ChunkDemuxerStream::ChunkDemuxerStream(Type type) | 688 ChunkDemuxerStream::ChunkDemuxerStream(Type type) |
| 648 : type_(type), | 689 : type_(type), |
| 649 state_(UNINITIALIZED) { | 690 state_(UNINITIALIZED) { |
| 650 } | 691 } |
| 651 | 692 |
| 652 void ChunkDemuxerStream::StartReturningData() { | 693 void ChunkDemuxerStream::StartReturningData() { |
| 653 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; | 694 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; |
| 654 base::AutoLock auto_lock(lock_); | 695 base::AutoLock auto_lock(lock_); |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1409 lock_.AssertAcquired(); | 1450 lock_.AssertAcquired(); |
| 1410 for (SourceStateMap::const_iterator itr = source_state_map_.begin(); | 1451 for (SourceStateMap::const_iterator itr = source_state_map_.begin(); |
| 1411 itr != source_state_map_.end(); ++itr) { | 1452 itr != source_state_map_.end(); ++itr) { |
| 1412 if (itr->second->IsSeekWaitingForData()) | 1453 if (itr->second->IsSeekWaitingForData()) |
| 1413 return true; | 1454 return true; |
| 1414 } | 1455 } |
| 1415 | 1456 |
| 1416 return false; | 1457 return false; |
| 1417 } | 1458 } |
| 1418 | 1459 |
| 1419 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { | 1460 void ChunkDemuxer::OnSourceInitDone(bool success, |
| 1420 DVLOG(1) << "OnSourceInitDone(" << success << ", " | 1461 TimeDelta duration, |
| 1421 << duration.InSecondsF() << ")"; | 1462 bool auto_update_timestamp_offset) { |
|
acolwell GONE FROM CHROMIUM
2014/03/17 22:52:17
nit: No need to expose this detail to ChunkDemuxer
DaleCurtis
2014/03/18 00:14:02
Done.
| |
| 1463 DVLOG(1) << "OnSourceInitDone(" << success << ", " << duration.InSecondsF() | |
| 1464 << ", " << auto_update_timestamp_offset << ")"; | |
| 1422 lock_.AssertAcquired(); | 1465 lock_.AssertAcquired(); |
| 1423 DCHECK_EQ(state_, INITIALIZING); | 1466 DCHECK_EQ(state_, INITIALIZING); |
| 1424 if (!success || (!audio_ && !video_)) { | 1467 if (!success || (!audio_ && !video_)) { |
| 1425 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1468 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
| 1426 return; | 1469 return; |
| 1427 } | 1470 } |
| 1428 | 1471 |
| 1429 if (duration != TimeDelta() && duration_ == kNoTimestamp()) | 1472 if (duration != TimeDelta() && duration_ == kNoTimestamp()) |
| 1430 UpdateDuration(duration); | 1473 UpdateDuration(duration); |
| 1431 | 1474 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1573 } | 1616 } |
| 1574 | 1617 |
| 1575 void ChunkDemuxer::ShutdownAllStreams() { | 1618 void ChunkDemuxer::ShutdownAllStreams() { |
| 1576 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1619 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
| 1577 itr != source_state_map_.end(); ++itr) { | 1620 itr != source_state_map_.end(); ++itr) { |
| 1578 itr->second->Shutdown(); | 1621 itr->second->Shutdown(); |
| 1579 } | 1622 } |
| 1580 } | 1623 } |
| 1581 | 1624 |
| 1582 } // namespace media | 1625 } // namespace media |
| OLD | NEW |