| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/cast/test/fake_media_source.h" | 5 #include "media/cast/test/fake_media_source.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/scoped_file.h" | 10 #include "base/files/scoped_file.h" |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 // AVFormatContext is owned by the glue. | 131 // AVFormatContext is owned by the glue. |
| 132 av_format_context_ = glue_->format_context(); | 132 av_format_context_ = glue_->format_context(); |
| 133 if (avformat_find_stream_info(av_format_context_, NULL) < 0) { | 133 if (avformat_find_stream_info(av_format_context_, NULL) < 0) { |
| 134 LOG(ERROR) << "Cannot find stream information."; | 134 LOG(ERROR) << "Cannot find stream information."; |
| 135 return; | 135 return; |
| 136 } | 136 } |
| 137 | 137 |
| 138 // Prepare FFmpeg decoders. | 138 // Prepare FFmpeg decoders. |
| 139 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { | 139 for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) { |
| 140 AVStream* av_stream = av_format_context_->streams[i]; | 140 AVStream* av_stream = av_format_context_->streams[i]; |
| 141 AVCodecContext* av_codec_context = av_stream->codec; | 141 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> av_codec_context( |
| 142 AVStreamToAVCodecContext(av_stream)); |
| 143 if (!av_codec_context) { |
| 144 LOG(ERROR) << "Cannot get a codec context for the codec: " |
| 145 << av_stream->codecpar->codec_id; |
| 146 continue; |
| 147 } |
| 148 |
| 142 AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id); | 149 AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id); |
| 143 | 150 |
| 144 if (!av_codec) { | 151 if (!av_codec) { |
| 145 LOG(ERROR) << "Cannot find decoder for the codec: " | 152 LOG(ERROR) << "Cannot find decoder for the codec: " |
| 146 << av_codec_context->codec_id; | 153 << av_codec_context->codec_id; |
| 147 continue; | 154 continue; |
| 148 } | 155 } |
| 149 | 156 |
| 150 // Number of threads for decoding. | 157 // Number of threads for decoding. |
| 151 av_codec_context->thread_count = 2; | 158 av_codec_context->thread_count = 2; |
| 152 av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; | 159 av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| 153 av_codec_context->request_sample_fmt = AV_SAMPLE_FMT_S16; | 160 av_codec_context->request_sample_fmt = AV_SAMPLE_FMT_S16; |
| 154 | 161 |
| 155 if (avcodec_open2(av_codec_context, av_codec, NULL) < 0) { | 162 if (avcodec_open2(av_codec_context.get(), av_codec, nullptr) < 0) { |
| 156 LOG(ERROR) << "Cannot open AVCodecContext for the codec: " | 163 LOG(ERROR) << "Cannot open AVCodecContext for the codec: " |
| 157 << av_codec_context->codec_id; | 164 << av_codec_context->codec_id; |
| 158 return; | 165 return; |
| 159 } | 166 } |
| 160 | 167 |
| 161 if (av_codec->type == AVMEDIA_TYPE_AUDIO) { | 168 if (av_codec->type == AVMEDIA_TYPE_AUDIO) { |
| 162 if (av_codec_context->sample_fmt == AV_SAMPLE_FMT_S16P) { | 169 if (av_codec_context->sample_fmt == AV_SAMPLE_FMT_S16P) { |
| 163 LOG(ERROR) << "Audio format not supported."; | 170 LOG(ERROR) << "Audio format not supported."; |
| 164 continue; | 171 continue; |
| 165 } | 172 } |
| 166 ChannelLayout layout = ChannelLayoutToChromeChannelLayout( | 173 ChannelLayout layout = ChannelLayoutToChromeChannelLayout( |
| 167 av_codec_context->channel_layout, | 174 av_codec_context->channel_layout, |
| 168 av_codec_context->channels); | 175 av_codec_context->channels); |
| 169 if (layout == CHANNEL_LAYOUT_UNSUPPORTED) { | 176 if (layout == CHANNEL_LAYOUT_UNSUPPORTED) { |
| 170 LOG(ERROR) << "Unsupported audio channels layout."; | 177 LOG(ERROR) << "Unsupported audio channels layout."; |
| 171 continue; | 178 continue; |
| 172 } | 179 } |
| 173 if (audio_stream_index_ != -1) { | 180 if (audio_stream_index_ != -1) { |
| 174 LOG(WARNING) << "Found multiple audio streams."; | 181 LOG(WARNING) << "Found multiple audio streams."; |
| 175 } | 182 } |
| 176 audio_stream_index_ = static_cast<int>(i); | 183 audio_stream_index_ = static_cast<int>(i); |
| 184 av_audio_context_ = std::move(av_codec_context); |
| 177 source_audio_params_.Reset( | 185 source_audio_params_.Reset( |
| 178 AudioParameters::AUDIO_PCM_LINEAR, | 186 AudioParameters::AUDIO_PCM_LINEAR, layout, |
| 179 layout, | 187 av_audio_context_->sample_rate, |
| 180 av_codec_context->sample_rate, | 188 8 * av_get_bytes_per_sample(av_audio_context_->sample_fmt), |
| 181 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt), | 189 av_audio_context_->sample_rate / kAudioPacketsPerSecond); |
| 182 av_codec_context->sample_rate / kAudioPacketsPerSecond); | |
| 183 source_audio_params_.set_channels_for_discrete( | 190 source_audio_params_.set_channels_for_discrete( |
| 184 av_codec_context->channels); | 191 av_audio_context_->channels); |
| 185 CHECK(source_audio_params_.IsValid()); | 192 CHECK(source_audio_params_.IsValid()); |
| 186 LOG(INFO) << "Source file has audio."; | 193 LOG(INFO) << "Source file has audio."; |
| 187 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { | 194 } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) { |
| 188 VideoPixelFormat format = | 195 VideoPixelFormat format = |
| 189 AVPixelFormatToVideoPixelFormat(av_codec_context->pix_fmt); | 196 AVPixelFormatToVideoPixelFormat(av_codec_context->pix_fmt); |
| 190 if (format != PIXEL_FORMAT_YV12) { | 197 if (format != PIXEL_FORMAT_YV12) { |
| 191 LOG(ERROR) << "Cannot handle non YV12 video format: " << format; | 198 LOG(ERROR) << "Cannot handle non YV12 video format: " << format; |
| 192 continue; | 199 continue; |
| 193 } | 200 } |
| 194 if (video_stream_index_ != -1) { | 201 if (video_stream_index_ != -1) { |
| 195 LOG(WARNING) << "Found multiple video streams."; | 202 LOG(WARNING) << "Found multiple video streams."; |
| 196 } | 203 } |
| 197 video_stream_index_ = static_cast<int>(i); | 204 video_stream_index_ = static_cast<int>(i); |
| 205 av_video_context_ = std::move(av_codec_context); |
| 198 if (final_fps > 0) { | 206 if (final_fps > 0) { |
| 199 // If video is played at a manual speed audio needs to match. | 207 // If video is played at a manual speed audio needs to match. |
| 200 playback_rate_ = 1.0 * final_fps * | 208 playback_rate_ = 1.0 * final_fps * |
| 201 av_stream->r_frame_rate.den / av_stream->r_frame_rate.num; | 209 av_stream->r_frame_rate.den / av_stream->r_frame_rate.num; |
| 202 video_frame_rate_numerator_ = final_fps; | 210 video_frame_rate_numerator_ = final_fps; |
| 203 video_frame_rate_denominator_ = 1; | 211 video_frame_rate_denominator_ = 1; |
| 204 } else { | 212 } else { |
| 205 playback_rate_ = 1.0; | 213 playback_rate_ = 1.0; |
| 206 video_frame_rate_numerator_ = av_stream->r_frame_rate.num; | 214 video_frame_rate_numerator_ = av_stream->r_frame_rate.num; |
| 207 video_frame_rate_denominator_ = av_stream->r_frame_rate.den; | 215 video_frame_rate_denominator_ = av_stream->r_frame_rate.den; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) { | 457 void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) { |
| 450 // Audio. | 458 // Audio. |
| 451 AVFrame* avframe = av_frame_alloc(); | 459 AVFrame* avframe = av_frame_alloc(); |
| 452 | 460 |
| 453 // Make a shallow copy of packet so we can slide packet.data as frames are | 461 // Make a shallow copy of packet so we can slide packet.data as frames are |
| 454 // decoded from the packet; otherwise av_packet_unref() will corrupt memory. | 462 // decoded from the packet; otherwise av_packet_unref() will corrupt memory. |
| 455 AVPacket packet_temp = *packet.get(); | 463 AVPacket packet_temp = *packet.get(); |
| 456 | 464 |
| 457 do { | 465 do { |
| 458 int frame_decoded = 0; | 466 int frame_decoded = 0; |
| 459 int result = avcodec_decode_audio4( | 467 int result = avcodec_decode_audio4(av_audio_context_.get(), avframe, |
| 460 av_audio_context(), avframe, &frame_decoded, &packet_temp); | 468 &frame_decoded, &packet_temp); |
| 461 CHECK(result >= 0) << "Failed to decode audio."; | 469 CHECK(result >= 0) << "Failed to decode audio."; |
| 462 packet_temp.size -= result; | 470 packet_temp.size -= result; |
| 463 packet_temp.data += result; | 471 packet_temp.data += result; |
| 464 if (!frame_decoded) | 472 if (!frame_decoded) |
| 465 continue; | 473 continue; |
| 466 | 474 |
| 467 int frames_read = avframe->nb_samples; | 475 int frames_read = avframe->nb_samples; |
| 468 if (frames_read < 0) | 476 if (frames_read < 0) |
| 469 break; | 477 break; |
| 470 | 478 |
| 471 if (!audio_sent_ts_) { | 479 if (!audio_sent_ts_) { |
| 472 // Initialize the base time to the first packet in the file. | 480 // Initialize the base time to the first packet in the file. |
| 473 // This is set to the frequency we send to the receiver. | 481 // This is set to the frequency we send to the receiver. |
| 474 // Not the frequency of the source file. This is because we | 482 // Not the frequency of the source file. This is because we |
| 475 // increment the frame count by samples we sent. | 483 // increment the frame count by samples we sent. |
| 476 audio_sent_ts_.reset( | 484 audio_sent_ts_.reset( |
| 477 new AudioTimestampHelper(output_audio_params_.sample_rate())); | 485 new AudioTimestampHelper(output_audio_params_.sample_rate())); |
| 478 // For some files this is an invalid value. | 486 // For some files this is an invalid value. |
| 479 base::TimeDelta base_ts; | 487 base::TimeDelta base_ts; |
| 480 audio_sent_ts_->SetBaseTimestamp(base_ts); | 488 audio_sent_ts_->SetBaseTimestamp(base_ts); |
| 481 } | 489 } |
| 482 | 490 |
| 483 scoped_refptr<AudioBuffer> buffer = AudioBuffer::CopyFrom( | 491 scoped_refptr<AudioBuffer> buffer = AudioBuffer::CopyFrom( |
| 484 AVSampleFormatToSampleFormat(av_audio_context()->sample_fmt, | 492 AVSampleFormatToSampleFormat(av_audio_context_->sample_fmt, |
| 485 av_audio_context()->codec_id), | 493 av_audio_context_->codec_id), |
| 486 ChannelLayoutToChromeChannelLayout(av_audio_context()->channel_layout, | 494 ChannelLayoutToChromeChannelLayout(av_audio_context_->channel_layout, |
| 487 av_audio_context()->channels), | 495 av_audio_context_->channels), |
| 488 av_audio_context()->channels, av_audio_context()->sample_rate, | 496 av_audio_context_->channels, av_audio_context_->sample_rate, |
| 489 frames_read, &avframe->data[0], | 497 frames_read, &avframe->data[0], |
| 490 PtsToTimeDelta(avframe->pkt_pts, av_audio_stream()->time_base)); | 498 PtsToTimeDelta(avframe->pts, av_audio_stream()->time_base)); |
| 491 audio_algo_.EnqueueBuffer(buffer); | 499 audio_algo_.EnqueueBuffer(buffer); |
| 492 av_frame_unref(avframe); | 500 av_frame_unref(avframe); |
| 493 } while (packet_temp.size > 0); | 501 } while (packet_temp.size > 0); |
| 494 av_frame_free(&avframe); | 502 av_frame_free(&avframe); |
| 495 | 503 |
| 496 const int frames_needed_to_scale = | 504 const int frames_needed_to_scale = |
| 497 playback_rate_ * av_audio_context()->sample_rate / | 505 playback_rate_ * av_audio_context_->sample_rate / kAudioPacketsPerSecond; |
| 498 kAudioPacketsPerSecond; | |
| 499 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { | 506 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { |
| 500 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), 0, | 507 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), 0, |
| 501 audio_fifo_input_bus_->frames(), | 508 audio_fifo_input_bus_->frames(), |
| 502 playback_rate_)) { | 509 playback_rate_)) { |
| 503 // Nothing can be scaled. Decode some more. | 510 // Nothing can be scaled. Decode some more. |
| 504 return; | 511 return; |
| 505 } | 512 } |
| 506 | 513 |
| 507 // Prevent overflow of audio data in the FIFO. | 514 // Prevent overflow of audio data in the FIFO. |
| 508 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() | 515 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() |
| (...skipping 14 matching lines...) Expand all Loading... |
| 523 output_audio_params_.sample_rate() / kAudioPacketsPerSecond)); | 530 output_audio_params_.sample_rate() / kAudioPacketsPerSecond)); |
| 524 audio_converter_->Convert(resampled_bus.get()); | 531 audio_converter_->Convert(resampled_bus.get()); |
| 525 audio_bus_queue_.push(resampled_bus.release()); | 532 audio_bus_queue_.push(resampled_bus.release()); |
| 526 } | 533 } |
| 527 } | 534 } |
| 528 | 535 |
| 529 void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) { | 536 void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) { |
| 530 // Video. | 537 // Video. |
| 531 int got_picture; | 538 int got_picture; |
| 532 AVFrame* avframe = av_frame_alloc(); | 539 AVFrame* avframe = av_frame_alloc(); |
| 533 CHECK(avcodec_decode_video2( | 540 CHECK(avcodec_decode_video2(av_video_context_.get(), avframe, &got_picture, |
| 534 av_video_context(), avframe, &got_picture, packet.get()) >= 0) | 541 packet.get()) >= 0) |
| 535 << "Video decode error."; | 542 << "Video decode error."; |
| 536 if (!got_picture) { | 543 if (!got_picture) { |
| 537 av_frame_free(&avframe); | 544 av_frame_free(&avframe); |
| 538 return; | 545 return; |
| 539 } | 546 } |
| 540 gfx::Size size(av_video_context()->width, av_video_context()->height); | 547 gfx::Size size(av_video_context_->width, av_video_context_->height); |
| 541 | 548 |
| 542 if (!video_first_pts_set_) { | 549 if (!video_first_pts_set_) { |
| 543 video_first_pts_ = avframe->pkt_pts; | 550 video_first_pts_ = avframe->pts; |
| 544 video_first_pts_set_ = true; | 551 video_first_pts_set_ = true; |
| 545 } | 552 } |
| 546 const AVRational& time_base = av_video_stream()->time_base; | 553 const AVRational& time_base = av_video_stream()->time_base; |
| 547 base::TimeDelta timestamp = | 554 base::TimeDelta timestamp = |
| 548 PtsToTimeDelta(avframe->pkt_pts - video_first_pts_, time_base); | 555 PtsToTimeDelta(avframe->pts - video_first_pts_, time_base); |
| 549 if (timestamp < last_video_frame_timestamp_) { | 556 if (timestamp < last_video_frame_timestamp_) { |
| 550 // Stream has rewound. Rebase |video_first_pts_|. | 557 // Stream has rewound. Rebase |video_first_pts_|. |
| 551 const AVRational& frame_rate = av_video_stream()->r_frame_rate; | 558 const AVRational& frame_rate = av_video_stream()->r_frame_rate; |
| 552 timestamp = last_video_frame_timestamp_ + | 559 timestamp = last_video_frame_timestamp_ + |
| 553 (base::TimeDelta::FromSeconds(1) * frame_rate.den / frame_rate.num); | 560 (base::TimeDelta::FromSeconds(1) * frame_rate.den / frame_rate.num); |
| 554 const int64_t adjustment_pts = TimeDeltaToPts(timestamp, time_base); | 561 const int64_t adjustment_pts = TimeDeltaToPts(timestamp, time_base); |
| 555 video_first_pts_ = avframe->pkt_pts - adjustment_pts; | 562 video_first_pts_ = avframe->pts - adjustment_pts; |
| 556 } | 563 } |
| 557 | 564 |
| 558 scoped_refptr<media::VideoFrame> video_frame = | 565 scoped_refptr<media::VideoFrame> video_frame = |
| 559 VideoFrame::WrapExternalYuvData( | 566 VideoFrame::WrapExternalYuvData( |
| 560 media::PIXEL_FORMAT_YV12, size, gfx::Rect(size), size, | 567 media::PIXEL_FORMAT_YV12, size, gfx::Rect(size), size, |
| 561 avframe->linesize[0], avframe->linesize[1], avframe->linesize[2], | 568 avframe->linesize[0], avframe->linesize[1], avframe->linesize[2], |
| 562 avframe->data[0], avframe->data[1], avframe->data[2], timestamp); | 569 avframe->data[0], avframe->data[1], avframe->data[2], timestamp); |
| 563 if (!video_frame) | 570 if (!video_frame) |
| 564 return; | 571 return; |
| 565 video_frame_queue_.push(video_frame); | 572 video_frame_queue_.push(video_frame); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 } | 619 } |
| 613 | 620 |
| 614 AVStream* FakeMediaSource::av_audio_stream() { | 621 AVStream* FakeMediaSource::av_audio_stream() { |
| 615 return av_format_context_->streams[audio_stream_index_]; | 622 return av_format_context_->streams[audio_stream_index_]; |
| 616 } | 623 } |
| 617 | 624 |
| 618 AVStream* FakeMediaSource::av_video_stream() { | 625 AVStream* FakeMediaSource::av_video_stream() { |
| 619 return av_format_context_->streams[video_stream_index_]; | 626 return av_format_context_->streams[video_stream_index_]; |
| 620 } | 627 } |
| 621 | 628 |
| 622 AVCodecContext* FakeMediaSource::av_audio_context() { | |
| 623 return av_audio_stream()->codec; | |
| 624 } | |
| 625 | |
| 626 AVCodecContext* FakeMediaSource::av_video_context() { | |
| 627 return av_video_stream()->codec; | |
| 628 } | |
| 629 | |
| 630 } // namespace cast | 629 } // namespace cast |
| 631 } // namespace media | 630 } // namespace media |
| OLD | NEW |