Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 231283005: Add live mode detection in WebM MediaSource parser. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 96 // success - True if initialization was successful, false otherwise.
97 // initialization was successful. False if an error 97 // duration - Stream duration. Only valid if |success| is true.
98 // occurred. 98 // timeline_offset - Indicates the source Time associated with
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 99 // presentation timestamp 0. A null Time is returned if
103 // no mapping to Time exists. Only contains a 100 // no mapping to Time exists. Only contains a
104 // valid value if the first parameter is true. 101 // valid value if |success| is true.
105 typedef base::Callback<void(bool, TimeDelta, base::Time)> InitCB; 102 // live_mode - True when the stream is a live stream.
103 typedef base::Callback<void(bool success,
104 TimeDelta duration,
105 base::Time timeline_offset,
106 bool live_mode)> InitCB;
106 107
107 SourceState( 108 SourceState(
108 scoped_ptr<StreamParser> stream_parser, 109 scoped_ptr<StreamParser> stream_parser,
109 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb, 110 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb,
110 const CreateDemuxerStreamCB& create_demuxer_stream_cb); 111 const CreateDemuxerStreamCB& create_demuxer_stream_cb);
111 112
112 ~SourceState(); 113 ~SourceState();
113 114
114 void Init(const InitCB& init_cb, 115 void Init(const InitCB& init_cb,
115 bool allow_audio, 116 bool allow_audio,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 // frame's track. 189 // frame's track.
189 // Returns true on a successful call. Returns false if an error occurred while 190 // Returns true on a successful call. Returns false if an error occurred while
190 // processing the buffers. 191 // processing the buffers.
191 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, 192 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
192 const StreamParser::BufferQueue& video_buffers, 193 const StreamParser::BufferQueue& video_buffers,
193 const StreamParser::TextBufferQueueMap& text_map); 194 const StreamParser::TextBufferQueueMap& text_map);
194 195
195 void OnSourceInitDone(bool success, 196 void OnSourceInitDone(bool success,
196 TimeDelta duration, 197 TimeDelta duration,
197 base::Time timeline_offset, 198 base::Time timeline_offset,
198 bool auto_update_timestamp_offset); 199 bool auto_update_timestamp_offset,
200 bool live_mode);
199 201
200 CreateDemuxerStreamCB create_demuxer_stream_cb_; 202 CreateDemuxerStreamCB create_demuxer_stream_cb_;
201 NewTextTrackCB new_text_track_cb_; 203 NewTextTrackCB new_text_track_cb_;
202 204
203 // During Append(), if OnNewBuffers() coded frame processing updates the 205 // During Append(), if OnNewBuffers() coded frame processing updates the
204 // timestamp offset then |*timestamp_offset_during_append_| is also updated 206 // 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 207 // so Append()'s caller can know the new offset. This pointer is only non-NULL
206 // during the lifetime of an Append() call. 208 // during the lifetime of an Append() call.
207 TimeDelta* timestamp_offset_during_append_; 209 TimeDelta* timestamp_offset_during_append_;
208 210
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 timestamp_offset_before_processing == *timestamp_offset_during_append_) { 698 timestamp_offset_before_processing == *timestamp_offset_during_append_) {
697 *timestamp_offset_during_append_ = new_timestamp_offset; 699 *timestamp_offset_during_append_ = new_timestamp_offset;
698 } 700 }
699 701
700 return true; 702 return true;
701 } 703 }
702 704
703 void SourceState::OnSourceInitDone(bool success, 705 void SourceState::OnSourceInitDone(bool success,
704 TimeDelta duration, 706 TimeDelta duration,
705 base::Time timeline_offset, 707 base::Time timeline_offset,
706 bool auto_update_timestamp_offset) { 708 bool auto_update_timestamp_offset,
709 bool live_mode) {
707 auto_update_timestamp_offset_ = auto_update_timestamp_offset; 710 auto_update_timestamp_offset_ = auto_update_timestamp_offset;
708 base::ResetAndReturn(&init_cb_).Run( 711 base::ResetAndReturn(&init_cb_).Run(
709 success, duration, timeline_offset); 712 success, duration, timeline_offset, live_mode);
710 } 713 }
711 714
712 ChunkDemuxerStream::ChunkDemuxerStream(Type type, bool splice_frames_enabled) 715 ChunkDemuxerStream::ChunkDemuxerStream(Type type, bool splice_frames_enabled)
713 : type_(type), 716 : type_(type),
714 state_(UNINITIALIZED), 717 state_(UNINITIALIZED),
715 splice_frames_enabled_(splice_frames_enabled) {} 718 splice_frames_enabled_(splice_frames_enabled) {}
716 719
717 void ChunkDemuxerStream::StartReturningData() { 720 void ChunkDemuxerStream::StartReturningData() {
718 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; 721 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()";
719 base::AutoLock auto_lock(lock_); 722 base::AutoLock auto_lock(lock_);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 bool splice_frames_enabled) 986 bool splice_frames_enabled)
984 : state_(WAITING_FOR_INIT), 987 : state_(WAITING_FOR_INIT),
985 cancel_next_seek_(false), 988 cancel_next_seek_(false),
986 host_(NULL), 989 host_(NULL),
987 open_cb_(open_cb), 990 open_cb_(open_cb),
988 need_key_cb_(need_key_cb), 991 need_key_cb_(need_key_cb),
989 enable_text_(false), 992 enable_text_(false),
990 log_cb_(log_cb), 993 log_cb_(log_cb),
991 duration_(kNoTimestamp()), 994 duration_(kNoTimestamp()),
992 user_specified_duration_(-1), 995 user_specified_duration_(-1),
996 live_mode_(false),
993 splice_frames_enabled_(splice_frames_enabled) { 997 splice_frames_enabled_(splice_frames_enabled) {
994 DCHECK(!open_cb_.is_null()); 998 DCHECK(!open_cb_.is_null());
995 DCHECK(!need_key_cb_.is_null()); 999 DCHECK(!need_key_cb_.is_null());
996 } 1000 }
997 1001
998 void ChunkDemuxer::Initialize( 1002 void ChunkDemuxer::Initialize(
999 DemuxerHost* host, 1003 DemuxerHost* host,
1000 const PipelineStatusCB& cb, 1004 const PipelineStatusCB& cb,
1001 bool enable_text_tracks) { 1005 bool enable_text_tracks) {
1002 DVLOG(1) << "Init()"; 1006 DVLOG(1) << "Init()";
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 } 1077 }
1074 1078
1075 TimeDelta ChunkDemuxer::GetStartTime() const { 1079 TimeDelta ChunkDemuxer::GetStartTime() const {
1076 return TimeDelta(); 1080 return TimeDelta();
1077 } 1081 }
1078 1082
1079 base::Time ChunkDemuxer::GetTimelineOffset() const { 1083 base::Time ChunkDemuxer::GetTimelineOffset() const {
1080 return timeline_offset_; 1084 return timeline_offset_;
1081 } 1085 }
1082 1086
1087 bool ChunkDemuxer::IsLiveMode() const {
1088 return live_mode_;
1089 }
1090
1083 void ChunkDemuxer::StartWaitingForSeek(TimeDelta seek_time) { 1091 void ChunkDemuxer::StartWaitingForSeek(TimeDelta seek_time) {
1084 DVLOG(1) << "StartWaitingForSeek()"; 1092 DVLOG(1) << "StartWaitingForSeek()";
1085 base::AutoLock auto_lock(lock_); 1093 base::AutoLock auto_lock(lock_);
1086 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN || 1094 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN ||
1087 state_ == PARSE_ERROR) << state_; 1095 state_ == PARSE_ERROR) << state_;
1088 DCHECK(seek_cb_.is_null()); 1096 DCHECK(seek_cb_.is_null());
1089 1097
1090 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 1098 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
1091 return; 1099 return;
1092 1100
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 lock_.AssertAcquired(); 1498 lock_.AssertAcquired();
1491 for (SourceStateMap::const_iterator itr = source_state_map_.begin(); 1499 for (SourceStateMap::const_iterator itr = source_state_map_.begin();
1492 itr != source_state_map_.end(); ++itr) { 1500 itr != source_state_map_.end(); ++itr) {
1493 if (itr->second->IsSeekWaitingForData()) 1501 if (itr->second->IsSeekWaitingForData())
1494 return true; 1502 return true;
1495 } 1503 }
1496 1504
1497 return false; 1505 return false;
1498 } 1506 }
1499 1507
1500 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration, 1508 void ChunkDemuxer::OnSourceInitDone(bool success,
1501 base::Time timeline_offset) { 1509 TimeDelta duration,
1510 base::Time timeline_offset,
1511 bool live_mode) {
1502 DVLOG(1) << "OnSourceInitDone(" << success << ", " 1512 DVLOG(1) << "OnSourceInitDone(" << success << ", "
1503 << duration.InSecondsF() << ")"; 1513 << duration.InSecondsF() << ")";
1504 lock_.AssertAcquired(); 1514 lock_.AssertAcquired();
1505 DCHECK_EQ(state_, INITIALIZING); 1515 DCHECK_EQ(state_, INITIALIZING);
1506 if (!success || (!audio_ && !video_)) { 1516 if (!success || (!audio_ && !video_)) {
1507 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1517 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1508 return; 1518 return;
1509 } 1519 }
1510 1520
1511 if (duration != TimeDelta() && duration_ == kNoTimestamp()) 1521 if (duration != TimeDelta() && duration_ == kNoTimestamp())
1512 UpdateDuration(duration); 1522 UpdateDuration(duration);
1513 1523
1514 if (!timeline_offset.is_null()) { 1524 if (!timeline_offset.is_null()) {
1515 if (!timeline_offset_.is_null() && 1525 if (!timeline_offset_.is_null() &&
1516 timeline_offset != timeline_offset_) { 1526 timeline_offset != timeline_offset_) {
1517 MEDIA_LOG(log_cb_) 1527 MEDIA_LOG(log_cb_)
1518 << "Timeline offset is not the same across all SourceBuffers."; 1528 << "Timeline offset is not the same across all SourceBuffers.";
1519 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1529 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1520 return; 1530 return;
1521 } 1531 }
1522 1532
1523 timeline_offset_ = timeline_offset; 1533 timeline_offset_ = timeline_offset;
1524 } 1534 }
1525 1535
1536 live_mode_ |= live_mode;
1537
1526 // Wait until all streams have initialized. 1538 // Wait until all streams have initialized.
1527 if ((!source_id_audio_.empty() && !audio_) || 1539 if ((!source_id_audio_.empty() && !audio_) ||
1528 (!source_id_video_.empty() && !video_)) 1540 (!source_id_video_.empty() && !video_)) {
1529 return; 1541 return;
1542 }
1530 1543
1531 SeekAllSources(GetStartTime()); 1544 SeekAllSources(GetStartTime());
1532 StartReturningData(); 1545 StartReturningData();
1533 1546
1534 if (duration_ == kNoTimestamp()) 1547 if (duration_ == kNoTimestamp())
1535 duration_ = kInfiniteDuration(); 1548 duration_ = kInfiniteDuration();
1536 1549
1537 // The demuxer is now initialized after the |start_timestamp_| was set. 1550 // The demuxer is now initialized after the |start_timestamp_| was set.
1538 ChangeState_Locked(INITIALIZED); 1551 ChangeState_Locked(INITIALIZED);
1539 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 1552 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1668 } 1681 }
1669 1682
1670 void ChunkDemuxer::ShutdownAllStreams() { 1683 void ChunkDemuxer::ShutdownAllStreams() {
1671 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1684 for (SourceStateMap::iterator itr = source_state_map_.begin();
1672 itr != source_state_map_.end(); ++itr) { 1685 itr != source_state_map_.end(); ++itr) {
1673 itr->second->Shutdown(); 1686 itr->second->Shutdown();
1674 } 1687 }
1675 } 1688 }
1676 1689
1677 } // namespace media 1690 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698