// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>

#include "base/bind.h"
#include "base/logging.h"
#include "media/webm/cluster_builder.h"
#include "media/webm/webm_cluster_parser.h"
#include "media/webm/webm_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::InSequence;
using ::testing::Return;
using ::testing::_;

namespace media {

enum {
  kTimecodeScale = 1000000,  // Timecode scale for millisecond timestamps.
  kAudioTrackNum = 1,
  kVideoTrackNum = 2,
};

struct BlockInfo {
  int track_num;
  int timestamp;
  int duration;
  bool use_simple_block;
};

const BlockInfo kDefaultBlockInfo[] = {
  { kAudioTrackNum, 0, 23, true },
  { kAudioTrackNum, 23, 23, true },
  { kVideoTrackNum, 33, 34, true },
  { kAudioTrackNum, 46, 23, true },
  { kVideoTrackNum, 67, 33, false },
  { kAudioTrackNum, 69, 23, false },
  { kVideoTrackNum, 100, 33, false },
};

static scoped_ptr<Cluster> CreateCluster(int timecode,
                                         const BlockInfo* block_info,
                                         int block_count) {
  ClusterBuilder cb;
  cb.SetClusterTimecode(0);

  for (int i = 0; i < block_count; i++) {
    uint8 data[] = { 0x00 };
    if (block_info[i].use_simple_block) {
      cb.AddSimpleBlock(block_info[i].track_num,
                        block_info[i].timestamp,
                        0, data, sizeof(data));
      continue;
    }

    CHECK_GE(block_info[i].duration, 0);
    cb.AddBlockGroup(block_info[i].track_num,
                     block_info[i].timestamp,
                     block_info[i].duration,
                     0, data, sizeof(data));
  }

  return cb.Finish();
}

static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers,
                          const WebMClusterParser::BufferQueue& video_buffers,
                          const BlockInfo* block_info,
                          int block_count) {
  size_t audio_offset = 0;
  size_t video_offset = 0;
  for (int i = 0; i < block_count; i++) {
    const WebMClusterParser::BufferQueue* buffers = NULL;
    size_t* offset;

    if (block_info[i].track_num == kAudioTrackNum) {
      buffers = &audio_buffers;
      offset = &audio_offset;
    } else if (block_info[i].track_num == kVideoTrackNum) {
      buffers = &video_buffers;
      offset = &video_offset;
    } else {
      LOG(ERROR) << "Unexpected track number " << block_info[i].track_num;
      return false;
    }

    if (*offset >= buffers->size())
      return false;

    scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++];


    EXPECT_EQ(buffer->GetTimestamp().InMilliseconds(), block_info[i].timestamp);

    if (!block_info[i].use_simple_block)
      EXPECT_NE(buffer->GetDuration(), kNoTimestamp());

    if (buffer->GetDuration() != kNoTimestamp())
      EXPECT_EQ(buffer->GetDuration().InMilliseconds(), block_info[i].duration);
  }

  return true;
}

static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser,
                          const BlockInfo* block_info,
                          int block_count) {
  return VerifyBuffers(parser->audio_buffers(),
                       parser->video_buffers(),
                       block_info,
                       block_count);
}

static void AppendToEnd(const WebMClusterParser::BufferQueue& src,
                        WebMClusterParser::BufferQueue* dest) {
  for (WebMClusterParser::BufferQueue::const_iterator itr = src.begin();
       itr != src.end(); ++itr) {
    dest->push_back(*itr);
  }
}

class WebMClusterParserTest : public testing::Test {
 public:
  WebMClusterParserTest()
      : parser_(new WebMClusterParser(
          kTimecodeScale, kAudioTrackNum, kVideoTrackNum, "", "", LogCB())) {
  }

 protected:
  scoped_ptr<WebMClusterParser> parser_;
};

