// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/media/sandbox/format_guesstimator.h"

#include <algorithm>
#include <vector>

#include "base/bind.h"
#include "base/path_service.h"
#include "base/time/time.h"
#include "cobalt/math/size.h"
#include "cobalt/media/base/audio_codecs.h"
#include "cobalt/media/base/audio_decoder_config.h"
#include "cobalt/media/base/demuxer_stream.h"
#include "cobalt/media/base/media_tracks.h"
#include "cobalt/media/base/video_codecs.h"
#include "cobalt/media/base/video_decoder_config.h"
#include "cobalt/media/filters/chunk_demuxer.h"
#include "cobalt/media/sandbox/web_media_player_helper.h"
#include "cobalt/render_tree/image.h"
#include "net/base/filename_util.h"
#include "net/base/url_util.h"
#include "starboard/common/string.h"
#include "starboard/file.h"
#include "starboard/memory.h"
#include "starboard/types.h"

namespace cobalt {
namespace media {
namespace sandbox {

namespace {

// Container to organize the pairs of supported mime types and their codecs.
struct SupportedTypeCodecInfo {
  std::string mime;
  std::string codecs;
};

// The possible mime and codec configurations that are supported by cobalt.
const std::vector<SupportedTypeCodecInfo> kSupportedTypesAndCodecs = {
    {"audio/mp4", "ac-3"},          {"audio/mp4", "ec-3"},
    {"audio/mp4", "mp4a.40.2"},     {"audio/webm", "opus"},

    {"video/mp4", "av01.0.05M.08"}, {"video/mp4", "avc1.640028, mp4a.40.2"},
    {"video/mp4", "avc1.640028"},   {"video/mp4", "hvc1.1.6.H150.90"},
    {"video/webm", "vp9"},
};

// Can be called as:
//   IsFormat("https://example.com/audio.mp4", ".mp4")
//   IsFormat("cobalt/demos/video.webm", ".webm")
bool IsFormat(const std::string& path_or_url, const std::string& format) {
  DCHECK(!format.empty() && format[0] == '.') << "Invalid format: " << format;
  return path_or_url.size() > format.size() &&
         path_or_url.substr(path_or_url.size() - format.size()) == format;
}

base::FilePath ResolvePath(const std::string& path) {
  base::FilePath result(path);
  if (!result.IsAbsolute()) {
    base::FilePath content_path;
    base::PathService::Get(base::DIR_TEST_DATA, &content_path);
    result = content_path.Append(result);
  }
  if (SbFileCanOpen(result.value().c_str(), kSbFileOpenOnly | kSbFileRead)) {
    return result;
  }
  return base::FilePath();
}

// Read the first 256kb of the local file specified by |path|.  If the size
// of the file is less than 256kb, the function reads all of its content.
std::vector<uint8_t> ReadHeader(const base::FilePath& path) {
  // Size of the input file to be read into memory for checking the validity
  // of ChunkDemuxer::AppendData() calls.
  const int64_t kHeaderSize = 256 * 1024;  // 256kb
  starboard::ScopedFile file(path.value().c_str(),
                             kSbFileOpenOnly | kSbFileRead);
  int64_t bytes_to_read = std::min(kHeaderSize, file.GetSize());
  DCHECK_GE(bytes_to_read, 0);
  std::vector<uint8_t> buffer(bytes_to_read);
  auto bytes_read =
      file.Read(reinterpret_cast<char*>(buffer.data()), bytes_to_read);
  DCHECK_EQ(bytes_to_read, bytes_read);

  return buffer;
}

void OnInitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
  SB_UNREFERENCED_PARAMETER(tracks);
}

}  // namespace

FormatGuesstimator::FormatGuesstimator(const std::string& path_or_url,
                                       MediaModule* media_module) {
  GURL url(path_or_url);
  if (url.is_valid()) {
    // If it is a url, assume that it is a progressive video.
    InitializeAsProgressive(url);
    return;
  }
  base::FilePath path = ResolvePath(path_or_url);
  if (path.empty() || !SbFileCanOpen(path.value().c_str(), kSbFileRead)) {
    return;
  }
  InitializeAsAdaptive(path, media_module);
}

void FormatGuesstimator::InitializeAsProgressive(const GURL& url) {
  // Mp4 is the only supported progressive format.
  if (!IsFormat(url.spec(), ".mp4")) {
    return;
  }
  progressive_url_ = url;
  mime_ = "video/mp4";
  codecs_ = "avc1.640028, mp4a.40.2";
}

void FormatGuesstimator::InitializeAsAdaptive(const base::FilePath& path,
                                              MediaModule* media_module) {
  std::vector<uint8_t> header = ReadHeader(path);

  for (const auto& expected_supported_info : kSupportedTypesAndCodecs) {
    DCHECK(mime_.empty());
    DCHECK(codecs_.empty());

    ChunkDemuxer* chunk_demuxer = NULL;
    WebMediaPlayerHelper::ChunkDemuxerOpenCB open_cb = base::Bind(
        [](ChunkDemuxer** handle, ChunkDemuxer* chunk_demuxer) -> void {
          *handle = chunk_demuxer;
        },
        &chunk_demuxer);
    // We create a new |web_media_player_helper| every iteration in order to
    // obtain a handle to a new |ChunkDemuxer| without any accumulated state as
    // a result of previous calls to |AddId| and |AppendData| methods.
    WebMediaPlayerHelper web_media_player_helper(media_module, open_cb,
                                                 math::Size(1920, 1080));

    // |chunk_demuxer| will be set when |open_cb| is called asynchronously
    // during initialization of |web_media_player_helper|. Wait until it is set
    // before proceeding.
    while (!chunk_demuxer) {
      base::RunLoop().RunUntilIdle();
    }

    const std::string id = "stream";
    if (chunk_demuxer->AddId(id, expected_supported_info.mime,
                             expected_supported_info.codecs) !=
        ChunkDemuxer::kOk) {
      continue;
    }

    chunk_demuxer->SetTracksWatcher(id, base::Bind(OnInitSegmentReceived));

    base::TimeDelta unused_timestamp;
    if (!chunk_demuxer->AppendData(id, header.data(), header.size(),
                                   base::TimeDelta(), media::kInfiniteDuration,
                                   &unused_timestamp)) {
      // Failing to |AppendData()| means the chosen format is not the file's
      // true format.
      continue;
    }

    // Succeeding |AppendData()| may be a false positive (i.e. the expected
    // configuration does not match with the configuration determined by the
    // ChunkDemuxer). To confirm, we check the decoder configuration determined
    // by the ChunkDemuxer against the chosen format.
    if (auto demuxer_stream =
            chunk_demuxer->GetStream(DemuxerStream::Type::AUDIO)) {
      const AudioDecoderConfig& decoder_config =
          demuxer_stream->audio_decoder_config();
      if (StringToAudioCodec(expected_supported_info.codecs) ==
          decoder_config.codec()) {
        adaptive_path_ = path;
        mime_ = expected_supported_info.mime;
        codecs_ = expected_supported_info.codecs;
        break;
      }
      continue;
    }
    auto demuxer_stream = chunk_demuxer->GetStream(DemuxerStream::Type::VIDEO);
    DCHECK(demuxer_stream);
    const VideoDecoderConfig& decoder_config =
        demuxer_stream->video_decoder_config();
    if (StringToVideoCodec(expected_supported_info.codecs) ==
        decoder_config.codec()) {
      adaptive_path_ = path;
      mime_ = expected_supported_info.mime;
      codecs_ = expected_supported_info.codecs;
      break;
    }
  }
}

}  // namespace sandbox
}  // namespace media
}  // namespace cobalt
