176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org/*
276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *
476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *  Use of this source code is governed by a BSD-style license
576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *  that can be found in the LICENSE file in the root of the source
676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *  tree. An additional intellectual property rights grant can be found
776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *  in the file PATENTS.  All contributing project authors may
876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *  be found in the AUTHORS file in the root of the source tree.
976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org */
1076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
1176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include <string>
1276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
13693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#include "./vpx_config.h"
1476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/codec_factory.h"
1576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/decode_test_driver.h"
1676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/ivf_video_source.h"
1776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/md5_helper.h"
1876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/test_vectors.h"
1976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/util.h"
20693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#if CONFIG_WEBM_IO
2176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#include "test/webm_video_source.h"
22693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#endif
2376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
2476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgnamespace {
2576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
2676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgconst int kVideoNameParam = 1;
2776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgconst char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
2876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
2976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgstruct ExternalFrameBuffer {
3076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  uint8_t *data;
3176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  size_t size;
3276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int in_use;
3376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org};
3476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
3576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Class to manipulate a list of external frame buffers.
3676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgclass ExternalFrameBufferList {
3776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org public:
3876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList()
3976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      : num_buffers_(0),
4076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        ext_fb_list_(NULL) {}
4176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
4276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual ~ExternalFrameBufferList() {
4376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    for (int i = 0; i < num_buffers_; ++i) {
4476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      delete [] ext_fb_list_[i].data;
4576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
4676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    delete [] ext_fb_list_;
4776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
4876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
4976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Creates the list to hold the external buffers. Returns true on success.
5076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  bool CreateBufferList(int num_buffers) {
5176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (num_buffers < 0)
5276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      return false;
5376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
5476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    num_buffers_ = num_buffers;
5576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ext_fb_list_ = new ExternalFrameBuffer[num_buffers_];
5676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    EXPECT_TRUE(ext_fb_list_ != NULL);
5776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    memset(ext_fb_list_, 0, sizeof(ext_fb_list_[0]) * num_buffers_);
5876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return true;
5976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
6076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
6176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Searches the frame buffer list for a free frame buffer. Makes sure
6276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // that the frame buffer is at least |min_size| in bytes. Marks that the
6376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // frame buffer is in use by libvpx. Finally sets |fb| to point to the
6476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // external frame buffer. Returns < 0 on an error.
6576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int GetFreeFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
6676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    EXPECT_TRUE(fb != NULL);
6776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    const int idx = FindFreeBufferIndex();
6876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (idx == num_buffers_)
6976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      return -1;
7076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
7176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (ext_fb_list_[idx].size < min_size) {
7276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      delete [] ext_fb_list_[idx].data;
7376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ext_fb_list_[idx].data = new uint8_t[min_size];
7476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ext_fb_list_[idx].size = min_size;
7576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
7676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
7776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    SetFrameBuffer(idx, fb);
7876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return 0;
7976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
8076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
8176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Test function that will not allocate any data for the frame buffer.
8276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Returns < 0 on an error.
8376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int GetZeroFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
8476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    EXPECT_TRUE(fb != NULL);
8576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    const int idx = FindFreeBufferIndex();
8676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (idx == num_buffers_)
8776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      return -1;
8876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
8976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (ext_fb_list_[idx].size < min_size) {
9076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      delete [] ext_fb_list_[idx].data;
9176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ext_fb_list_[idx].data = NULL;
9276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ext_fb_list_[idx].size = min_size;
9376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
9476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
9576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    SetFrameBuffer(idx, fb);
9676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return 0;
9776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
9876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
9976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Marks the external frame buffer that |fb| is pointing too as free.
10076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Returns < 0 on an error.
10176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int ReturnFrameBuffer(vpx_codec_frame_buffer_t *fb) {
10276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    EXPECT_TRUE(fb != NULL);
10376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ExternalFrameBuffer *const ext_fb =
10476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        reinterpret_cast<ExternalFrameBuffer*>(fb->priv);
10576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    EXPECT_TRUE(ext_fb != NULL);
10676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    EXPECT_EQ(1, ext_fb->in_use);
10776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ext_fb->in_use = 0;
10876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return 0;
10976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
11076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
11176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Checks that the ximage data is contained within the external frame buffer
11276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // private data passed back in the ximage.
11376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  void CheckXImageFrameBuffer(const vpx_image_t *img) {
11476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (img->fb_priv != NULL) {
11576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      const struct ExternalFrameBuffer *const ext_fb =
11676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org          reinterpret_cast<ExternalFrameBuffer*>(img->fb_priv);
11776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
11876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ASSERT_TRUE(img->planes[0] >= ext_fb->data &&
11976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                  img->planes[0] < (ext_fb->data + ext_fb->size));
12076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
12176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
12276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
12376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org private:
12476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Returns the index of the first free frame buffer. Returns |num_buffers_|
12576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // if there are no free frame buffers.
12676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int FindFreeBufferIndex() {
12776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    int i;
12876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    // Find a free frame buffer.
12976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    for (i = 0; i < num_buffers_; ++i) {
13076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      if (!ext_fb_list_[i].in_use)
13176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        break;
13276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
13376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return i;
13476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
13576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
13676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Sets |fb| to an external frame buffer. idx is the index into the frame
13776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // buffer list.
13876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  void SetFrameBuffer(int idx, vpx_codec_frame_buffer_t *fb) {
13976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_TRUE(fb != NULL);
14076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    fb->data = ext_fb_list_[idx].data;
14176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    fb->size = ext_fb_list_[idx].size;
14276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_EQ(0, ext_fb_list_[idx].in_use);
14376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ext_fb_list_[idx].in_use = 1;
14476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    fb->priv = &ext_fb_list_[idx];
14576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
14676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
14776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int num_buffers_;
14876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBuffer *ext_fb_list_;
14976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org};
15076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
15176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Callback used by libvpx to request the application to return a frame
15276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// buffer of at least |min_size| in bytes.
15376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgint get_vp9_frame_buffer(void *user_priv, size_t min_size,
15476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                         vpx_codec_frame_buffer_t *fb) {
15576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList *const fb_list =
15676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
15776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  return fb_list->GetFreeFrameBuffer(min_size, fb);
15876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
15976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
16076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Callback used by libvpx to tell the application that |fb| is not needed
16176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// anymore.
16276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgint release_vp9_frame_buffer(void *user_priv,
16376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                             vpx_codec_frame_buffer_t *fb) {
16476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList *const fb_list =
16576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
16676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  return fb_list->ReturnFrameBuffer(fb);
16776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
16876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
16976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Callback will not allocate data for frame buffer.
17076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgint get_vp9_zero_frame_buffer(void *user_priv, size_t min_size,
17176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                              vpx_codec_frame_buffer_t *fb) {
17276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList *const fb_list =
17376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
17476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  return fb_list->GetZeroFrameBuffer(min_size, fb);
17576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
17676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
17776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Callback will allocate one less byte than |min_size|.
17876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgint get_vp9_one_less_byte_frame_buffer(void *user_priv, size_t min_size,
17976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                       vpx_codec_frame_buffer_t *fb) {
18076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList *const fb_list =
18176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
18276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  return fb_list->GetFreeFrameBuffer(min_size - 1, fb);
18376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
18476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
18576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Callback will not release the external frame buffer.
18676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgint do_not_release_vp9_frame_buffer(void *user_priv,
18776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                    vpx_codec_frame_buffer_t *fb) {
18876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  (void)user_priv;
18976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  (void)fb;
19076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  return 0;
19176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
19276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
19376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Class for testing passing in external frame buffers to libvpx.
19476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgclass ExternalFrameBufferMD5Test
19576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    : public ::libvpx_test::DecoderTest,
19676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      public ::libvpx_test::CodecTestWithParam<const char*> {
19776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org protected:
19876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferMD5Test()
19976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
20076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        md5_file_(NULL),
20176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        num_buffers_(0) {}
20276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
20376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual ~ExternalFrameBufferMD5Test() {
20476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (md5_file_ != NULL)
20576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      fclose(md5_file_);
20676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
20776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
20876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual void PreDecodeFrameHook(
20976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      const libvpx_test::CompressedVideoSource &video,
21076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      libvpx_test::Decoder *decoder) {
21176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (num_buffers_ > 0 && video.frame_number() == 0) {
21276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      // Have libvpx use frame buffers we create.
21376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ASSERT_TRUE(fb_list_.CreateBufferList(num_buffers_));
21476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      ASSERT_EQ(VPX_CODEC_OK,
21576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                decoder->SetFrameBufferFunctions(
21693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                    GetVP9FrameBuffer, ReleaseVP9FrameBuffer, this));
21776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
21876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
21976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
22076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  void OpenMD5File(const std::string &md5_file_name_) {
22176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
22276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
22376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        << md5_file_name_;
22476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
22576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
22676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual void DecompressedFrameHook(const vpx_image_t &img,
22776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                     const unsigned int frame_number) {
22876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_TRUE(md5_file_ != NULL);
22976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    char expected_md5[33];
23076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    char junk[128];
23176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
23276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    // Read correct md5 checksums.
23376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
23476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_NE(EOF, res) << "Read md5 data failed";
23576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    expected_md5[32] = '\0';
23676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
23776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ::libvpx_test::MD5 md5_res;
23876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    md5_res.Add(&img);
23976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    const char *const actual_md5 = md5_res.Get();
24076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
24176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    // Check md5 match.
24276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_STREQ(expected_md5, actual_md5)
24376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        << "Md5 checksums don't match: frame number = " << frame_number;
24476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
24576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
24676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Callback to get a free external frame buffer. Return value < 0 is an
24776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // error.
24893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  static int GetVP9FrameBuffer(void *user_priv, size_t min_size,
24976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                               vpx_codec_frame_buffer_t *fb) {
25076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ExternalFrameBufferMD5Test *const md5Test =
25176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
25276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return md5Test->fb_list_.GetFreeFrameBuffer(min_size, fb);
25376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
25476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
25576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Callback to release an external frame buffer. Return value < 0 is an
25676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // error.
25776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  static int ReleaseVP9FrameBuffer(void *user_priv,
25876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                   vpx_codec_frame_buffer_t *fb) {
25976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ExternalFrameBufferMD5Test *const md5Test =
26076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
26176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return md5Test->fb_list_.ReturnFrameBuffer(fb);
26276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
26376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
26476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; }
26576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int num_buffers() const { return num_buffers_; }
26676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
26776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org private:
26876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  FILE *md5_file_;
26976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int num_buffers_;
27076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList fb_list_;
27176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org};
27276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
273693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#if CONFIG_WEBM_IO
27476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Class for testing passing in external frame buffers to libvpx.
27576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgclass ExternalFrameBufferTest : public ::testing::Test {
27676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org protected:
27776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferTest()
27876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      : video_(NULL),
27976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        decoder_(NULL),
28076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        num_buffers_(0) {}
28176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
28276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual void SetUp() {
28376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
28476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_TRUE(video_ != NULL);
28576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    video_->Init();
28676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    video_->Begin();
28776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
28876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    vpx_codec_dec_cfg_t cfg = {0};
28976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
29076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    ASSERT_TRUE(decoder_ != NULL);
29176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
29276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
29376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  virtual void TearDown() {
29476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    delete decoder_;
29576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    delete video_;
29676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
29776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
29876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Passes the external frame buffer information to libvpx.
29976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  vpx_codec_err_t SetFrameBufferFunctions(
30076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      int num_buffers,
30176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      vpx_get_frame_buffer_cb_fn_t cb_get,
30276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      vpx_release_frame_buffer_cb_fn_t cb_release) {
30376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (num_buffers > 0) {
30476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      num_buffers_ = num_buffers;
30576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      EXPECT_TRUE(fb_list_.CreateBufferList(num_buffers_));
30676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
30776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
30876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return decoder_->SetFrameBufferFunctions(cb_get, cb_release, &fb_list_);
30976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
31076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
31176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  vpx_codec_err_t DecodeOneFrame() {
31276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    const vpx_codec_err_t res =
31376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
31476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    CheckDecodedFrames();
31576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    if (res == VPX_CODEC_OK)
31676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      video_->Next();
31776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return res;
31876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
31976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
32076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  vpx_codec_err_t DecodeRemainingFrames() {
32176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    for (; video_->cxdata() != NULL; video_->Next()) {
32276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      const vpx_codec_err_t res =
32376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org          decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
32476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      if (res != VPX_CODEC_OK)
32576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org        return res;
32676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      CheckDecodedFrames();
32776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
32876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    return VPX_CODEC_OK;
32976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
33076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
33176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org private:
33276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  void CheckDecodedFrames() {
33376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
33476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    const vpx_image_t *img = NULL;
33576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
33676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    // Get decompressed data
33776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    while ((img = dec_iter.Next()) != NULL) {
33876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      fb_list_.CheckXImageFrameBuffer(img);
33976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    }
34076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
34176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
34276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  libvpx_test::WebMVideoSource *video_;
34376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  libvpx_test::VP9Decoder *decoder_;
34476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  int num_buffers_;
34576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ExternalFrameBufferList fb_list_;
34676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org};
347693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#endif  // CONFIG_WEBM_IO
34876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
34976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// This test runs through the set of test vectors, and decodes them.
35076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Libvpx will call into the application to allocate a frame buffer when
35176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// needed. The md5 checksums are computed for each frame in the video file.
35276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// If md5 checksums match the correct md5 data, then the test is passed.
35376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// Otherwise, the test failed.
35476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
35576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const std::string filename = GET_PARAM(kVideoNameParam);
35676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  libvpx_test::CompressedVideoSource *video = NULL;
35776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
35876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
35976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
36076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int jitter_buffers = 4;
36176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers =
36276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
36376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  set_num_buffers(num_buffers);
36476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
36576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#if CONFIG_VP8_DECODER
36676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Tell compiler we are not using kVP8TestVectors.
36776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  (void)libvpx_test::kVP8TestVectors;
36876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#endif
36976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
37076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Open compressed video file.
37176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  if (filename.substr(filename.length() - 3, 3) == "ivf") {
37276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    video = new libvpx_test::IVFVideoSource(filename);
37376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  } else {
374693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#if CONFIG_WEBM_IO
37576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org    video = new libvpx_test::WebMVideoSource(filename);
376693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#else
377693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
378693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com            filename.c_str());
379693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com    return;
380693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#endif
38176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  }
38276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_TRUE(video != NULL);
38376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  video->Init();
38476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
38576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Construct md5 file name.
38676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const std::string md5_filename = filename + ".md5";
38776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  OpenMD5File(md5_filename);
38876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
38976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Decode frame, and check the md5 matching.
39076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
39176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  delete video;
39276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
39376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
394693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#if CONFIG_WEBM_IO
39576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, MinFrameBuffers) {
39676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Minimum number of external frame buffers for VP9 is
39776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS.
39876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
39976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK,
40076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(
40176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
40276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
40376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
40476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
40576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, EightJitterBuffers) {
40676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
40776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // #VPX_MAXIMUM_WORK_BUFFERS + eight jitter buffers.
40876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int jitter_buffers = 8;
40976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers =
41076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
41176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK,
41276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(
41376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
41476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
41576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
41676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
41776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, NotEnoughBuffers) {
41876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // Minimum number of external frame buffers for VP9 is
41976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. Most files will
42076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  // only use 5 frame buffers at one time.
42176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = 2;
42276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK,
42376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(
42476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
42576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
42676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
42776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
42876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
42976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, NoRelease) {
43076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
43176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK,
43276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
43376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                    do_not_release_vp9_frame_buffer));
43476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
43576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
43676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
43776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
43876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, NullRealloc) {
43976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
44076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK,
44176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(num_buffers, get_vp9_zero_frame_buffer,
44276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                    release_vp9_frame_buffer));
44376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
44476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
44576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
44676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, ReallocOneLessByte) {
44776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
44876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK,
44976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(
45076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                num_buffers, get_vp9_one_less_byte_frame_buffer,
45176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                release_vp9_frame_buffer));
45276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
45376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
45476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
45576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, NullGetFunction) {
45676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
45776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
45876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(num_buffers, NULL,
45976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                                    release_vp9_frame_buffer));
46076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
46176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
46276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, NullReleaseFunction) {
46376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
46476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
46576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer, NULL));
46676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
46776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
46876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgTEST_F(ExternalFrameBufferTest, SetAfterDecode) {
46976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
47076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
47176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  ASSERT_EQ(VPX_CODEC_ERROR,
47276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org            SetFrameBufferFunctions(
47376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
47476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
475693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com#endif  // CONFIG_WEBM_IO
47676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
47776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgVP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test,
47893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                          ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
47993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                                              libvpx_test::kVP9TestVectors +
48093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                                              libvpx_test::kNumVP9TestVectors));
48176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}  // namespace
482