OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // Implements a Demuxer that can switch among different data sources mid-stream. | 5 // Implements a Demuxer that can switch among different data sources mid-stream. |
6 // Uses FFmpegDemuxer under the covers, so see the caveats at the top of | 6 // Uses FFmpegDemuxer under the covers, so see the caveats at the top of |
7 // ffmpeg_demuxer.h. | 7 // ffmpeg_demuxer.h. |
8 | 8 |
9 #include "media/filters/chunk_demuxer.h" | 9 #include "media/filters/chunk_demuxer.h" |
10 | 10 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "media/webm/webm_info_parser.h" | 22 #include "media/webm/webm_info_parser.h" |
23 #include "media/webm/webm_tracks_parser.h" | 23 #include "media/webm/webm_tracks_parser.h" |
24 | 24 |
25 namespace media { | 25 namespace media { |
26 | 26 |
27 // WebM File Header. This is prepended to the INFO & TRACKS | 27 // WebM File Header. This is prepended to the INFO & TRACKS |
28 // data passed to Init() before handing it to FFmpeg. Essentially | 28 // data passed to Init() before handing it to FFmpeg. Essentially |
29 // we are making the INFO & TRACKS data look like a small WebM | 29 // we are making the INFO & TRACKS data look like a small WebM |
30 // file so we can use FFmpeg to initialize the AVFormatContext. | 30 // file so we can use FFmpeg to initialize the AVFormatContext. |
31 // | 31 // |
32 // TODO(acolwell): Remove this once GetAVStream() has been removed from | 32 // TODO(acolwell): Remove this when we construct AudioDecoderConfig and |
33 // the DemuxerStream interface. | 33 // VideoDecoderConfig without requiring an AVStream object. |
34 static const uint8 kWebMHeader[] = { | 34 static const uint8 kWebMHeader[] = { |
35 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f) | 35 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f) |
36 0x42, 0x86, 0x81, 0x01, // EBMLVersion = 1 | 36 0x42, 0x86, 0x81, 0x01, // EBMLVersion = 1 |
37 0x42, 0xF7, 0x81, 0x01, // EBMLReadVersion = 1 | 37 0x42, 0xF7, 0x81, 0x01, // EBMLReadVersion = 1 |
38 0x42, 0xF2, 0x81, 0x04, // EBMLMaxIDLength = 4 | 38 0x42, 0xF2, 0x81, 0x04, // EBMLMaxIDLength = 4 |
39 0x42, 0xF3, 0x81, 0x08, // EBMLMaxSizeLength = 8 | 39 0x42, 0xF3, 0x81, 0x08, // EBMLMaxSizeLength = 8 |
40 0x42, 0x82, 0x84, 0x77, 0x65, 0x62, 0x6D, // DocType = "webm" | 40 0x42, 0x82, 0x84, 0x77, 0x65, 0x62, 0x6D, // DocType = "webm" |
41 0x42, 0x87, 0x81, 0x02, // DocTypeVersion = 2 | 41 0x42, 0x87, 0x81, 0x02, // DocTypeVersion = 2 |
42 0x42, 0x85, 0x81, 0x02, // DocTypeReadVersion = 2 | 42 0x42, 0x85, 0x81, 0x02, // DocTypeReadVersion = 2 |
43 // EBML end | 43 // EBML end |
(...skipping 28 matching lines...) Expand all Loading... |
72 | 72 |
73 void AddBuffers(const BufferQueue& buffers); | 73 void AddBuffers(const BufferQueue& buffers); |
74 void Shutdown(); | 74 void Shutdown(); |
75 | 75 |
76 bool GetLastBufferTimestamp(base::TimeDelta* timestamp) const; | 76 bool GetLastBufferTimestamp(base::TimeDelta* timestamp) const; |
77 | 77 |
78 // DemuxerStream methods. | 78 // DemuxerStream methods. |
79 virtual void Read(const ReadCallback& read_callback); | 79 virtual void Read(const ReadCallback& read_callback); |
80 virtual Type type(); | 80 virtual Type type(); |
81 virtual void EnableBitstreamConverter(); | 81 virtual void EnableBitstreamConverter(); |
82 virtual AVStream* GetAVStream(); | |
83 virtual const AudioDecoderConfig& audio_decoder_config(); | 82 virtual const AudioDecoderConfig& audio_decoder_config(); |
| 83 virtual const VideoDecoderConfig& video_decoder_config(); |
84 | 84 |
85 private: | 85 private: |
86 Type type_; | 86 Type type_; |
87 AVStream* av_stream_; | 87 AVStream* av_stream_; |
88 AudioDecoderConfig audio_config_; | 88 AudioDecoderConfig audio_config_; |
| 89 VideoDecoderConfig video_config_; |
89 | 90 |
90 mutable base::Lock lock_; | 91 mutable base::Lock lock_; |
91 ReadCBQueue read_cbs_; | 92 ReadCBQueue read_cbs_; |
92 BufferQueue buffers_; | 93 BufferQueue buffers_; |
93 bool shutdown_called_; | 94 bool shutdown_called_; |
94 bool received_end_of_stream_; | 95 bool received_end_of_stream_; |
95 | 96 |
96 // Keeps track of the timestamp of the last buffer we have | 97 // Keeps track of the timestamp of the last buffer we have |
97 // added to |buffers_|. This is used to enforce buffers with strictly | 98 // added to |buffers_|. This is used to enforce buffers with strictly |
98 // monotonically increasing timestamps. | 99 // monotonically increasing timestamps. |
99 base::TimeDelta last_buffer_timestamp_; | 100 base::TimeDelta last_buffer_timestamp_; |
100 | 101 |
101 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 102 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
102 }; | 103 }; |
103 | 104 |
104 ChunkDemuxerStream::ChunkDemuxerStream(Type type, AVStream* stream) | 105 ChunkDemuxerStream::ChunkDemuxerStream(Type type, AVStream* stream) |
105 : type_(type), | 106 : type_(type), |
106 av_stream_(stream), | 107 av_stream_(stream), |
107 shutdown_called_(false), | 108 shutdown_called_(false), |
108 received_end_of_stream_(false), | 109 received_end_of_stream_(false), |
109 last_buffer_timestamp_(kNoTimestamp) { | 110 last_buffer_timestamp_(kNoTimestamp) { |
110 if (type_ == AUDIO) { | 111 if (type_ == AUDIO) { |
111 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); | 112 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); |
| 113 } else if (type_ == VIDEO) { |
| 114 AVStreamToVideoDecoderConfig(stream, &video_config_); |
112 } | 115 } |
113 } | 116 } |
114 | 117 |
115 ChunkDemuxerStream::~ChunkDemuxerStream() {} | 118 ChunkDemuxerStream::~ChunkDemuxerStream() {} |
116 | 119 |
117 void ChunkDemuxerStream::Flush() { | 120 void ChunkDemuxerStream::Flush() { |
118 VLOG(1) << "Flush()"; | 121 VLOG(1) << "Flush()"; |
119 base::AutoLock auto_lock(lock_); | 122 base::AutoLock auto_lock(lock_); |
120 buffers_.clear(); | 123 buffers_.clear(); |
121 received_end_of_stream_ = false; | 124 received_end_of_stream_ = false; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 } | 267 } |
265 | 268 |
266 DCHECK(buffer.get()); | 269 DCHECK(buffer.get()); |
267 read_callback.Run(buffer); | 270 read_callback.Run(buffer); |
268 } | 271 } |
269 | 272 |
270 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } | 273 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } |
271 | 274 |
272 void ChunkDemuxerStream::EnableBitstreamConverter() {} | 275 void ChunkDemuxerStream::EnableBitstreamConverter() {} |
273 | 276 |
274 AVStream* ChunkDemuxerStream::GetAVStream() { return av_stream_; } | |
275 | |
276 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { | 277 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { |
277 CHECK_EQ(type_, AUDIO); | 278 CHECK_EQ(type_, AUDIO); |
278 return audio_config_; | 279 return audio_config_; |
279 } | 280 } |
280 | 281 |
| 282 const VideoDecoderConfig& ChunkDemuxerStream::video_decoder_config() { |
| 283 CHECK_EQ(type_, VIDEO); |
| 284 return video_config_; |
| 285 } |
| 286 |
281 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) | 287 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) |
282 : state_(WAITING_FOR_INIT), | 288 : state_(WAITING_FOR_INIT), |
283 client_(client), | 289 client_(client), |
284 format_context_(NULL), | 290 format_context_(NULL), |
285 buffered_bytes_(0), | 291 buffered_bytes_(0), |
286 seek_waits_for_data_(true) { | 292 seek_waits_for_data_(true) { |
287 DCHECK(client); | 293 DCHECK(client); |
288 } | 294 } |
289 | 295 |
290 ChunkDemuxer::~ChunkDemuxer() { | 296 ChunkDemuxer::~ChunkDemuxer() { |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 base::AutoUnlock auto_unlock(lock_); | 737 base::AutoUnlock auto_unlock(lock_); |
732 if (cb.is_null()) { | 738 if (cb.is_null()) { |
733 host()->SetError(error); | 739 host()->SetError(error); |
734 return; | 740 return; |
735 } | 741 } |
736 cb.Run(error); | 742 cb.Run(error); |
737 } | 743 } |
738 } | 744 } |
739 | 745 |
740 } // namespace media | 746 } // namespace media |
OLD | NEW |