15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string> 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This has to be included first. 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// See http://code.google.com/p/googletest/issues/detail?id=371 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/gpu/media/vaapi_h264_decoder.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/video_decoder_config.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/libyuv/include/libyuv.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This program is run like this: 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// DISPLAY=:0 ./vaapi_h264_decoder_unittest --input_file input.h264 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// [--output_file output.i420] [--md5sum expected_md5_hex] 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The input is read from input.h264. The output is written to output.i420 if it 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// is given. It also verifies the MD5 sum of the decoded I420 data if the 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// expected MD5 sum is given. 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content { 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// These are the command line parameters 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::FilePath g_input_file; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::FilePath g_output_file; 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string g_md5sum; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// These default values are used if nothing is specified in the command line. 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const base::FilePath::CharType* kDefaultInputFile = 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FILE_PATH_LITERAL("test-25fps.h264"); 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kDefaultMD5Sum = "3af866863225b956001252ebeccdb71d"; 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class encapsulates the use of VaapiH264Decoder to a simpler interface. 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// It reads an H.264 Annex B bytestream from a file and outputs the decoded 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// frames (in I420 format) to another file. The output file can be played by 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// $ mplayer test_dec.yuv -demuxer rawvideo -rawvideo w=1920:h=1080 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// To use the class, construct an instance, call Initialize() to specify the 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// input and output file paths, then call Run() to decode the whole stream and 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// output the frames. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class must be created, called and destroyed on a single thread, and 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// does nothing internally on any other thread. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class VaapiH264DecoderLoop { 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VaapiH264DecoderLoop(); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~VaapiH264DecoderLoop(); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Initialize the decoder. Return true if successful. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool Initialize(base::FilePath input_file, base::FilePath output_file); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Run the decode loop. The decoded data is written to the file specified by 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // output_file in Initialize(). Return true if all decoding is successful. 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool Run(); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the MD5 sum of the decoded data. 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string GetMD5Sum(); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Callback from the decoder when a picture is decoded. 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void OutputPicture(int32 input_id, 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<VASurface>& va_surface); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Recycle one surface and put it on available_surfaces_ list. 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RecycleSurface(VASurfaceID va_surface_id); 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Give all surfaces in available_surfaces_ to the decoder. 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RefillSurfaces(); 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Free the current set of surfaces and allocate a new set of 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // surfaces. Returns true when successful. 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool AllocateNewSurfaces(); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Use the data in the frame: write to file and update MD5 sum. 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool ProcessVideoFrame(const scoped_refptr<media::VideoFrame>& frame); 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<VaapiWrapper> wrapper_; 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<VaapiH264Decoder> decoder_; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string data_; // data read from input_file 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath output_file_; // output data is written to this file 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<VASurfaceID> available_surfaces_; 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // These members (x_display_, num_outputted_pictures_, num_surfaces_) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // need to be initialized and possibly freed manually. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Display* x_display_; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int num_outputted_pictures_; // number of pictures already outputted 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t num_surfaces_; // number of surfaces in the current set of surfaces 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MD5Context md5_context_; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VaapiH264DecoderLoop::VaapiH264DecoderLoop() 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : x_display_(NULL), num_outputted_pictures_(0), num_surfaces_(0) { 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MD5Init(&md5_context_); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VaapiH264DecoderLoop::~VaapiH264DecoderLoop() { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We need to destruct decoder and wrapper first because: 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (1) The decoder has a reference to the wrapper. 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (2) The wrapper has a reference to x_display_. 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decoder_.reset(); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wrapper_.reset(); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (x_display_) { 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XCloseDisplay(x_display_); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LogOnError(VaapiH264Decoder::VAVDAH264DecoderFailure error) { 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(FATAL) << "Oh noes! Decoder failed: " << error; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264DecoderLoop::Initialize(base::FilePath input_file, 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath output_file) { 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) x_display_ = XOpenDisplay(NULL); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!x_display_) { 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Can't open X display"; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCodecProfile profile = media::H264PROFILE_BASELINE; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Closure report_error_cb = 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&LogOnError, VaapiH264Decoder::VAAPI_ERROR); 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wrapper_ = VaapiWrapper::Create( 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VaapiWrapper::kDecode, profile, x_display_, report_error_cb); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!wrapper_.get()) { 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Can't create vaapi wrapper"; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decoder_.reset(new VaapiH264Decoder( 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wrapper_.get(), 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&VaapiH264DecoderLoop::OutputPicture, base::Unretained(this)), 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&LogOnError))); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::ReadFileToString(input_file, &data_)) { 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "failed to read input data from " << input_file.value(); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int input_id = 0; // We don't use input_id in this class. 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decoder_->SetStream( 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<const uint8*>(data_.c_str()), data_.size(), input_id); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This creates or truncates output_file. 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Without it, AppendToFile() will not work. 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!output_file.empty()) { 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(output_file, NULL, 0) != 0) { 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output_file_ = output_file; 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264DecoderLoop::Run() { 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (1) { 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (decoder_->Decode()) { 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case VaapiH264Decoder::kDecodeError: 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Decode Error"; 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case VaapiH264Decoder::kAllocateNewSurfaces: 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Allocate new surfaces"; 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!AllocateNewSurfaces()) { 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to allocate new surfaces"; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case VaapiH264Decoder::kRanOutOfStreamData: { 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool rc = decoder_->Flush(); 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Flush returns " << rc; 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return rc; 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case VaapiH264Decoder::kRanOutOfSurfaces: 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Ran out of surfaces"; 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RefillSurfaces(); 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string VaapiH264DecoderLoop::GetMD5Sum() { 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MD5Digest digest; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MD5Final(&digest, &md5_context_); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MD5DigestToBase16(digest); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<media::VideoFrame> CopyNV12ToI420(VAImage* image, void* mem) { 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int width = image->width; 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int height = image->height; 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "CopyNV12ToI420 width=" << width << ", height=" << height; 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Size coded_size(width, height); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Rect visible_rect(width, height); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Size natural_size(width, height); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame = 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoFrame::CreateFrame(media::VideoFrame::I420, 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) coded_size, 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visible_rect, 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) natural_size, 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta()); 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* mem_byte_ptr = static_cast<uint8_t*>(mem); 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* src_y = mem_byte_ptr + image->offsets[0]; 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* src_uv = mem_byte_ptr + image->offsets[1]; 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int src_stride_y = image->pitches[0]; 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int src_stride_uv = image->pitches[1]; 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* dst_y = frame->data(media::VideoFrame::kYPlane); 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* dst_u = frame->data(media::VideoFrame::kUPlane); 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* dst_v = frame->data(media::VideoFrame::kVPlane); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int dst_stride_y = frame->stride(media::VideoFrame::kYPlane); 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int dst_stride_u = frame->stride(media::VideoFrame::kUPlane); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int dst_stride_v = frame->stride(media::VideoFrame::kVPlane); 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rc = libyuv::NV12ToI420(src_y, 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) src_stride_y, 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) src_uv, 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) src_stride_uv, 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dst_y, 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dst_stride_y, 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dst_u, 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dst_stride_u, 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dst_v, 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dst_stride_v, 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) width, 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) height); 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_EQ(0, rc); 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return frame; 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264DecoderLoop::ProcessVideoFrame( 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame) { 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame->HashFrameForTesting(&md5_context_); 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (output_file_.empty()) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < media::VideoFrame::NumPlanes(frame->format()); i++) { 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int to_write = media::VideoFrame::PlaneAllocationSize( 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame->format(), i, frame->coded_size()); 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* buf = reinterpret_cast<const char*>(frame->data(i)); 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int written = base::AppendToFile(output_file_, buf, to_write); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (written != to_write) 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VaapiH264DecoderLoop::OutputPicture( 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32 input_id, 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<VASurface>& va_surface) { 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "OutputPicture: picture " << num_outputted_pictures_++; 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VAImage image; 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* mem; 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!wrapper_->GetVaImageForTesting(va_surface->id(), &image, &mem)) { 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Cannot get VAImage."; 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (image.format.fourcc != VA_FOURCC_NV12) { 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Unexpected image format: " << image.format.fourcc; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wrapper_->ReturnVaImageForTesting(&image); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Convert NV12 to I420 format. 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame = CopyNV12ToI420(&image, mem); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (frame.get()) { 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ProcessVideoFrame(frame)) { 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Write to file failed"; 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Cannot convert image to I420."; 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wrapper_->ReturnVaImageForTesting(&image); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VaapiH264DecoderLoop::RecycleSurface(VASurfaceID va_surface_id) { 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) available_surfaces_.push_back(va_surface_id); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VaapiH264DecoderLoop::RefillSurfaces() { 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < available_surfaces_.size(); i++) { 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VASurface::ReleaseCB release_cb = base::Bind( 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &VaapiH264DecoderLoop::RecycleSurface, base::Unretained(this)); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<VASurface> surface( 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new VASurface(available_surfaces_[i], release_cb)); 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decoder_->ReuseSurface(surface); 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) available_surfaces_.clear(); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264DecoderLoop::AllocateNewSurfaces() { 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_EQ(num_surfaces_, available_surfaces_.size()) 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "not all surfaces are returned"; 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) available_surfaces_.clear(); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wrapper_->DestroySurfaces(); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Size size = decoder_->GetPicSize(); 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_surfaces_ = decoder_->GetRequiredNumOfPictures(); 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return wrapper_->CreateSurfaces(size, num_surfaces_, &available_surfaces_); 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(VaapiH264DecoderTest, TestDecode) { 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath input_file = g_input_file; 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath output_file = g_output_file; 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string md5sum = g_md5sum; 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If nothing specified, use the default file in the source tree. 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (input_file.empty() && output_file.empty() && md5sum.empty()) { 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) input_file = base::FilePath(kDefaultInputFile); 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) md5sum = kDefaultMD5Sum; 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_FALSE(input_file.empty()) << "Need to specify --input_file"; 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Input File: " << input_file.value(); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Output File: " << output_file.value(); 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Expected MD5 sum: " << md5sum; 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::VaapiH264DecoderLoop loop; 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(loop.Initialize(input_file, output_file)) 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "initialize decoder loop failed"; 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(loop.Run()) << "run decoder loop failed"; 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!md5sum.empty()) { 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string actual = loop.GetMD5Sum(); 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Actual MD5 sum: " << actual; 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(md5sum, actual); 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace content 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int main(int argc, char** argv) { 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::CommandLine::Init(argc, argv); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Needed to enable DVLOG through --vmodule. 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) logging::LoggingSettings settings; 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(logging::InitLogging(settings)); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Process command line. 3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(cmd_line); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::CommandLine::SwitchMap switches = cmd_line->GetSwitches(); 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (base::CommandLine::SwitchMap::const_iterator it = switches.begin(); 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != switches.end(); 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->first == "input_file") { 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::g_input_file = base::FilePath(it->second); 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->first == "output_file") { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::g_output_file = base::FilePath(it->second); 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->first == "md5sum") { 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::g_md5sum = it->second; 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->first == "v" || it->first == "vmodule") 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return RUN_ALL_TESTS(); 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 387