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/webm/webm_cluster_parser.h" | 5 #include "media/webm/webm_cluster_parser.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/sys_byteorder.h" | 10 #include "base/sys_byteorder.h" |
11 #include "media/base/buffers.h" | 11 #include "media/base/buffers.h" |
12 #include "media/base/decrypt_config.h" | 12 #include "media/base/decrypt_config.h" |
13 #include "media/webm/webm_constants.h" | 13 #include "media/webm/webm_constants.h" |
14 #include "media/webm/webm_crypto_helpers.h" | 14 #include "media/webm/webm_crypto_helpers.h" |
| 15 #include "media/webm/webm_webvtt_parser.h" |
15 | 16 |
16 namespace media { | 17 namespace media { |
17 | 18 |
18 WebMClusterParser::TextTrackIterator::TextTrackIterator( | 19 WebMClusterParser::TextTrackIterator::TextTrackIterator( |
19 const TextTrackMap& text_track_map) : | 20 const TextTrackMap& text_track_map) : |
20 iterator_(text_track_map.begin()), | 21 iterator_(text_track_map.begin()), |
21 iterator_end_(text_track_map.end()) { | 22 iterator_end_(text_track_map.end()) { |
22 } | 23 } |
23 | 24 |
24 WebMClusterParser::TextTrackIterator::TextTrackIterator( | 25 WebMClusterParser::TextTrackIterator::TextTrackIterator( |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 return false; | 301 return false; |
301 } | 302 } |
302 | 303 |
303 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { | 304 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { |
304 MEDIA_LOG(log_cb_) | 305 MEDIA_LOG(log_cb_) |
305 << "Got a block with a timecode before the previous block."; | 306 << "Got a block with a timecode before the previous block."; |
306 return false; | 307 return false; |
307 } | 308 } |
308 | 309 |
309 Track* track = NULL; | 310 Track* track = NULL; |
| 311 bool is_text = false; |
310 std::string encryption_key_id; | 312 std::string encryption_key_id; |
311 if (track_num == audio_.track_num()) { | 313 if (track_num == audio_.track_num()) { |
312 track = &audio_; | 314 track = &audio_; |
313 encryption_key_id = audio_encryption_key_id_; | 315 encryption_key_id = audio_encryption_key_id_; |
314 } else if (track_num == video_.track_num()) { | 316 } else if (track_num == video_.track_num()) { |
315 track = &video_; | 317 track = &video_; |
316 encryption_key_id = video_encryption_key_id_; | 318 encryption_key_id = video_encryption_key_id_; |
317 } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) { | 319 } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) { |
318 return true; | 320 return true; |
319 } else if (Track* const text_track = FindTextTrack(track_num)) { | 321 } else if (Track* const text_track = FindTextTrack(track_num)) { |
320 if (is_simple_block) // BlockGroup is required for WebVTT cues | 322 if (is_simple_block) // BlockGroup is required for WebVTT cues |
321 return false; | 323 return false; |
322 if (block_duration < 0) // not specified | 324 if (block_duration < 0) // not specified |
323 return false; | 325 return false; |
324 track = text_track; | 326 track = text_track; |
| 327 is_text = true; |
325 } else { | 328 } else { |
326 MEDIA_LOG(log_cb_) << "Unexpected track number " << track_num; | 329 MEDIA_LOG(log_cb_) << "Unexpected track number " << track_num; |
327 return false; | 330 return false; |
328 } | 331 } |
329 | 332 |
330 last_block_timecode_ = timecode; | 333 last_block_timecode_ = timecode; |
331 | 334 |
332 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( | 335 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( |
333 (cluster_timecode_ + timecode) * timecode_multiplier_); | 336 (cluster_timecode_ + timecode) * timecode_multiplier_); |
334 | 337 |
335 // The first bit of the flags is set when a SimpleBlock contains only | 338 // The first bit of the flags is set when a SimpleBlock contains only |
336 // keyframes. If this is a Block, then inspection of the payload is | 339 // keyframes. If this is a Block, then inspection of the payload is |
337 // necessary to determine whether it contains a keyframe or not. | 340 // necessary to determine whether it contains a keyframe or not. |
338 // http://www.matroska.org/technical/specs/index.html | 341 // http://www.matroska.org/technical/specs/index.html |
339 bool is_keyframe = | 342 bool is_keyframe = |
340 is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size); | 343 is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size); |
341 | 344 |
342 scoped_refptr<StreamParserBuffer> buffer = | 345 scoped_refptr<StreamParserBuffer> buffer; |
343 StreamParserBuffer::CopyFrom(data, size, additional, additional_size, | 346 if (!is_text) { |
344 is_keyframe); | 347 buffer = StreamParserBuffer::CopyFrom(data, size, |
| 348 additional, additional_size, |
| 349 is_keyframe); |
| 350 } else { |
| 351 std::string id, settings, content; |
| 352 WebMWebVTTParser::Parse(data, size, |
| 353 &id, &settings, &content); |
| 354 |
| 355 // The DecoderBuffer only supports a single side data item. In the case of |
| 356 // a WebVTT cue, we can have potentially two side data items. In order to |
| 357 // avoid disrupting DecoderBuffer any more than we need to, we copy both |
| 358 // side data items onto a single one, and terminate each with a NUL marker. |
| 359 std::vector<char> side_data; |
| 360 side_data.reserve(id.length() + 1 + settings.length() + 1); |
| 361 side_data.insert(side_data.end(), id.begin(), id.end()); |
| 362 side_data.push_back(0); |
| 363 side_data.insert(side_data.end(), settings.begin(), settings.end()); |
| 364 side_data.push_back(0); |
| 365 |
| 366 buffer = StreamParserBuffer::CopyFrom( |
| 367 reinterpret_cast<const uint8*>(content.data()), |
| 368 content.length(), |
| 369 reinterpret_cast<const uint8*>(side_data.data()), |
| 370 side_data.size(), |
| 371 is_keyframe); |
| 372 } |
345 | 373 |
346 // Every encrypted Block has a signal byte and IV prepended to it. Current | 374 // Every encrypted Block has a signal byte and IV prepended to it. Current |
347 // encrypted WebM request for comments specification is here | 375 // encrypted WebM request for comments specification is here |
348 // http://wiki.webmproject.org/encryption/webm-encryption-rfc | 376 // http://wiki.webmproject.org/encryption/webm-encryption-rfc |
349 if (!encryption_key_id.empty()) { | 377 if (!encryption_key_id.empty()) { |
350 scoped_ptr<DecryptConfig> config(WebMCreateDecryptConfig( | 378 scoped_ptr<DecryptConfig> config(WebMCreateDecryptConfig( |
351 data, size, | 379 data, size, |
352 reinterpret_cast<const uint8*>(encryption_key_id.data()), | 380 reinterpret_cast<const uint8*>(encryption_key_id.data()), |
353 encryption_key_id.size())); | 381 encryption_key_id.size())); |
354 if (!config) | 382 if (!config) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 WebMClusterParser::FindTextTrack(int track_num) { | 459 WebMClusterParser::FindTextTrack(int track_num) { |
432 const TextTrackMap::iterator it = text_track_map_.find(track_num); | 460 const TextTrackMap::iterator it = text_track_map_.find(track_num); |
433 | 461 |
434 if (it == text_track_map_.end()) | 462 if (it == text_track_map_.end()) |
435 return NULL; | 463 return NULL; |
436 | 464 |
437 return &it->second; | 465 return &it->second; |
438 } | 466 } |
439 | 467 |
440 } // namespace media | 468 } // namespace media |
OLD | NEW |