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 |