OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
wuchengli
2015/09/04 11:59:44
IIRC, the first line of the change description wil
| |
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 |
11 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
(...skipping 12 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 | |
wuchengli
2015/09/04 11:59:44
Document if the id starts from 0. It's confusing l
| |
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(); |
655 | 662 |
656 gfx::Size natural_size(visible_size.size()); | 663 gfx::Size natural_size(visible_size.size()); |
657 // The default output format of ffmpeg video decoder is YV12. | 664 // The default output format of ffmpeg video decoder is YV12. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
733 else | 740 else |
734 decoder_->Decode(next_buffer, decode_cb_); | 741 decoder_->Decode(next_buffer, decode_cb_); |
735 } | 742 } |
736 } | 743 } |
737 | 744 |
738 void VideoFrameQualityValidator::VerifyOutputFrame( | 745 void VideoFrameQualityValidator::VerifyOutputFrame( |
739 const scoped_refptr<media::VideoFrame>& output_frame) { | 746 const scoped_refptr<media::VideoFrame>& output_frame) { |
740 scoped_refptr<media::VideoFrame> original_frame = original_frames_.front(); | 747 scoped_refptr<media::VideoFrame> original_frame = original_frames_.front(); |
741 original_frames_.pop(); | 748 original_frames_.pop(); |
742 gfx::Size visible_size = original_frame->visible_rect().size(); | 749 gfx::Size visible_size = original_frame->visible_rect().size(); |
750 frame_id_++; | |
743 | 751 |
744 int planes[] = {media::VideoFrame::kYPlane, media::VideoFrame::kUPlane, | 752 int planes[] = {media::VideoFrame::kYPlane, media::VideoFrame::kUPlane, |
745 media::VideoFrame::kVPlane}; | 753 media::VideoFrame::kVPlane}; |
746 double difference = 0; | 754 double difference = 0; |
747 for (int plane : planes) { | 755 for (int plane : planes) { |
748 uint8_t* original_plane = original_frame->data(plane); | 756 uint8_t* original_plane = original_frame->data(plane); |
749 uint8_t* output_plane = output_frame->data(plane); | 757 uint8_t* output_plane = output_frame->data(plane); |
750 | 758 |
751 size_t rows = | 759 size_t rows = |
752 media::VideoFrame::Rows(plane, kInputFormat, visible_size.height()); | 760 media::VideoFrame::Rows(plane, kInputFormat, visible_size.height()); |
753 size_t columns = | 761 size_t columns = |
754 media::VideoFrame::Columns(plane, kInputFormat, visible_size.width()); | 762 media::VideoFrame::Columns(plane, kInputFormat, visible_size.width()); |
755 size_t stride = original_frame->stride(plane); | 763 size_t stride = original_frame->stride(plane); |
756 | 764 |
757 for (size_t i = 0; i < rows; i++) | 765 for (size_t i = 0; i < rows; i++) |
758 for (size_t j = 0; j < columns; j++) | 766 for (size_t j = 0; j < columns; j++) |
759 difference += std::abs(original_plane[stride * i + j] - | 767 difference += std::abs(original_plane[stride * i + j] - |
760 output_plane[stride * i + j]); | 768 output_plane[stride * i + j]); |
761 } | 769 } |
762 // Divide the difference by the size of frame. | 770 // Divide the difference by the size of frame. |
763 difference /= media::VideoFrame::AllocationSize(kInputFormat, visible_size); | 771 difference /= media::VideoFrame::AllocationSize(kInputFormat, visible_size); |
764 EXPECT_TRUE(difference <= kDecodeSimilarityThreshold) | 772 |
765 << "differrence = " << difference << " > decode similarity threshold"; | 773 // Save both origin and output frames to files if its difference is larger |
wuchengli
2015/09/04 11:59:44
s/its/their/
| |
774 // than kDecodeSimilarityThreshold | |
wuchengli
2015/09/04 11:59:44
add . at the end.
| |
775 if (difference >= kDecodeSimilarityThreshold) { | |
776 ADD_FAILURE() << "differrence = " << difference | |
777 << " > decode similarity threshold"; | |
778 std::string filename = | |
779 base::StringPrintf("%.4d_origin_frame.png", frame_id_); | |
780 SaveFrameToFile(original_frame, base::FilePath::FromUTF8Unsafe(filename)); | |
781 filename = base::StringPrintf("%.4d_output_frame.png", frame_id_); | |
782 SaveFrameToFile(output_frame, base::FilePath::FromUTF8Unsafe(filename)); | |
783 } | |
784 } | |
785 | |
786 void VideoFrameQualityValidator::SaveFrameToFile( | |
787 const scoped_refptr<media::VideoFrame>& frame, | |
788 const base::FilePath& filename) { | |
789 const int RGB32_BYTES_PER_PIXEL = 4; | |
790 size_t row_bytes = frame->visible_rect().width() * RGB32_BYTES_PER_PIXEL; | |
791 uint8* rgb_pixels = reinterpret_cast<uint8*>( | |
792 base::AlignedAlloc(row_bytes * frame->coded_size().height() + | |
wuchengli
2015/09/04 11:59:44
Why do we need the alignment?
| |
793 media::VideoFrame::kFrameSizePadding, | |
wuchengli
2015/09/04 11:59:44
Is this required?
| |
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); | |
wuchengli
2015/09/04 11:59:44
Is the original frame also YV12? We should documen
| |
802 | |
803 std::vector<unsigned char> png_output; | |
804 LOG_ASSERT(gfx::PNGCodec::Encode( | |
805 rgb_pixels, gfx::PNGCodec::FORMAT_RGBA, frame->coded_size(), | |
wuchengli
2015/09/04 11:59:43
why this is not visible_rect()?
| |
806 base::checked_cast<int>(row_bytes), true, | |
807 std::vector<gfx::PNGCodec::Comment>(), &png_output)); | |
808 base::AlignedFree(rgb_pixels); | |
809 base::WriteFile(filename, reinterpret_cast<char*>(&png_output[0]), | |
810 base::checked_cast<int>(png_output.size())); | |
811 | |
wuchengli
2015/09/04 11:59:44
remove blank line
| |
766 } | 812 } |
767 | 813 |
768 class VEAClient : public VideoEncodeAccelerator::Client { | 814 class VEAClient : public VideoEncodeAccelerator::Client { |
769 public: | 815 public: |
770 VEAClient(TestStream* test_stream, | 816 VEAClient(TestStream* test_stream, |
771 ClientStateNotification<ClientState>* note, | 817 ClientStateNotification<ClientState>* note, |
772 bool save_to_file, | 818 bool save_to_file, |
773 unsigned int keyframe_period, | 819 unsigned int keyframe_period, |
774 bool force_bitrate, | 820 bool force_bitrate, |
775 bool test_perf, | 821 bool test_perf, |
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1765 | 1811 |
1766 content::g_env = | 1812 content::g_env = |
1767 reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( | 1813 reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( |
1768 testing::AddGlobalTestEnvironment( | 1814 testing::AddGlobalTestEnvironment( |
1769 new content::VideoEncodeAcceleratorTestEnvironment( | 1815 new content::VideoEncodeAcceleratorTestEnvironment( |
1770 test_stream_data.Pass(), log_path, run_at_fps, | 1816 test_stream_data.Pass(), log_path, run_at_fps, |
1771 needs_encode_latency, verify_all_output))); | 1817 needs_encode_latency, verify_all_output))); |
1772 | 1818 |
1773 return RUN_ALL_TESTS(); | 1819 return RUN_ALL_TESTS(); |
1774 } | 1820 } |
OLD | NEW |