Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(830)

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 1935873002: Implement disabling and enabling media tracks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@track-control2
Patch Set: rebase + buildfix Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698