| 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; |
| 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 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |