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/ffmpeg_demuxer.h" | 5 #include "media/filters/ffmpeg_demuxer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 // | 29 // |
30 // FFmpegDemuxerStream | 30 // FFmpegDemuxerStream |
31 // | 31 // |
32 FFmpegDemuxerStream::FFmpegDemuxerStream( | 32 FFmpegDemuxerStream::FFmpegDemuxerStream( |
33 FFmpegDemuxer* demuxer, | 33 FFmpegDemuxer* demuxer, |
34 AVStream* stream) | 34 AVStream* stream) |
35 : demuxer_(demuxer), | 35 : demuxer_(demuxer), |
36 stream_(stream), | 36 stream_(stream), |
37 type_(UNKNOWN), | 37 type_(UNKNOWN), |
38 stopped_(false), | 38 stopped_(false), |
39 last_packet_timestamp_(kNoTimestamp()) { | 39 last_packet_timestamp_(kNoTimestamp()), |
| 40 bitstream_converter_enabled_(false) { |
40 DCHECK(demuxer_); | 41 DCHECK(demuxer_); |
41 | 42 |
42 // Determine our media format. | 43 // Determine our media format. |
43 switch (stream->codec->codec_type) { | 44 switch (stream->codec->codec_type) { |
44 case AVMEDIA_TYPE_AUDIO: | 45 case AVMEDIA_TYPE_AUDIO: |
45 type_ = AUDIO; | 46 type_ = AUDIO; |
46 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); | 47 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); |
47 break; | 48 break; |
48 case AVMEDIA_TYPE_VIDEO: | 49 case AVMEDIA_TYPE_VIDEO: |
49 type_ = VIDEO; | 50 type_ = VIDEO; |
50 AVStreamToVideoDecoderConfig(stream, &video_config_); | 51 AVStreamToVideoDecoderConfig(stream, &video_config_); |
51 break; | 52 break; |
52 default: | 53 default: |
53 NOTREACHED(); | 54 NOTREACHED(); |
54 break; | 55 break; |
55 } | 56 } |
56 | 57 |
57 // Calculate the duration. | 58 // Calculate the duration. |
58 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); | 59 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); |
| 60 |
| 61 if (stream_->codec->codec_id == CODEC_ID_H264) { |
| 62 bitstream_converter_.reset( |
| 63 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); |
| 64 } |
59 } | 65 } |
60 | 66 |
61 bool FFmpegDemuxerStream::HasPendingReads() { | 67 bool FFmpegDemuxerStream::HasPendingReads() { |
62 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); | 68 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); |
63 base::AutoLock auto_lock(lock_); | 69 base::AutoLock auto_lock(lock_); |
64 DCHECK(!stopped_ || read_queue_.empty()) | 70 DCHECK(!stopped_ || read_queue_.empty()) |
65 << "Read queue should have been emptied if demuxing stream is stopped"; | 71 << "Read queue should have been emptied if demuxing stream is stopped"; |
66 return !read_queue_.empty(); | 72 return !read_queue_.empty(); |
67 } | 73 } |
68 | 74 |
69 void FFmpegDemuxerStream::EnqueuePacket( | 75 void FFmpegDemuxerStream::EnqueuePacket( |
70 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet) { | 76 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet) { |
71 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); | 77 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); |
72 | 78 |
73 base::AutoLock auto_lock(lock_); | 79 base::AutoLock auto_lock(lock_); |
74 if (stopped_) { | 80 if (stopped_) { |
75 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; | 81 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; |
76 return; | 82 return; |
77 } | 83 } |
78 | 84 |
79 scoped_refptr<DecoderBuffer> buffer; | 85 scoped_refptr<DecoderBuffer> buffer; |
80 if (!packet.get()) { | 86 if (!packet.get()) { |
81 buffer = DecoderBuffer::CreateEOSBuffer(); | 87 buffer = DecoderBuffer::CreateEOSBuffer(); |
82 } else { | 88 } else { |
83 // Convert the packet if there is a bitstream filter. | 89 // Convert the packet if there is a bitstream filter. |
84 if (packet->data && bitstream_converter_.get() && | 90 if (packet->data && bitstream_converter_enabled_ && |
85 !bitstream_converter_->ConvertPacket(packet.get())) { | 91 !bitstream_converter_->ConvertPacket(packet.get())) { |
86 LOG(ERROR) << "Format converstion failed."; | 92 LOG(ERROR) << "Format converstion failed."; |
87 } | 93 } |
88 | 94 |
89 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will | 95 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will |
90 // reference inner memory of FFmpeg. As such we should transfer the packet | 96 // reference inner memory of FFmpeg. As such we should transfer the packet |
91 // into memory we control. | 97 // into memory we control. |
92 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); | 98 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); |
93 buffer->SetTimestamp(ConvertStreamTimestamp( | 99 buffer->SetTimestamp(ConvertStreamTimestamp( |
94 stream_->time_base, packet->pts)); | 100 stream_->time_base, packet->pts)); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 ReadCB read_cb(read_queue_.front()); | 208 ReadCB read_cb(read_queue_.front()); |
203 buffer_queue_.pop_front(); | 209 buffer_queue_.pop_front(); |
204 read_queue_.pop_front(); | 210 read_queue_.pop_front(); |
205 | 211 |
206 // Execute the callback. | 212 // Execute the callback. |
207 read_cb.Run(DemuxerStream::kOk, buffer); | 213 read_cb.Run(DemuxerStream::kOk, buffer); |
208 } | 214 } |
209 | 215 |
210 void FFmpegDemuxerStream::EnableBitstreamConverter() { | 216 void FFmpegDemuxerStream::EnableBitstreamConverter() { |
211 base::AutoLock auto_lock(lock_); | 217 base::AutoLock auto_lock(lock_); |
212 // Called by hardware decoder to require different bitstream converter. | 218 CHECK(bitstream_converter_.get()); |
213 // Currently we assume that converter is determined by codec_id; | 219 bitstream_converter_enabled_ = true; |
214 DCHECK(stream_); | |
215 DCHECK_EQ(stream_->codec->codec_id, CODEC_ID_H264); | |
216 bitstream_converter_.reset( | |
217 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); | |
218 } | 220 } |
219 | 221 |
220 const AudioDecoderConfig& FFmpegDemuxerStream::audio_decoder_config() { | 222 const AudioDecoderConfig& FFmpegDemuxerStream::audio_decoder_config() { |
221 CHECK_EQ(type_, AUDIO); | 223 CHECK_EQ(type_, AUDIO); |
222 return audio_config_; | 224 return audio_config_; |
223 } | 225 } |
224 | 226 |
225 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { | 227 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { |
226 CHECK_EQ(type_, VIDEO); | 228 CHECK_EQ(type_, VIDEO); |
227 return video_config_; | 229 return video_config_; |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 } else if (audio) { | 729 } else if (audio) { |
728 buffered = audio->GetBufferedRanges(); | 730 buffered = audio->GetBufferedRanges(); |
729 } else if (video) { | 731 } else if (video) { |
730 buffered = video->GetBufferedRanges(); | 732 buffered = video->GetBufferedRanges(); |
731 } | 733 } |
732 for (size_t i = 0; i < buffered.size(); ++i) | 734 for (size_t i = 0; i < buffered.size(); ++i) |
733 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 735 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
734 } | 736 } |
735 | 737 |
736 } // namespace media | 738 } // namespace media |
OLD | NEW |