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 #include <inttypes.h> | 5 #include <inttypes.h> |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <queue> | 8 #include <queue> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "base/threading/thread_checker.h" | 24 #include "base/threading/thread_checker.h" |
25 #include "base/time/time.h" | 25 #include "base/time/time.h" |
26 #include "base/timer/timer.h" | 26 #include "base/timer/timer.h" |
27 #include "content/common/gpu/media/video_accelerator_unittest_helpers.h" | 27 #include "content/common/gpu/media/video_accelerator_unittest_helpers.h" |
28 #include "media/base/bind_to_current_loop.h" | 28 #include "media/base/bind_to_current_loop.h" |
29 #include "media/base/bitstream_buffer.h" | 29 #include "media/base/bitstream_buffer.h" |
30 #include "media/base/decoder_buffer.h" | 30 #include "media/base/decoder_buffer.h" |
31 #include "media/base/test_data_util.h" | 31 #include "media/base/test_data_util.h" |
32 #include "media/base/video_decoder.h" | 32 #include "media/base/video_decoder.h" |
33 #include "media/base/video_frame.h" | 33 #include "media/base/video_frame.h" |
34 #include "media/base/yuv_convert.h" | |
34 #include "media/filters/ffmpeg_glue.h" | 35 #include "media/filters/ffmpeg_glue.h" |
35 #include "media/filters/ffmpeg_video_decoder.h" | 36 #include "media/filters/ffmpeg_video_decoder.h" |
36 #include "media/filters/h264_parser.h" | 37 #include "media/filters/h264_parser.h" |
37 #include "media/filters/ivf_parser.h" | 38 #include "media/filters/ivf_parser.h" |
38 #include "media/video/fake_video_encode_accelerator.h" | 39 #include "media/video/fake_video_encode_accelerator.h" |
39 #include "media/video/video_encode_accelerator.h" | 40 #include "media/video/video_encode_accelerator.h" |
40 #include "testing/gtest/include/gtest/gtest.h" | 41 #include "testing/gtest/include/gtest/gtest.h" |
42 #include "ui/gfx/codec/png_codec.h" | |
41 | 43 |
42 #if defined(OS_CHROMEOS) | 44 #if defined(OS_CHROMEOS) |
43 #if defined(ARCH_CPU_ARMEL) || (defined(USE_OZONE) && defined(USE_V4L2_CODEC)) | 45 #if defined(ARCH_CPU_ARMEL) || (defined(USE_OZONE) && defined(USE_V4L2_CODEC)) |
44 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" | 46 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" |
45 #endif | 47 #endif |
46 #if defined(ARCH_CPU_X86_FAMILY) | 48 #if defined(ARCH_CPU_X86_FAMILY) |
47 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" | 49 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" |
48 #include "content/common/gpu/media/vaapi_wrapper.h" | 50 #include "content/common/gpu/media/vaapi_wrapper.h" |
49 // Status has been defined as int in Xlib.h. | 51 // Status has been defined as int in Xlib.h. |
50 #undef Status | 52 #undef Status |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
608 void AddDecodeBuffer(const scoped_refptr<media::DecoderBuffer>& buffer); | 610 void AddDecodeBuffer(const scoped_refptr<media::DecoderBuffer>& buffer); |
609 // Flush the decoder. | 611 // Flush the decoder. |
610 void Flush(); | 612 void Flush(); |
611 | 613 |
612 private: | 614 private: |
613 void InitializeCB(bool success); | 615 void InitializeCB(bool success); |
614 void DecodeDone(media::VideoDecoder::Status status); | 616 void DecodeDone(media::VideoDecoder::Status status); |
615 void FlushDone(media::VideoDecoder::Status status); | 617 void FlushDone(media::VideoDecoder::Status status); |
616 void VerifyOutputFrame(const scoped_refptr<media::VideoFrame>& output_frame); | 618 void VerifyOutputFrame(const scoped_refptr<media::VideoFrame>& output_frame); |
617 void Decode(); | 619 void Decode(); |
620 void SaveFrameToFile(const scoped_refptr<media::VideoFrame>& frame, | |
621 const base::FilePath& filename); | |
618 | 622 |
619 enum State { UNINITIALIZED, INITIALIZED, DECODING, ERROR }; | 623 enum State { UNINITIALIZED, INITIALIZED, DECODING, ERROR }; |
620 | 624 |
621 const media::VideoCodecProfile profile_; | 625 const media::VideoCodecProfile profile_; |
622 scoped_ptr<media::FFmpegVideoDecoder> decoder_; | 626 scoped_ptr<media::FFmpegVideoDecoder> decoder_; |
623 media::VideoDecoder::DecodeCB decode_cb_; | 627 media::VideoDecoder::DecodeCB decode_cb_; |
624 // Decode callback of an EOS buffer. | 628 // Decode callback of an EOS buffer. |
625 media::VideoDecoder::DecodeCB eos_decode_cb_; | 629 media::VideoDecoder::DecodeCB eos_decode_cb_; |
626 // Callback of Flush(). Called after all frames are decoded. | 630 // Callback of Flush(). Called after all frames are decoded. |
627 const base::Closure flush_complete_cb_; | 631 const base::Closure flush_complete_cb_; |
628 const base::Closure decode_error_cb_; | 632 const base::Closure decode_error_cb_; |
629 State decoder_state_; | 633 State decoder_state_; |
630 std::queue<scoped_refptr<media::VideoFrame>> original_frames_; | 634 std::queue<scoped_refptr<media::VideoFrame>> original_frames_; |
631 std::queue<scoped_refptr<media::DecoderBuffer>> decode_buffers_; | 635 std::queue<scoped_refptr<media::DecoderBuffer>> decode_buffers_; |
636 | |
637 int frame_id_; | |
632 }; | 638 }; |
633 | 639 |
634 VideoFrameQualityValidator::VideoFrameQualityValidator( | 640 VideoFrameQualityValidator::VideoFrameQualityValidator( |
635 const media::VideoCodecProfile profile, | 641 const media::VideoCodecProfile profile, |
636 const base::Closure& flush_complete_cb, | 642 const base::Closure& flush_complete_cb, |
637 const base::Closure& decode_error_cb) | 643 const base::Closure& decode_error_cb) |
638 : profile_(profile), | 644 : profile_(profile), |
639 decoder_(new media::FFmpegVideoDecoder(base::MessageLoop::current() | 645 decoder_(new media::FFmpegVideoDecoder(base::MessageLoop::current() |
640 ->task_runner())), | 646 ->task_runner())), |
641 decode_cb_(base::Bind(&VideoFrameQualityValidator::DecodeDone, | 647 decode_cb_(base::Bind(&VideoFrameQualityValidator::DecodeDone, |
642 base::Unretained(this))), | 648 base::Unretained(this))), |
643 eos_decode_cb_(base::Bind(&VideoFrameQualityValidator::FlushDone, | 649 eos_decode_cb_(base::Bind(&VideoFrameQualityValidator::FlushDone, |
644 base::Unretained(this))), | 650 base::Unretained(this))), |
645 flush_complete_cb_(flush_complete_cb), | 651 flush_complete_cb_(flush_complete_cb), |
646 decode_error_cb_(decode_error_cb), | 652 decode_error_cb_(decode_error_cb), |
647 decoder_state_(UNINITIALIZED) { | 653 decoder_state_(UNINITIALIZED), |
654 frame_id_(0) { | |
648 // Allow decoding of individual NALU. Entire frames are required by default. | 655 // Allow decoding of individual NALU. Entire frames are required by default. |
649 decoder_->set_decode_nalus(true); | 656 decoder_->set_decode_nalus(true); |
650 } | 657 } |
651 | 658 |
652 void VideoFrameQualityValidator::Initialize(const gfx::Size& coded_size, | 659 void VideoFrameQualityValidator::Initialize(const gfx::Size& coded_size, |
653 const gfx::Rect& visible_size) { | 660 const gfx::Rect& visible_size) { |
654 media::FFmpegGlue::InitializeFFmpeg(); | 661 media::FFmpegGlue::InitializeFFmpeg(); |
662 media::InitializeCPUSpecificYUVConversions(); | |
655 | 663 |
656 gfx::Size natural_size(visible_size.size()); | 664 gfx::Size natural_size(visible_size.size()); |
657 // The default output format of ffmpeg video decoder is YV12. | 665 // The default output format of ffmpeg video decoder is YV12. |
658 media::VideoDecoderConfig config; | 666 media::VideoDecoderConfig config; |
659 if (IsVP8(profile_)) | 667 if (IsVP8(profile_)) |
660 config.Initialize(media::kCodecVP8, media::VP8PROFILE_ANY, kInputFormat, | 668 config.Initialize(media::kCodecVP8, media::VP8PROFILE_ANY, kInputFormat, |
661 media::COLOR_SPACE_UNSPECIFIED, coded_size, visible_size, | 669 media::COLOR_SPACE_UNSPECIFIED, coded_size, visible_size, |
662 natural_size, NULL, 0, false); | 670 natural_size, NULL, 0, false); |
663 else if (IsH264(profile_)) | 671 else if (IsH264(profile_)) |
664 config.Initialize(media::kCodecH264, media::H264PROFILE_MAIN, kInputFormat, | 672 config.Initialize(media::kCodecH264, media::H264PROFILE_MAIN, kInputFormat, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
733 else | 741 else |
734 decoder_->Decode(next_buffer, decode_cb_); | 742 decoder_->Decode(next_buffer, decode_cb_); |
735 } | 743 } |
736 } | 744 } |
737 | 745 |
738 void VideoFrameQualityValidator::VerifyOutputFrame( | 746 void VideoFrameQualityValidator::VerifyOutputFrame( |
739 const scoped_refptr<media::VideoFrame>& output_frame) { | 747 const scoped_refptr<media::VideoFrame>& output_frame) { |
740 scoped_refptr<media::VideoFrame> original_frame = original_frames_.front(); | 748 scoped_refptr<media::VideoFrame> original_frame = original_frames_.front(); |
741 original_frames_.pop(); | 749 original_frames_.pop(); |
742 gfx::Size visible_size = original_frame->visible_rect().size(); | 750 gfx::Size visible_size = original_frame->visible_rect().size(); |
751 frame_id_++; | |
743 | 752 |
744 int planes[] = {media::VideoFrame::kYPlane, media::VideoFrame::kUPlane, | 753 int planes[] = {media::VideoFrame::kYPlane, media::VideoFrame::kUPlane, |
745 media::VideoFrame::kVPlane}; | 754 media::VideoFrame::kVPlane}; |
746 double difference = 0; | 755 double difference = 0; |
747 for (int plane : planes) { | 756 for (int plane : planes) { |
748 uint8_t* original_plane = original_frame->data(plane); | 757 uint8_t* original_plane = original_frame->data(plane); |
749 uint8_t* output_plane = output_frame->data(plane); | 758 uint8_t* output_plane = output_frame->data(plane); |
750 | 759 |
751 size_t rows = | 760 size_t rows = |
752 media::VideoFrame::Rows(plane, kInputFormat, visible_size.height()); | 761 media::VideoFrame::Rows(plane, kInputFormat, visible_size.height()); |
753 size_t columns = | 762 size_t columns = |
754 media::VideoFrame::Columns(plane, kInputFormat, visible_size.width()); | 763 media::VideoFrame::Columns(plane, kInputFormat, visible_size.width()); |
755 size_t stride = original_frame->stride(plane); | 764 size_t stride = original_frame->stride(plane); |
756 | 765 |
757 for (size_t i = 0; i < rows; i++) | 766 for (size_t i = 0; i < rows; i++) |
758 for (size_t j = 0; j < columns; j++) | 767 for (size_t j = 0; j < columns; j++) |
759 difference += std::abs(original_plane[stride * i + j] - | 768 difference += std::abs(original_plane[stride * i + j] - |
760 output_plane[stride * i + j]); | 769 output_plane[stride * i + j]); |
761 } | 770 } |
762 // Divide the difference by the size of frame. | 771 // Divide the difference by the size of frame. |
763 difference /= media::VideoFrame::AllocationSize(kInputFormat, visible_size); | 772 difference /= media::VideoFrame::AllocationSize(kInputFormat, visible_size); |
764 EXPECT_TRUE(difference <= kDecodeSimilarityThreshold) | 773 EXPECT_TRUE(difference <= kDecodeSimilarityThreshold) |
765 << "differrence = " << difference << " > decode similarity threshold"; | 774 << "differrence = " << difference << " > decode similarity threshold"; |
775 | |
776 // Save both origin and output frames to files if its difference is larger | |
777 // than kDecodeSimilarityThreshold | |
778 if (difference >= kDecodeSimilarityThreshold) { | |
779 std::string filename = | |
780 base::StringPrintf("%.4d_origin_frame.png", frame_id_); | |
781 SaveFrameToFile(original_frame, base::FilePath::FromUTF8Unsafe(filename)); | |
782 filename = base::StringPrintf("%.4d_output_frame.png", frame_id_); | |
783 SaveFrameToFile(output_frame, base::FilePath::FromUTF8Unsafe(filename)); | |
Owen Lin
2015/09/04 03:34:47
Remove EXPECT_TRUE at l.773
Add the following line
| |
784 } | |
785 } | |
786 | |
787 void VideoFrameQualityValidator::SaveFrameToFile( | |
788 const scoped_refptr<media::VideoFrame>& frame, | |
789 const base::FilePath& filename) { | |
790 size_t row_bytes = frame->visible_rect().width() * 4u; | |
Owen Lin
2015/09/04 03:34:47
const int RGB32_BYTES_PER_PIXEL = 4;
| |
791 uint8* rgb_pixels = reinterpret_cast<uint8*>( | |
792 base::AlignedAlloc(row_bytes * frame->coded_size().height() + | |
793 media::VideoFrame::kFrameSizePadding, | |
794 media::VideoFrame::kFrameAddressAlignment)); | |
795 media::ConvertYUVToRGB32( | |
796 frame->data(media::VideoFrame::kYPlane), | |
797 frame->data(media::VideoFrame::kUPlane), | |
798 frame->data(media::VideoFrame::kVPlane), rgb_pixels, | |
799 frame->visible_rect().width(), frame->visible_rect().height(), | |
800 frame->stride(media::VideoFrame::kYPlane), | |
801 frame->stride(media::VideoFrame::kUPlane), row_bytes, media::YV12); | |
802 | |
803 std::vector<unsigned char> png_output; | |
804 CHECK(gfx::PNGCodec::Encode( | |
Owen Lin
2015/09/04 03:34:47
LOG_ASSERT
| |
805 rgb_pixels, gfx::PNGCodec::FORMAT_RGBA, frame->coded_size(), | |
806 base::checked_cast<int>(row_bytes), true, | |
807 std::vector<gfx::PNGCodec::Comment>(), &png_output)); | |
808 base::WriteFile(filename, reinterpret_cast<char*>(&*png_output.begin()), | |
Owen Lin
2015/09/04 03:34:47
&png_output[0]
| |
809 base::checked_cast<int>(png_output.size())); | |
810 base::AlignedFree(rgb_pixels); | |
766 } | 811 } |
767 | 812 |
768 class VEAClient : public VideoEncodeAccelerator::Client { | 813 class VEAClient : public VideoEncodeAccelerator::Client { |
769 public: | 814 public: |
770 VEAClient(TestStream* test_stream, | 815 VEAClient(TestStream* test_stream, |
771 ClientStateNotification<ClientState>* note, | 816 ClientStateNotification<ClientState>* note, |
772 bool save_to_file, | 817 bool save_to_file, |
773 unsigned int keyframe_period, | 818 unsigned int keyframe_period, |
774 bool force_bitrate, | 819 bool force_bitrate, |
775 bool test_perf, | 820 bool test_perf, |
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1765 | 1810 |
1766 content::g_env = | 1811 content::g_env = |
1767 reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( | 1812 reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( |
1768 testing::AddGlobalTestEnvironment( | 1813 testing::AddGlobalTestEnvironment( |
1769 new content::VideoEncodeAcceleratorTestEnvironment( | 1814 new content::VideoEncodeAcceleratorTestEnvironment( |
1770 test_stream_data.Pass(), log_path, run_at_fps, | 1815 test_stream_data.Pass(), log_path, run_at_fps, |
1771 needs_encode_latency, verify_all_output))); | 1816 needs_encode_latency, verify_all_output))); |
1772 | 1817 |
1773 return RUN_ALL_TESTS(); | 1818 return RUN_ALL_TESTS(); |
1774 } | 1819 } |
OLD | NEW |