// Copyright (c) 2011 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 <stddef.h>
#include <stdint.h>

#include <cstring>

#include "base/bind.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/media.h"
#include "media/base/media_util.h"
#include "media/base/test_data_util.h"
#include "media/base/video_decoder_config.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/filters/ffmpeg_glue.h"
#include "media/filters/in_memory_url_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

class FFmpegCommonTest : public testing::Test {
 public:
  FFmpegCommonTest() {}
  ~FFmpegCommonTest() override = default;
};

uint8_t kExtraData[5] = {0x00, 0x01, 0x02, 0x03, 0x04};

template <typename T>
void TestConfigConvertExtraData(
    AVStream* stream,
    T* decoder_config,
    const base::Callback<bool(const AVStream*, T*)>& converter_fn) {
  // Should initially convert.
  EXPECT_TRUE(converter_fn.Run(stream, decoder_config));

  // Store orig to let FFmpeg free whatever it allocated.
  AVCodecParameters* codec_parameters = stream->codecpar;
  uint8_t* orig_extradata = codec_parameters->extradata;
  int orig_extradata_size = codec_parameters->extradata_size;

  // Valid combination: extra_data = nullptr && size = 0.
  codec_parameters->extradata = nullptr;
  codec_parameters->extradata_size = 0;
  EXPECT_TRUE(converter_fn.Run(stream, decoder_config));
  EXPECT_EQ(static_cast<size_t>(codec_parameters->extradata_size),
            decoder_config->extra_data().size());

  // Valid combination: extra_data = non-nullptr && size > 0.
  codec_parameters->extradata = &kExtraData[0];
  codec_parameters->extradata_size = base::size(kExtraData);
  EXPECT_TRUE(converter_fn.Run(stream, decoder_config));
  EXPECT_EQ(static_cast<size_t>(codec_parameters->extradata_size),
            decoder_config->extra_data().size());
  EXPECT_EQ(
      0, memcmp(codec_parameters->extradata, &decoder_config->extra_data()[0],
                decoder_config->extra_data().size()));

  // Possible combination: extra_data = nullptr && size != 0, but the converter
  // function considers this valid and having no extra_data, due to behavior of
  // avcodec_parameters_to_context().
  codec_parameters->extradata = nullptr;
  codec_parameters->extradata_size = 10;
  EXPECT_TRUE(converter_fn.Run(stream, decoder_config));
  EXPECT_EQ(0UL, decoder_config->extra_data().size());

  // Invalid combination: extra_data = non-nullptr && size = 0.
  codec_parameters->extradata = &kExtraData[0];
  codec_parameters->extradata_size = 0;
  EXPECT_FALSE(converter_fn.Run(stream, decoder_config));

  // Restore orig values for sane cleanup.
  codec_parameters->extradata = orig_extradata;
  codec_parameters->extradata_size = orig_extradata_size;
}

TEST_F(FFmpegCommonTest, AVStreamToDecoderConfig) {
  // Open a file to get a real AVStreams from FFmpeg.
  base::MemoryMappedFile file;
  ASSERT_TRUE(file.Initialize(GetTestDataFilePath("bear-320x240.webm")));
  InMemoryUrlProtocol protocol(file.data(), file.length(), false);
  FFmpegGlue glue(&protocol);
  ASSERT_TRUE(glue.OpenContext());
  AVFormatContext* format_context = glue.format_context();

  // Find the audio and video streams and test valid and invalid combinations
  // for extradata and extradata_size.
  bool found_audio = false;
  bool found_video = false;
  for (size_t i = 0;
       i < format_context->nb_streams && (!found_audio || !found_video);
       ++i) {
    AVStream* stream = format_context->streams[i];
    AVCodecParameters* codec_parameters = stream->codecpar;
    AVMediaType codec_type = codec_parameters->codec_type;

    if (codec_type == AVMEDIA_TYPE_AUDIO) {
      if (found_audio)
        continue;
      found_audio = true;
      AudioDecoderConfig audio_config;
      TestConfigConvertExtraData(stream, &audio_config,
                                 base::Bind(&AVStreamToAudioDecoderConfig));
    } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
      if (found_video)
        continue;
      found_video = true;
      VideoDecoderConfig video_config;
      TestConfigConvertExtraData(stream, &video_config,
                                 base::Bind(&AVStreamToVideoDecoderConfig));
    } else {
      // Only process audio/video.
      continue;
    }
  }

  ASSERT_TRUE(found_audio);
  ASSERT_TRUE(found_video);
}

