Chromium Code Reviews| 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 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 packet.get()->size - data_offset); | 247 packet.get()->size - data_offset); |
| 248 } | 248 } |
| 249 | 249 |
| 250 int skip_samples_size = 0; | 250 int skip_samples_size = 0; |
| 251 const uint32* skip_samples_ptr = | 251 const uint32* skip_samples_ptr = |
| 252 reinterpret_cast<const uint32*>(av_packet_get_side_data( | 252 reinterpret_cast<const uint32*>(av_packet_get_side_data( |
| 253 packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); | 253 packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); |
| 254 const int kSkipSamplesValidSize = 10; | 254 const int kSkipSamplesValidSize = 10; |
| 255 const int kSkipEndSamplesOffset = 1; | 255 const int kSkipEndSamplesOffset = 1; |
| 256 if (skip_samples_size >= kSkipSamplesValidSize) { | 256 if (skip_samples_size >= kSkipSamplesValidSize) { |
| 257 // Because FFmpeg rolls codec delay and skip samples into one we can only | 257 // Because FFmpeg rolls codec delay and skip samples into one we can only |
|
wolenetz
2015/07/29 21:57:27
Is there any AV_PKT_DATA_SKIP_SAMPLES (front skip)
DaleCurtis
2015/07/30 01:28:14
Added a DCHECK and reflowed the conditional for su
| |
| 258 // allow front discard padding on the first buffer. Otherwise the discard | 258 // allow front discard padding on the first buffer. Otherwise the discard |
| 259 // helper can't figure out which data to discard. See AudioDiscardHelper. | 259 // helper can't figure out which data to discard. See AudioDiscardHelper. |
| 260 int discard_front_samples = base::ByteSwapToLE32(*skip_samples_ptr); | 260 int discard_front_samples = base::ByteSwapToLE32(*skip_samples_ptr); |
| 261 if (last_packet_timestamp_ != kNoTimestamp() && discard_front_samples) { | 261 if (last_packet_timestamp_ != kNoTimestamp() && discard_front_samples) { |
| 262 DLOG(ERROR) << "Skip samples are only allowed for the first packet."; | 262 DLOG(ERROR) << "Skip samples are only allowed for the first packet."; |
| 263 discard_front_samples = 0; | 263 discard_front_samples = 0; |
| 264 } | 264 } |
| 265 | 265 |
| 266 const int discard_end_samples = | 266 const int discard_end_samples = |
| 267 base::ByteSwapToLE32(*(skip_samples_ptr + kSkipEndSamplesOffset)); | 267 base::ByteSwapToLE32(*(skip_samples_ptr + kSkipEndSamplesOffset)); |
| 268 const int samples_per_second = | 268 const int samples_per_second = |
| 269 audio_decoder_config().samples_per_second(); | 269 audio_decoder_config().samples_per_second(); |
| 270 buffer->set_discard_padding(std::make_pair( | 270 buffer->set_discard_padding(std::make_pair( |
| 271 FramesToTimeDelta(discard_front_samples, samples_per_second), | 271 FramesToTimeDelta(discard_front_samples, samples_per_second), |
| 272 FramesToTimeDelta(discard_end_samples, samples_per_second))); | 272 FramesToTimeDelta(discard_end_samples, samples_per_second))); |
| 273 } else if (type() == AUDIO && stream_->codec->delay > 0 && | |
| 274 packet->pts <= stream_->start_time && | |
| 275 stream_->codec->codec_id == AV_CODEC_ID_OPUS) { | |
| 276 // FFmpeg does not encode the opus pre-skip value within the packet side | |
| 277 // data, so when we encounter the first packet in a stream ensure the | |
| 278 // codec delay is applied per spec. | |
| 279 // | |
| 280 // |stream_->codec->delay| has been added to packet->pts automatically by | |
| 281 // ffmpeg, so the delta between the start time and the packet pts is the | |
| 282 // amount of delay remaining to trim. | |
| 283 buffer->set_discard_padding(std::make_pair( | |
| 284 FramesToTimeDelta(std::min(static_cast<int64_t>(packet->duration), | |
| 285 stream_->start_time - packet->pts), | |
| 286 audio_decoder_config().samples_per_second()), | |
| 287 base::TimeDelta())); | |
|
wolenetz
2015/07/29 21:57:27
Could there be a single packet that is both the st
DaleCurtis
2015/07/30 01:28:14
Done.
| |
| 273 } | 288 } |
| 274 | 289 |
| 275 if (decrypt_config) | 290 if (decrypt_config) |
| 276 buffer->set_decrypt_config(decrypt_config.Pass()); | 291 buffer->set_decrypt_config(decrypt_config.Pass()); |
| 277 } | 292 } |
| 278 | 293 |
| 279 if (packet->duration >= 0) { | 294 if (packet->duration >= 0) { |
| 280 buffer->set_duration( | 295 buffer->set_duration( |
| 281 ConvertStreamTimestamp(stream_->time_base, packet->duration)); | 296 ConvertStreamTimestamp(stream_->time_base, packet->duration)); |
| 282 } else { | 297 } else { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 // otherwise we can end up waiting for a pre-seek read to complete even though | 636 // otherwise we can end up waiting for a pre-seek read to complete even though |
| 622 // we know we're going to drop it on the floor. | 637 // we know we're going to drop it on the floor. |
| 623 | 638 |
| 624 // FFmpeg requires seeks to be adjusted according to the lowest starting time. | 639 // FFmpeg requires seeks to be adjusted according to the lowest starting time. |
| 625 // Since EnqueuePacket() rebased negative timestamps by the start time, we | 640 // Since EnqueuePacket() rebased negative timestamps by the start time, we |
| 626 // must correct the shift here. | 641 // must correct the shift here. |
| 627 // | 642 // |
| 628 // Additionally, to workaround limitations in how we expose seekable ranges to | 643 // Additionally, to workaround limitations in how we expose seekable ranges to |
| 629 // Blink (http://crbug.com/137275), we also want to clamp seeks before the | 644 // Blink (http://crbug.com/137275), we also want to clamp seeks before the |
| 630 // start time to the start time. | 645 // start time to the start time. |
| 631 const base::TimeDelta seek_time = | 646 base::TimeDelta seek_time = start_time_ < base::TimeDelta() |
| 632 start_time_ < base::TimeDelta() ? time + start_time_ | 647 ? time + start_time_ |
| 633 : time < start_time_ ? start_time_ : time; | 648 : time < start_time_ ? start_time_ : time; |
| 649 | |
| 650 // When seeking in an opus stream we need to ensure we deliver enough data to | |
| 651 // satisfy the seek preroll; otherwise the audio at the actual seek time will | |
| 652 // not be entirely accurate. | |
| 653 FFmpegDemuxerStream* audio_stream = GetFFmpegStream(DemuxerStream::AUDIO); | |
| 654 if (audio_stream) { | |
| 655 const AudioDecoderConfig& config = audio_stream->audio_decoder_config(); | |
| 656 if (config.codec() == kCodecOpus) | |
| 657 seek_time = std::max(start_time_, seek_time - config.seek_preroll()); | |
| 658 } | |
| 634 | 659 |
| 635 // Choose the seeking stream based on whether it contains the seek time, if no | 660 // Choose the seeking stream based on whether it contains the seek time, if no |
| 636 // match can be found prefer the preferred stream. | 661 // match can be found prefer the preferred stream. |
| 637 // | 662 // |
| 638 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a | 663 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a |
| 639 // given container will demux all packets after the seek point. Instead it | 664 // given container will demux all packets after the seek point. Instead it |
| 640 // only guarantees that all packets after the file position of the seek will | 665 // only guarantees that all packets after the file position of the seek will |
| 641 // be demuxed. It's an open question whether FFmpeg should fix this: | 666 // be demuxed. It's an open question whether FFmpeg should fix this: |
| 642 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html | 667 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html |
| 643 // Tracked by http://crbug.com/387996. | 668 // Tracked by http://crbug.com/387996. |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1197 // when av_read_frame() returns success code. See bug comment for ideas: | 1222 // when av_read_frame() returns success code. See bug comment for ideas: |
| 1198 // | 1223 // |
| 1199 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 | 1224 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 |
| 1200 if (!packet->data) { | 1225 if (!packet->data) { |
| 1201 ScopedAVPacket new_packet(new AVPacket()); | 1226 ScopedAVPacket new_packet(new AVPacket()); |
| 1202 av_new_packet(new_packet.get(), 0); | 1227 av_new_packet(new_packet.get(), 0); |
| 1203 av_packet_copy_props(new_packet.get(), packet.get()); | 1228 av_packet_copy_props(new_packet.get(), packet.get()); |
| 1204 packet.swap(new_packet); | 1229 packet.swap(new_packet); |
| 1205 } | 1230 } |
| 1206 | 1231 |
| 1207 // Special case for opus in ogg. FFmpeg is pre-trimming the codec delay | |
| 1208 // from the packet timestamp. Chrome expects to handle this itself inside | |
| 1209 // the decoder, so shift timestamps by the delay in this case. | |
| 1210 // TODO(dalecurtis): Try to get fixed upstream. See http://crbug.com/328207 | |
| 1211 if (strcmp(glue_->format_context()->iformat->name, "ogg") == 0) { | |
| 1212 const AVCodecContext* codec_context = | |
| 1213 glue_->format_context()->streams[packet->stream_index]->codec; | |
| 1214 if (codec_context->codec_id == AV_CODEC_ID_OPUS && | |
| 1215 codec_context->delay > 0) { | |
| 1216 packet->pts += codec_context->delay; | |
| 1217 } | |
| 1218 } | |
| 1219 | |
| 1220 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; | 1232 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; |
| 1221 demuxer_stream->EnqueuePacket(packet.Pass()); | 1233 demuxer_stream->EnqueuePacket(packet.Pass()); |
| 1222 } | 1234 } |
| 1223 | 1235 |
| 1224 // Keep reading until we've reached capacity. | 1236 // Keep reading until we've reached capacity. |
| 1225 ReadFrameIfNeeded(); | 1237 ReadFrameIfNeeded(); |
| 1226 } | 1238 } |
| 1227 | 1239 |
| 1228 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { | 1240 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { |
| 1229 DCHECK(task_runner_->BelongsToCurrentThread()); | 1241 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1303 | 1315 |
| 1304 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1316 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
| 1305 DCHECK(task_runner_->BelongsToCurrentThread()); | 1317 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1306 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. | 1318 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. |
| 1307 if (stream) | 1319 if (stream) |
| 1308 stream->SetLiveness(liveness); | 1320 stream->SetLiveness(liveness); |
| 1309 } | 1321 } |
| 1310 } | 1322 } |
| 1311 | 1323 |
| 1312 } // namespace media | 1324 } // namespace media |
| OLD | NEW |