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/base64.h" | 10 #include "base/base64.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
22 #include "base/time/time.h" | 22 #include "base/time/time.h" |
23 #include "media/base/audio_decoder_config.h" | 23 #include "media/base/audio_decoder_config.h" |
24 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
25 #include "media/base/decoder_buffer.h" | 25 #include "media/base/decoder_buffer.h" |
26 #include "media/base/decrypt_config.h" | 26 #include "media/base/decrypt_config.h" |
27 #include "media/base/limits.h" | 27 #include "media/base/limits.h" |
28 #include "media/base/media_log.h" | 28 #include "media/base/media_log.h" |
29 #include "media/base/video_decoder_config.h" | 29 #include "media/base/video_decoder_config.h" |
30 #include "media/ffmpeg/ffmpeg_common.h" | 30 #include "media/ffmpeg/ffmpeg_common.h" |
| 31 #include "media/filters/ffmpeg_aac_bitstream_converter.h" |
| 32 #include "media/filters/ffmpeg_bitstream_converter.h" |
31 #include "media/filters/ffmpeg_glue.h" | 33 #include "media/filters/ffmpeg_glue.h" |
32 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h" | 34 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h" |
33 #include "media/filters/webvtt_util.h" | 35 #include "media/filters/webvtt_util.h" |
34 #include "media/formats/webm/webm_crypto_helpers.h" | 36 #include "media/formats/webm/webm_crypto_helpers.h" |
35 | 37 |
36 namespace media { | 38 namespace media { |
37 | 39 |
38 static base::Time ExtractTimelineOffset(AVFormatContext* format_context) { | 40 static base::Time ExtractTimelineOffset(AVFormatContext* format_context) { |
39 if (strstr(format_context->iformat->name, "webm") || | 41 if (strstr(format_context->iformat->name, "webm") || |
40 strstr(format_context->iformat->name, "matroska")) { | 42 strstr(format_context->iformat->name, "matroska")) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 90 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, |
89 AVStream* stream) | 91 AVStream* stream) |
90 : demuxer_(demuxer), | 92 : demuxer_(demuxer), |
91 task_runner_(base::MessageLoopProxy::current()), | 93 task_runner_(base::MessageLoopProxy::current()), |
92 stream_(stream), | 94 stream_(stream), |
93 type_(UNKNOWN), | 95 type_(UNKNOWN), |
94 end_of_stream_(false), | 96 end_of_stream_(false), |
95 last_packet_timestamp_(kNoTimestamp()), | 97 last_packet_timestamp_(kNoTimestamp()), |
96 last_packet_duration_(kNoTimestamp()), | 98 last_packet_duration_(kNoTimestamp()), |
97 video_rotation_(VIDEO_ROTATION_0), | 99 video_rotation_(VIDEO_ROTATION_0), |
98 bitstream_converter_enabled_(false), | |
99 fixup_negative_ogg_timestamps_(false) { | 100 fixup_negative_ogg_timestamps_(false) { |
100 DCHECK(demuxer_); | 101 DCHECK(demuxer_); |
101 | 102 |
102 bool is_encrypted = false; | 103 bool is_encrypted = false; |
103 int rotation = 0; | 104 int rotation = 0; |
104 AVDictionaryEntry* rotation_entry = NULL; | 105 AVDictionaryEntry* rotation_entry = NULL; |
105 | 106 |
106 // Determine our media format. | 107 // Determine our media format. |
107 switch (stream->codec->codec_type) { | 108 switch (stream->codec->codec_type) { |
108 case AVMEDIA_TYPE_AUDIO: | 109 case AVMEDIA_TYPE_AUDIO: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 type_ = TEXT; | 142 type_ = TEXT; |
142 break; | 143 break; |
143 default: | 144 default: |
144 NOTREACHED(); | 145 NOTREACHED(); |
145 break; | 146 break; |
146 } | 147 } |
147 | 148 |
148 // Calculate the duration. | 149 // Calculate the duration. |
149 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); | 150 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); |
150 | 151 |
151 #if defined(USE_PROPRIETARY_CODECS) | |
152 if (stream_->codec->codec_id == AV_CODEC_ID_H264) { | |
153 bitstream_converter_.reset( | |
154 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); | |
155 } | |
156 #endif | |
157 | |
158 if (is_encrypted) { | 152 if (is_encrypted) { |
159 AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL, | 153 AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL, |
160 0); | 154 0); |
161 DCHECK(key); | 155 DCHECK(key); |
162 DCHECK(key->value); | 156 DCHECK(key->value); |
163 if (!key || !key->value) | 157 if (!key || !key->value) |
164 return; | 158 return; |
165 base::StringPiece base64_key_id(key->value); | 159 base::StringPiece base64_key_id(key->value); |
166 std::string enc_key_id; | 160 std::string enc_key_id; |
167 base::Base64Decode(base64_key_id, &enc_key_id); | 161 base::Base64Decode(base64_key_id, &enc_key_id); |
168 DCHECK(!enc_key_id.empty()); | 162 DCHECK(!enc_key_id.empty()); |
169 if (enc_key_id.empty()) | 163 if (enc_key_id.empty()) |
170 return; | 164 return; |
171 | 165 |
172 encryption_key_id_.assign(enc_key_id); | 166 encryption_key_id_.assign(enc_key_id); |
173 demuxer_->FireNeedKey(kWebMInitDataType, enc_key_id); | 167 demuxer_->FireNeedKey(kWebMInitDataType, enc_key_id); |
174 } | 168 } |
175 } | 169 } |
176 | 170 |
177 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { | 171 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { |
178 DCHECK(task_runner_->BelongsToCurrentThread()); | 172 DCHECK(task_runner_->BelongsToCurrentThread()); |
179 | 173 |
180 if (!demuxer_ || end_of_stream_) { | 174 if (!demuxer_ || end_of_stream_) { |
181 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; | 175 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; |
182 return; | 176 return; |
183 } | 177 } |
184 | 178 |
185 #if defined(USE_PROPRIETARY_CODECS) | 179 #if defined(USE_PROPRIETARY_CODECS) |
186 // Convert the packet if there is a bitstream filter. | 180 // Convert the packet if there is a bitstream filter. |
187 if (packet->data && bitstream_converter_enabled_ && | 181 if (packet->data && bitstream_converter_ && |
188 !bitstream_converter_->ConvertPacket(packet.get())) { | 182 !bitstream_converter_->ConvertPacket(packet.get())) { |
189 LOG(ERROR) << "Format conversion failed."; | 183 LOG(ERROR) << "Format conversion failed."; |
190 } | 184 } |
191 #endif | 185 #endif |
192 | 186 |
193 // Get side data if any. For now, the only type of side_data is VP8 Alpha. We | 187 // Get side data if any. For now, the only type of side_data is VP8 Alpha. We |
194 // keep this generic so that other side_data types in the future can be | 188 // keep this generic so that other side_data types in the future can be |
195 // handled the same way as well. | 189 // handled the same way as well. |
196 av_packet_split_side_data(packet.get()); | 190 av_packet_split_side_data(packet.get()); |
197 | 191 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 void FFmpegDemuxerStream::SetEndOfStream() { | 370 void FFmpegDemuxerStream::SetEndOfStream() { |
377 DCHECK(task_runner_->BelongsToCurrentThread()); | 371 DCHECK(task_runner_->BelongsToCurrentThread()); |
378 end_of_stream_ = true; | 372 end_of_stream_ = true; |
379 SatisfyPendingRead(); | 373 SatisfyPendingRead(); |
380 } | 374 } |
381 | 375 |
382 void FFmpegDemuxerStream::FlushBuffers() { | 376 void FFmpegDemuxerStream::FlushBuffers() { |
383 DCHECK(task_runner_->BelongsToCurrentThread()); | 377 DCHECK(task_runner_->BelongsToCurrentThread()); |
384 DCHECK(read_cb_.is_null()) << "There should be no pending read"; | 378 DCHECK(read_cb_.is_null()) << "There should be no pending read"; |
385 | 379 |
386 // H264 requires that we resend the header after flush. | 380 // H264 and AAC require that we resend the header after flush. |
387 // Reset its bitstream for converter to do so. | 381 // Reset bitstream for converter to do so. |
388 // This is related to chromium issue 140371 (http://crbug.com/140371). | 382 // This is related to chromium issue 140371 (http://crbug.com/140371). |
389 ResetBitstreamConverter(); | 383 ResetBitstreamConverter(); |
390 | 384 |
391 buffer_queue_.Clear(); | 385 buffer_queue_.Clear(); |
392 end_of_stream_ = false; | 386 end_of_stream_ = false; |
393 last_packet_timestamp_ = kNoTimestamp(); | 387 last_packet_timestamp_ = kNoTimestamp(); |
394 last_packet_duration_ = kNoTimestamp(); | 388 last_packet_duration_ = kNoTimestamp(); |
395 } | 389 } |
396 | 390 |
397 void FFmpegDemuxerStream::Stop() { | 391 void FFmpegDemuxerStream::Stop() { |
(...skipping 28 matching lines...) Expand all Loading... |
426 return; | 420 return; |
427 } | 421 } |
428 | 422 |
429 SatisfyPendingRead(); | 423 SatisfyPendingRead(); |
430 } | 424 } |
431 | 425 |
432 void FFmpegDemuxerStream::EnableBitstreamConverter() { | 426 void FFmpegDemuxerStream::EnableBitstreamConverter() { |
433 DCHECK(task_runner_->BelongsToCurrentThread()); | 427 DCHECK(task_runner_->BelongsToCurrentThread()); |
434 | 428 |
435 #if defined(USE_PROPRIETARY_CODECS) | 429 #if defined(USE_PROPRIETARY_CODECS) |
436 CHECK(bitstream_converter_.get()); | 430 InitBitstreamConverter(); |
437 bitstream_converter_enabled_ = true; | |
438 #else | 431 #else |
439 NOTREACHED() << "Proprietary codecs not enabled."; | 432 NOTREACHED() << "Proprietary codecs not enabled."; |
440 #endif | 433 #endif |
441 } | 434 } |
442 | 435 |
443 void FFmpegDemuxerStream::ResetBitstreamConverter() { | 436 void FFmpegDemuxerStream::ResetBitstreamConverter() { |
444 #if defined(USE_PROPRIETARY_CODECS) | 437 #if defined(USE_PROPRIETARY_CODECS) |
445 if (!bitstream_converter_enabled_ || !bitstream_converter_) | 438 if (bitstream_converter_) |
446 return; | 439 InitBitstreamConverter(); |
447 | |
448 bitstream_converter_.reset( | |
449 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); | |
450 #endif // defined(USE_PROPRIETARY_CODECS) | 440 #endif // defined(USE_PROPRIETARY_CODECS) |
451 } | 441 } |
452 | 442 |
| 443 void FFmpegDemuxerStream::InitBitstreamConverter() { |
| 444 #if defined(USE_PROPRIETARY_CODECS) |
| 445 if (stream_->codec->codec_id == AV_CODEC_ID_H264) { |
| 446 bitstream_converter_.reset( |
| 447 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); |
| 448 } else if (stream_->codec->codec_id == AV_CODEC_ID_AAC) { |
| 449 bitstream_converter_.reset( |
| 450 new FFmpegAACBitstreamConverter(stream_->codec)); |
| 451 } |
| 452 #endif // defined(USE_PROPRIETARY_CODECS) |
| 453 } |
| 454 |
453 bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; } | 455 bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; } |
454 | 456 |
455 AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() { | 457 AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() { |
456 DCHECK(task_runner_->BelongsToCurrentThread()); | 458 DCHECK(task_runner_->BelongsToCurrentThread()); |
457 CHECK_EQ(type_, AUDIO); | 459 CHECK_EQ(type_, AUDIO); |
458 return audio_config_; | 460 return audio_config_; |
459 } | 461 } |
460 | 462 |
461 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { | 463 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { |
462 DCHECK(task_runner_->BelongsToCurrentThread()); | 464 DCHECK(task_runner_->BelongsToCurrentThread()); |
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 } | 1266 } |
1265 for (size_t i = 0; i < buffered.size(); ++i) | 1267 for (size_t i = 0; i < buffered.size(); ++i) |
1266 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 1268 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
1267 } | 1269 } |
1268 | 1270 |
1269 void FFmpegDemuxer::OnDataSourceError() { | 1271 void FFmpegDemuxer::OnDataSourceError() { |
1270 host_->OnDemuxerError(PIPELINE_ERROR_READ); | 1272 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
1271 } | 1273 } |
1272 | 1274 |
1273 } // namespace media | 1275 } // namespace media |
OLD | NEW |