// 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 "content/renderer/media/rtc_video_renderer.h"

#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"

namespace content {

RTCVideoRenderer::RTCVideoRenderer(
    const blink::WebMediaStreamTrack& video_track,
    const base::Closure& error_cb,
    const RepaintCB& repaint_cb)
    : error_cb_(error_cb),
      repaint_cb_(repaint_cb),
      message_loop_proxy_(base::MessageLoopProxy::current()),
      state_(kStopped),
      video_track_(video_track) {
  MaybeRenderSignalingFrame(video_track_.source().readyState());
}

RTCVideoRenderer::~RTCVideoRenderer() {
}

void RTCVideoRenderer::Start() {
  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kStopped);

  AddToVideoTrack(this, video_track_);
  state_ = kStarted;
}

void RTCVideoRenderer::Stop() {
  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
  RemoveFromVideoTrack(this, video_track_);
}

void RTCVideoRenderer::Play() {
  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
  if (state_ == kPaused) {
    state_ = kStarted;
  }
}

void RTCVideoRenderer::Pause() {
  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
  if (state_ == kStarted) {
    state_ = kPaused;
  }
}

void RTCVideoRenderer::OnReadyStateChanged(
    blink::WebMediaStreamSource::ReadyState state) {
  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
  MaybeRenderSignalingFrame(state);
}

void RTCVideoRenderer::OnVideoFrame(
    const scoped_refptr<media::VideoFrame>& frame) {
  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
  if (state_ != kStarted) {
    return;
  }

  TRACE_EVENT_INSTANT1("rtc_video_renderer",
                       "OnVideoFrame",
                       TRACE_EVENT_SCOPE_THREAD,
                       "timestamp",
                       frame->GetTimestamp().InMilliseconds());
  repaint_cb_.Run(frame);
}

void RTCVideoRenderer::MaybeRenderSignalingFrame(
    blink::WebMediaStreamSource::ReadyState state) {
  // Render a small black frame if the track transition to ended.
  // This is necessary to make sure audio can play if the video tag src is
  // a MediaStream video track that has been rejected or ended.
  if (state == blink::WebMediaStreamSource::ReadyStateEnded) {
    const int kMinFrameSize = 2;
    const gfx::Size size(kMinFrameSize, kMinFrameSize);
    scoped_refptr<media::VideoFrame> video_frame =
        media::VideoFrame::CreateBlackFrame(size);
    OnVideoFrame(video_frame);
  }
}

}  // namespace content