1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/codec_factory.h"
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/decode_test_driver.h"
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/ivf_video_source.h"
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/md5_helper.h"
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/test_vectors.h"
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/util.h"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/webm_video_source.h"
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan
21233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace {
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan
23233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst int kVideoNameParam = 1;
24233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan
26233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ExternalFrameBuffer {
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint8_t *data;
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t size;
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int in_use;
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Class to manipulate a list of external frame buffers.
33233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass ExternalFrameBufferList {
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan public:
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList()
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan      : num_buffers_(0),
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ext_fb_list_(NULL) {}
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan  virtual ~ExternalFrameBufferList() {
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int i = 0; i < num_buffers_; ++i) {
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete [] ext_fb_list_[i].data;
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] ext_fb_list_;
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Creates the list to hold the external buffers. Returns true on success.
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan  bool CreateBufferList(int num_buffers) {
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (num_buffers < 0)
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan    num_buffers_ = num_buffers;
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ext_fb_list_ = new ExternalFrameBuffer[num_buffers_];
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(ext_fb_list_ != NULL);
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan    memset(ext_fb_list_, 0, sizeof(ext_fb_list_[0]) * num_buffers_);
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Searches the frame buffer list for a free frame buffer. Makes sure
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // that the frame buffer is at least |min_size| in bytes. Marks that the
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // frame buffer is in use by libvpx. Finally sets |fb| to point to the
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // external frame buffer. Returns < 0 on an error.
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int GetFreeFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(fb != NULL);
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int idx = FindFreeBufferIndex();
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx == num_buffers_)
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ext_fb_list_[idx].size < min_size) {
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete [] ext_fb_list_[idx].data;
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ext_fb_list_[idx].data = new uint8_t[min_size];
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ext_fb_list_[idx].size = min_size;
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan    SetFrameBuffer(idx, fb);
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Test function that will not allocate any data for the frame buffer.
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Returns < 0 on an error.
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int GetZeroFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(fb != NULL);
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int idx = FindFreeBufferIndex();
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx == num_buffers_)
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ext_fb_list_[idx].size < min_size) {
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete [] ext_fb_list_[idx].data;
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ext_fb_list_[idx].data = NULL;
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ext_fb_list_[idx].size = min_size;
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan    SetFrameBuffer(idx, fb);
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Marks the external frame buffer that |fb| is pointing too as free.
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Returns < 0 on an error.
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int ReturnFrameBuffer(vpx_codec_frame_buffer_t *fb) {
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(fb != NULL);
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ExternalFrameBuffer *const ext_fb =
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan        reinterpret_cast<ExternalFrameBuffer*>(fb->priv);
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(ext_fb != NULL);
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_EQ(1, ext_fb->in_use);
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ext_fb->in_use = 0;
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Checks that the ximage data is contained within the external frame buffer
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // private data passed back in the ximage.
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void CheckXImageFrameBuffer(const vpx_image_t *img) {
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (img->fb_priv != NULL) {
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const struct ExternalFrameBuffer *const ext_fb =
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan          reinterpret_cast<ExternalFrameBuffer*>(img->fb_priv);
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ASSERT_TRUE(img->planes[0] >= ext_fb->data &&
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  img->planes[0] < (ext_fb->data + ext_fb->size));
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan private:
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Returns the index of the first free frame buffer. Returns |num_buffers_|
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // if there are no free frame buffers.
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int FindFreeBufferIndex() {
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int i;
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Find a free frame buffer.
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < num_buffers_; ++i) {
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!ext_fb_list_[i].in_use)
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return i;
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Sets |fb| to an external frame buffer. idx is the index into the frame
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // buffer list.
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void SetFrameBuffer(int idx, vpx_codec_frame_buffer_t *fb) {
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_TRUE(fb != NULL);
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fb->data = ext_fb_list_[idx].data;
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fb->size = ext_fb_list_[idx].size;
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_EQ(0, ext_fb_list_[idx].in_use);
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ext_fb_list_[idx].in_use = 1;
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fb->priv = &ext_fb_list_[idx];
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int num_buffers_;
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBuffer *ext_fb_list_;
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Callback used by libvpx to request the application to return a frame
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan// buffer of at least |min_size| in bytes.
150233d2500723e5594f3e7c70896ffeeef32b9c950ywanint get_vp9_frame_buffer(void *user_priv, size_t min_size,
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         vpx_codec_frame_buffer_t *fb) {
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList *const fb_list =
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return fb_list->GetFreeFrameBuffer(min_size, fb);
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Callback used by libvpx to tell the application that |fb| is not needed
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan// anymore.
159233d2500723e5594f3e7c70896ffeeef32b9c950ywanint release_vp9_frame_buffer(void *user_priv,
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             vpx_codec_frame_buffer_t *fb) {
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList *const fb_list =
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return fb_list->ReturnFrameBuffer(fb);
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Callback will not allocate data for frame buffer.
167233d2500723e5594f3e7c70896ffeeef32b9c950ywanint get_vp9_zero_frame_buffer(void *user_priv, size_t min_size,
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              vpx_codec_frame_buffer_t *fb) {
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList *const fb_list =
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return fb_list->GetZeroFrameBuffer(min_size, fb);
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Callback will allocate one less byte than |min_size|.
175233d2500723e5594f3e7c70896ffeeef32b9c950ywanint get_vp9_one_less_byte_frame_buffer(void *user_priv, size_t min_size,
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       vpx_codec_frame_buffer_t *fb) {
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList *const fb_list =
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return fb_list->GetFreeFrameBuffer(min_size - 1, fb);
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Callback will not release the external frame buffer.
183233d2500723e5594f3e7c70896ffeeef32b9c950ywanint do_not_release_vp9_frame_buffer(void *user_priv,
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    vpx_codec_frame_buffer_t *fb) {
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void)user_priv;
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void)fb;
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Class for testing passing in external frame buffers to libvpx.
191233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass ExternalFrameBufferMD5Test
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : public ::libvpx_test::DecoderTest,
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan      public ::libvpx_test::CodecTestWithParam<const char*> {
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan protected:
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferMD5Test()
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan      : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan        md5_file_(NULL),
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan        num_buffers_(0) {}
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  virtual ~ExternalFrameBufferMD5Test() {
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (md5_file_ != NULL)
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fclose(md5_file_);
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan  virtual void PreDecodeFrameHook(
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const libvpx_test::CompressedVideoSource &video,
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan      libvpx_test::Decoder *decoder) {
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (num_buffers_ > 0 && video.frame_number() == 0) {
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Have libvpx use frame buffers we create.
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ASSERT_TRUE(fb_list_.CreateBufferList(num_buffers_));
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ASSERT_EQ(VPX_CODEC_OK,
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan                decoder->SetFrameBufferFunctions(
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    GetVP9FrameBuffer, ReleaseVP9FrameBuffer, this));
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void OpenMD5File(const std::string &md5_file_name_) {
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan        << md5_file_name_;
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  virtual void DecompressedFrameHook(const vpx_image_t &img,
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     const unsigned int frame_number) {
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_TRUE(md5_file_ != NULL);
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char expected_md5[33];
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char junk[128];
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Read correct md5 checksums.
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_NE(EOF, res) << "Read md5 data failed";
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    expected_md5[32] = '\0';
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ::libvpx_test::MD5 md5_res;
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    md5_res.Add(&img);
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const char *const actual_md5 = md5_res.Get();
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check md5 match.
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_STREQ(expected_md5, actual_md5)
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan        << "Md5 checksums don't match: frame number = " << frame_number;
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Callback to get a free external frame buffer. Return value < 0 is an
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // error.
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan  static int GetVP9FrameBuffer(void *user_priv, size_t min_size,
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               vpx_codec_frame_buffer_t *fb) {
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ExternalFrameBufferMD5Test *const md5Test =
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan        reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return md5Test->fb_list_.GetFreeFrameBuffer(min_size, fb);
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Callback to release an external frame buffer. Return value < 0 is an
253233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // error.
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan  static int ReleaseVP9FrameBuffer(void *user_priv,
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   vpx_codec_frame_buffer_t *fb) {
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ExternalFrameBufferMD5Test *const md5Test =
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan        reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return md5Test->fb_list_.ReturnFrameBuffer(fb);
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; }
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int num_buffers() const { return num_buffers_; }
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan private:
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FILE *md5_file_;
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int num_buffers_;
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList fb_list_;
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Class for testing passing in external frame buffers to libvpx.
271233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass ExternalFrameBufferTest : public ::testing::Test {
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan protected:
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferTest()
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan      : video_(NULL),
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan        decoder_(NULL),
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan        num_buffers_(0) {}
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan  virtual void SetUp() {
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan    video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_TRUE(video_ != NULL);
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    video_->Init();
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan    video_->Begin();
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_dec_cfg_t cfg = {0};
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan    decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ASSERT_TRUE(decoder_ != NULL);
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
289233d2500723e5594f3e7c70896ffeeef32b9c950ywan  virtual void TearDown() {
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete decoder_;
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete video_;
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Passes the external frame buffer information to libvpx.
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_err_t SetFrameBufferFunctions(
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int num_buffers,
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vpx_get_frame_buffer_cb_fn_t cb_get,
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan      vpx_release_frame_buffer_cb_fn_t cb_release) {
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (num_buffers > 0) {
300233d2500723e5594f3e7c70896ffeeef32b9c950ywan      num_buffers_ = num_buffers;
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EXPECT_TRUE(fb_list_.CreateBufferList(num_buffers_));
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return decoder_->SetFrameBufferFunctions(cb_get, cb_release, &fb_list_);
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_err_t DecodeOneFrame() {
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const vpx_codec_err_t res =
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan        decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
310233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CheckDecodedFrames();
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (res == VPX_CODEC_OK)
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan      video_->Next();
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return res;
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
316233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_err_t DecodeRemainingFrames() {
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (; video_->cxdata() != NULL; video_->Next()) {
318233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const vpx_codec_err_t res =
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan          decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (res != VPX_CODEC_OK)
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return res;
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan      CheckDecodedFrames();
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
324233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return VPX_CODEC_OK;
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
326233d2500723e5594f3e7c70896ffeeef32b9c950ywan
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan private:
328233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void CheckDecodedFrames() {
329233d2500723e5594f3e7c70896ffeeef32b9c950ywan    libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
330233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const vpx_image_t *img = NULL;
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Get decompressed data
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while ((img = dec_iter.Next()) != NULL) {
334233d2500723e5594f3e7c70896ffeeef32b9c950ywan      fb_list_.CheckXImageFrameBuffer(img);
335233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
337233d2500723e5594f3e7c70896ffeeef32b9c950ywan
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan  libvpx_test::WebMVideoSource *video_;
339233d2500723e5594f3e7c70896ffeeef32b9c950ywan  libvpx_test::VP9Decoder *decoder_;
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int num_buffers_;
341233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ExternalFrameBufferList fb_list_;
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
344233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This test runs through the set of test vectors, and decodes them.
345233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Libvpx will call into the application to allocate a frame buffer when
346233d2500723e5594f3e7c70896ffeeef32b9c950ywan// needed. The md5 checksums are computed for each frame in the video file.
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan// If md5 checksums match the correct md5 data, then the test is passed.
348233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Otherwise, the test failed.
349233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const std::string filename = GET_PARAM(kVideoNameParam);
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan  libvpx_test::CompressedVideoSource *video = NULL;
352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
354233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
355233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int jitter_buffers = 4;
356233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers =
357233d2500723e5594f3e7c70896ffeeef32b9c950ywan      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
358233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_num_buffers(num_buffers);
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan
360233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_VP8_DECODER
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Tell compiler we are not using kVP8TestVectors.
362233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void)libvpx_test::kVP8TestVectors;
363233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Open compressed video file.
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (filename.substr(filename.length() - 3, 3) == "ivf") {
367233d2500723e5594f3e7c70896ffeeef32b9c950ywan    video = new libvpx_test::IVFVideoSource(filename);
368233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
369233d2500723e5594f3e7c70896ffeeef32b9c950ywan    video = new libvpx_test::WebMVideoSource(filename);
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
371233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_TRUE(video != NULL);
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan  video->Init();
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
374233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Construct md5 file name.
375233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const std::string md5_filename = filename + ".md5";
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan  OpenMD5File(md5_filename);
377233d2500723e5594f3e7c70896ffeeef32b9c950ywan
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Decode frame, and check the md5 matching.
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete video;
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
382233d2500723e5594f3e7c70896ffeeef32b9c950ywan
383233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, MinFrameBuffers) {
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Minimum number of external frame buffers for VP9 is
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS.
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK,
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(
389233d2500723e5594f3e7c70896ffeeef32b9c950ywan                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
390233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan
393233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, EightJitterBuffers) {
394233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // #VPX_MAXIMUM_WORK_BUFFERS + eight jitter buffers.
396233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int jitter_buffers = 8;
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers =
398233d2500723e5594f3e7c70896ffeeef32b9c950ywan      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
399233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK,
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(
401233d2500723e5594f3e7c70896ffeeef32b9c950ywan                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
402233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
405233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, NotEnoughBuffers) {
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Minimum number of external frame buffers for VP9 is
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. Most files will
408233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // only use 5 frame buffers at one time.
409233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = 2;
410233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK,
411233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(
412233d2500723e5594f3e7c70896ffeeef32b9c950ywan                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
415233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
416233d2500723e5594f3e7c70896ffeeef32b9c950ywan
417233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, NoRelease) {
418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK,
420233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
421233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    do_not_release_vp9_frame_buffer));
422233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
424233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
426233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, NullRealloc) {
427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
428233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK,
429233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(num_buffers, get_vp9_zero_frame_buffer,
430233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    release_vp9_frame_buffer));
431233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
432233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
433233d2500723e5594f3e7c70896ffeeef32b9c950ywan
434233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, ReallocOneLessByte) {
435233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
436233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK,
437233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(
438233d2500723e5594f3e7c70896ffeeef32b9c950ywan                num_buffers, get_vp9_one_less_byte_frame_buffer,
439233d2500723e5594f3e7c70896ffeeef32b9c950ywan                release_vp9_frame_buffer));
440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
441233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
442233d2500723e5594f3e7c70896ffeeef32b9c950ywan
443233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, NullGetFunction) {
444233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
445233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
446233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(num_buffers, NULL,
447233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    release_vp9_frame_buffer));
448233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
450233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, NullReleaseFunction) {
451233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
452233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
453233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer, NULL));
454233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
455233d2500723e5594f3e7c70896ffeeef32b9c950ywan
456233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_F(ExternalFrameBufferTest, SetAfterDecode) {
457233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
458233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
459233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ASSERT_EQ(VPX_CODEC_ERROR,
460233d2500723e5594f3e7c70896ffeeef32b9c950ywan            SetFrameBufferFunctions(
461233d2500723e5594f3e7c70896ffeeef32b9c950ywan                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
462233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
463233d2500723e5594f3e7c70896ffeeef32b9c950ywan
464233d2500723e5594f3e7c70896ffeeef32b9c950ywanVP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test,
465233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
466233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              libvpx_test::kVP9TestVectors +
467233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              libvpx_test::kNumVP9TestVectors));
468233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace
469