Home | History | Annotate | Download | only in video_sender
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/cast/video_sender/video_encoder.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "media/base/video_frame.h"
     11 #include "media/cast/cast_defines.h"
     12 
     13 namespace media {
     14 namespace cast {
     15 
     16 void LogFrameEncodedEvent(CastEnvironment* const cast_environment,
     17                           const base::TimeTicks& capture_time) {
     18   cast_environment->Logging()->InsertFrameEvent(kVideoFrameEncoded,
     19       GetVideoRtpTimestamp(capture_time), kFrameIdUnknown);
     20 }
     21 
     22 VideoEncoder::VideoEncoder(scoped_refptr<CastEnvironment> cast_environment,
     23                            const VideoSenderConfig& video_config,
     24                            uint8 max_unacked_frames)
     25     : video_config_(video_config),
     26       cast_environment_(cast_environment),
     27       skip_next_frame_(false),
     28       skip_count_(0) {
     29   if (video_config.codec == kVp8) {
     30     vp8_encoder_.reset(new Vp8Encoder(video_config, max_unacked_frames));
     31   } else {
     32     DCHECK(false) << "Invalid config";  // Codec not supported.
     33   }
     34 
     35   dynamic_config_.key_frame_requested = false;
     36   dynamic_config_.latest_frame_id_to_reference = kStartFrameId;
     37   dynamic_config_.bit_rate = video_config.start_bitrate;
     38 }
     39 
     40 VideoEncoder::~VideoEncoder() {}
     41 
     42 bool VideoEncoder::EncodeVideoFrame(
     43     const scoped_refptr<media::VideoFrame>& video_frame,
     44     const base::TimeTicks& capture_time,
     45     const FrameEncodedCallback& frame_encoded_callback) {
     46   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
     47   if (video_config_.codec != kVp8) return false;
     48 
     49   if (skip_next_frame_) {
     50     ++skip_count_;
     51     VLOG(1) << "Skip encoding frame";
     52     return false;
     53   }
     54 
     55   cast_environment_->Logging()->InsertFrameEvent(kVideoFrameSentToEncoder,
     56       GetVideoRtpTimestamp(capture_time), kFrameIdUnknown);
     57   cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER, FROM_HERE,
     58       base::Bind(&VideoEncoder::EncodeVideoFrameEncoderThread,
     59                  base::Unretained(this), video_frame, capture_time,
     60                  dynamic_config_, frame_encoded_callback));
     61 
     62   dynamic_config_.key_frame_requested = false;
     63   return true;
     64 }
     65 
     66 void VideoEncoder::EncodeVideoFrameEncoderThread(
     67     const scoped_refptr<media::VideoFrame>& video_frame,
     68     const base::TimeTicks& capture_time,
     69     const CodecDynamicConfig& dynamic_config,
     70     const FrameEncodedCallback& frame_encoded_callback) {
     71   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_ENCODER));
     72   if (dynamic_config.key_frame_requested) {
     73     vp8_encoder_->GenerateKeyFrame();
     74   }
     75   vp8_encoder_->LatestFrameIdToReference(
     76       dynamic_config.latest_frame_id_to_reference);
     77   vp8_encoder_->UpdateRates(dynamic_config.bit_rate);
     78 
     79   scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame());
     80   bool retval = vp8_encoder_->Encode(video_frame, encoded_frame.get());
     81 
     82   cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
     83       base::Bind(LogFrameEncodedEvent, cast_environment_, capture_time));
     84 
     85   if (!retval) {
     86     VLOG(1) << "Encoding failed";
     87     return;
     88   }
     89   if (encoded_frame->data.size() <= 0) {
     90     VLOG(1) << "Encoding resulted in an empty frame";
     91     return;
     92   }
     93   cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
     94       base::Bind(frame_encoded_callback,
     95           base::Passed(&encoded_frame), capture_time));
     96 }
     97 
     98 // Inform the encoder about the new target bit rate.
     99 void VideoEncoder::SetBitRate(int new_bit_rate) {
    100   dynamic_config_.bit_rate = new_bit_rate;
    101 }
    102 
    103 // Inform the encoder to not encode the next frame.
    104 void VideoEncoder::SkipNextFrame(bool skip_next_frame) {
    105   skip_next_frame_ = skip_next_frame;
    106 }
    107 
    108 // Inform the encoder to encode the next frame as a key frame.
    109 void VideoEncoder::GenerateKeyFrame() {
    110   dynamic_config_.key_frame_requested = true;
    111 }
    112 
    113 // Inform the encoder to only reference frames older or equal to frame_id;
    114 void VideoEncoder::LatestFrameIdToReference(uint32 frame_id) {
    115   dynamic_config_.latest_frame_id_to_reference = frame_id;
    116 }
    117 
    118 int VideoEncoder::NumberOfSkippedFrames() const {
    119   return skip_count_;
    120 }
    121 
    122 }  //  namespace cast
    123 }  //  namespace media
    124