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

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 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
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/mojo/services/mojo_demuxer_stream_adapter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/mojo/services/mojo_demuxer_stream_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698