TEST_F(FFmpegCommonTest, AVStreamToAudioDecoderConfig_OpusAmbisonics_4ch) {
  base::MemoryMappedFile file;
  ASSERT_TRUE(file.Initialize(
      GetTestDataFilePath("bear-opus-end-trimming-4ch-channelmapping2.webm")));
  InMemoryUrlProtocol protocol(file.data(), file.length(), false);
  FFmpegGlue glue(&protocol);
  ASSERT_TRUE(glue.OpenContext());

  AVFormatContext* format_context = glue.format_context();
  EXPECT_EQ(static_cast<unsigned int>(1), format_context->nb_streams);
  AVStream* stream = format_context->streams[0];

  AVCodecParameters* codec_parameters = stream->codecpar;
  EXPECT_EQ(AVMEDIA_TYPE_AUDIO, codec_parameters->codec_type);

  AudioDecoderConfig audio_config;
  ASSERT_TRUE(AVStreamToAudioDecoderConfig(stream, &audio_config));

  EXPECT_EQ(kCodecOpus, audio_config.codec());
  EXPECT_EQ(CHANNEL_LAYOUT_QUAD, audio_config.channel_layout());
  EXPECT_EQ(4, audio_config.channels());
}

TEST_F(FFmpegCommonTest, AVStreamToAudioDecoderConfig_OpusAmbisonics_11ch) {
  base::MemoryMappedFile file;
  ASSERT_TRUE(file.Initialize(
      GetTestDataFilePath("bear-opus-end-trimming-11ch-channelmapping2.webm")));
  InMemoryUrlProtocol protocol(file.data(), file.length(), false);
  FFmpegGlue glue(&protocol);
  ASSERT_TRUE(glue.OpenContext());

  AVFormatContext* format_context = glue.format_context();
  EXPECT_EQ(static_cast<unsigned int>(1), format_context->nb_streams);
  AVStream* stream = format_context->streams[0];

  AVCodecParameters* codec_parameters = stream->codecpar;
  EXPECT_EQ(AVMEDIA_TYPE_AUDIO, codec_parameters->codec_type);

  AudioDecoderConfig audio_config;
  ASSERT_TRUE(AVStreamToAudioDecoderConfig(stream, &audio_config));

  EXPECT_EQ(kCodecOpus, audio_config.codec());
  EXPECT_EQ(CHANNEL_LAYOUT_DISCRETE, audio_config.channel_layout());
  EXPECT_EQ(11, audio_config.channels());
}

TEST_F(FFmpegCommonTest, AVStreamToAudioDecoderConfig_9ch_wav) {
  base::MemoryMappedFile file;
  ASSERT_TRUE(file.Initialize(GetTestDataFilePath("9ch.wav")));
  InMemoryUrlProtocol protocol(file.data(), file.length(), false);
  FFmpegGlue glue(&protocol);
  ASSERT_TRUE(glue.OpenContext());

  AVFormatContext* format_context = glue.format_context();
  EXPECT_EQ(static_cast<unsigned int>(1), format_context->nb_streams);
  AVStream* stream = format_context->streams[0];

  AVCodecParameters* codec_parameters = stream->codecpar;
  EXPECT_EQ(AVMEDIA_TYPE_AUDIO, codec_parameters->codec_type);

  AudioDecoderConfig audio_config;
  ASSERT_TRUE(AVStreamToAudioDecoderConfig(stream, &audio_config));

  EXPECT_EQ(kCodecPCM, audio_config.codec());
  EXPECT_EQ(CHANNEL_LAYOUT_DISCRETE, audio_config.channel_layout());
  EXPECT_EQ(9, audio_config.channels());
}

