1ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org/*
2ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *
4ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *  Use of this source code is governed by a BSD-style license
5ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *  that can be found in the LICENSE file in the root of the source
6ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *  tree. An additional intellectual property rights grant can be found
7ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *  in the file PATENTS.  All contributing project authors may
8ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org */
10ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
11ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#ifndef TEST_DECODE_TEST_DRIVER_H_
12ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#define TEST_DECODE_TEST_DRIVER_H_
13ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#include <cstring>
14ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#include "third_party/googletest/src/include/gtest/gtest.h"
15f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "./vpx_config.h"
16ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#include "vpx/vpx_decoder.h"
17ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
18ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.orgnamespace libvpx_test {
19ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
20923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.orgclass CodecFactory;
21ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.orgclass CompressedVideoSource;
22ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
23ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org// Provides an object to handle decoding output
24ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.orgclass DxDataIterator {
25ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org public:
26ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  explicit DxDataIterator(vpx_codec_ctx_t *decoder)
27ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org      : decoder_(decoder), iter_(NULL) {}
28ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
29ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  const vpx_image_t *Next() {
30ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    return vpx_codec_get_frame(decoder_, &iter_);
31ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
32ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
33ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org private:
34ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  vpx_codec_ctx_t  *decoder_;
35ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  vpx_codec_iter_t  iter_;
36ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org};
37ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
38ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org// Provides a simplified interface to manage one video decoding.
39f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org// Similar to Encoder class, the exact services should be added
40f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org// as more tests are added.
41ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.orgclass Decoder {
42ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org public:
43ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
44923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org      : cfg_(cfg), deadline_(deadline), init_done_(false) {
45ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    memset(&decoder_, 0, sizeof(decoder_));
46ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
47ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
48923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  virtual ~Decoder() {
49ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    vpx_codec_destroy(&decoder_);
50ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
51ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
52e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org  vpx_codec_err_t PeekStream(const uint8_t *cxdata, size_t size,
53e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org                             vpx_codec_stream_info_t *stream_info);
54e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org
5576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size);
56ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
57e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size,
58e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org                              void *user_priv);
59e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org
60ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  DxDataIterator GetDxData() {
61ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    return DxDataIterator(&decoder_);
62ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
63ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
64ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  void set_deadline(unsigned long deadline) {
65ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    deadline_ = deadline;
66ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
67ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
68ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  void Control(int ctrl_id, int arg) {
69923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org    InitOnce();
70ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
71ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
72ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
73ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
74ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org  void Control(int ctrl_id, const void *arg) {
75923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org    InitOnce();
76ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org    const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
77ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org    ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
78ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org  }
79ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org
80923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  const char* DecodeError() {
81ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    const char *detail = vpx_codec_error_detail(&decoder_);
82ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    return detail ? detail : vpx_codec_error(&decoder_);
83ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  }
84ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
8576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Passes the external frame buffer information to libvpx.
8676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  vpx_codec_err_t SetFrameBufferFunctions(
8776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      vpx_get_frame_buffer_cb_fn_t cb_get,
8876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      vpx_release_frame_buffer_cb_fn_t cb_release, void *user_priv) {
8976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    InitOnce();
9076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return vpx_codec_set_frame_buffer_functions(
9176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        &decoder_, cb_get, cb_release, user_priv);
9276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
9376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
94ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org  const char* GetDecoderName() const {
95e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org    return vpx_codec_iface_name(CodecInterface());
96e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org  }
97e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org
98ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org  bool IsVP8() const;
99ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org
100ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org protected:
10176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual vpx_codec_iface_t* CodecInterface() const = 0;
102923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org
103923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  void InitOnce() {
104923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org    if (!init_done_) {
105923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org      const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_,
106923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org                                                     CodecInterface(),
107923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org                                                     &cfg_, 0);
108923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org      ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
109923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org      init_done_ = true;
110923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org    }
111ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org  }
112ab3cb4e3f1f39482ee3bd15c6918af868144d6dejohannkoenig@chromium.org
113ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  vpx_codec_ctx_t     decoder_;
114ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  vpx_codec_dec_cfg_t cfg_;
115ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  unsigned int        deadline_;
116923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  bool                init_done_;
117ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org};
118ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
119ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org// Common test functionality for all Decoder tests.
120ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.orgclass DecoderTest {
121ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org public:
122923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  // Main decoding loop
123ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  virtual void RunLoop(CompressedVideoSource *video);
12495aa45d73048f952dcaad0037429cc6751b34f2fjohannkoenig@google.com  virtual void RunLoop(CompressedVideoSource *video,
12595aa45d73048f952dcaad0037429cc6751b34f2fjohannkoenig@google.com                       const vpx_codec_dec_cfg_t &dec_cfg);
126ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
127d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org  // Hook to be called before decompressing every frame.
128d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org  virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/,
129d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org                                  Decoder* /*decoder*/) {}
130d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org
131f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org  // Hook to be called to handle decode result. Return true to continue.
132f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
133d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org                                  const CompressedVideoSource& /*video*/,
134f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org                                  Decoder *decoder) {
135f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org    EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
136f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org    return VPX_CODEC_OK == res_dec;
137f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org  }
138f6ac5240e9583122bd001dbee63a53b28e6f5beafgalligan@chromium.org
139ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  // Hook to be called on every decompressed frame.
140d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org  virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
141d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org                                     const unsigned int /*frame_number*/) {}
142ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
143ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org  // Hook to be called on peek result
144ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org  virtual void HandlePeekResult(Decoder* const decoder,
145ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org                                CompressedVideoSource *video,
146ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org                                const vpx_codec_err_t res_peek);
147ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org
148ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org protected:
149923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  explicit DecoderTest(const CodecFactory *codec) : codec_(codec) {}
150ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
151ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org  virtual ~DecoderTest() {}
152923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org
153923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org  const CodecFactory *codec_;
154ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org};
155ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
156ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org}  // namespace libvpx_test
157ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org
158ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#endif  // TEST_DECODE_TEST_DRIVER_H_
159