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 <memory> | 8 #include <memory> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 265 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
266 stream_(stream), | 266 stream_(stream), |
267 audio_config_(audio_config.release()), | 267 audio_config_(audio_config.release()), |
268 video_config_(video_config.release()), | 268 video_config_(video_config.release()), |
269 type_(UNKNOWN), | 269 type_(UNKNOWN), |
270 liveness_(LIVENESS_UNKNOWN), | 270 liveness_(LIVENESS_UNKNOWN), |
271 end_of_stream_(false), | 271 end_of_stream_(false), |
272 last_packet_timestamp_(kNoTimestamp()), | 272 last_packet_timestamp_(kNoTimestamp()), |
273 last_packet_duration_(kNoTimestamp()), | 273 last_packet_duration_(kNoTimestamp()), |
274 video_rotation_(VIDEO_ROTATION_0), | 274 video_rotation_(VIDEO_ROTATION_0), |
| 275 is_enabled_(true), |
| 276 waiting_for_keyframe_(false), |
275 fixup_negative_timestamps_(false) { | 277 fixup_negative_timestamps_(false) { |
276 DCHECK(demuxer_); | 278 DCHECK(demuxer_); |
277 | 279 |
278 bool is_encrypted = false; | 280 bool is_encrypted = false; |
279 int rotation = 0; | 281 int rotation = 0; |
280 AVDictionaryEntry* rotation_entry = NULL; | 282 AVDictionaryEntry* rotation_entry = NULL; |
281 | 283 |
282 // Determine our media format. | 284 // Determine our media format. |
283 switch (stream->codec->codec_type) { | 285 switch (stream->codec->codec_type) { |
284 case AVMEDIA_TYPE_AUDIO: | 286 case AVMEDIA_TYPE_AUDIO: |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 } | 353 } |
352 | 354 |
353 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { | 355 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { |
354 DCHECK(task_runner_->BelongsToCurrentThread()); | 356 DCHECK(task_runner_->BelongsToCurrentThread()); |
355 | 357 |
356 if (!demuxer_ || end_of_stream_) { | 358 if (!demuxer_ || end_of_stream_) { |
357 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; | 359 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; |
358 return; | 360 return; |
359 } | 361 } |
360 | 362 |
| 363 if (waiting_for_keyframe_) { |
| 364 if (packet.get()->flags & AV_PKT_FLAG_KEY) |
| 365 waiting_for_keyframe_ = false; |
| 366 else { |
| 367 DVLOG(3) << "Dropped non-keyframe pts=" << packet->pts; |
| 368 return; |
| 369 } |
| 370 } |
| 371 |
361 #if defined(USE_PROPRIETARY_CODECS) | 372 #if defined(USE_PROPRIETARY_CODECS) |
362 // Convert the packet if there is a bitstream filter. | 373 // Convert the packet if there is a bitstream filter. |
363 if (packet->data && bitstream_converter_ && | 374 if (packet->data && bitstream_converter_ && |
364 !bitstream_converter_->ConvertPacket(packet.get())) { | 375 !bitstream_converter_->ConvertPacket(packet.get())) { |
365 LOG(ERROR) << "Format conversion failed."; | 376 LOG(ERROR) << "Format conversion failed."; |
366 } | 377 } |
367 #endif | 378 #endif |
368 | 379 |
369 // Get side data if any. For now, the only type of side_data is VP8 Alpha. We | 380 // Get side data if any. For now, the only type of side_data is VP8 Alpha. We |
370 // keep this generic so that other side_data types in the future can be | 381 // keep this generic so that other side_data types in the future can be |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 // Don't accept any additional reads if we've been told to stop. | 622 // Don't accept any additional reads if we've been told to stop. |
612 // The |demuxer_| may have been destroyed in the pipeline thread. | 623 // The |demuxer_| may have been destroyed in the pipeline thread. |
613 // | 624 // |
614 // TODO(scherkus): it would be cleaner to reply with an error message. | 625 // TODO(scherkus): it would be cleaner to reply with an error message. |
615 if (!demuxer_) { | 626 if (!demuxer_) { |
616 base::ResetAndReturn(&read_cb_).Run( | 627 base::ResetAndReturn(&read_cb_).Run( |
617 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); | 628 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); |
618 return; | 629 return; |
619 } | 630 } |
620 | 631 |
| 632 if (!is_enabled_) { |
| 633 DVLOG(1) << "Read from disabled stream, returning EOS"; |
| 634 base::ResetAndReturn(&read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer()); |
| 635 return; |
| 636 } |
| 637 |
621 SatisfyPendingRead(); | 638 SatisfyPendingRead(); |
622 } | 639 } |
623 | 640 |
624 void FFmpegDemuxerStream::EnableBitstreamConverter() { | 641 void FFmpegDemuxerStream::EnableBitstreamConverter() { |
625 DCHECK(task_runner_->BelongsToCurrentThread()); | 642 DCHECK(task_runner_->BelongsToCurrentThread()); |
626 | 643 |
627 #if defined(USE_PROPRIETARY_CODECS) | 644 #if defined(USE_PROPRIETARY_CODECS) |
628 InitBitstreamConverter(); | 645 InitBitstreamConverter(); |
629 #else | 646 #else |
630 NOTREACHED() << "Proprietary codecs not enabled."; | 647 NOTREACHED() << "Proprietary codecs not enabled."; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 DCHECK(task_runner_->BelongsToCurrentThread()); | 691 DCHECK(task_runner_->BelongsToCurrentThread()); |
675 DCHECK_EQ(type_, VIDEO); | 692 DCHECK_EQ(type_, VIDEO); |
676 DCHECK(video_config_.get()); | 693 DCHECK(video_config_.get()); |
677 return *video_config_; | 694 return *video_config_; |
678 } | 695 } |
679 | 696 |
680 VideoRotation FFmpegDemuxerStream::video_rotation() { | 697 VideoRotation FFmpegDemuxerStream::video_rotation() { |
681 return video_rotation_; | 698 return video_rotation_; |
682 } | 699 } |
683 | 700 |
| 701 bool FFmpegDemuxerStream::enabled() const { |
| 702 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 703 return is_enabled_; |
| 704 } |
| 705 |
| 706 void FFmpegDemuxerStream::set_enabled(bool enabled, base::TimeDelta timestamp) { |
| 707 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 708 if (enabled == is_enabled_) |
| 709 return; |
| 710 |
| 711 is_enabled_ = enabled; |
| 712 if (is_enabled_) { |
| 713 waiting_for_keyframe_ = true; |
| 714 if (!stream_restarted_cb_.is_null()) |
| 715 stream_restarted_cb_.Run(this, timestamp); |
| 716 } |
| 717 if (!is_enabled_ && !read_cb_.is_null()) { |
| 718 DVLOG(1) << "Read from disabled stream, returning EOS"; |
| 719 base::ResetAndReturn(&read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer()); |
| 720 return; |
| 721 } |
| 722 } |
| 723 |
| 724 void FFmpegDemuxerStream::SetStreamRestartedCB(const StreamRestartedCB& cb) { |
| 725 DCHECK(!cb.is_null()); |
| 726 stream_restarted_cb_ = cb; |
| 727 } |
| 728 |
684 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { | 729 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { |
685 DCHECK(task_runner_->BelongsToCurrentThread()); | 730 DCHECK(task_runner_->BelongsToCurrentThread()); |
686 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); | 731 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); |
687 liveness_ = liveness; | 732 liveness_ = liveness; |
688 } | 733 } |
689 | 734 |
690 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { | 735 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { |
691 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); | 736 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); |
692 } | 737 } |
693 | 738 |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 packet_buffer = packet_buffer->next; | 1169 packet_buffer = packet_buffer->next; |
1125 } | 1170 } |
1126 } | 1171 } |
1127 | 1172 |
1128 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks()); | 1173 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks()); |
1129 AVStream* audio_stream = NULL; | 1174 AVStream* audio_stream = NULL; |
1130 AudioDecoderConfig audio_config; | 1175 AudioDecoderConfig audio_config; |
1131 AVStream* video_stream = NULL; | 1176 AVStream* video_stream = NULL; |
1132 VideoDecoderConfig video_config; | 1177 VideoDecoderConfig video_config; |
1133 | 1178 |
| 1179 DCHECK(track_id_to_demux_stream_map_.empty()); |
| 1180 |
1134 // If available, |start_time_| will be set to the lowest stream start time. | 1181 // If available, |start_time_| will be set to the lowest stream start time. |
1135 start_time_ = kInfiniteDuration(); | 1182 start_time_ = kInfiniteDuration(); |
1136 | 1183 |
1137 base::TimeDelta max_duration; | 1184 base::TimeDelta max_duration; |
1138 int detected_audio_track_count = 0; | 1185 int detected_audio_track_count = 0; |
1139 int detected_video_track_count = 0; | 1186 int detected_video_track_count = 0; |
1140 int detected_text_track_count = 0; | 1187 int detected_text_track_count = 0; |
1141 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 1188 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
1142 AVStream* stream = format_context->streams[i]; | 1189 AVStream* stream = format_context->streams[i]; |
1143 const AVCodecContext* codec_context = stream->codec; | 1190 const AVCodecContext* codec_context = stream->codec; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1239 MediaTrack* media_track = nullptr; | 1286 MediaTrack* media_track = nullptr; |
1240 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 1287 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
1241 CHECK(!audio_stream); | 1288 CHECK(!audio_stream); |
1242 audio_stream = stream; | 1289 audio_stream = stream; |
1243 audio_config = streams_[i]->audio_decoder_config(); | 1290 audio_config = streams_[i]->audio_decoder_config(); |
1244 RecordAudioCodecStats(audio_config); | 1291 RecordAudioCodecStats(audio_config); |
1245 | 1292 |
1246 media_track = media_tracks->AddAudioTrack(audio_config, track_id, "main", | 1293 media_track = media_tracks->AddAudioTrack(audio_config, track_id, "main", |
1247 track_label, track_language); | 1294 track_label, track_language); |
1248 media_track->set_id(base::UintToString(track_id)); | 1295 media_track->set_id(base::UintToString(track_id)); |
| 1296 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == |
| 1297 track_id_to_demux_stream_map_.end()); |
| 1298 track_id_to_demux_stream_map_[media_track->id()] = streams_[i]; |
1249 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | 1299 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
1250 CHECK(!video_stream); | 1300 CHECK(!video_stream); |
1251 video_stream = stream; | 1301 video_stream = stream; |
1252 video_config = streams_[i]->video_decoder_config(); | 1302 video_config = streams_[i]->video_decoder_config(); |
1253 | 1303 |
1254 RecordVideoCodecStats(video_config, stream->codec->color_range, | 1304 RecordVideoCodecStats(video_config, stream->codec->color_range, |
1255 media_log_.get()); | 1305 media_log_.get()); |
1256 | 1306 |
1257 media_track = media_tracks->AddVideoTrack(video_config, track_id, "main", | 1307 media_track = media_tracks->AddVideoTrack(video_config, track_id, "main", |
1258 track_label, track_language); | 1308 track_label, track_language); |
1259 media_track->set_id(base::UintToString(track_id)); | 1309 media_track->set_id(base::UintToString(track_id)); |
| 1310 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == |
| 1311 track_id_to_demux_stream_map_.end()); |
| 1312 track_id_to_demux_stream_map_[media_track->id()] = streams_[i]; |
1260 } | 1313 } |
1261 | 1314 |
1262 max_duration = std::max(max_duration, streams_[i]->duration()); | 1315 max_duration = std::max(max_duration, streams_[i]->duration()); |
1263 | 1316 |
1264 const base::TimeDelta start_time = | 1317 const base::TimeDelta start_time = |
1265 ExtractStartTime(stream, start_time_estimates[i]); | 1318 ExtractStartTime(stream, start_time_estimates[i]); |
1266 const bool has_start_time = start_time != kNoTimestamp(); | 1319 const bool has_start_time = start_time != kNoTimestamp(); |
1267 | 1320 |
1268 // Always prefer the video stream for seeking. If none exists, we'll swap | 1321 // Always prefer the video stream for seeking. If none exists, we'll swap |
1269 // the fallback stream with the preferred stream below. | 1322 // the fallback stream with the preferred stream below. |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1462 (*iter)->FlushBuffers(); | 1515 (*iter)->FlushBuffers(); |
1463 } | 1516 } |
1464 | 1517 |
1465 // Resume reading until capacity. | 1518 // Resume reading until capacity. |
1466 ReadFrameIfNeeded(); | 1519 ReadFrameIfNeeded(); |
1467 | 1520 |
1468 // Notify we're finished seeking. | 1521 // Notify we're finished seeking. |
1469 cb.Run(PIPELINE_OK); | 1522 cb.Run(PIPELINE_OK); |
1470 } | 1523 } |
1471 | 1524 |
| 1525 void FFmpegDemuxer::OnEnabledAudioTracksChanged( |
| 1526 const std::vector<MediaTrack::Id>& track_ids, |
| 1527 base::TimeDelta currTime) { |
| 1528 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1529 bool enabled = false; |
| 1530 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); |
| 1531 CHECK(audio_stream); |
| 1532 if (track_ids.size() > 0) { |
| 1533 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == audio_stream); |
| 1534 enabled = true; |
| 1535 } |
| 1536 DVLOG(1) << __FUNCTION__ << ": " << (enabled ? "enabling" : "disabling") |
| 1537 << " audio stream"; |
| 1538 audio_stream->set_enabled(enabled, currTime); |
| 1539 } |
| 1540 |
| 1541 void FFmpegDemuxer::OnSelectedVideoTrackChanged( |
| 1542 const std::vector<MediaTrack::Id>& track_ids, |
| 1543 base::TimeDelta currTime) { |
| 1544 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1545 bool enabled = false; |
| 1546 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO); |
| 1547 CHECK(video_stream); |
| 1548 if (track_ids.size() > 0) { |
| 1549 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == video_stream); |
| 1550 enabled = true; |
| 1551 } |
| 1552 DVLOG(1) << __FUNCTION__ << ": " << (enabled ? "enabling" : "disabling") |
| 1553 << " video stream"; |
| 1554 video_stream->set_enabled(enabled, currTime); |
| 1555 } |
| 1556 |
1472 void FFmpegDemuxer::ReadFrameIfNeeded() { | 1557 void FFmpegDemuxer::ReadFrameIfNeeded() { |
1473 DCHECK(task_runner_->BelongsToCurrentThread()); | 1558 DCHECK(task_runner_->BelongsToCurrentThread()); |
1474 | 1559 |
1475 // Make sure we have work to do before reading. | 1560 // Make sure we have work to do before reading. |
1476 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || | 1561 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || |
1477 pending_read_ || pending_seek_) { | 1562 pending_read_ || pending_seek_) { |
1478 return; | 1563 return; |
1479 } | 1564 } |
1480 | 1565 |
1481 // Allocate and read an AVPacket from the media. Save |packet_ptr| since | 1566 // Allocate and read an AVPacket from the media. Save |packet_ptr| since |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 // | 1634 // |
1550 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 | 1635 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 |
1551 if (!packet->data) { | 1636 if (!packet->data) { |
1552 ScopedAVPacket new_packet(new AVPacket()); | 1637 ScopedAVPacket new_packet(new AVPacket()); |
1553 av_new_packet(new_packet.get(), 0); | 1638 av_new_packet(new_packet.get(), 0); |
1554 av_packet_copy_props(new_packet.get(), packet.get()); | 1639 av_packet_copy_props(new_packet.get(), packet.get()); |
1555 packet.swap(new_packet); | 1640 packet.swap(new_packet); |
1556 } | 1641 } |
1557 | 1642 |
1558 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; | 1643 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; |
1559 demuxer_stream->EnqueuePacket(std::move(packet)); | 1644 if (demuxer_stream->enabled()) |
| 1645 demuxer_stream->EnqueuePacket(std::move(packet)); |
1560 } | 1646 } |
1561 | 1647 |
1562 // Keep reading until we've reached capacity. | 1648 // Keep reading until we've reached capacity. |
1563 ReadFrameIfNeeded(); | 1649 ReadFrameIfNeeded(); |
1564 } | 1650 } |
1565 | 1651 |
1566 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { | 1652 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { |
1567 DCHECK(task_runner_->BelongsToCurrentThread()); | 1653 DCHECK(task_runner_->BelongsToCurrentThread()); |
1568 StreamVector::iterator iter; | 1654 StreamVector::iterator iter; |
1569 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 1655 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1611 | 1697 |
1612 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1698 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1613 DCHECK(task_runner_->BelongsToCurrentThread()); | 1699 DCHECK(task_runner_->BelongsToCurrentThread()); |
1614 for (auto* stream : streams_) { | 1700 for (auto* stream : streams_) { |
1615 if (stream) | 1701 if (stream) |
1616 stream->SetLiveness(liveness); | 1702 stream->SetLiveness(liveness); |
1617 } | 1703 } |
1618 } | 1704 } |
1619 | 1705 |
1620 } // namespace media | 1706 } // namespace media |
OLD | NEW |