TEST_F(FFmpegCommonTest, TimeBaseConversions) {
  const int64_t test_data[][5] = {
      {1, 2, 1, 500000, 1}, {1, 3, 1, 333333, 1}, {1, 3, 2, 666667, 2},
  };

  for (size_t i = 0; i < base::size(test_data); ++i) {
    SCOPED_TRACE(i);

    AVRational time_base;
    time_base.num = static_cast<int>(test_data[i][0]);
    time_base.den = static_cast<int>(test_data[i][1]);

    base::TimeDelta time_delta =
        ConvertFromTimeBase(time_base, test_data[i][2]);

    EXPECT_EQ(time_delta.InMicroseconds(), test_data[i][3]);
    EXPECT_EQ(ConvertToTimeBase(time_base, time_delta), test_data[i][4]);
  }
}

TEST_F(FFmpegCommonTest, VerifyFormatSizes) {
  for (AVSampleFormat format = AV_SAMPLE_FMT_NONE;
       format < AV_SAMPLE_FMT_NB;
       format = static_cast<AVSampleFormat>(format + 1)) {
    std::vector<AVCodecID> codec_ids(1, AV_CODEC_ID_NONE);
    if (format == AV_SAMPLE_FMT_S32)
      codec_ids.push_back(AV_CODEC_ID_PCM_S24LE);
    for (const auto& codec_id : codec_ids) {
      SampleFormat sample_format =
          AVSampleFormatToSampleFormat(format, codec_id);
      if (sample_format == kUnknownSampleFormat) {
        // This format not supported, so skip it.
        continue;
      }

      // Have FFMpeg compute the size of a buffer of 1 channel / 1 frame
      // with 1 byte alignment to make sure the sizes match.
      int single_buffer_size =
          av_samples_get_buffer_size(NULL, 1, 1, format, 1);
      int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
      EXPECT_EQ(bytes_per_channel, single_buffer_size);
    }
  }
}

// Verifies there are no collisions of the codec name hashes used for UMA.  Also
// includes code for updating the histograms XML.
TEST_F(FFmpegCommonTest, VerifyUmaCodecHashes) {
  const AVCodecDescriptor* desc = avcodec_descriptor_next(nullptr);

  std::map<int32_t, const char*> sorted_hashes;
  while (desc) {
    const int32_t hash = HashCodecName(desc->name);
    // Ensure there are no collisions.
    ASSERT_TRUE(sorted_hashes.find(hash) == sorted_hashes.end());
    sorted_hashes[hash] = desc->name;

    desc = avcodec_descriptor_next(desc);
  }

  // Add a none entry for when no codec is detected.
  static const char kUnknownCodec[] = "none";
  const int32_t hash = HashCodecName(kUnknownCodec);
  ASSERT_TRUE(sorted_hashes.find(hash) == sorted_hashes.end());
  sorted_hashes[hash] = kUnknownCodec;

  // Uncomment the following lines to generate the "FFmpegCodecHashes" enum for
  // usage in the histogram metrics file.  While it regenerates *ALL* values, it
  // should only be used to *ADD* values to histograms file.  Never delete any
  // values; diff should verify.
#if 0
  static const std::vector<std::pair<std::string, int32_t>> kDeprecatedHashes =
      {
          {"brender_pix_deprecated", -1866047250},
          {"adpcm_vima_deprecated", -1782518388},
          {"pcm_s32le_planar_deprecated", -1328796639},
          {"webp_deprecated", -993429906},
          {"paf_video_deprecated", -881893142},
          {"vima_deprecated", -816209197},
          {"iff_byterun1", -777478450},
          {"paf_audio_deprecated", -630356729},

          {"exr_deprecated", -418117523},
          {"hevc_deprecated", -414733739},
          {"vp7_deprecated", -197551526},
          {"escape130_deprecated", 73149662},
          {"tak_deprecated", 1041617024},
          {"opus_deprecated", 1165132763},
          {"g2m_deprecated", 1194572884},

          {"pcm_s24le_planar_deprecated", 1535518292},
          {"sanm_deprecated", 2047102762},

          {"mpegvideo_xvmc_deprecated", 1550758811},
          {"voxware_deprecated", 1656834662}
      };

  for (auto& kv : kDeprecatedHashes)
    sorted_hashes[kv.second] = kv.first.c_str();
  printf("<enum name=\"FFmpegCodecHashes\">\n");
  for (const auto& kv : sorted_hashes)
    printf("  <int value=\"%d\" label=\"%s\"/>\n", kv.first, kv.second);
  printf("</enum>\n");
#endif
}
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
TEST_F(FFmpegCommonTest, VerifyH264Profile) {
  // Open a file to get a real AVStreams from FFmpeg.
  base::MemoryMappedFile file;
  ASSERT_TRUE(file.Initialize(GetTestDataFilePath("bear-1280x720.mp4")));
  InMemoryUrlProtocol protocol(file.data(), file.length(), false);
  FFmpegGlue glue(&protocol);
  ASSERT_TRUE(glue.OpenContext());
  AVFormatContext* format_context = glue.format_context();

  for (size_t i = 0; i < format_context->nb_streams; ++i) {
    AVStream* stream = format_context->streams[i];
    AVCodecParameters* codec_parameters = stream->codecpar;
    AVMediaType codec_type = codec_parameters->codec_type;

    if (codec_type == AVMEDIA_TYPE_VIDEO) {
      VideoDecoderConfig video_config;
      EXPECT_TRUE(AVStreamToVideoDecoderConfig(stream, &video_config));
      EXPECT_EQ(H264PROFILE_HIGH, video_config.profile());
    } else {
      // Only process video.
      continue;
    }
  }
}
#endif

