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/filters/chunk_demuxer.h" | 5 #include "media/filters/chunk_demuxer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "media/base/audio_decoder_config.h" | 10 #include "media/base/audio_decoder_config.h" |
11 #include "media/base/stream_parser_buffer.h" | 11 #include "media/base/stream_parser_buffer.h" |
12 #include "media/base/video_decoder_config.h" | 12 #include "media/base/video_decoder_config.h" |
13 #include "media/filters/chunk_demuxer_client.h" | 13 #include "media/filters/chunk_demuxer_client.h" |
14 #include "media/webm/webm_stream_parser.h" | 14 #include "media/webm/webm_stream_parser.h" |
15 | 15 |
16 namespace media { | 16 namespace media { |
17 | 17 |
| 18 struct CodecInfo { |
| 19 const char* name; |
| 20 DemuxerStream::Type type; |
| 21 }; |
| 22 |
| 23 typedef StreamParser* (*ParserFactoryFunction)(); |
| 24 |
18 struct SupportedTypeInfo { | 25 struct SupportedTypeInfo { |
19 const char* type; | 26 const char* type; |
20 const char** codecs; | 27 const ParserFactoryFunction factory_function; |
| 28 const CodecInfo** codecs; |
21 }; | 29 }; |
22 | 30 |
23 static const char* kVideoWebMCodecs[] = { "vp8", "vorbis", NULL }; | 31 static const CodecInfo kVP8CodecInfo = { "vp8", DemuxerStream::VIDEO }; |
24 static const char* kAudioWebMCodecs[] = { "vorbis", NULL }; | 32 static const CodecInfo kVorbisCodecInfo = { "vorbis", DemuxerStream::AUDIO }; |
| 33 |
| 34 static const CodecInfo* kVideoWebMCodecs[] = { |
| 35 &kVP8CodecInfo, |
| 36 &kVorbisCodecInfo, |
| 37 NULL |
| 38 }; |
| 39 |
| 40 static const CodecInfo* kAudioWebMCodecs[] = { |
| 41 &kVorbisCodecInfo, |
| 42 NULL |
| 43 }; |
| 44 |
| 45 static StreamParser* BuildWebMParser() { |
| 46 return new WebMStreamParser(); |
| 47 } |
25 | 48 |
26 static const SupportedTypeInfo kSupportedTypeInfo[] = { | 49 static const SupportedTypeInfo kSupportedTypeInfo[] = { |
27 { "video/webm", kVideoWebMCodecs }, | 50 { "video/webm", &BuildWebMParser, kVideoWebMCodecs }, |
28 { "audio/webm", kAudioWebMCodecs }, | 51 { "audio/webm", &BuildWebMParser, kAudioWebMCodecs }, |
29 }; | 52 }; |
30 | 53 |
31 // Checks to see if the specified |type| and |codecs| list are supported. | 54 // Checks to see if the specified |type| and |codecs| list are supported. |
32 // Returns true if |type| and all codecs listed in |codecs| are supported. | 55 // Returns true if |type| and all codecs listed in |codecs| are supported. |
33 // Returns false otherwise. | 56 // |factory_function| contains a function that can build a StreamParser |
| 57 // for this type. |
| 58 // |has_audio| is true if an audio codec was specified. |
| 59 // |has_video| is true if a video codec was specified. |
| 60 // Returns false otherwise. The values of |factory_function|, |has_audio|, |
| 61 // and |has_video| are undefined. |
34 static bool IsSupported(const std::string& type, | 62 static bool IsSupported(const std::string& type, |
35 std::vector<std::string>& codecs) { | 63 std::vector<std::string>& codecs, |
| 64 ParserFactoryFunction* factory_function, |
| 65 bool* has_audio, |
| 66 bool* has_video) { |
| 67 *factory_function = NULL; |
| 68 *has_audio = false; |
| 69 *has_video = false; |
| 70 |
36 // Search for the SupportedTypeInfo for |type| | 71 // Search for the SupportedTypeInfo for |type| |
37 for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) { | 72 for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) { |
38 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i]; | 73 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i]; |
39 if (type == type_info.type) { | 74 if (type == type_info.type) { |
40 // Make sure all the codecs specified in |codecs| are | 75 // Make sure all the codecs specified in |codecs| are |
41 // in the supported type info. | 76 // in the supported type info. |
42 for (size_t j = 0; j < codecs.size(); ++j) { | 77 for (size_t j = 0; j < codecs.size(); ++j) { |
43 // Search the type info for a match. | 78 // Search the type info for a match. |
44 bool found_codec = false; | 79 bool found_codec = false; |
45 for (int k = 0; type_info.codecs[k] && !found_codec; ++k) | 80 DemuxerStream::Type codec_type = DemuxerStream::UNKNOWN; |
46 found_codec = (codecs[j] == type_info.codecs[k]); | 81 |
| 82 for (int k = 0; type_info.codecs[k]; ++k) { |
| 83 if (codecs[j] == type_info.codecs[k]->name) { |
| 84 found_codec = true; |
| 85 codec_type = type_info.codecs[k]->type; |
| 86 break; |
| 87 } |
| 88 } |
47 | 89 |
48 if (!found_codec) | 90 if (!found_codec) |
49 return false; | 91 return false; |
| 92 |
| 93 switch (codec_type) { |
| 94 case DemuxerStream::AUDIO: |
| 95 *has_audio = true; |
| 96 break; |
| 97 case DemuxerStream::VIDEO: |
| 98 *has_video = true; |
| 99 break; |
| 100 default: |
| 101 DVLOG(1) << "Unsupported codec type '"<< codec_type << "' for " |
| 102 << codecs[j]; |
| 103 return false; |
| 104 } |
50 } | 105 } |
51 | 106 |
| 107 *factory_function = type_info.factory_function; |
| 108 |
52 // All codecs were supported by this |type|. | 109 // All codecs were supported by this |type|. |
53 return true; | 110 return true; |
54 } | 111 } |
55 } | 112 } |
56 | 113 |
57 // |type| didn't match any of the supported types. | 114 // |type| didn't match any of the supported types. |
58 return false; | 115 return false; |
59 } | 116 } |
60 | 117 |
61 class ChunkDemuxerStream : public DemuxerStream { | 118 class ChunkDemuxerStream : public DemuxerStream { |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 void ChunkDemuxer::Initialize(DemuxerHost* host, | 467 void ChunkDemuxer::Initialize(DemuxerHost* host, |
411 const PipelineStatusCB& cb) { | 468 const PipelineStatusCB& cb) { |
412 DVLOG(1) << "Init()"; | 469 DVLOG(1) << "Init()"; |
413 { | 470 { |
414 base::AutoLock auto_lock(lock_); | 471 base::AutoLock auto_lock(lock_); |
415 DCHECK_EQ(state_, WAITING_FOR_INIT); | 472 DCHECK_EQ(state_, WAITING_FOR_INIT); |
416 host_ = host; | 473 host_ = host; |
417 | 474 |
418 ChangeState_Locked(INITIALIZING); | 475 ChangeState_Locked(INITIALIZING); |
419 init_cb_ = cb; | 476 init_cb_ = cb; |
420 | |
421 source_buffer_.reset(new SourceBuffer()); | |
422 | |
423 source_buffer_->Init( | |
424 base::Bind(&ChunkDemuxer::OnSourceBufferInitDone, this), | |
425 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this)), | |
426 base::Bind(&ChunkDemuxer::OnAudioBuffers, base::Unretained(this)), | |
427 base::Bind(&ChunkDemuxer::OnVideoBuffers, base::Unretained(this)), | |
428 base::Bind(&ChunkDemuxer::OnKeyNeeded, base::Unretained(this))); | |
429 } | 477 } |
430 | 478 |
431 client_->DemuxerOpened(this); | 479 client_->DemuxerOpened(this); |
432 } | 480 } |
433 | 481 |
434 void ChunkDemuxer::Stop(const base::Closure& callback) { | 482 void ChunkDemuxer::Stop(const base::Closure& callback) { |
435 DVLOG(1) << "Stop()"; | 483 DVLOG(1) << "Stop()"; |
436 Shutdown(); | 484 Shutdown(); |
437 callback.Run(); | 485 callback.Run(); |
438 } | 486 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 | 558 |
511 seek_waits_for_data_ = true; | 559 seek_waits_for_data_ = true; |
512 ChangeState_Locked(INITIALIZED); | 560 ChangeState_Locked(INITIALIZED); |
513 } | 561 } |
514 | 562 |
515 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, | 563 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
516 const std::string& type, | 564 const std::string& type, |
517 std::vector<std::string>& codecs) { | 565 std::vector<std::string>& codecs) { |
518 DCHECK_GT(codecs.size(), 0u); | 566 DCHECK_GT(codecs.size(), 0u); |
519 | 567 |
520 if (!IsSupported(type, codecs)) | 568 bool has_audio = false; |
| 569 bool has_video = false; |
| 570 ParserFactoryFunction factory_function = NULL; |
| 571 if (!IsSupported(type, codecs, &factory_function, &has_audio, &has_video)) |
521 return kNotSupported; | 572 return kNotSupported; |
522 | 573 |
523 // TODO(acolwell): Support for more than one ID | 574 // TODO(acolwell): Support for more than one ID |
524 // will be added as part of http://crbug.com/122909 | 575 // will be added as part of http://crbug.com/122909 |
525 if (!source_id_.empty()) | 576 if (!source_id_.empty()) |
526 return kReachedIdLimit; | 577 return kReachedIdLimit; |
527 | 578 |
528 source_id_ = id; | 579 source_id_ = id; |
| 580 |
| 581 StreamParser::NewBuffersCB audio_cb; |
| 582 StreamParser::NewBuffersCB video_cb; |
| 583 |
| 584 if (has_audio) { |
| 585 audio_cb = base::Bind(&ChunkDemuxer::OnAudioBuffers, |
| 586 base::Unretained(this)); |
| 587 } |
| 588 |
| 589 if (has_video) { |
| 590 video_cb = base::Bind(&ChunkDemuxer::OnVideoBuffers, |
| 591 base::Unretained(this)); |
| 592 } |
| 593 |
| 594 scoped_ptr<StreamParser> stream_parser(factory_function()); |
| 595 |
| 596 CHECK(stream_parser.get()); |
| 597 |
| 598 source_buffer_.reset(new SourceBuffer()); |
| 599 source_buffer_->Init( |
| 600 stream_parser.Pass(), |
| 601 base::Bind(&ChunkDemuxer::OnSourceBufferInitDone, this), |
| 602 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this)), |
| 603 audio_cb, |
| 604 video_cb, |
| 605 base::Bind(&ChunkDemuxer::OnKeyNeeded, base::Unretained(this))); |
| 606 |
529 return kOk; | 607 return kOk; |
530 } | 608 } |
531 | 609 |
532 void ChunkDemuxer::RemoveId(const std::string& id) { | 610 void ChunkDemuxer::RemoveId(const std::string& id) { |
533 CHECK(!source_id_.empty()); | 611 CHECK(!source_id_.empty()); |
534 CHECK_EQ(source_id_, id); | 612 CHECK_EQ(source_id_, id); |
535 source_id_ = ""; | 613 source_id_ = ""; |
536 } | 614 } |
537 | 615 |
538 bool ChunkDemuxer::GetBufferedRanges(const std::string& id, | 616 bool ChunkDemuxer::GetBufferedRanges(const std::string& id, |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 return true; | 913 return true; |
836 } | 914 } |
837 | 915 |
838 bool ChunkDemuxer::OnKeyNeeded(scoped_array<uint8> init_data, | 916 bool ChunkDemuxer::OnKeyNeeded(scoped_array<uint8> init_data, |
839 int init_data_size) { | 917 int init_data_size) { |
840 client_->KeyNeeded(init_data.Pass(), init_data_size); | 918 client_->KeyNeeded(init_data.Pass(), init_data_size); |
841 return true; | 919 return true; |
842 } | 920 } |
843 | 921 |
844 } // namespace media | 922 } // namespace media |
OLD | NEW |