Chromium Code Reviews| 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 13 matching lines...) Expand all Loading... | |
| 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 once GetAVStream() has been removed from |
| 33 // the DemuxerStream interface. | 33 // the DemuxerStream interface. |
| 34 // ^^^^^^^^^^^ IS THIS STILL NEEDED? ^^^^^^^^^^^^ | |
|
acolwell GONE FROM CHROMIUM
2011/10/26 17:09:13
For now yes since we still need an AVStream to con
scherkus (not reviewing)
2011/10/26 19:08:00
Done.
| |
| 34 static const uint8 kWebMHeader[] = { | 35 static const uint8 kWebMHeader[] = { |
| 35 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f) | 36 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f) |
| 36 0x42, 0x86, 0x81, 0x01, // EBMLVersion = 1 | 37 0x42, 0x86, 0x81, 0x01, // EBMLVersion = 1 |
| 37 0x42, 0xF7, 0x81, 0x01, // EBMLReadVersion = 1 | 38 0x42, 0xF7, 0x81, 0x01, // EBMLReadVersion = 1 |
| 38 0x42, 0xF2, 0x81, 0x04, // EBMLMaxIDLength = 4 | 39 0x42, 0xF2, 0x81, 0x04, // EBMLMaxIDLength = 4 |
| 39 0x42, 0xF3, 0x81, 0x08, // EBMLMaxSizeLength = 8 | 40 0x42, 0xF3, 0x81, 0x08, // EBMLMaxSizeLength = 8 |
| 40 0x42, 0x82, 0x84, 0x77, 0x65, 0x62, 0x6D, // DocType = "webm" | 41 0x42, 0x82, 0x84, 0x77, 0x65, 0x62, 0x6D, // DocType = "webm" |
| 41 0x42, 0x87, 0x81, 0x02, // DocTypeVersion = 2 | 42 0x42, 0x87, 0x81, 0x02, // DocTypeVersion = 2 |
| 42 0x42, 0x85, 0x81, 0x02, // DocTypeReadVersion = 2 | 43 0x42, 0x85, 0x81, 0x02, // DocTypeReadVersion = 2 |
| 43 // EBML end | 44 // EBML end |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 72 | 73 |
| 73 void AddBuffers(const BufferQueue& buffers); | 74 void AddBuffers(const BufferQueue& buffers); |
| 74 void Shutdown(); | 75 void Shutdown(); |
| 75 | 76 |
| 76 bool GetLastBufferTimestamp(base::TimeDelta* timestamp) const; | 77 bool GetLastBufferTimestamp(base::TimeDelta* timestamp) const; |
| 77 | 78 |
| 78 // DemuxerStream methods. | 79 // DemuxerStream methods. |
| 79 virtual void Read(const ReadCallback& read_callback); | 80 virtual void Read(const ReadCallback& read_callback); |
| 80 virtual Type type(); | 81 virtual Type type(); |
| 81 virtual void EnableBitstreamConverter(); | 82 virtual void EnableBitstreamConverter(); |
| 82 virtual AVStream* GetAVStream(); | |
| 83 virtual const AudioDecoderConfig& audio_decoder_config(); | 83 virtual const AudioDecoderConfig& audio_decoder_config(); |
| 84 virtual const VideoDecoderConfig& video_decoder_config(); | |
| 84 | 85 |
| 85 private: | 86 private: |
| 86 Type type_; | 87 Type type_; |
| 87 AVStream* av_stream_; | 88 AVStream* av_stream_; |
| 88 AudioDecoderConfig audio_config_; | 89 AudioDecoderConfig audio_config_; |
| 90 VideoDecoderConfig video_config_; | |
| 89 | 91 |
| 90 mutable base::Lock lock_; | 92 mutable base::Lock lock_; |
| 91 ReadCBQueue read_cbs_; | 93 ReadCBQueue read_cbs_; |
| 92 BufferQueue buffers_; | 94 BufferQueue buffers_; |
| 93 bool shutdown_called_; | 95 bool shutdown_called_; |
| 94 bool received_end_of_stream_; | 96 bool received_end_of_stream_; |
| 95 | 97 |
| 96 // Keeps track of the timestamp of the last buffer we have | 98 // Keeps track of the timestamp of the last buffer we have |
| 97 // added to |buffers_|. This is used to enforce buffers with strictly | 99 // added to |buffers_|. This is used to enforce buffers with strictly |
| 98 // monotonically increasing timestamps. | 100 // monotonically increasing timestamps. |
| 99 base::TimeDelta last_buffer_timestamp_; | 101 base::TimeDelta last_buffer_timestamp_; |
| 100 | 102 |
| 101 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 103 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
| 102 }; | 104 }; |
| 103 | 105 |
| 104 ChunkDemuxerStream::ChunkDemuxerStream(Type type, AVStream* stream) | 106 ChunkDemuxerStream::ChunkDemuxerStream(Type type, AVStream* stream) |
| 105 : type_(type), | 107 : type_(type), |
| 106 av_stream_(stream), | 108 av_stream_(stream), |
| 107 shutdown_called_(false), | 109 shutdown_called_(false), |
| 108 received_end_of_stream_(false), | 110 received_end_of_stream_(false), |
| 109 last_buffer_timestamp_(kNoTimestamp) { | 111 last_buffer_timestamp_(kNoTimestamp) { |
| 110 if (type_ == AUDIO) { | 112 if (type_ == AUDIO) { |
| 111 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); | 113 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); |
| 114 } else if (type_ == VIDEO) { | |
| 115 AVCodecContextToVideoDecoderConfig(stream->codec, | |
| 116 stream->r_frame_rate, | |
| 117 GetAspectRatio(stream), | |
| 118 &video_config_); | |
| 112 } | 119 } |
| 113 } | 120 } |
| 114 | 121 |
| 115 ChunkDemuxerStream::~ChunkDemuxerStream() {} | 122 ChunkDemuxerStream::~ChunkDemuxerStream() {} |
| 116 | 123 |
| 117 void ChunkDemuxerStream::Flush() { | 124 void ChunkDemuxerStream::Flush() { |
| 118 VLOG(1) << "Flush()"; | 125 VLOG(1) << "Flush()"; |
| 119 base::AutoLock auto_lock(lock_); | 126 base::AutoLock auto_lock(lock_); |
| 120 buffers_.clear(); | 127 buffers_.clear(); |
| 121 received_end_of_stream_ = false; | 128 received_end_of_stream_ = false; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 } | 271 } |
| 265 | 272 |
| 266 DCHECK(buffer.get()); | 273 DCHECK(buffer.get()); |
| 267 read_callback.Run(buffer); | 274 read_callback.Run(buffer); |
| 268 } | 275 } |
| 269 | 276 |
| 270 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } | 277 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } |
| 271 | 278 |
| 272 void ChunkDemuxerStream::EnableBitstreamConverter() {} | 279 void ChunkDemuxerStream::EnableBitstreamConverter() {} |
| 273 | 280 |
| 274 AVStream* ChunkDemuxerStream::GetAVStream() { return av_stream_; } | |
| 275 | |
| 276 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { | 281 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { |
| 277 CHECK_EQ(type_, AUDIO); | 282 CHECK_EQ(type_, AUDIO); |
| 278 return audio_config_; | 283 return audio_config_; |
| 279 } | 284 } |
| 280 | 285 |
| 286 const VideoDecoderConfig& ChunkDemuxerStream::video_decoder_config() { | |
| 287 CHECK_EQ(type_, VIDEO); | |
| 288 return video_config_; | |
| 289 } | |
| 290 | |
| 281 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) | 291 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) |
| 282 : state_(WAITING_FOR_INIT), | 292 : state_(WAITING_FOR_INIT), |
| 283 client_(client), | 293 client_(client), |
| 284 format_context_(NULL), | 294 format_context_(NULL), |
| 285 buffered_bytes_(0), | 295 buffered_bytes_(0), |
| 286 seek_waits_for_data_(true) { | 296 seek_waits_for_data_(true) { |
| 287 DCHECK(client); | 297 DCHECK(client); |
| 288 } | 298 } |
| 289 | 299 |
| 290 ChunkDemuxer::~ChunkDemuxer() { | 300 ChunkDemuxer::~ChunkDemuxer() { |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 731 base::AutoUnlock auto_unlock(lock_); | 741 base::AutoUnlock auto_unlock(lock_); |
| 732 if (cb.is_null()) { | 742 if (cb.is_null()) { |
| 733 host()->SetError(error); | 743 host()->SetError(error); |
| 734 return; | 744 return; |
| 735 } | 745 } |
| 736 cb.Run(error); | 746 cb.Run(error); |
| 737 } | 747 } |
| 738 } | 748 } |
| 739 | 749 |
| 740 } // namespace media | 750 } // namespace media |
| OLD | NEW |