// Verifies that the HDR Metadata and VideoColorSpace are correctly parsed.
TEST_F(FFmpegCommonTest, VerifyHDRMetadataAndColorSpaceInfo) {
  // Open a file to get a real AVStreams from FFmpeg.
  base::MemoryMappedFile file;
  ASSERT_TRUE(file.Initialize(GetTestDataFilePath("colour.webm")));
  InMemoryUrlProtocol protocol(file.data(), file.length(), false);
  FFmpegGlue glue(&protocol);
  ASSERT_TRUE(glue.OpenContext());
  AVFormatContext* format_context = glue.format_context();
  ASSERT_EQ(format_context->nb_streams, 1u);

  AVStream* stream = format_context->streams[0];
  AVCodecParameters* codec_parameters = stream->codecpar;
  AVMediaType codec_type = codec_parameters->codec_type;
  ASSERT_EQ(codec_type, AVMEDIA_TYPE_VIDEO);

  VideoDecoderConfig video_config;
  EXPECT_TRUE(AVStreamToVideoDecoderConfig(stream, &video_config));
  ASSERT_TRUE(video_config.hdr_metadata().has_value());
  EXPECT_EQ(30.0,
            video_config.hdr_metadata()->mastering_metadata.luminance_min);
  EXPECT_EQ(40.0,
            video_config.hdr_metadata()->mastering_metadata.luminance_max);
  EXPECT_EQ(gfx::PointF(0.1, 0.2),
            video_config.hdr_metadata()->mastering_metadata.primary_r);
  EXPECT_EQ(gfx::PointF(0.1, 0.2),
            video_config.hdr_metadata()->mastering_metadata.primary_g);
  EXPECT_EQ(gfx::PointF(0.1, 0.2),
            video_config.hdr_metadata()->mastering_metadata.primary_b);
  EXPECT_EQ(gfx::PointF(0.1, 0.2),
            video_config.hdr_metadata()->mastering_metadata.white_point);

  EXPECT_EQ(VideoColorSpace(VideoColorSpace::PrimaryID::SMPTEST428_1,
                            VideoColorSpace::TransferID::LOG,
                            VideoColorSpace::MatrixID::RGB,
                            gfx::ColorSpace::RangeID::FULL),
            video_config.color_space_info());
}
}  // namespace media
