| 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "media/base/audio_decoder_config.h" | 13 #include "media/base/audio_decoder_config.h" |
| 14 #include "media/base/data_buffer.h" | 14 #include "media/base/decoder_buffer.h" |
| 15 #include "media/base/limits.h" | 15 #include "media/base/limits.h" |
| 16 #include "media/base/media_switches.h" | 16 #include "media/base/media_switches.h" |
| 17 #include "media/base/video_decoder_config.h" | 17 #include "media/base/video_decoder_config.h" |
| 18 #include "media/ffmpeg/ffmpeg_common.h" | 18 #include "media/ffmpeg/ffmpeg_common.h" |
| 19 #include "media/filters/bitstream_converter.h" | 19 #include "media/filters/bitstream_converter.h" |
| 20 #include "media/filters/ffmpeg_demuxer.h" | 20 #include "media/filters/ffmpeg_demuxer.h" |
| 21 #include "media/filters/ffmpeg_glue.h" | 21 #include "media/filters/ffmpeg_glue.h" |
| 22 #include "media/filters/ffmpeg_h264_bitstream_converter.h" | 22 #include "media/filters/ffmpeg_h264_bitstream_converter.h" |
| 23 | 23 |
| 24 namespace media { | 24 namespace media { |
| 25 | 25 |
| 26 // | 26 // |
| 27 // AVPacketBuffer | |
| 28 // | |
| 29 class AVPacketBuffer : public Buffer { | |
| 30 public: | |
| 31 AVPacketBuffer(scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet, | |
| 32 const base::TimeDelta& timestamp, | |
| 33 const base::TimeDelta& duration) | |
| 34 : Buffer(timestamp, duration), | |
| 35 packet_(packet.Pass()) { | |
| 36 } | |
| 37 | |
| 38 // Buffer implementation. | |
| 39 virtual const uint8* GetData() const { | |
| 40 return reinterpret_cast<const uint8*>(packet_->data); | |
| 41 } | |
| 42 | |
| 43 virtual int GetDataSize() const { | |
| 44 return packet_->size; | |
| 45 } | |
| 46 | |
| 47 protected: | |
| 48 virtual ~AVPacketBuffer() {} | |
| 49 | |
| 50 private: | |
| 51 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet_; | |
| 52 | |
| 53 DISALLOW_COPY_AND_ASSIGN(AVPacketBuffer); | |
| 54 }; | |
| 55 | |
| 56 | |
| 57 // | |
| 58 // FFmpegDemuxerStream | 27 // FFmpegDemuxerStream |
| 59 // | 28 // |
| 60 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 29 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, |
| 61 AVStream* stream) | 30 AVStream* stream) |
| 62 : demuxer_(demuxer), | 31 : demuxer_(demuxer), |
| 63 stream_(stream), | 32 stream_(stream), |
| 64 type_(UNKNOWN), | 33 type_(UNKNOWN), |
| 65 discontinuous_(false), | 34 discontinuous_(false), |
| 66 stopped_(false) { | 35 stopped_(false) { |
| 67 DCHECK(demuxer_); | 36 DCHECK(demuxer_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 89 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 58 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 90 base::AutoLock auto_lock(lock_); | 59 base::AutoLock auto_lock(lock_); |
| 91 DCHECK(!stopped_ || read_queue_.empty()) | 60 DCHECK(!stopped_ || read_queue_.empty()) |
| 92 << "Read queue should have been emptied if demuxing stream is stopped"; | 61 << "Read queue should have been emptied if demuxing stream is stopped"; |
| 93 return !read_queue_.empty(); | 62 return !read_queue_.empty(); |
| 94 } | 63 } |
| 95 | 64 |
| 96 void FFmpegDemuxerStream::EnqueuePacket( | 65 void FFmpegDemuxerStream::EnqueuePacket( |
| 97 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet) { | 66 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet) { |
| 98 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 67 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 99 base::TimeDelta timestamp = | |
| 100 ConvertStreamTimestamp(stream_->time_base, packet->pts); | |
| 101 base::TimeDelta duration = | |
| 102 ConvertStreamTimestamp(stream_->time_base, packet->duration); | |
| 103 | 68 |
| 104 base::AutoLock auto_lock(lock_); | 69 base::AutoLock auto_lock(lock_); |
| 105 if (stopped_) { | 70 if (stopped_) { |
| 106 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; | 71 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; |
| 107 return; | 72 return; |
| 108 } | 73 } |
| 109 | 74 |
| 110 // Convert if the packet if there is bitstream filter. | 75 // Convert if the packet if there is bitstream filter. |
| 111 if (packet->data && bitstream_converter_.get() && | 76 if (packet->data && bitstream_converter_.get() && |
| 112 !bitstream_converter_->ConvertPacket(packet.get())) { | 77 !bitstream_converter_->ConvertPacket(packet.get())) { |
| 113 LOG(ERROR) << "Format converstion failed."; | 78 LOG(ERROR) << "Format converstion failed."; |
| 114 } | 79 } |
| 115 | 80 |
| 116 // Enqueue the callback and attempt to satisfy a read immediately. | 81 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will |
| 117 scoped_refptr<Buffer> buffer( | 82 // reference inner memory of FFmpeg. As such we should transfer the packet |
| 118 new AVPacketBuffer(packet.Pass(), timestamp, duration)); | 83 // into memory we control. |
| 119 if (!buffer) { | 84 scoped_refptr<DecoderBuffer> buffer = DecoderBuffer::CopyFrom( |
| 120 NOTREACHED() << "Unable to allocate AVPacketBuffer"; | 85 packet->data, packet->size); |
| 121 return; | 86 buffer->SetTimestamp(ConvertStreamTimestamp(stream_->time_base, packet->pts)); |
| 122 } | 87 buffer->SetDuration(ConvertStreamTimestamp( |
| 88 stream_->time_base, packet->duration)); |
| 123 buffer_queue_.push_back(buffer); | 89 buffer_queue_.push_back(buffer); |
| 124 FulfillPendingRead(); | 90 FulfillPendingRead(); |
| 125 return; | 91 return; |
| 126 } | 92 } |
| 127 | 93 |
| 128 void FFmpegDemuxerStream::FlushBuffers() { | 94 void FFmpegDemuxerStream::FlushBuffers() { |
| 129 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 95 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 130 base::AutoLock auto_lock(lock_); | 96 base::AutoLock auto_lock(lock_); |
| 131 DCHECK(read_queue_.empty()) << "Read requests should be empty"; | 97 DCHECK(read_queue_.empty()) << "Read requests should be empty"; |
| 132 buffer_queue_.clear(); | 98 buffer_queue_.clear(); |
| 133 } | 99 } |
| 134 | 100 |
| 135 void FFmpegDemuxerStream::Stop() { | 101 void FFmpegDemuxerStream::Stop() { |
| 136 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 102 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 137 base::AutoLock auto_lock(lock_); | 103 base::AutoLock auto_lock(lock_); |
| 138 buffer_queue_.clear(); | 104 buffer_queue_.clear(); |
| 139 for (ReadQueue::iterator it = read_queue_.begin(); | 105 for (ReadQueue::iterator it = read_queue_.begin(); |
| 140 it != read_queue_.end(); ++it) { | 106 it != read_queue_.end(); ++it) { |
| 141 it->Run(scoped_refptr<Buffer>(new DataBuffer(0))); | 107 it->Run(scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))); |
| 142 } | 108 } |
| 143 read_queue_.clear(); | 109 read_queue_.clear(); |
| 144 stopped_ = true; | 110 stopped_ = true; |
| 145 } | 111 } |
| 146 | 112 |
| 147 base::TimeDelta FFmpegDemuxerStream::duration() { | 113 base::TimeDelta FFmpegDemuxerStream::duration() { |
| 148 return duration_; | 114 return duration_; |
| 149 } | 115 } |
| 150 | 116 |
| 151 DemuxerStream::Type FFmpegDemuxerStream::type() { | 117 DemuxerStream::Type FFmpegDemuxerStream::type() { |
| 152 return type_; | 118 return type_; |
| 153 } | 119 } |
| 154 | 120 |
| 155 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { | 121 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { |
| 156 DCHECK(!read_cb.is_null()); | 122 DCHECK(!read_cb.is_null()); |
| 157 | 123 |
| 158 base::AutoLock auto_lock(lock_); | 124 base::AutoLock auto_lock(lock_); |
| 159 // Don't accept any additional reads if we've been told to stop. | 125 // Don't accept any additional reads if we've been told to stop. |
| 160 // The demuxer_ may have been destroyed in the pipleine thread. | 126 // The demuxer_ may have been destroyed in the pipleine thread. |
| 161 // | 127 // |
| 162 // TODO(scherkus): it would be cleaner if we replied with an error message. | 128 // TODO(scherkus): it would be cleaner if we replied with an error message. |
| 163 if (stopped_) { | 129 if (stopped_) { |
| 164 read_cb.Run(scoped_refptr<Buffer>(new DataBuffer(0))); | 130 read_cb.Run(scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))); |
| 165 return; | 131 return; |
| 166 } | 132 } |
| 167 | 133 |
| 168 // Buffers are only queued when there are no pending reads. | 134 // Buffers are only queued when there are no pending reads. |
| 169 DCHECK(buffer_queue_.empty() || read_queue_.empty()); | 135 DCHECK(buffer_queue_.empty() || read_queue_.empty()); |
| 170 | 136 |
| 171 if (buffer_queue_.empty()) { | 137 if (buffer_queue_.empty()) { |
| 172 demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind( | 138 demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind( |
| 173 &FFmpegDemuxerStream::ReadTask, this, read_cb)); | 139 &FFmpegDemuxerStream::ReadTask, this, read_cb)); |
| 174 return; | 140 return; |
| 175 } | 141 } |
| 176 | 142 |
| 177 // Send the oldest buffer back. | 143 // Send the oldest buffer back. |
| 178 scoped_refptr<Buffer> buffer = buffer_queue_.front(); | 144 scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front(); |
| 179 buffer_queue_.pop_front(); | 145 buffer_queue_.pop_front(); |
| 180 read_cb.Run(buffer); | 146 read_cb.Run(buffer); |
| 181 } | 147 } |
| 182 | 148 |
| 183 void FFmpegDemuxerStream::ReadTask(const ReadCB& read_cb) { | 149 void FFmpegDemuxerStream::ReadTask(const ReadCB& read_cb) { |
| 184 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 150 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 185 | 151 |
| 186 base::AutoLock auto_lock(lock_); | 152 base::AutoLock auto_lock(lock_); |
| 187 // Don't accept any additional reads if we've been told to stop. | 153 // Don't accept any additional reads if we've been told to stop. |
| 188 // | 154 // |
| 189 // TODO(scherkus): it would be cleaner if we replied with an error message. | 155 // TODO(scherkus): it would be cleaner if we replied with an error message. |
| 190 if (stopped_) { | 156 if (stopped_) { |
| 191 read_cb.Run(scoped_refptr<Buffer>(new DataBuffer(0))); | 157 read_cb.Run(scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))); |
| 192 return; | 158 return; |
| 193 } | 159 } |
| 194 | 160 |
| 195 // Enqueue the callback and attempt to satisfy it immediately. | 161 // Enqueue the callback and attempt to satisfy it immediately. |
| 196 read_queue_.push_back(read_cb); | 162 read_queue_.push_back(read_cb); |
| 197 FulfillPendingRead(); | 163 FulfillPendingRead(); |
| 198 | 164 |
| 199 // Check if there are still pending reads, demux some more. | 165 // Check if there are still pending reads, demux some more. |
| 200 if (!read_queue_.empty()) { | 166 if (!read_queue_.empty()) { |
| 201 demuxer_->PostDemuxTask(); | 167 demuxer_->PostDemuxTask(); |
| 202 } | 168 } |
| 203 } | 169 } |
| 204 | 170 |
| 205 void FFmpegDemuxerStream::FulfillPendingRead() { | 171 void FFmpegDemuxerStream::FulfillPendingRead() { |
| 206 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 172 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 207 lock_.AssertAcquired(); | 173 lock_.AssertAcquired(); |
| 208 if (buffer_queue_.empty() || read_queue_.empty()) { | 174 if (buffer_queue_.empty() || read_queue_.empty()) { |
| 209 return; | 175 return; |
| 210 } | 176 } |
| 211 | 177 |
| 212 // Dequeue a buffer and pending read pair. | 178 // Dequeue a buffer and pending read pair. |
| 213 scoped_refptr<Buffer> buffer = buffer_queue_.front(); | 179 scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front(); |
| 214 ReadCB read_cb(read_queue_.front()); | 180 ReadCB read_cb(read_queue_.front()); |
| 215 buffer_queue_.pop_front(); | 181 buffer_queue_.pop_front(); |
| 216 read_queue_.pop_front(); | 182 read_queue_.pop_front(); |
| 217 | 183 |
| 218 // Execute the callback. | 184 // Execute the callback. |
| 219 read_cb.Run(buffer); | 185 read_cb.Run(buffer); |
| 220 } | 186 } |
| 221 | 187 |
| 222 void FFmpegDemuxerStream::EnableBitstreamConverter() { | 188 void FFmpegDemuxerStream::EnableBitstreamConverter() { |
| 223 // Called by hardware decoder to require different bitstream converter. | 189 // Called by hardware decoder to require different bitstream converter. |
| 224 // Currently we assume that converter is determined by codec_id; | 190 // Currently we assume that converter is determined by codec_id; |
| 225 DCHECK(stream_); | 191 DCHECK(stream_); |
| 226 | 192 |
| 227 if (stream_->codec->codec_id == CODEC_ID_H264) { | 193 if (stream_->codec->codec_id == CODEC_ID_H264) { |
| 228 // Use Chromium bitstream converter in case of H.264 | 194 // Use Chromium bitstream converter in case of H.264 |
| 229 bitstream_converter_.reset( | 195 bitstream_converter_.reset( |
| 230 new FFmpegH264BitstreamConverter(stream_->codec)); | 196 new FFmpegH264BitstreamConverter(stream_->codec)); |
| 231 CHECK(bitstream_converter_->Initialize()); | 197 CHECK(bitstream_converter_->Initialize()); |
| 232 return; | 198 } else if (stream_->codec->codec_id == CODEC_ID_MPEG4) { |
| 233 } | |
| 234 | |
| 235 const char* filter_name = NULL; | |
| 236 if (stream_->codec->codec_id == CODEC_ID_MPEG4) { | |
| 237 filter_name = "mpeg4video_es"; | |
| 238 } else if (stream_->codec->codec_id == CODEC_ID_WMV3) { | |
| 239 filter_name = "vc1_asftorcv"; | |
| 240 } else if (stream_->codec->codec_id == CODEC_ID_VC1) { | |
| 241 filter_name = "vc1_asftoannexg"; | |
| 242 } | |
| 243 | |
| 244 if (filter_name) { | |
| 245 bitstream_converter_.reset( | 199 bitstream_converter_.reset( |
| 246 new FFmpegBitstreamConverter(filter_name, stream_->codec)); | 200 new FFmpegBitstreamConverter("mpeg4video_es", stream_->codec)); |
| 247 CHECK(bitstream_converter_->Initialize()); | 201 CHECK(bitstream_converter_->Initialize()); |
| 248 } | 202 } |
| 249 } | 203 } |
| 250 | 204 |
| 251 const AudioDecoderConfig& FFmpegDemuxerStream::audio_decoder_config() { | 205 const AudioDecoderConfig& FFmpegDemuxerStream::audio_decoder_config() { |
| 252 CHECK_EQ(type_, AUDIO); | 206 CHECK_EQ(type_, AUDIO); |
| 253 return audio_config_; | 207 return audio_config_; |
| 254 } | 208 } |
| 255 | 209 |
| 256 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { | 210 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 DCHECK_GE(packet->stream_index, 0); | 597 DCHECK_GE(packet->stream_index, 0); |
| 644 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); | 598 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); |
| 645 | 599 |
| 646 // Defend against ffmpeg giving us a bad stream index. | 600 // Defend against ffmpeg giving us a bad stream index. |
| 647 if (packet->stream_index >= 0 && | 601 if (packet->stream_index >= 0 && |
| 648 packet->stream_index < static_cast<int>(streams_.size()) && | 602 packet->stream_index < static_cast<int>(streams_.size()) && |
| 649 streams_[packet->stream_index] && | 603 streams_[packet->stream_index] && |
| 650 (!audio_disabled_ || | 604 (!audio_disabled_ || |
| 651 streams_[packet->stream_index]->type() != DemuxerStream::AUDIO)) { | 605 streams_[packet->stream_index]->type() != DemuxerStream::AUDIO)) { |
| 652 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; | 606 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; |
| 653 | |
| 654 // If a packet is returned by FFmpeg's av_parser_parse2() | |
| 655 // the packet will reference an inner memory of FFmpeg. | |
| 656 // In this case, the packet's "destruct" member is NULL, | |
| 657 // and it MUST be duplicated. This fixes issue with MP3 and possibly | |
| 658 // other codecs. It is safe to call this function even if the packet does | |
| 659 // not refer to inner memory from FFmpeg. | |
| 660 av_dup_packet(packet.get()); | |
| 661 | |
| 662 demuxer_stream->EnqueuePacket(packet.Pass()); | 607 demuxer_stream->EnqueuePacket(packet.Pass()); |
| 663 } | 608 } |
| 664 | 609 |
| 665 // Create a loop by posting another task. This allows seek and message loop | 610 // Create a loop by posting another task. This allows seek and message loop |
| 666 // quit tasks to get processed. | 611 // quit tasks to get processed. |
| 667 if (StreamsHavePendingReads()) { | 612 if (StreamsHavePendingReads()) { |
| 668 PostDemuxTask(); | 613 PostDemuxTask(); |
| 669 } | 614 } |
| 670 } | 615 } |
| 671 | 616 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 read_event_.Wait(); | 668 read_event_.Wait(); |
| 724 return last_read_bytes_; | 669 return last_read_bytes_; |
| 725 } | 670 } |
| 726 | 671 |
| 727 void FFmpegDemuxer::SignalReadCompleted(int size) { | 672 void FFmpegDemuxer::SignalReadCompleted(int size) { |
| 728 last_read_bytes_ = size; | 673 last_read_bytes_ = size; |
| 729 read_event_.Signal(); | 674 read_event_.Signal(); |
| 730 } | 675 } |
| 731 | 676 |
| 732 } // namespace media | 677 } // namespace media |
| OLD | NEW |