/*
 *  Copyright (c) 2011 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 "video_engine/vie_file_recorder.h"

#include "modules/utility/interface/file_player.h"
#include "modules/utility/interface/file_recorder.h"
#include "system_wrappers/interface/critical_section_wrapper.h"
#include "system_wrappers/interface/tick_util.h"
#include "system_wrappers/interface/trace.h"
#include "video_engine/vie_defines.h"

namespace webrtc {

ViEFileRecorder::ViEFileRecorder(int instanceID)
    : recorder_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      file_recorder_(NULL),
      is_first_frame_recorded_(false),
      is_out_stream_started_(false),
      instance_id_(instanceID),
      frame_delay_(0),
      audio_channel_(-1),
      audio_source_(NO_AUDIO),
      voe_file_interface_(NULL) {
}

ViEFileRecorder::~ViEFileRecorder() {
  StopRecording();
  delete recorder_cs_;
}

int ViEFileRecorder::StartRecording(const char* file_nameUTF8,
                                    const VideoCodec& codec_inst,
                                    AudioSource audio_source,
                                    int audio_channel,
                                    const CodecInst& audio_codec_inst,
                                    VoiceEngine* voe_ptr,
                                    const FileFormats file_format) {
  CriticalSectionScoped lock(*recorder_cs_);

  if (file_recorder_) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, instance_id_,
                 "ViEFileRecorder::StartRecording() - already recording.");
    return -1;
  }
  file_recorder_ = FileRecorder::CreateFileRecorder(instance_id_, file_format);
  if (!file_recorder_) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, instance_id_,
                 "ViEFileRecorder::StartRecording() failed to create recoder.");
    return -1;
  }

  int error = file_recorder_->StartRecordingVideoFile(file_nameUTF8,
                                                      audio_codec_inst,
                                                      codec_inst,
                                                      AMRFileStorage,
                                                      audio_source == NO_AUDIO);
  if (error) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, instance_id_,
                 "ViEFileRecorder::StartRecording() failed to "
                 "StartRecordingVideoFile.");
    FileRecorder::DestroyFileRecorder(file_recorder_);
    file_recorder_ = NULL;
    return -1;
  }

  audio_source_ = audio_source;
  if (voe_ptr && audio_source != NO_AUDIO) {
    // VoE interface has been provided and we want to record audio.
    voe_file_interface_ = VoEFile::GetInterface(voe_ptr);
    if (!voe_file_interface_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, instance_id_,
                   "ViEFileRecorder::StartRecording() failed to get VEFile "
                   "interface");
      return -1;
    }

    // Always L16.
    CodecInst engine_audio_codec_inst = {96, "L16", audio_codec_inst.plfreq,
                                         audio_codec_inst.plfreq / 100, 1,
                                         audio_codec_inst.plfreq * 16 };

    switch (audio_source) {
      // case NO_AUDIO is checked above.
      case MICROPHONE:
        error = voe_file_interface_->StartRecordingMicrophone(
            this, &engine_audio_codec_inst);
        break;
      case PLAYOUT:
        error = voe_file_interface_->StartRecordingPlayout(
            audio_channel, this, &engine_audio_codec_inst);
        break;
      default:
        assert(!"Unknown audio_source");
    }
    if (error != 0) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, instance_id_,
                   "ViEFileRecorder::StartRecording() failed to start recording"
                   " audio");
      FileRecorder::DestroyFileRecorder(file_recorder_);
      file_recorder_ = NULL;
      return -1;
    }
    is_out_stream_started_ = true;
    audio_channel_ = audio_channel;
  }
  is_first_frame_recorded_ = false;
  return 0;
}

int ViEFileRecorder::StopRecording() {
  int error = 0;
  // We can not hold the ptr_cs_ while accessing VoE functions. It might cause
  // deadlock in Write.
  if (voe_file_interface_) {
    switch (audio_source_) {
      case MICROPHONE:
        error = voe_file_interface_->StopRecordingMicrophone();
        break;
      case PLAYOUT:
        error = voe_file_interface_->StopRecordingPlayout(audio_channel_);
        break;
      case NO_AUDIO:
        break;
      default:
        assert(!"Unknown audio_source");
    }
    if (error != 0) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, instance_id_,
                   "ViEFileRecorder::StopRecording() failed to stop recording "
                   "audio");
    }
  }
  CriticalSectionScoped lock(*recorder_cs_);
  if (voe_file_interface_) {
    voe_file_interface_->Release();
    voe_file_interface_ = NULL;
  }

  if (file_recorder_) {
    if (file_recorder_->IsRecording()) {
      int error = file_recorder_->StopRecording();
      if (error) {
        return -1;
      }
    }
    FileRecorder::DestroyFileRecorder(file_recorder_);
    file_recorder_ = NULL;
  }
  is_first_frame_recorded_ = false;
  is_out_stream_started_ = false;
  return 0;
}

void ViEFileRecorder::SetFrameDelay(int frame_delay) {
  CriticalSectionScoped lock(*recorder_cs_);
  frame_delay_ = frame_delay;
}

bool ViEFileRecorder::RecordingStarted() {
  CriticalSectionScoped lock(*recorder_cs_);
  return file_recorder_ && file_recorder_->IsRecording();
}

bool ViEFileRecorder::FirstFrameRecorded() {
  CriticalSectionScoped lock(*recorder_cs_);
  return is_first_frame_recorded_;
}

bool ViEFileRecorder::IsRecordingFileFormat(const FileFormats file_format) {
  CriticalSectionScoped lock(*recorder_cs_);
  return (file_recorder_->RecordingFileFormat() == file_format) ? true : false;
}

void ViEFileRecorder::RecordVideoFrame(const VideoFrame& video_frame) {
  CriticalSectionScoped lock(*recorder_cs_);

  if (file_recorder_ && file_recorder_->IsRecording()) {
    if (!IsRecordingFileFormat(kFileFormatAviFile))
      return;

    // Compensate for frame delay in order to get audio/video sync when
    // recording local video.
    const WebRtc_UWord32 time_stamp = video_frame.TimeStamp();
    const WebRtc_Word64 render_time_stamp = video_frame.RenderTimeMs();
    VideoFrame& unconst_video_frame = const_cast<VideoFrame&>(video_frame);
    unconst_video_frame.SetTimeStamp(time_stamp - 90 * frame_delay_);
    unconst_video_frame.SetRenderTime(render_time_stamp - frame_delay_);

    file_recorder_->RecordVideoToFile(unconst_video_frame);

    unconst_video_frame.SetRenderTime(render_time_stamp);
    unconst_video_frame.SetTimeStamp(time_stamp);
  }
}

bool ViEFileRecorder::Write(const void* buf, int len) {
  if (!is_out_stream_started_)
    return true;

  // Always 10 ms L16 from VoE.
  if (len % (2 * 80)) {
    // Not 2 bytes 80 samples.
    WEBRTC_TRACE(kTraceError, kTraceVideo, audio_channel_,
                 "Audio length not supported: %d.", len);
    return true;
  }

  AudioFrame audio_frame;
  WebRtc_UWord16 length_in_samples = len / 2;
  audio_frame.UpdateFrame(audio_channel_, 0,
                          static_cast<const WebRtc_Word16*>(buf),
                          length_in_samples, length_in_samples * 100,
                          AudioFrame::kUndefined,
                          AudioFrame::kVadUnknown);

  CriticalSectionScoped lock(*recorder_cs_);
  if (file_recorder_ && file_recorder_->IsRecording()) {
    TickTime tick_time = TickTime::Now();
    file_recorder_->RecordAudioToFile(audio_frame, &tick_time);
  }

  // Always return true to continue recording.
  return true;
}

int ViEFileRecorder::Rewind() {
  // Not supported!
  return -1;
}

}  // namespace webrtc
