Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 // Test application that simulates a cast sender - Data can be either generated | 5 // Test application that simulates a cast sender - Data can be either generated |
| 6 // or read from a file. | 6 // or read from a file. |
| 7 | 7 |
| 8 #include <queue> | 8 #include <queue> |
| 9 | 9 |
| 10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 video_config.max_qp = 40; | 133 video_config.max_qp = 40; |
| 134 | 134 |
| 135 // SSRCs and payload type. Don't change them. | 135 // SSRCs and payload type. Don't change them. |
| 136 video_config.rtp_config.ssrc = 11; | 136 video_config.rtp_config.ssrc = 11; |
| 137 video_config.incoming_feedback_ssrc = 12; | 137 video_config.incoming_feedback_ssrc = 12; |
| 138 video_config.rtp_config.payload_type = 96; | 138 video_config.rtp_config.payload_type = 96; |
| 139 video_config.rtp_config.max_delay_ms = 300; | 139 video_config.rtp_config.max_delay_ms = 300; |
| 140 return video_config; | 140 return video_config; |
| 141 } | 141 } |
| 142 | 142 |
| 143 void AVFreeFrame(AVFrame* frame) { avcodec_free_frame(&frame); } | 143 void AVFreeFrame(AVFrame* frame) { av_frame_free(&frame); } |
| 144 | 144 |
| 145 class SendProcess { | 145 class SendProcess { |
| 146 public: | 146 public: |
| 147 SendProcess(scoped_refptr<base::SingleThreadTaskRunner> thread_proxy, | 147 SendProcess(scoped_refptr<base::SingleThreadTaskRunner> thread_proxy, |
| 148 base::TickClock* clock, | 148 base::TickClock* clock, |
| 149 const VideoSenderConfig& video_config) | 149 const VideoSenderConfig& video_config) |
| 150 : test_app_thread_proxy_(thread_proxy), | 150 : test_app_thread_proxy_(thread_proxy), |
| 151 video_config_(video_config), | 151 video_config_(video_config), |
| 152 synthetic_count_(0), | 152 synthetic_count_(0), |
| 153 clock_(clock), | 153 clock_(clock), |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 LOG(INFO) << "Unknown packet."; | 526 LOG(INFO) << "Unknown packet."; |
| 527 packet.reset(); | 527 packet.reset(); |
| 528 } | 528 } |
| 529 return packet.Pass(); | 529 return packet.Pass(); |
| 530 } | 530 } |
| 531 | 531 |
| 532 void DecodeAudio(ScopedAVPacket packet) { | 532 void DecodeAudio(ScopedAVPacket packet) { |
| 533 // Audio. | 533 // Audio. |
| 534 AVFrame* avframe = av_frame_alloc(); | 534 AVFrame* avframe = av_frame_alloc(); |
| 535 | 535 |
| 536 // Shallow copy of the packet. | 536 // Make a shallow copy of packet so we can slide packet.data as frames are |
| 537 // decoded from the packet; otherwise av_free_packet() will corrupt memory. | |
| 537 AVPacket packet_temp = *packet.get(); | 538 AVPacket packet_temp = *packet.get(); |
| 538 | 539 |
| 539 do { | 540 do { |
| 540 avcodec_get_frame_defaults(avframe); | |
| 541 int frame_decoded = 0; | 541 int frame_decoded = 0; |
| 542 int result = avcodec_decode_audio4( | 542 int result = avcodec_decode_audio4( |
| 543 av_audio_context(), avframe, &frame_decoded, &packet_temp); | 543 av_audio_context(), avframe, &frame_decoded, &packet_temp); |
| 544 CHECK(result >= 0) << "Failed to decode audio."; | 544 CHECK(result >= 0) << "Failed to decode audio."; |
| 545 packet_temp.size -= result; | 545 packet_temp.size -= result; |
| 546 packet_temp.data += result; | 546 packet_temp.data += result; |
| 547 if (!frame_decoded) | 547 if (!frame_decoded) |
| 548 continue; | 548 continue; |
| 549 | 549 |
| 550 int frames_read = avframe->nb_samples; | 550 int frames_read = avframe->nb_samples; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 570 ChannelLayoutToChromeChannelLayout( | 570 ChannelLayoutToChromeChannelLayout( |
| 571 av_audio_context()->channel_layout, | 571 av_audio_context()->channel_layout, |
| 572 av_audio_context()->channels), | 572 av_audio_context()->channels), |
| 573 av_audio_context()->channels, | 573 av_audio_context()->channels, |
| 574 av_audio_context()->sample_rate, | 574 av_audio_context()->sample_rate, |
| 575 frames_read, | 575 frames_read, |
| 576 &avframe->data[0], | 576 &avframe->data[0], |
| 577 // Note: Not all files have correct values for pkt_pts. | 577 // Note: Not all files have correct values for pkt_pts. |
| 578 base::TimeDelta::FromMilliseconds(avframe->pkt_pts)); | 578 base::TimeDelta::FromMilliseconds(avframe->pkt_pts)); |
| 579 audio_algo_.EnqueueBuffer(buffer); | 579 audio_algo_.EnqueueBuffer(buffer); |
| 580 av_frame_unref(avframe); | |
| 580 } while (packet_temp.size > 0); | 581 } while (packet_temp.size > 0); |
| 581 avcodec_free_frame(&avframe); | 582 av_frame_free(&avframe); |
| 582 | 583 |
| 583 const int frames_needed_to_scale = | 584 const int frames_needed_to_scale = |
| 584 playback_rate_ * av_audio_context()->sample_rate / | 585 playback_rate_ * av_audio_context()->sample_rate / |
| 585 kAudioPacketsPerSecond; | 586 kAudioPacketsPerSecond; |
| 586 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { | 587 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { |
| 587 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), | 588 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), |
| 588 audio_fifo_input_bus_->frames())) { | 589 audio_fifo_input_bus_->frames())) { |
| 589 // Nothing can be scaled. Decode some more. | 590 // Nothing can be scaled. Decode some more. |
| 590 return; | 591 return; |
| 591 } | 592 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 611 audio_resampler_->Resample(resampled_bus->frames(), | 612 audio_resampler_->Resample(resampled_bus->frames(), |
| 612 resampled_bus.get()); | 613 resampled_bus.get()); |
| 613 audio_bus_queue_.push(resampled_bus.release()); | 614 audio_bus_queue_.push(resampled_bus.release()); |
| 614 } | 615 } |
| 615 } | 616 } |
| 616 | 617 |
| 617 void DecodeVideo(ScopedAVPacket packet) { | 618 void DecodeVideo(ScopedAVPacket packet) { |
| 618 // Video. | 619 // Video. |
| 619 int got_picture; | 620 int got_picture; |
| 620 AVFrame* avframe = av_frame_alloc(); | 621 AVFrame* avframe = av_frame_alloc(); |
| 621 avcodec_get_frame_defaults(avframe); | |
| 622 // Tell the decoder to reorder for us. | 622 // Tell the decoder to reorder for us. |
| 623 avframe->reordered_opaque = | 623 avframe->reordered_opaque = |
| 624 av_video_context()->reordered_opaque = packet->pts; | 624 av_video_context()->reordered_opaque = packet->pts; |
| 625 CHECK(avcodec_decode_video2( | 625 CHECK(avcodec_decode_video2( |
| 626 av_video_context(), avframe, &got_picture, packet.get()) >= 0) | 626 av_video_context(), avframe, &got_picture, packet.get()) >= 0) |
| 627 << "Video decode error."; | 627 << "Video decode error."; |
| 628 if (!got_picture) | 628 if (!got_picture) |
|
wolenetz
2014/05/20 22:37:10
Need to free avframe before returning early here?
DaleCurtis
2014/05/20 23:00:45
Done.
| |
| 629 return; | 629 return; |
| 630 gfx::Size size(av_video_context()->width, av_video_context()->height); | 630 gfx::Size size(av_video_context()->width, av_video_context()->height); |
| 631 if (!video_first_pts_set_ || | 631 if (!video_first_pts_set_ || |
| 632 avframe->reordered_opaque < video_first_pts_) { | 632 avframe->reordered_opaque < video_first_pts_) { |
| 633 video_first_pts_set_ = true; | 633 video_first_pts_set_ = true; |
| 634 video_first_pts_ = avframe->reordered_opaque; | 634 video_first_pts_ = avframe->reordered_opaque; |
| 635 } | 635 } |
| 636 int64 pts = avframe->reordered_opaque - video_first_pts_; | 636 int64 pts = avframe->reordered_opaque - video_first_pts_; |
| 637 video_frame_queue_.push( | 637 video_frame_queue_.push( |
| 638 VideoFrame::WrapExternalYuvData( | 638 VideoFrame::WrapExternalYuvData( |
| 639 media::VideoFrame::YV12, | 639 media::VideoFrame::YV12, |
| 640 size, | 640 size, |
| 641 gfx::Rect(size), | 641 gfx::Rect(size), |
| 642 size, | 642 size, |
| 643 avframe->linesize[0], | 643 avframe->linesize[0], |
| 644 avframe->linesize[1], | 644 avframe->linesize[1], |
| 645 avframe->linesize[2], | 645 avframe->linesize[2], |
| 646 avframe->data[0], | 646 avframe->data[0], |
| 647 avframe->data[1], | 647 avframe->data[1], |
| 648 avframe->data[2], | 648 avframe->data[2], |
| 649 base::TimeDelta::FromMilliseconds(pts), | 649 base::TimeDelta::FromMilliseconds(pts), |
| 650 base::Bind(&AVFreeFrame, avframe))); | 650 base::Bind(&AVFreeFrame, avframe))); |
|
wolenetz
2014/05/20 22:37:10
Need to av_frame_unref(avframe) prior to AVFreeFra
DaleCurtis
2014/05/20 23:00:45
No, that's done by av_frame_free().
| |
| 651 } | 651 } |
| 652 | 652 |
| 653 void Decode(bool decode_audio) { | 653 void Decode(bool decode_audio) { |
| 654 // Read the stream until one video frame can be decoded. | 654 // Read the stream until one video frame can be decoded. |
| 655 while (true) { | 655 while (true) { |
| 656 if (decode_audio && !audio_bus_queue_.empty()) | 656 if (decode_audio && !audio_bus_queue_.empty()) |
| 657 return; | 657 return; |
| 658 if (!decode_audio && !video_frame_queue_.empty()) | 658 if (!decode_audio && !video_frame_queue_.empty()) |
| 659 return; | 659 return; |
| 660 | 660 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1011 base::Passed(&audio_stats_subscriber), | 1011 base::Passed(&audio_stats_subscriber), |
| 1012 base::Passed(&offset_estimator)), | 1012 base::Passed(&offset_estimator)), |
| 1013 base::TimeDelta::FromSeconds(logging_duration_seconds)); | 1013 base::TimeDelta::FromSeconds(logging_duration_seconds)); |
| 1014 | 1014 |
| 1015 send_process->Start(cast_sender->audio_frame_input(), | 1015 send_process->Start(cast_sender->audio_frame_input(), |
| 1016 cast_sender->video_frame_input()); | 1016 cast_sender->video_frame_input()); |
| 1017 | 1017 |
| 1018 io_message_loop.Run(); | 1018 io_message_loop.Run(); |
| 1019 return 0; | 1019 return 0; |
| 1020 } | 1020 } |
| OLD | NEW |