Chromium Code Reviews| 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 return; | |
|
chcunningham
2016/06/24 23:32:55
This would be good to DVLOG - "Dropping non-key fr
servolk
2016/06/25 00:36:33
Done.
| |
| 368 } | |
| 369 | |
| 361 #if defined(USE_PROPRIETARY_CODECS) | 370 #if defined(USE_PROPRIETARY_CODECS) |
| 362 // Convert the packet if there is a bitstream filter. | 371 // Convert the packet if there is a bitstream filter. |
| 363 if (packet->data && bitstream_converter_ && | 372 if (packet->data && bitstream_converter_ && |
| 364 !bitstream_converter_->ConvertPacket(packet.get())) { | 373 !bitstream_converter_->ConvertPacket(packet.get())) { |
| 365 LOG(ERROR) << "Format conversion failed."; | 374 LOG(ERROR) << "Format conversion failed."; |
| 366 } | 375 } |
| 367 #endif | 376 #endif |
| 368 | 377 |
| 369 // Get side data if any. For now, the only type of side_data is VP8 Alpha. We | 378 // 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 | 379 // 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. | 620 // Don't accept any additional reads if we've been told to stop. |
| 612 // The |demuxer_| may have been destroyed in the pipeline thread. | 621 // The |demuxer_| may have been destroyed in the pipeline thread. |
| 613 // | 622 // |
| 614 // TODO(scherkus): it would be cleaner to reply with an error message. | 623 // TODO(scherkus): it would be cleaner to reply with an error message. |
| 615 if (!demuxer_) { | 624 if (!demuxer_) { |
| 616 base::ResetAndReturn(&read_cb_).Run( | 625 base::ResetAndReturn(&read_cb_).Run( |
| 617 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); | 626 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); |
| 618 return; | 627 return; |
| 619 } | 628 } |
| 620 | 629 |
| 630 if (!is_enabled_) { | |
| 631 DVLOG(1) << "Read from disabled stream, returning EOS"; | |
| 632 base::ResetAndReturn(&read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer()); | |
| 633 return; | |
| 634 } | |
| 635 | |
| 621 SatisfyPendingRead(); | 636 SatisfyPendingRead(); |
| 622 } | 637 } |
| 623 | 638 |
| 624 void FFmpegDemuxerStream::EnableBitstreamConverter() { | 639 void FFmpegDemuxerStream::EnableBitstreamConverter() { |
| 625 DCHECK(task_runner_->BelongsToCurrentThread()); | 640 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 626 | 641 |
| 627 #if defined(USE_PROPRIETARY_CODECS) | 642 #if defined(USE_PROPRIETARY_CODECS) |
| 628 InitBitstreamConverter(); | 643 InitBitstreamConverter(); |
| 629 #else | 644 #else |
| 630 NOTREACHED() << "Proprietary codecs not enabled."; | 645 NOTREACHED() << "Proprietary codecs not enabled."; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 DCHECK(task_runner_->BelongsToCurrentThread()); | 689 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 675 DCHECK_EQ(type_, VIDEO); | 690 DCHECK_EQ(type_, VIDEO); |
| 676 DCHECK(video_config_.get()); | 691 DCHECK(video_config_.get()); |
| 677 return *video_config_; | 692 return *video_config_; |
| 678 } | 693 } |
| 679 | 694 |
| 680 VideoRotation FFmpegDemuxerStream::video_rotation() { | 695 VideoRotation FFmpegDemuxerStream::video_rotation() { |
| 681 return video_rotation_; | 696 return video_rotation_; |
| 682 } | 697 } |
| 683 | 698 |
| 699 bool FFmpegDemuxerStream::enabled() const { | |
| 700 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 701 return is_enabled_; | |
| 702 } | |
| 703 | |
| 704 void FFmpegDemuxerStream::set_enabled(bool enabled, base::TimeDelta timestamp) { | |
| 705 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 706 if (enabled == is_enabled_) | |
| 707 return; | |
| 708 | |
| 709 is_enabled_ = enabled; | |
| 710 if (is_enabled_) { | |
| 711 waiting_for_keyframe_ = true; | |
| 712 if (!stream_restarted_cb_.is_null()) | |
| 713 stream_restarted_cb_.Run(this, timestamp); | |
| 714 } | |
| 715 if (!is_enabled_ && !read_cb_.is_null()) { | |
| 716 DVLOG(1) << "Read from disabled stream, returning EOS"; | |
| 717 base::ResetAndReturn(&read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer()); | |
| 718 return; | |
| 719 } | |
| 720 } | |
| 721 | |
| 722 void FFmpegDemuxerStream::SetStreamRestartedCB(const StreamRestartedCB& cb) { | |
| 723 DCHECK(!cb.is_null()); | |
| 724 stream_restarted_cb_ = cb; | |
| 725 } | |
| 726 | |
| 684 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { | 727 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { |
| 685 DCHECK(task_runner_->BelongsToCurrentThread()); | 728 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 686 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); | 729 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); |
| 687 liveness_ = liveness; | 730 liveness_ = liveness; |
| 688 } | 731 } |
| 689 | 732 |
| 690 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { | 733 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { |
| 691 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); | 734 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); |
| 692 } | 735 } |
| 693 | 736 |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1462 (*iter)->FlushBuffers(); | 1505 (*iter)->FlushBuffers(); |
| 1463 } | 1506 } |
| 1464 | 1507 |
| 1465 // Resume reading until capacity. | 1508 // Resume reading until capacity. |
| 1466 ReadFrameIfNeeded(); | 1509 ReadFrameIfNeeded(); |
| 1467 | 1510 |
| 1468 // Notify we're finished seeking. | 1511 // Notify we're finished seeking. |
| 1469 cb.Run(PIPELINE_OK); | 1512 cb.Run(PIPELINE_OK); |
| 1470 } | 1513 } |
| 1471 | 1514 |
| 1515 void FFmpegDemuxer::OnEnabledAudioTracksChanged( | |
| 1516 const std::vector<MediaTrack::Id>& track_ids, | |
| 1517 base::TimeDelta currTime) { | |
| 1518 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 1519 bool enabled = false; | |
| 1520 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); | |
| 1521 CHECK(audio_stream); | |
| 1522 if (track_ids.size() > 0) { | |
| 1523 // DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == audio_stream); | |
| 1524 enabled = true; | |
| 1525 } | |
| 1526 audio_stream->set_enabled(enabled, currTime); | |
| 1527 } | |
| 1528 | |
| 1529 void FFmpegDemuxer::OnSelectedVideoTrackChanged( | |
| 1530 const std::vector<MediaTrack::Id>& track_ids, | |
| 1531 base::TimeDelta currTime) { | |
| 1532 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 1533 bool enabled = false; | |
| 1534 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO); | |
| 1535 CHECK(video_stream); | |
| 1536 if (track_ids.size() > 0) { | |
| 1537 // DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == video_stream); | |
| 1538 enabled = true; | |
| 1539 } | |
| 1540 video_stream->set_enabled(enabled, currTime); | |
| 1541 } | |
| 1542 | |
| 1472 void FFmpegDemuxer::ReadFrameIfNeeded() { | 1543 void FFmpegDemuxer::ReadFrameIfNeeded() { |
| 1473 DCHECK(task_runner_->BelongsToCurrentThread()); | 1544 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1474 | 1545 |
| 1475 // Make sure we have work to do before reading. | 1546 // Make sure we have work to do before reading. |
| 1476 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || | 1547 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || |
| 1477 pending_read_ || pending_seek_) { | 1548 pending_read_ || pending_seek_) { |
| 1478 return; | 1549 return; |
| 1479 } | 1550 } |
| 1480 | 1551 |
| 1481 // Allocate and read an AVPacket from the media. Save |packet_ptr| since | 1552 // 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 // | 1620 // |
| 1550 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 | 1621 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 |
| 1551 if (!packet->data) { | 1622 if (!packet->data) { |
| 1552 ScopedAVPacket new_packet(new AVPacket()); | 1623 ScopedAVPacket new_packet(new AVPacket()); |
| 1553 av_new_packet(new_packet.get(), 0); | 1624 av_new_packet(new_packet.get(), 0); |
| 1554 av_packet_copy_props(new_packet.get(), packet.get()); | 1625 av_packet_copy_props(new_packet.get(), packet.get()); |
| 1555 packet.swap(new_packet); | 1626 packet.swap(new_packet); |
| 1556 } | 1627 } |
| 1557 | 1628 |
| 1558 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; | 1629 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; |
| 1559 demuxer_stream->EnqueuePacket(std::move(packet)); | 1630 if (demuxer_stream->enabled()) |
| 1631 demuxer_stream->EnqueuePacket(std::move(packet)); | |
| 1560 } | 1632 } |
| 1561 | 1633 |
| 1562 // Keep reading until we've reached capacity. | 1634 // Keep reading until we've reached capacity. |
| 1563 ReadFrameIfNeeded(); | 1635 ReadFrameIfNeeded(); |
| 1564 } | 1636 } |
| 1565 | 1637 |
| 1566 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { | 1638 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { |
| 1567 DCHECK(task_runner_->BelongsToCurrentThread()); | 1639 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1568 StreamVector::iterator iter; | 1640 StreamVector::iterator iter; |
| 1569 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 1641 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1611 | 1683 |
| 1612 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1684 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
| 1613 DCHECK(task_runner_->BelongsToCurrentThread()); | 1685 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1614 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. | 1686 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. |
| 1615 if (stream) | 1687 if (stream) |
| 1616 stream->SetLiveness(liveness); | 1688 stream->SetLiveness(liveness); |
| 1617 } | 1689 } |
| 1618 } | 1690 } |
| 1619 | 1691 |
| 1620 } // namespace media | 1692 } // namespace media |
| OLD | NEW |