/*
 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_tools/video_file_writer.h"

#include <cstdio>
#include <string>

#include "api/scoped_refptr.h"
#include "api/video/video_frame_buffer.h"
#include "rtc_tools/video_file_reader.h"
#include "test/gtest.h"
#include "test/testsupport/file_utils.h"

namespace webrtc {
namespace test {

class VideoFileWriterTest : public ::testing::Test {
 public:
  void SetUp() override {
    video_filename_ = TempFilename(test::OutputPath(), "test_video_file.y4m");

    // Create simple test video of size 6x4.
    FILE* file = fopen(video_filename_.c_str(), "wb");
    ASSERT_TRUE(file != nullptr);
    fprintf(file, "YUV4MPEG2 W6 H4 F60:1 C420 dummyParam\n");
    fprintf(file, "FRAME\n");

    const int i420_size = width * height * 3 / 2;
    // First frame.
    for (int i = 0; i < i420_size; ++i)
      fputc(static_cast<char>(i), file);
    fprintf(file, "FRAME\n");
    // Second frame.
    for (int i = 0; i < i420_size; ++i)
      fputc(static_cast<char>(i + i420_size), file);
    fclose(file);

    // Open the newly created file.
    video_ = test::OpenY4mFile(video_filename_);
    ASSERT_TRUE(video_);
    ASSERT_EQ(video_->number_of_frames(), 2u);
  }

  void TearDown() override {
    if (!video_filename_.empty()) {
      RemoveFile(video_filename_);
    }
    if (!written_video_filename_.empty()) {
      RemoveFile(written_video_filename_);
    }
  }

  // Write and read Y4M file.
  void WriteVideoY4m() {
    // Cleanup existing file if any.
    if (!written_video_filename_.empty()) {
      RemoveFile(written_video_filename_);
    }
    // Create an unique filename, e.g. test_video_file2.y4mZapata.
    written_video_filename_ =
        TempFilename(test::OutputPath(), "test_video_file2.y4m");
    test::WriteY4mVideoToFile(video_, written_video_filename_, fps);
    written_video_ = test::OpenY4mFile(written_video_filename_);
    ASSERT_TRUE(written_video_);
  }

  // Write and read YUV file.
  void WriteVideoYuv() {
    // Cleanup existing file if any.
    if (!written_video_filename_.empty()) {
      RemoveFile(written_video_filename_);
    }
    // Create an unique filename, e.g. test_video_file2.yuvZapata.
    written_video_filename_ =
        TempFilename(test::OutputPath(), "test_video_file2.yuv");
    test::WriteYuvVideoToFile(video_, written_video_filename_, fps);
    written_video_ = test::OpenYuvFile(written_video_filename_, width, height);
    ASSERT_TRUE(written_video_);
  }

  const int width = 6;
  const int height = 4;
  const int fps = 60;
  scoped_refptr<test::Video> video_;
  scoped_refptr<test::Video> written_video_;
  // Each video object must be backed by file!
  std::string video_filename_;
  std::string written_video_filename_;
};

TEST_F(VideoFileWriterTest, TestParsingFileHeaderY4m) {
  WriteVideoY4m();
  EXPECT_EQ(video_->width(), written_video_->width());
  EXPECT_EQ(video_->height(), written_video_->height());
}

TEST_F(VideoFileWriterTest, TestParsingFileHeaderYuv) {
  WriteVideoYuv();
  EXPECT_EQ(video_->width(), written_video_->width());
  EXPECT_EQ(video_->height(), written_video_->height());
}

TEST_F(VideoFileWriterTest, TestParsingNumberOfFramesY4m) {
  WriteVideoY4m();
  EXPECT_EQ(video_->number_of_frames(), written_video_->number_of_frames());
}

TEST_F(VideoFileWriterTest, TestParsingNumberOfFramesYuv) {
  WriteVideoYuv();
  EXPECT_EQ(video_->number_of_frames(), written_video_->number_of_frames());
}

TEST_F(VideoFileWriterTest, TestPixelContentY4m) {
  WriteVideoY4m();
  int cnt = 0;
  for (const scoped_refptr<I420BufferInterface> frame : *written_video_) {
    for (int i = 0; i < width * height; ++i, ++cnt)
      EXPECT_EQ(cnt, frame->DataY()[i]);
    for (int i = 0; i < width / 2 * height / 2; ++i, ++cnt)
      EXPECT_EQ(cnt, frame->DataU()[i]);
    for (int i = 0; i < width / 2 * height / 2; ++i, ++cnt)
      EXPECT_EQ(cnt, frame->DataV()[i]);
  }
}

TEST_F(VideoFileWriterTest, TestPixelContentYuv) {
  WriteVideoYuv();
  int cnt = 0;
  for (const scoped_refptr<I420BufferInterface> frame : *written_video_) {
    for (int i = 0; i < width * height; ++i, ++cnt)
      EXPECT_EQ(cnt, frame->DataY()[i]);
    for (int i = 0; i < width / 2 * height / 2; ++i, ++cnt)
      EXPECT_EQ(cnt, frame->DataU()[i]);
    for (int i = 0; i < width / 2 * height / 2; ++i, ++cnt)
      EXPECT_EQ(cnt, frame->DataV()[i]);
  }
}

}  // namespace test
}  // namespace webrtc
