| 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 <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 !video_config->IsValidConfig()) { | 240 !video_config->IsValidConfig()) { |
| 241 MEDIA_LOG(ERROR, media_log) | 241 MEDIA_LOG(ERROR, media_log) |
| 242 << "FFmpegDemuxer: failed creating video stream"; | 242 << "FFmpegDemuxer: failed creating video stream"; |
| 243 return nullptr; | 243 return nullptr; |
| 244 } | 244 } |
| 245 | 245 |
| 246 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config " | 246 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config " |
| 247 << video_config->AsHumanReadableString(); | 247 << video_config->AsHumanReadableString(); |
| 248 } | 248 } |
| 249 | 249 |
| 250 return base::WrapUnique(new FFmpegDemuxerStream( | 250 return base::WrapUnique( |
| 251 demuxer, stream, std::move(audio_config), std::move(video_config))); | 251 new FFmpegDemuxerStream(demuxer, stream, std::move(audio_config), |
| 252 std::move(video_config), media_log)); |
| 252 } | 253 } |
| 253 | 254 |
| 254 static void UnmarkEndOfStreamAndClearError(AVFormatContext* format_context) { | 255 static void UnmarkEndOfStreamAndClearError(AVFormatContext* format_context) { |
| 255 format_context->pb->eof_reached = 0; | 256 format_context->pb->eof_reached = 0; |
| 256 format_context->pb->error = 0; | 257 format_context->pb->error = 0; |
| 257 } | 258 } |
| 258 | 259 |
| 259 // | 260 // |
| 260 // FFmpegDemuxerStream | 261 // FFmpegDemuxerStream |
| 261 // | 262 // |
| 262 FFmpegDemuxerStream::FFmpegDemuxerStream( | 263 FFmpegDemuxerStream::FFmpegDemuxerStream( |
| 263 FFmpegDemuxer* demuxer, | 264 FFmpegDemuxer* demuxer, |
| 264 AVStream* stream, | 265 AVStream* stream, |
| 265 std::unique_ptr<AudioDecoderConfig> audio_config, | 266 std::unique_ptr<AudioDecoderConfig> audio_config, |
| 266 std::unique_ptr<VideoDecoderConfig> video_config) | 267 std::unique_ptr<VideoDecoderConfig> video_config, |
| 268 scoped_refptr<MediaLog> media_log) |
| 267 : demuxer_(demuxer), | 269 : demuxer_(demuxer), |
| 268 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 270 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 269 stream_(stream), | 271 stream_(stream), |
| 270 start_time_(kNoTimestamp), | 272 start_time_(kNoTimestamp), |
| 271 audio_config_(audio_config.release()), | 273 audio_config_(audio_config.release()), |
| 272 video_config_(video_config.release()), | 274 video_config_(video_config.release()), |
| 275 media_log_(std::move(media_log)), |
| 273 type_(UNKNOWN), | 276 type_(UNKNOWN), |
| 274 liveness_(LIVENESS_UNKNOWN), | 277 liveness_(LIVENESS_UNKNOWN), |
| 275 end_of_stream_(false), | 278 end_of_stream_(false), |
| 276 last_packet_timestamp_(kNoTimestamp), | 279 last_packet_timestamp_(kNoTimestamp), |
| 277 last_packet_duration_(kNoTimestamp), | 280 last_packet_duration_(kNoTimestamp), |
| 278 video_rotation_(VIDEO_ROTATION_0), | 281 video_rotation_(VIDEO_ROTATION_0), |
| 279 is_enabled_(true), | 282 is_enabled_(true), |
| 280 waiting_for_keyframe_(false), | 283 waiting_for_keyframe_(false), |
| 281 aborted_(false), | 284 aborted_(false), |
| 282 fixup_negative_timestamps_(false) { | 285 fixup_negative_timestamps_(false) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 DVLOG(1) << "FFmpeg returned a buffer with a negative duration! " | 475 DVLOG(1) << "FFmpeg returned a buffer with a negative duration! " |
| 473 << packet->duration; | 476 << packet->duration; |
| 474 buffer->set_duration(kNoTimestamp); | 477 buffer->set_duration(kNoTimestamp); |
| 475 } | 478 } |
| 476 | 479 |
| 477 // Note: If pts is AV_NOPTS_VALUE, stream_timestamp will be kNoTimestamp. | 480 // Note: If pts is AV_NOPTS_VALUE, stream_timestamp will be kNoTimestamp. |
| 478 const base::TimeDelta stream_timestamp = | 481 const base::TimeDelta stream_timestamp = |
| 479 ConvertStreamTimestamp(stream_->time_base, packet->pts); | 482 ConvertStreamTimestamp(stream_->time_base, packet->pts); |
| 480 | 483 |
| 481 if (stream_timestamp == kNoTimestamp) { | 484 if (stream_timestamp == kNoTimestamp) { |
| 485 MEDIA_LOG(ERROR, media_log_) << "FFmpegDemuxer: PTS is not defined"; |
| 482 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE); | 486 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE); |
| 483 return; | 487 return; |
| 484 } | 488 } |
| 485 | 489 |
| 486 const bool is_audio = type() == AUDIO; | 490 const bool is_audio = type() == AUDIO; |
| 487 | 491 |
| 488 // If this file has negative timestamps don't rebase any other stream types | 492 // If this file has negative timestamps don't rebase any other stream types |
| 489 // against the negative starting time. | 493 // against the negative starting time. |
| 490 base::TimeDelta start_time = demuxer_->start_time(); | 494 base::TimeDelta start_time = demuxer_->start_time(); |
| 491 if (fixup_negative_timestamps_ && !is_audio && | 495 if (fixup_negative_timestamps_ && !is_audio && |
| 492 start_time < base::TimeDelta()) { | 496 start_time < base::TimeDelta()) { |
| 493 start_time = base::TimeDelta(); | 497 start_time = base::TimeDelta(); |
| 494 } | 498 } |
| 495 | 499 |
| 496 // Don't rebase timestamps for positive start times, the HTML Media Spec | 500 // Don't rebase timestamps for positive start times, the HTML Media Spec |
| 497 // details this in section "4.8.10.6 Offsets into the media resource." We | 501 // details this in section "4.8.10.6 Offsets into the media resource." We |
| 498 // will still need to rebase timestamps before seeking with FFmpeg though. | 502 // will still need to rebase timestamps before seeking with FFmpeg though. |
| 499 if (start_time > base::TimeDelta()) | 503 if (start_time > base::TimeDelta()) |
| 500 start_time = base::TimeDelta(); | 504 start_time = base::TimeDelta(); |
| 501 | 505 |
| 502 buffer->set_timestamp(stream_timestamp - start_time); | 506 buffer->set_timestamp(stream_timestamp - start_time); |
| 503 | 507 |
| 504 // Only allow negative timestamps past if we know they'll be fixed up by the | 508 // Only allow negative timestamps past if we know they'll be fixed up by the |
| 505 // code paths below; otherwise they should be treated as a parse error. | 509 // code paths below; otherwise they should be treated as a parse error. |
| 506 if (!fixup_negative_timestamps_ && buffer->timestamp() < base::TimeDelta()) { | 510 if (!fixup_negative_timestamps_ && buffer->timestamp() < base::TimeDelta()) { |
| 511 MEDIA_LOG(DEBUG, media_log_) |
| 512 << "FFmpegDemuxer: unfixable negative timestamp"; |
| 507 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE); | 513 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE); |
| 508 return; | 514 return; |
| 509 } | 515 } |
| 510 | 516 |
| 511 // If enabled, and no codec delay is present, mark audio packets with negative | 517 // If enabled, and no codec delay is present, mark audio packets with negative |
| 512 // timestamps for post-decode discard. If codec delay is present, discard is | 518 // timestamps for post-decode discard. If codec delay is present, discard is |
| 513 // handled by the decoder using that value. | 519 // handled by the decoder using that value. |
| 514 if (fixup_negative_timestamps_ && is_audio && | 520 if (fixup_negative_timestamps_ && is_audio && |
| 515 stream_timestamp < base::TimeDelta() && | 521 stream_timestamp < base::TimeDelta() && |
| 516 buffer->duration() != kNoTimestamp && | 522 buffer->duration() != kNoTimestamp && |
| (...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 DCHECK(pending_read_); | 1725 DCHECK(pending_read_); |
| 1720 pending_read_ = false; | 1726 pending_read_ = false; |
| 1721 | 1727 |
| 1722 if (stopped_ || !pending_seek_cb_.is_null()) | 1728 if (stopped_ || !pending_seek_cb_.is_null()) |
| 1723 return; | 1729 return; |
| 1724 | 1730 |
| 1725 // Consider the stream as ended if: | 1731 // Consider the stream as ended if: |
| 1726 // - either underlying ffmpeg returned an error | 1732 // - either underlying ffmpeg returned an error |
| 1727 // - or FFMpegDemuxer reached the maximum allowed memory usage. | 1733 // - or FFMpegDemuxer reached the maximum allowed memory usage. |
| 1728 if (result < 0 || IsMaxMemoryUsageReached()) { | 1734 if (result < 0 || IsMaxMemoryUsageReached()) { |
| 1729 DVLOG(1) << __func__ << " result=" << result | 1735 if (result < 0) { |
| 1730 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); | 1736 MEDIA_LOG(DEBUG, media_log_) |
| 1737 << GetDisplayName() |
| 1738 << ": av_read_frame(): " << AVErrorToString(result); |
| 1739 } else { |
| 1740 MEDIA_LOG(DEBUG, media_log_) |
| 1741 << GetDisplayName() << ": memory limit exceeded"; |
| 1742 } |
| 1743 |
| 1731 // Update the duration based on the highest elapsed time across all streams. | 1744 // Update the duration based on the highest elapsed time across all streams. |
| 1732 base::TimeDelta max_duration; | 1745 base::TimeDelta max_duration; |
| 1733 for (const auto& stream : streams_) { | 1746 for (const auto& stream : streams_) { |
| 1734 if (!stream) | 1747 if (!stream) |
| 1735 continue; | 1748 continue; |
| 1736 | 1749 |
| 1737 base::TimeDelta duration = stream->duration(); | 1750 base::TimeDelta duration = stream->duration(); |
| 1738 if (duration != kNoTimestamp && duration > max_duration) | 1751 if (duration != kNoTimestamp && duration > max_duration) |
| 1739 max_duration = duration; | 1752 max_duration = duration; |
| 1740 } | 1753 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 | 1847 |
| 1835 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1848 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
| 1836 DCHECK(task_runner_->BelongsToCurrentThread()); | 1849 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1837 for (const auto& stream : streams_) { | 1850 for (const auto& stream : streams_) { |
| 1838 if (stream) | 1851 if (stream) |
| 1839 stream->SetLiveness(liveness); | 1852 stream->SetLiveness(liveness); |
| 1840 } | 1853 } |
| 1841 } | 1854 } |
| 1842 | 1855 |
| 1843 } // namespace media | 1856 } // namespace media |
| OLD | NEW |