| 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 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |