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

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

Issue 13419002: Media Source dispatches inband text tracks (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase Created 7 years, 7 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
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.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 <deque> 8 #include <deque>
9 #include <limits> 9 #include <limits>
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_proxy.h" 14 #include "base/message_loop_proxy.h"
15 #include "media/base/audio_decoder_config.h" 15 #include "media/base/audio_decoder_config.h"
16 #include "media/base/stream_parser_buffer.h" 16 #include "media/base/stream_parser_buffer.h"
17 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
18 #include "media/filters/stream_parser_factory.h" 18 #include "media/filters/stream_parser_factory.h"
19 #include "media/webm/webm_webvtt_parser.h"
19 20
20 using base::TimeDelta; 21 using base::TimeDelta;
21 22
22 namespace media { 23 namespace media {
23 24
24 // Contains state belonging to a source id. 25 // Contains state belonging to a source id.
25 class SourceState { 26 class SourceState {
26 public: 27 public:
27 explicit SourceState(scoped_ptr<StreamParser> stream_parser); 28 explicit SourceState(scoped_ptr<StreamParser> stream_parser);
28 29
29 void Init(const StreamParser::InitCB& init_cb, 30 void Init(const StreamParser::InitCB& init_cb,
30 const StreamParser::NewConfigCB& config_cb, 31 const StreamParser::NewConfigCB& config_cb,
31 const StreamParser::NewBuffersCB& audio_cb, 32 const StreamParser::NewBuffersCB& audio_cb,
32 const StreamParser::NewBuffersCB& video_cb, 33 const StreamParser::NewBuffersCB& video_cb,
34 const StreamParser::NewTextBuffersCB& text_cb,
33 const StreamParser::NeedKeyCB& need_key_cb, 35 const StreamParser::NeedKeyCB& need_key_cb,
36 const AddTextTrackCB& add_text_track_cb,
34 const StreamParser::NewMediaSegmentCB& new_segment_cb, 37 const StreamParser::NewMediaSegmentCB& new_segment_cb,
35 const LogCB& log_cb); 38 const LogCB& log_cb);
36 39
37 // Appends new data to the StreamParser. 40 // Appends new data to the StreamParser.
38 // Returns true if the data was successfully appended. Returns false if an 41 // Returns true if the data was successfully appended. Returns false if an
39 // error occurred. 42 // error occurred.
40 bool Append(const uint8* data, size_t length); 43 bool Append(const uint8* data, size_t length);
41 44
42 // Aborts the current append sequence and resets the parser. 45 // Aborts the current append sequence and resets the parser.
43 void Abort(); 46 void Abort();
(...skipping 17 matching lines...) Expand all
61 void OnEndOfMediaSegment(); 64 void OnEndOfMediaSegment();
62 65
63 // Called by the |stream_parser_| when new buffers have been parsed. It 66 // Called by the |stream_parser_| when new buffers have been parsed. It
64 // applies |timestamp_offset_| to all buffers in |buffers| and then calls 67 // applies |timestamp_offset_| to all buffers in |buffers| and then calls
65 // |new_buffers_cb| with the modified buffers. 68 // |new_buffers_cb| with the modified buffers.
66 // Returns true on a successful call. Returns false if an error occured while 69 // Returns true on a successful call. Returns false if an error occured while
67 // processing the buffers. 70 // processing the buffers.
68 bool OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb, 71 bool OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb,
69 const StreamParser::BufferQueue& buffers); 72 const StreamParser::BufferQueue& buffers);
70 73
74 // Called by the |stream_parser_| when new text buffers have been parsed. It
75 // applies |timestamp_offset_| to all buffers in |buffers| and then calls
76 // |new_buffers_cb| with the modified buffers.
77 // Returns true on a successful call. Returns false if an error occured while
78 // processing the buffers.
79 bool OnTextBuffers(const StreamParser::NewTextBuffersCB& new_buffers_cb,
80 TextTrack* text_track,
81 const StreamParser::BufferQueue& buffers);
82
71 // Helper function that adds |timestamp_offset_| to each buffer in |buffers|. 83 // Helper function that adds |timestamp_offset_| to each buffer in |buffers|.
72 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers); 84 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers);
73 85
74 // The offset to apply to media segment timestamps. 86 // The offset to apply to media segment timestamps.
75 TimeDelta timestamp_offset_; 87 TimeDelta timestamp_offset_;
76 88
77 // Keeps track of whether |timestamp_offset_| can be modified. 89 // Keeps track of whether |timestamp_offset_| can be modified.
78 bool can_update_offset_; 90 bool can_update_offset_;
79 91
80 // The object used to parse appended data. 92 // The object used to parse appended data.
81 scoped_ptr<StreamParser> stream_parser_; 93 scoped_ptr<StreamParser> stream_parser_;
82 94
83 DISALLOW_COPY_AND_ASSIGN(SourceState); 95 DISALLOW_COPY_AND_ASSIGN(SourceState);
84 }; 96 };
85 97
86 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser) 98 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser)
87 : can_update_offset_(true), 99 : can_update_offset_(true),
88 stream_parser_(stream_parser.release()) { 100 stream_parser_(stream_parser.release()) {
89 } 101 }
90 102
91 void SourceState::Init(const StreamParser::InitCB& init_cb, 103 void SourceState::Init(const StreamParser::InitCB& init_cb,
92 const StreamParser::NewConfigCB& config_cb, 104 const StreamParser::NewConfigCB& config_cb,
93 const StreamParser::NewBuffersCB& audio_cb, 105 const StreamParser::NewBuffersCB& audio_cb,
94 const StreamParser::NewBuffersCB& video_cb, 106 const StreamParser::NewBuffersCB& video_cb,
107 const StreamParser::NewTextBuffersCB& text_cb,
95 const StreamParser::NeedKeyCB& need_key_cb, 108 const StreamParser::NeedKeyCB& need_key_cb,
109 const AddTextTrackCB& add_text_track_cb,
96 const StreamParser::NewMediaSegmentCB& new_segment_cb, 110 const StreamParser::NewMediaSegmentCB& new_segment_cb,
97 const LogCB& log_cb) { 111 const LogCB& log_cb) {
98 stream_parser_->Init(init_cb, config_cb, 112 stream_parser_->Init(init_cb, config_cb,
99 base::Bind(&SourceState::OnBuffers, 113 base::Bind(&SourceState::OnBuffers,
100 base::Unretained(this), audio_cb), 114 base::Unretained(this), audio_cb),
101 base::Bind(&SourceState::OnBuffers, 115 base::Bind(&SourceState::OnBuffers,
102 base::Unretained(this), video_cb), 116 base::Unretained(this), video_cb),
117 base::Bind(&SourceState::OnTextBuffers,
118 base::Unretained(this), text_cb),
103 need_key_cb, 119 need_key_cb,
120 add_text_track_cb,
104 base::Bind(&SourceState::OnNewMediaSegment, 121 base::Bind(&SourceState::OnNewMediaSegment,
105 base::Unretained(this), new_segment_cb), 122 base::Unretained(this), new_segment_cb),
106 base::Bind(&SourceState::OnEndOfMediaSegment, 123 base::Bind(&SourceState::OnEndOfMediaSegment,
107 base::Unretained(this)), 124 base::Unretained(this)),
108 log_cb); 125 log_cb);
109 } 126 }
110 127
111 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { 128 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) {
112 if (!can_update_offset_) 129 if (!can_update_offset_)
113 return false; 130 return false;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 bool SourceState::OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb, 173 bool SourceState::OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb,
157 const StreamParser::BufferQueue& buffers) { 174 const StreamParser::BufferQueue& buffers) {
158 if (new_buffers_cb.is_null()) 175 if (new_buffers_cb.is_null())
159 return false; 176 return false;
160 177
161 AdjustBufferTimestamps(buffers); 178 AdjustBufferTimestamps(buffers);
162 179
163 return new_buffers_cb.Run(buffers); 180 return new_buffers_cb.Run(buffers);
164 } 181 }
165 182
183 bool SourceState::OnTextBuffers(
184 const StreamParser::NewTextBuffersCB& new_buffers_cb,
185 TextTrack* text_track,
186 const StreamParser::BufferQueue& buffers) {
187 if (new_buffers_cb.is_null())
188 return false;
189
190 AdjustBufferTimestamps(buffers);
191
192 return new_buffers_cb.Run(text_track, buffers);
193 }
194
166 class ChunkDemuxerStream : public DemuxerStream { 195 class ChunkDemuxerStream : public DemuxerStream {
167 public: 196 public:
168 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 197 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
169 typedef std::deque<ReadCB> ReadCBQueue; 198 typedef std::deque<ReadCB> ReadCBQueue;
170 typedef std::deque<base::Closure> ClosureQueue; 199 typedef std::deque<base::Closure> ClosureQueue;
171 200
172 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, 201 ChunkDemuxerStream(const AudioDecoderConfig& audio_config,
173 const LogCB& log_cb); 202 const LogCB& log_cb);
174 ChunkDemuxerStream(const VideoDecoderConfig& video_config, 203 ChunkDemuxerStream(const VideoDecoderConfig& video_config,
175 const LogCB& log_cb); 204 const LogCB& log_cb);
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 *buffer = StreamParserBuffer::CreateEOSBuffer(); 567 *buffer = StreamParserBuffer::CreateEOSBuffer();
539 return true; 568 return true;
540 } 569 }
541 570
542 NOTREACHED(); 571 NOTREACHED();
543 return false; 572 return false;
544 } 573 }
545 574
546 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, 575 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb,
547 const NeedKeyCB& need_key_cb, 576 const NeedKeyCB& need_key_cb,
577 const AddTextTrackCB& add_text_track_cb,
548 const LogCB& log_cb) 578 const LogCB& log_cb)
549 : state_(WAITING_FOR_INIT), 579 : state_(WAITING_FOR_INIT),
550 host_(NULL), 580 host_(NULL),
551 open_cb_(open_cb), 581 open_cb_(open_cb),
552 need_key_cb_(need_key_cb), 582 need_key_cb_(need_key_cb),
583 add_text_track_cb_(add_text_track_cb),
553 log_cb_(log_cb), 584 log_cb_(log_cb),
554 duration_(kNoTimestamp()), 585 duration_(kNoTimestamp()),
555 user_specified_duration_(-1) { 586 user_specified_duration_(-1) {
556 DCHECK(!open_cb_.is_null()); 587 DCHECK(!open_cb_.is_null());
557 DCHECK(!need_key_cb_.is_null()); 588 DCHECK(!need_key_cb_.is_null());
558 } 589 }
559 590
560 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) { 591 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) {
561 DVLOG(1) << "Init()"; 592 DVLOG(1) << "Init()";
562 593
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 base::Unretained(this)); 734 base::Unretained(this));
704 } 735 }
705 736
706 scoped_ptr<SourceState> source_state(new SourceState(stream_parser.Pass())); 737 scoped_ptr<SourceState> source_state(new SourceState(stream_parser.Pass()));
707 source_state->Init( 738 source_state->Init(
708 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), 739 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
709 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), 740 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this),
710 has_audio, has_video), 741 has_audio, has_video),
711 audio_cb, 742 audio_cb,
712 video_cb, 743 video_cb,
744 base::Bind(&ChunkDemuxer::OnTextBuffers, base::Unretained(this)),
713 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)), 745 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)),
746 add_text_track_cb_,
714 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id), 747 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id),
715 log_cb_); 748 log_cb_);
716 749
717 source_state_map_[id] = source_state.release(); 750 source_state_map_[id] = source_state.release();
718 return kOk; 751 return kOk;
719 } 752 }
720 753
721 void ChunkDemuxer::RemoveId(const std::string& id) { 754 void ChunkDemuxer::RemoveId(const std::string& id) {
722 base::AutoLock auto_lock(lock_); 755 base::AutoLock auto_lock(lock_);
723 CHECK(IsValidId(id)); 756 CHECK(IsValidId(id));
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
1179 return false; 1212 return false;
1180 1213
1181 CHECK(IsValidId(source_id_video_)); 1214 CHECK(IsValidId(source_id_video_));
1182 if (!video_->Append(buffers)) 1215 if (!video_->Append(buffers))
1183 return false; 1216 return false;
1184 1217
1185 IncreaseDurationIfNecessary(buffers, video_.get()); 1218 IncreaseDurationIfNecessary(buffers, video_.get());
1186 return true; 1219 return true;
1187 } 1220 }
1188 1221
1222 bool ChunkDemuxer::OnTextBuffers(
1223 TextTrack* text_track,
1224 const StreamParser::BufferQueue& buffers) {
1225 lock_.AssertAcquired();
1226 DCHECK_NE(state_, SHUTDOWN);
1227
1228 // TODO(matthewjheaney): IncreaseDurationIfNecessary
1229
1230 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
1231 itr != buffers.end(); ++itr) {
1232 const StreamParserBuffer* const buffer = itr->get();
1233 const base::TimeDelta start = buffer->GetTimestamp();
1234 const base::TimeDelta end = start + buffer->GetDuration();
1235
1236 std::string id, settings, content;
1237
1238 WebMWebVTTParser::Parse(buffer->GetData(),
1239 buffer->GetDataSize(),
1240 &id, &settings, &content);
1241
1242 text_track->addWebVTTCue(start, end, id, content, settings);
1243 }
1244
1245 return true;
1246 }
1247
1189 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that 1248 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that
1190 // this method can be removed and need_key_cb_ can be passed directly 1249 // this method can be removed and need_key_cb_ can be passed directly
1191 // to the parser. 1250 // to the parser.
1192 bool ChunkDemuxer::OnNeedKey(const std::string& type, 1251 bool ChunkDemuxer::OnNeedKey(const std::string& type,
1193 scoped_ptr<uint8[]> init_data, 1252 scoped_ptr<uint8[]> init_data,
1194 int init_data_size) { 1253 int init_data_size) {
1195 lock_.AssertAcquired(); 1254 lock_.AssertAcquired();
1196 need_key_cb_.Run(type, init_data.Pass(), init_data_size); 1255 need_key_cb_.Run(type, init_data.Pass(), init_data_size);
1197 return true; 1256 return true;
1198 } 1257 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 1309
1251 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { 1310 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
1252 if (audio_ && !video_) 1311 if (audio_ && !video_)
1253 return audio_->GetBufferedRanges(duration_); 1312 return audio_->GetBufferedRanges(duration_);
1254 else if (!audio_ && video_) 1313 else if (!audio_ && video_)
1255 return video_->GetBufferedRanges(duration_); 1314 return video_->GetBufferedRanges(duration_);
1256 return ComputeIntersection(); 1315 return ComputeIntersection();
1257 } 1316 }
1258 1317
1259 } // namespace media 1318 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698