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

Side by Side Diff: media/webm/webm_stream_parser.cc

Issue 13419002: Media Source dispatches inband text tracks (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: clean compile 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
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/webm/webm_stream_parser.h" 5 #include "media/webm/webm_stream_parser.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "media/webm/webm_cluster_parser.h" 11 #include "media/webm/webm_cluster_parser.h"
12 #include "media/webm/webm_constants.h" 12 #include "media/webm/webm_constants.h"
13 #include "media/webm/webm_content_encodings.h" 13 #include "media/webm/webm_content_encodings.h"
14 #include "media/webm/webm_crypto_helpers.h" 14 #include "media/webm/webm_crypto_helpers.h"
15 #include "media/webm/webm_info_parser.h" 15 #include "media/webm/webm_info_parser.h"
16 #include "media/webm/webm_tracks_parser.h" 16 #include "media/webm/webm_tracks_parser.h"
17 17
18 namespace media { 18 namespace media {
19 19
20 // To fetch lines of text from embedded WebVTT cues.
21 class WebVTTParser {
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 This should be in its own file.
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
22 public:
23 // The payload is the embedded WebVTT cue, stored in a WebM block.
24 // The parser treats this as a UTF-8 byte stream.
25 WebVTTParser(const uint8* payload, int payload_size);
26
27 // Parse the cue identifier, settings, and content from the stream.
28 void operator()(std::string* id, std::string* settings, std::string* content);
29 private:
30 // Remove a byte from the stream, advancing the stream pointer.
31 // Returns true if a character was returned; false means "end of stream".
32 bool GetChar(char* c);
33
34 // Backup the stream pointer.
35 void UngetChar();
36
37 // Parse a line of text from the stream.
38 void ParseLine(std::string* line);
39
40 // Represents the portion of the stream that has not been consumed yet.
41 const uint8* ptr_;
42 const uint8* const ptr_end_;
43
44 DISALLOW_COPY_AND_ASSIGN(WebVTTParser);
45 };
46
47 WebVTTParser::WebVTTParser(const uint8* payload, int payload_size)
48 : ptr_(payload),
49 ptr_end_(payload + payload_size) {
50 }
51
52 void WebVTTParser::operator()(std::string* id,
53 std::string* settings,
54 std::string* content) {
55 ParseLine(id);
56 ParseLine(settings);
57 content->assign(ptr_, ptr_end_);
58 }
59
60 bool WebVTTParser::GetChar(char* c) {
61 if (ptr_ >= ptr_end_)
62 return false; // EOF
63
64 *c = *ptr_++;
65 return true;
66 }
67
68 void WebVTTParser::UngetChar() {
69 --ptr_;
70 }
71
72 void WebVTTParser::ParseLine(std::string* line_ptr) {
73 std::string& line = *line_ptr;
74 line.clear();
75
76 // Consume characters from the stream, until we reach end-of-line.
77
78 // The WebVTT spec states that lines may be terminated in any of the following
79 // three ways:
80 // LF
81 // CR
82 // CR LF
83
84 // The spec is here:
85 // http://wiki.webmproject.org/webm-metadata/temporal-metadata/webvtt-in-webm
86
87 enum {
88 kLF = '\x0A',
89 kCR = '\x0D'
90 };
91
92 for (;;) {
93 char c;
94
95 if (!GetChar(&c) || c == kLF)
96 return;
97
98 if (c == kCR) {
99 if (GetChar(&c) && c != kLF)
100 UngetChar();
101
102 return;
103 }
104
105 line.push_back(c);
106 }
107 }
108
20 WebMStreamParser::WebMStreamParser() 109 WebMStreamParser::WebMStreamParser()
21 : state_(kWaitingForInit), 110 : state_(kWaitingForInit),
22 waiting_for_buffers_(false) { 111 waiting_for_buffers_(false) {
23 } 112 }
24 113
25 WebMStreamParser::~WebMStreamParser() {} 114 WebMStreamParser::~WebMStreamParser() {}
26 115
27 void WebMStreamParser::Init(const InitCB& init_cb, 116 void WebMStreamParser::Init(const InitCB& init_cb,
28 const NewConfigCB& config_cb, 117 const NewConfigCB& config_cb,
29 const NewBuffersCB& audio_cb, 118 const NewBuffersCB& audio_cb,
30 const NewBuffersCB& video_cb, 119 const NewBuffersCB& video_cb,
31 const NeedKeyCB& need_key_cb, 120 const NeedKeyCB& need_key_cb,
121 const AddTextTrackCB& add_text_track_cb,
32 const NewMediaSegmentCB& new_segment_cb, 122 const NewMediaSegmentCB& new_segment_cb,
33 const base::Closure& end_of_segment_cb, 123 const base::Closure& end_of_segment_cb,
34 const LogCB& log_cb) { 124 const LogCB& log_cb) {
35 DCHECK_EQ(state_, kWaitingForInit); 125 DCHECK_EQ(state_, kWaitingForInit);
36 DCHECK(init_cb_.is_null()); 126 DCHECK(init_cb_.is_null());
37 DCHECK(!init_cb.is_null()); 127 DCHECK(!init_cb.is_null());
38 DCHECK(!config_cb.is_null()); 128 DCHECK(!config_cb.is_null());
39 DCHECK(!audio_cb.is_null() || !video_cb.is_null()); 129 DCHECK(!audio_cb.is_null() || !video_cb.is_null());
40 DCHECK(!need_key_cb.is_null()); 130 DCHECK(!need_key_cb.is_null());
41 DCHECK(!new_segment_cb.is_null()); 131 DCHECK(!new_segment_cb.is_null());
42 DCHECK(!end_of_segment_cb.is_null()); 132 DCHECK(!end_of_segment_cb.is_null());
43 133
44 ChangeState(kParsingHeaders); 134 ChangeState(kParsingHeaders);
45 init_cb_ = init_cb; 135 init_cb_ = init_cb;
46 config_cb_ = config_cb; 136 config_cb_ = config_cb;
47 audio_cb_ = audio_cb; 137 audio_cb_ = audio_cb;
48 video_cb_ = video_cb; 138 video_cb_ = video_cb;
49 need_key_cb_ = need_key_cb; 139 need_key_cb_ = need_key_cb;
140 add_text_track_cb_ = add_text_track_cb;
50 new_segment_cb_ = new_segment_cb; 141 new_segment_cb_ = new_segment_cb;
51 end_of_segment_cb_ = end_of_segment_cb; 142 end_of_segment_cb_ = end_of_segment_cb;
52 log_cb_ = log_cb; 143 log_cb_ = log_cb;
53 } 144 }
54 145
55 void WebMStreamParser::Flush() { 146 void WebMStreamParser::Flush() {
56 DCHECK_NE(state_, kWaitingForInit); 147 DCHECK_NE(state_, kWaitingForInit);
57 148
58 byte_queue_.Reset(); 149 byte_queue_.Reset();
59 150
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 282
192 const VideoDecoderConfig& video_config = tracks_parser.video_decoder_config(); 283 const VideoDecoderConfig& video_config = tracks_parser.video_decoder_config();
193 if (video_config.is_encrypted()) 284 if (video_config.is_encrypted())
194 FireNeedKey(tracks_parser.video_encryption_key_id()); 285 FireNeedKey(tracks_parser.video_encryption_key_id());
195 286
196 if (!config_cb_.Run(audio_config, video_config)) { 287 if (!config_cb_.Run(audio_config, video_config)) {
197 DVLOG(1) << "New config data isn't allowed."; 288 DVLOG(1) << "New config data isn't allowed.";
198 return -1; 289 return -1;
199 } 290 }
200 291
292 typedef std::set<int> TextTracksSet;
293 const TextTracksSet& text_tracks = tracks_parser.text_tracks();
294
295 for (TextTracksSet::const_iterator itr = text_tracks.begin();
296 itr != text_tracks.end(); ++itr) {
297 // TODO(matthewjheaney): parse track kind, name, lang
298 // Must also resolve ptr type
299 TextTrack* const text_cb = add_text_track_cb_.Run(kTextSubtitles, "", "");
300
301 // TODO(matthewjheaney): we need to explicitly deallocate text_cb,
302 // unless a scoped_ptr or somesuch is used.
303 text_track_map_.insert(std::make_pair(*itr, text_cb));
304 }
305
201 cluster_parser_.reset(new WebMClusterParser( 306 cluster_parser_.reset(new WebMClusterParser(
202 info_parser.timecode_scale(), 307 info_parser.timecode_scale(),
203 tracks_parser.audio_track_num(), 308 tracks_parser.audio_track_num(),
204 tracks_parser.video_track_num(), 309 tracks_parser.video_track_num(),
205 tracks_parser.text_tracks(), 310 tracks_parser.text_tracks(),
206 tracks_parser.ignored_tracks(), 311 tracks_parser.ignored_tracks(),
207 tracks_parser.audio_encryption_key_id(), 312 tracks_parser.audio_encryption_key_id(),
208 tracks_parser.video_encryption_key_id(), 313 tracks_parser.video_encryption_key_id(),
209 log_cb_)); 314 log_cb_));
210 315
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 new_segment_cb_.Run(cluster_start_time); 366 new_segment_cb_.Run(cluster_start_time);
262 waiting_for_buffers_ = false; 367 waiting_for_buffers_ = false;
263 } 368 }
264 369
265 if (!audio_buffers.empty() && !audio_cb_.Run(audio_buffers)) 370 if (!audio_buffers.empty() && !audio_cb_.Run(audio_buffers))
266 return -1; 371 return -1;
267 372
268 if (!video_buffers.empty() && !video_cb_.Run(video_buffers)) 373 if (!video_buffers.empty() && !video_cb_.Run(video_buffers))
269 return -1; 374 return -1;
270 375
376 WebMClusterParser::TextTrackIterator tt_iter =
377 cluster_parser_->CreateTextTrackIterator();
378
379 int tt_num;
380 const BufferQueue* tt_buffers;
381
382 while (tt_iter(&tt_num, &tt_buffers)) {
383 TextTrackMap::iterator cb_iter = text_track_map_.find(tt_num);
384
385 if (cb_iter == text_track_map_.end())
386 continue;
387
388 TextTrack* const text_cb = cb_iter->second;
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 nit: Just inline this in the call below.
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
389 OnTextBuffers(*tt_buffers, text_cb);
390 }
391
271 if (cluster_ended) 392 if (cluster_ended)
272 end_of_segment_cb_.Run(); 393 end_of_segment_cb_.Run();
273 394
274 return bytes_parsed; 395 return bytes_parsed;
275 } 396 }
276 397
277 void WebMStreamParser::FireNeedKey(const std::string& key_id) { 398 void WebMStreamParser::FireNeedKey(const std::string& key_id) {
278 int key_id_size = key_id.size(); 399 int key_id_size = key_id.size();
279 DCHECK_GT(key_id_size, 0); 400 DCHECK_GT(key_id_size, 0);
280 scoped_ptr<uint8[]> key_id_array(new uint8[key_id_size]); 401 scoped_ptr<uint8[]> key_id_array(new uint8[key_id_size]);
281 memcpy(key_id_array.get(), key_id.data(), key_id_size); 402 memcpy(key_id_array.get(), key_id.data(), key_id_size);
282 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_array.Pass(), key_id_size); 403 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_array.Pass(), key_id_size);
283 } 404 }
284 405
406 void WebMStreamParser::OnTextBuffers(const StreamParser::BufferQueue& buffers,
407 TextTrack* text_cb) {
408 // TODO(matthewjheaney): where is this done?
409 //AdjustBufferTimestamps(buffers);
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 This happens in SourceState::OnBuffers so you this
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
410
411 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
412 itr != buffers.end(); ++itr) {
413 OnTextBuffer(*itr, text_cb);
414 }
415 }
416
417 void WebMStreamParser::OnTextBuffer(const StreamParserBuffer* buffer,
418 TextTrack* text_cb) {
419 const base::TimeDelta start = buffer->GetTimestamp();
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 nit: Since most of these locals appear to only be
Matthew Heaney (Chromium) 2013/05/10 05:21:08 This function was cleaned up a bit because the par
420 const base::TimeDelta end = start + buffer->GetDuration();
421
422 const uint8* const payload = buffer->GetData();
423 const int payload_size = buffer->GetDataSize();
424
425 WebVTTParser parser(payload, payload_size);
426 std::string id, settings, content;
427
428 parser(&id, &settings, &content);
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 Seeing as it looks like you could rearrange this c
Matthew Heaney (Chromium) 2013/05/10 05:21:08 I moved the webvtt parser to its own class, and ad
429
430 text_cb->addWebVTTCue(start, end, id, content, settings);
431 }
432
285 } // namespace media 433 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698