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