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

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

Issue 195973006: Allow StreamParsers to request automatic timestampOffset updates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Revert appendWindow changes. Pre-calculate. Created 6 years, 9 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
« no previous file with comments | « media/base/stream_parser.h ('k') | media/filters/pipeline_integration_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/message_loop/message_loop_proxy.h" 14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "media/base/audio_decoder_config.h" 16 #include "media/base/audio_decoder_config.h"
17 #include "media/base/bind_to_current_loop.h" 17 #include "media/base/bind_to_current_loop.h"
18 #include "media/base/stream_parser_buffer.h" 18 #include "media/base/stream_parser_buffer.h"
19 #include "media/base/video_decoder_config.h" 19 #include "media/base/video_decoder_config.h"
20 #include "media/filters/legacy_frame_processor.h" 20 #include "media/filters/legacy_frame_processor.h"
21 #include "media/filters/stream_parser_factory.h" 21 #include "media/filters/stream_parser_factory.h"
22 22
23 using base::TimeDelta; 23 using base::TimeDelta;
24 24
25 namespace media { 25 namespace media {
26 26
27 static TimeDelta EndTimestamp(const StreamParser::BufferQueue& queue) {
28 return queue.back()->timestamp() + queue.back()->duration();
29 }
30
27 // List of time ranges for each SourceBuffer. 31 // List of time ranges for each SourceBuffer.
28 typedef std::list<Ranges<TimeDelta> > RangesList; 32 typedef std::list<Ranges<TimeDelta> > RangesList;
29 static Ranges<TimeDelta> ComputeIntersection(const RangesList& activeRanges, 33 static Ranges<TimeDelta> ComputeIntersection(const RangesList& activeRanges,
30 bool ended) { 34 bool ended) {
31 // Implementation of HTMLMediaElement.buffered algorithm in MSE spec. 35 // Implementation of HTMLMediaElement.buffered algorithm in MSE spec.
32 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sourc e.html#dom-htmlmediaelement.buffered 36 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sourc e.html#dom-htmlmediaelement.buffered
33 37
34 // Step 1: If activeSourceBuffers.length equals 0 then return an empty 38 // Step 1: If activeSourceBuffers.length equals 0 then return an empty
35 // TimeRanges object and abort these steps. 39 // TimeRanges object and abort these steps.
36 if (activeRanges.empty()) 40 if (activeRanges.empty())
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 // Contains state belonging to a source id. 86 // Contains state belonging to a source id.
83 class SourceState { 87 class SourceState {
84 public: 88 public:
85 // Callback signature used to create ChunkDemuxerStreams. 89 // Callback signature used to create ChunkDemuxerStreams.
86 typedef base::Callback<ChunkDemuxerStream*( 90 typedef base::Callback<ChunkDemuxerStream*(
87 DemuxerStream::Type)> CreateDemuxerStreamCB; 91 DemuxerStream::Type)> CreateDemuxerStreamCB;
88 92
89 typedef base::Callback<void( 93 typedef base::Callback<void(
90 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; 94 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB;
91 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 typedef base::Callback<void(bool, TimeDelta)> InitCB;
102
92 SourceState( 103 SourceState(
93 scoped_ptr<StreamParser> stream_parser, 104 scoped_ptr<StreamParser> stream_parser,
94 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb, 105 scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb,
95 const CreateDemuxerStreamCB& create_demuxer_stream_cb); 106 const CreateDemuxerStreamCB& create_demuxer_stream_cb);
96 107
97 ~SourceState(); 108 ~SourceState();
98 109
99 void Init(const StreamParser::InitCB& init_cb, 110 void Init(const InitCB& init_cb,
100 bool allow_audio, 111 bool allow_audio,
101 bool allow_video, 112 bool allow_video,
102 const StreamParser::NeedKeyCB& need_key_cb, 113 const StreamParser::NeedKeyCB& need_key_cb,
103 const NewTextTrackCB& new_text_track_cb); 114 const NewTextTrackCB& new_text_track_cb);
104 115
105 // Appends new data to the StreamParser. 116 // Appends new data to the StreamParser.
106 // Returns true if the data was successfully appended. Returns false if an 117 // Returns true if the data was successfully appended. Returns false if an
107 // error occurred. |*timestamp_offset| is used and possibly updated by the 118 // error occurred. |*timestamp_offset| is used and possibly updated by the
108 // append. |append_window_start| and |append_window_end| correspond to the MSE 119 // append. |append_window_start| and |append_window_end| correspond to the MSE
109 // spec's similarly named source buffer attributes that are used in coded 120 // spec's similarly named source buffer attributes that are used in coded
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 // Called by the |stream_parser_| when new buffers have been parsed. 181 // Called by the |stream_parser_| when new buffers have been parsed.
171 // It processes the new buffers using |frame_processor_|, which includes 182 // It processes the new buffers using |frame_processor_|, which includes
172 // appending the processed frames to associated demuxer streams for each 183 // appending the processed frames to associated demuxer streams for each
173 // frame's track. 184 // frame's track.
174 // Returns true on a successful call. Returns false if an error occurred while 185 // Returns true on a successful call. Returns false if an error occurred while
175 // processing the buffers. 186 // processing the buffers.
176 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, 187 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
177 const StreamParser::BufferQueue& video_buffers, 188 const StreamParser::BufferQueue& video_buffers,
178 const StreamParser::TextBufferQueueMap& text_map); 189 const StreamParser::TextBufferQueueMap& text_map);
179 190
191 void OnSourceInitDone(bool success,
192 TimeDelta duration,
193 bool auto_update_timestamp_offset);
194
180 CreateDemuxerStreamCB create_demuxer_stream_cb_; 195 CreateDemuxerStreamCB create_demuxer_stream_cb_;
181 NewTextTrackCB new_text_track_cb_; 196 NewTextTrackCB new_text_track_cb_;
182 197
183 // During Append(), if OnNewBuffers() coded frame processing updates the 198 // During Append(), if OnNewBuffers() coded frame processing updates the
184 // timestamp offset then |*timestamp_offset_during_append_| is also updated 199 // 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 200 // so Append()'s caller can know the new offset. This pointer is only non-NULL
186 // during the lifetime of an Append() call. 201 // during the lifetime of an Append() call.
187 TimeDelta* timestamp_offset_during_append_; 202 TimeDelta* timestamp_offset_during_append_;
188 203
189 // During Append(), coded frame processing triggered by OnNewBuffers() 204 // During Append(), coded frame processing triggered by OnNewBuffers()
(...skipping 19 matching lines...) Expand all
209 scoped_ptr<StreamParser> stream_parser_; 224 scoped_ptr<StreamParser> stream_parser_;
210 225
211 ChunkDemuxerStream* audio_; // Not owned by |this|. 226 ChunkDemuxerStream* audio_; // Not owned by |this|.
212 ChunkDemuxerStream* video_; // Not owned by |this|. 227 ChunkDemuxerStream* video_; // Not owned by |this|.
213 228
214 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; 229 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap;
215 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. 230 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers.
216 231
217 scoped_ptr<FrameProcessorBase> frame_processor_; 232 scoped_ptr<FrameProcessorBase> frame_processor_;
218 LogCB log_cb_; 233 LogCB log_cb_;
234 InitCB init_cb_;
235
236 // Indicates that timestampOffset should be updated automatically during
237 // OnNewBuffers() based on the earliest end timestamp of the buffers provided.
238 bool auto_update_timestamp_offset_;
219 239
220 DISALLOW_COPY_AND_ASSIGN(SourceState); 240 DISALLOW_COPY_AND_ASSIGN(SourceState);
221 }; 241 };
222 242
223 SourceState::SourceState( 243 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser,
224 scoped_ptr<StreamParser> stream_parser, 244 scoped_ptr<FrameProcessorBase> frame_processor,
225 scoped_ptr<FrameProcessorBase> frame_processor, 245 const LogCB& log_cb,
226 const LogCB& log_cb, 246 const CreateDemuxerStreamCB& create_demuxer_stream_cb)
227 const CreateDemuxerStreamCB& create_demuxer_stream_cb)
228 : create_demuxer_stream_cb_(create_demuxer_stream_cb), 247 : create_demuxer_stream_cb_(create_demuxer_stream_cb),
229 timestamp_offset_during_append_(NULL), 248 timestamp_offset_during_append_(NULL),
230 new_media_segment_(false), 249 new_media_segment_(false),
231 parsing_media_segment_(false), 250 parsing_media_segment_(false),
232 stream_parser_(stream_parser.release()), 251 stream_parser_(stream_parser.release()),
233 audio_(NULL), 252 audio_(NULL),
234 video_(NULL), 253 video_(NULL),
235 frame_processor_(frame_processor.release()), 254 frame_processor_(frame_processor.release()),
236 log_cb_(log_cb) { 255 log_cb_(log_cb),
256 auto_update_timestamp_offset_(false) {
237 DCHECK(!create_demuxer_stream_cb_.is_null()); 257 DCHECK(!create_demuxer_stream_cb_.is_null());
238 DCHECK(frame_processor_); 258 DCHECK(frame_processor_);
239 } 259 }
240 260
241 SourceState::~SourceState() { 261 SourceState::~SourceState() {
242 Shutdown(); 262 Shutdown();
243 263
244 STLDeleteValues(&text_stream_map_); 264 STLDeleteValues(&text_stream_map_);
245 } 265 }
246 266
247 void SourceState::Init(const StreamParser::InitCB& init_cb, 267 void SourceState::Init(const InitCB& init_cb,
248 bool allow_audio, 268 bool allow_audio,
249 bool allow_video, 269 bool allow_video,
250 const StreamParser::NeedKeyCB& need_key_cb, 270 const StreamParser::NeedKeyCB& need_key_cb,
251 const NewTextTrackCB& new_text_track_cb) { 271 const NewTextTrackCB& new_text_track_cb) {
252 new_text_track_cb_ = new_text_track_cb; 272 new_text_track_cb_ = new_text_track_cb;
273 init_cb_ = init_cb;
253 274
254 stream_parser_->Init(init_cb, 275 stream_parser_->Init(
255 base::Bind(&SourceState::OnNewConfigs, 276 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)),
256 base::Unretained(this), 277 base::Bind(&SourceState::OnNewConfigs,
257 allow_audio, 278 base::Unretained(this),
258 allow_video), 279 allow_audio,
259 base::Bind(&SourceState::OnNewBuffers, 280 allow_video),
260 base::Unretained(this)), 281 base::Bind(&SourceState::OnNewBuffers, base::Unretained(this)),
261 new_text_track_cb_.is_null(), 282 new_text_track_cb_.is_null(),
262 need_key_cb, 283 need_key_cb,
263 base::Bind(&SourceState::OnNewMediaSegment, 284 base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this)),
264 base::Unretained(this)), 285 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)),
265 base::Bind(&SourceState::OnEndOfMediaSegment, 286 log_cb_);
266 base::Unretained(this)),
267 log_cb_);
268 } 287 }
269 288
270 void SourceState::SetSequenceMode(bool sequence_mode) { 289 void SourceState::SetSequenceMode(bool sequence_mode) {
271 DCHECK(!parsing_media_segment_); 290 DCHECK(!parsing_media_segment_);
272 291
273 frame_processor_->SetSequenceMode(sequence_mode); 292 frame_processor_->SetSequenceMode(sequence_mode);
274 } 293 }
275 294
276 bool SourceState::Append(const uint8* data, size_t length, 295 bool SourceState::Append(const uint8* data, size_t length,
277 TimeDelta append_window_start, 296 TimeDelta append_window_start,
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 new_media_segment_ = false; 650 new_media_segment_ = false;
632 } 651 }
633 652
634 bool SourceState::OnNewBuffers( 653 bool SourceState::OnNewBuffers(
635 const StreamParser::BufferQueue& audio_buffers, 654 const StreamParser::BufferQueue& audio_buffers,
636 const StreamParser::BufferQueue& video_buffers, 655 const StreamParser::BufferQueue& video_buffers,
637 const StreamParser::TextBufferQueueMap& text_map) { 656 const StreamParser::TextBufferQueueMap& text_map) {
638 DVLOG(2) << "OnNewBuffers()"; 657 DVLOG(2) << "OnNewBuffers()";
639 DCHECK(timestamp_offset_during_append_); 658 DCHECK(timestamp_offset_during_append_);
640 659
641 return frame_processor_->ProcessFrames( 660 const TimeDelta timestamp_offset_before_processing =
642 audio_buffers, video_buffers, text_map, 661 *timestamp_offset_during_append_;
643 append_window_start_during_append_, append_window_end_during_append_, 662
644 &new_media_segment_, timestamp_offset_during_append_); 663 // Update the timestamp offset for audio/video tracks if it hasn't already
acolwell GONE FROM CHROMIUM 2014/03/18 19:57:16 nit: Please fix comment since you are only computi
DaleCurtis 2014/03/18 20:37:57 Done.
664 // been updated by the frame processor.
665 TimeDelta new_timestamp_offset = timestamp_offset_before_processing;
666 const bool have_audio_buffers = !audio_buffers.empty();
wolenetz 2014/03/18 20:23:33 nit: move these bools and their initializations in
DaleCurtis 2014/03/18 20:37:57 Done.
667 const bool have_video_buffers = !video_buffers.empty();
668 if (auto_update_timestamp_offset_) {
669 if (have_audio_buffers && have_video_buffers) {
670 new_timestamp_offset +=
671 std::min(EndTimestamp(audio_buffers), EndTimestamp(video_buffers));
672 } else if (have_audio_buffers) {
673 new_timestamp_offset += EndTimestamp(audio_buffers);
674 } else if (have_video_buffers) {
675 new_timestamp_offset += EndTimestamp(video_buffers);
676 }
677 }
678
679 if (!frame_processor_->ProcessFrames(audio_buffers,
680 video_buffers,
681 text_map,
682 append_window_start_during_append_,
683 append_window_end_during_append_,
684 &new_media_segment_,
685 timestamp_offset_during_append_)) {
686 return false;
687 }
688
689 // Only update the timestamp offset if the frame processor hasn't already.
690 if (timestamp_offset_before_processing == *timestamp_offset_during_append_)
wolenetz 2014/03/18 20:23:33 nit: though currently correct, add condition auto_
DaleCurtis 2014/03/18 20:37:57 Done.
691 *timestamp_offset_during_append_ = new_timestamp_offset;
692
693 return true;
694 }
695
696 void SourceState::OnSourceInitDone(bool success,
697 TimeDelta duration,
698 bool auto_update_timestamp_offset) {
699 auto_update_timestamp_offset_ = auto_update_timestamp_offset;
700 base::ResetAndReturn(&init_cb_).Run(success, duration);
645 } 701 }
646 702
647 ChunkDemuxerStream::ChunkDemuxerStream(Type type) 703 ChunkDemuxerStream::ChunkDemuxerStream(Type type)
648 : type_(type), 704 : type_(type),
649 state_(UNINITIALIZED) { 705 state_(UNINITIALIZED) {
650 } 706 }
651 707
652 void ChunkDemuxerStream::StartReturningData() { 708 void ChunkDemuxerStream::StartReturningData() {
653 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; 709 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()";
654 base::AutoLock auto_lock(lock_); 710 base::AutoLock auto_lock(lock_);
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 } 1629 }
1574 1630
1575 void ChunkDemuxer::ShutdownAllStreams() { 1631 void ChunkDemuxer::ShutdownAllStreams() {
1576 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1632 for (SourceStateMap::iterator itr = source_state_map_.begin();
1577 itr != source_state_map_.end(); ++itr) { 1633 itr != source_state_map_.end(); ++itr) {
1578 itr->second->Shutdown(); 1634 itr->second->Shutdown();
1579 } 1635 }
1580 } 1636 }
1581 1637
1582 } // namespace media 1638 } // namespace media
OLDNEW
« no previous file with comments | « media/base/stream_parser.h ('k') | media/filters/pipeline_integration_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698