TEST_F(WebMClusterParserTest, TestReset) {
  InSequence s;

  int block_count = arraysize(kDefaultBlockInfo);
  scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));

  // Send slightly less than the full cluster so all but the last block is
  // parsed.
  int result = parser_->Parse(cluster->data(), cluster->size() - 1);
  EXPECT_GT(result, 0);
  EXPECT_LT(result, cluster->size());

  ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count - 1));
  parser_->Reset();

  // Now parse a whole cluster to verify that all the blocks will get parsed.
  result = parser_->Parse(cluster->data(), cluster->size());
  EXPECT_EQ(result, cluster->size());
  ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count));
}

TEST_F(WebMClusterParserTest, ParseClusterWithSingleCall) {
  int block_count = arraysize(kDefaultBlockInfo);
  scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));

  int result = parser_->Parse(cluster->data(), cluster->size());
  EXPECT_EQ(cluster->size(), result);
  ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count));
}

TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) {
  int block_count = arraysize(kDefaultBlockInfo);
  scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));

  WebMClusterParser::BufferQueue audio_buffers;
  WebMClusterParser::BufferQueue video_buffers;

  const uint8* data = cluster->data();
  int size = cluster->size();
  int default_parse_size = 3;
  int parse_size = std::min(default_parse_size, size);

  while (size > 0) {
    int result = parser_->Parse(data, parse_size);
    ASSERT_GE(result, 0);
    ASSERT_LE(result, parse_size);

    if (result == 0) {
      // The parser needs more data so increase the parse_size a little.
      parse_size += default_parse_size;
      parse_size = std::min(parse_size, size);
      continue;
    }

    AppendToEnd(parser_->audio_buffers(), &audio_buffers);
    AppendToEnd(parser_->video_buffers(), &video_buffers);

    parse_size = default_parse_size;

    data += result;
    size -= result;
  }
  ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers, kDefaultBlockInfo,
                            block_count));
}

// Verify that both BlockGroups with the BlockDuration before the Block
// and BlockGroups with the BlockDuration after the Block are supported
// correctly.
// Note: Raw bytes are use here because ClusterBuilder only generates
// one of these scenarios.
TEST_F(WebMClusterParserTest, ParseBlockGroup) {
  const BlockInfo kBlockInfo[] = {
    { kAudioTrackNum, 0, 23, false },
    { kVideoTrackNum, 33, 34, false },
  };
  int block_count = arraysize(kBlockInfo);

  const uint8 kClusterData[] = {
    0x1F, 0x43, 0xB6, 0x75, 0x9B,  // Cluster(size=27)
    0xE7, 0x81, 0x00,  // Timecode(size=1, value=0)
    // BlockGroup with BlockDuration before Block.
    0xA0, 0x8A,  // BlockGroup(size=10)
    0x9B, 0x81, 0x17,  // BlockDuration(size=1, value=23)
    0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa,  // Block(size=5, track=1, ts=0)
    // BlockGroup with BlockDuration after Block.
    0xA0, 0x8A,  // BlockGroup(size=10)
    0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55,  // Block(size=5, track=2, ts=33)
    0x9B, 0x81, 0x22,  // BlockDuration(size=1, value=34)
  };
  const int kClusterSize = sizeof(kClusterData);

  int result = parser_->Parse(kClusterData, kClusterSize);
  EXPECT_EQ(result, kClusterSize);
  ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
}

TEST_F(WebMClusterParserTest, ParseSimpleBlockAndBlockGroupMixture) {
  const BlockInfo kBlockInfo[] = {
    { kAudioTrackNum, 0, 23, true },
    { kAudioTrackNum, 23, 23, false },
    { kVideoTrackNum, 33, 34, true },
    { kAudioTrackNum, 46, 23, false },
    { kVideoTrackNum, 67, 33, false },
  };
  int block_count = arraysize(kBlockInfo);
  scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));

  int result = parser_->Parse(cluster->data(), cluster->size());
  EXPECT_EQ(cluster->size(), result);
  ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
}

}  // namespace media
