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

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: Check track ids via track_id_to_demux_stream_map_ Created 4 years, 6 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;
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 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 packet_buffer = packet_buffer->next; 1167 packet_buffer = packet_buffer->next;
1125 } 1168 }
1126 } 1169 }
1127 1170
1128 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks()); 1171 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks());
1129 AVStream* audio_stream = NULL; 1172 AVStream* audio_stream = NULL;
1130 AudioDecoderConfig audio_config; 1173 AudioDecoderConfig audio_config;
1131 AVStream* video_stream = NULL; 1174 AVStream* video_stream = NULL;
1132 VideoDecoderConfig video_config; 1175 VideoDecoderConfig video_config;
1133 1176
1177 DCHECK(track_id_to_demux_stream_map_.empty());
1178
1134 // If available, |start_time_| will be set to the lowest stream start time. 1179 // If available, |start_time_| will be set to the lowest stream start time.
1135 start_time_ = kInfiniteDuration(); 1180 start_time_ = kInfiniteDuration();
1136 1181
1137 base::TimeDelta max_duration; 1182 base::TimeDelta max_duration;
1138 int detected_audio_track_count = 0; 1183 int detected_audio_track_count = 0;
1139 int detected_video_track_count = 0; 1184 int detected_video_track_count = 0;
1140 int detected_text_track_count = 0; 1185 int detected_text_track_count = 0;
1141 for (size_t i = 0; i < format_context->nb_streams; ++i) { 1186 for (size_t i = 0; i < format_context->nb_streams; ++i) {
1142 AVStream* stream = format_context->streams[i]; 1187 AVStream* stream = format_context->streams[i];
1143 const AVCodecContext* codec_context = stream->codec; 1188 const AVCodecContext* codec_context = stream->codec;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 MediaTrack* media_track = nullptr; 1284 MediaTrack* media_track = nullptr;
1240 if (codec_type == AVMEDIA_TYPE_AUDIO) { 1285 if (codec_type == AVMEDIA_TYPE_AUDIO) {
1241 CHECK(!audio_stream); 1286 CHECK(!audio_stream);
1242 audio_stream = stream; 1287 audio_stream = stream;
1243 audio_config = streams_[i]->audio_decoder_config(); 1288 audio_config = streams_[i]->audio_decoder_config();
1244 RecordAudioCodecStats(audio_config); 1289 RecordAudioCodecStats(audio_config);
1245 1290
1246 media_track = media_tracks->AddAudioTrack(audio_config, track_id, "main", 1291 media_track = media_tracks->AddAudioTrack(audio_config, track_id, "main",
1247 track_label, track_language); 1292 track_label, track_language);
1248 media_track->set_id(base::UintToString(track_id)); 1293 media_track->set_id(base::UintToString(track_id));
1294 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) ==
1295 track_id_to_demux_stream_map_.end());
1296 track_id_to_demux_stream_map_[media_track->id()] = streams_[i];
1249 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { 1297 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
1250 CHECK(!video_stream); 1298 CHECK(!video_stream);
1251 video_stream = stream; 1299 video_stream = stream;
1252 video_config = streams_[i]->video_decoder_config(); 1300 video_config = streams_[i]->video_decoder_config();
1253 1301
1254 RecordVideoCodecStats(video_config, stream->codec->color_range, 1302 RecordVideoCodecStats(video_config, stream->codec->color_range,
1255 media_log_.get()); 1303 media_log_.get());
1256 1304
1257 media_track = media_tracks->AddVideoTrack(video_config, track_id, "main", 1305 media_track = media_tracks->AddVideoTrack(video_config, track_id, "main",
1258 track_label, track_language); 1306 track_label, track_language);
1259 media_track->set_id(base::UintToString(track_id)); 1307 media_track->set_id(base::UintToString(track_id));
1308 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) ==
1309 track_id_to_demux_stream_map_.end());
1310 track_id_to_demux_stream_map_[media_track->id()] = streams_[i];
1260 } 1311 }
1261 1312
1262 max_duration = std::max(max_duration, streams_[i]->duration()); 1313 max_duration = std::max(max_duration, streams_[i]->duration());
1263 1314
1264 const base::TimeDelta start_time = 1315 const base::TimeDelta start_time =
1265 ExtractStartTime(stream, start_time_estimates[i]); 1316 ExtractStartTime(stream, start_time_estimates[i]);
1266 const bool has_start_time = start_time != kNoTimestamp(); 1317 const bool has_start_time = start_time != kNoTimestamp();
1267 1318
1268 // Always prefer the video stream for seeking. If none exists, we'll swap 1319 // Always prefer the video stream for seeking. If none exists, we'll swap
1269 // the fallback stream with the preferred stream below. 1320 // the fallback stream with the preferred stream below.
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 (*iter)->FlushBuffers(); 1513 (*iter)->FlushBuffers();
1463 } 1514 }
1464 1515
1465 // Resume reading until capacity. 1516 // Resume reading until capacity.
1466 ReadFrameIfNeeded(); 1517 ReadFrameIfNeeded();
1467 1518
1468 // Notify we're finished seeking. 1519 // Notify we're finished seeking.
1469 cb.Run(PIPELINE_OK); 1520 cb.Run(PIPELINE_OK);
1470 } 1521 }
1471 1522
1523 void FFmpegDemuxer::OnEnabledAudioTracksChanged(
1524 const std::vector<MediaTrack::Id>& track_ids,
1525 base::TimeDelta currTime) {
1526 DCHECK(task_runner_->BelongsToCurrentThread());
1527 bool enabled = false;
1528 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1529 CHECK(audio_stream);
1530 if (track_ids.size() > 0) {
1531 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == audio_stream);
1532 enabled = true;
1533 }
1534 audio_stream->set_enabled(enabled, currTime);
1535 }
1536
1537 void FFmpegDemuxer::OnSelectedVideoTrackChanged(
1538 const std::vector<MediaTrack::Id>& track_ids,
1539 base::TimeDelta currTime) {
1540 DCHECK(task_runner_->BelongsToCurrentThread());
1541 bool enabled = false;
1542 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1543 CHECK(video_stream);
1544 if (track_ids.size() > 0) {
1545 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == video_stream);
1546 enabled = true;
1547 }
1548 video_stream->set_enabled(enabled, currTime);
1549 }
1550
1472 void FFmpegDemuxer::ReadFrameIfNeeded() { 1551 void FFmpegDemuxer::ReadFrameIfNeeded() {
1473 DCHECK(task_runner_->BelongsToCurrentThread()); 1552 DCHECK(task_runner_->BelongsToCurrentThread());
1474 1553
1475 // Make sure we have work to do before reading. 1554 // Make sure we have work to do before reading.
1476 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || 1555 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() ||
1477 pending_read_ || pending_seek_) { 1556 pending_read_ || pending_seek_) {
1478 return; 1557 return;
1479 } 1558 }
1480 1559
1481 // Allocate and read an AVPacket from the media. Save |packet_ptr| since 1560 // 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 // 1628 //
1550 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 1629 // https://code.google.com/p/chromium/issues/detail?id=169133#c10
1551 if (!packet->data) { 1630 if (!packet->data) {
1552 ScopedAVPacket new_packet(new AVPacket()); 1631 ScopedAVPacket new_packet(new AVPacket());
1553 av_new_packet(new_packet.get(), 0); 1632 av_new_packet(new_packet.get(), 0);
1554 av_packet_copy_props(new_packet.get(), packet.get()); 1633 av_packet_copy_props(new_packet.get(), packet.get());
1555 packet.swap(new_packet); 1634 packet.swap(new_packet);
1556 } 1635 }
1557 1636
1558 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; 1637 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index];
1559 demuxer_stream->EnqueuePacket(std::move(packet)); 1638 if (demuxer_stream->enabled())
1639 demuxer_stream->EnqueuePacket(std::move(packet));
1560 } 1640 }
1561 1641
1562 // Keep reading until we've reached capacity. 1642 // Keep reading until we've reached capacity.
1563 ReadFrameIfNeeded(); 1643 ReadFrameIfNeeded();
1564 } 1644 }
1565 1645
1566 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { 1646 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() {
1567 DCHECK(task_runner_->BelongsToCurrentThread()); 1647 DCHECK(task_runner_->BelongsToCurrentThread());
1568 StreamVector::iterator iter; 1648 StreamVector::iterator iter;
1569 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 1649 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 1691
1612 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1692 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1613 DCHECK(task_runner_->BelongsToCurrentThread()); 1693 DCHECK(task_runner_->BelongsToCurrentThread());
1614 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. 1694 for (const auto& stream : streams_) { // |stream| is a ref to a pointer.
1615 if (stream) 1695 if (stream)
1616 stream->SetLiveness(liveness); 1696 stream->SetLiveness(liveness);
1617 } 1697 }
1618 } 1698 }
1619 1699
1620 } // namespace media 1700 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698