blob: ed24508e8fefbe548874f93d84a5ab2462381d49 [file] [log] [blame]
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/video_engine/internal/video_receive_stream.h"
12
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
14#include <stdlib.h>
pbos@webrtc.org29d58392013-05-16 12:08:03 +000015
16#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
17#include "webrtc/system_wrappers/interface/clock.h"
18#include "webrtc/video_engine/include/vie_base.h"
19#include "webrtc/video_engine/include/vie_capture.h"
20#include "webrtc/video_engine/include/vie_codec.h"
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000021#include "webrtc/video_engine/include/vie_external_codec.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000022#include "webrtc/video_engine/include/vie_network.h"
23#include "webrtc/video_engine/include/vie_render.h"
24#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
25#include "webrtc/video_engine/new_include/video_receive_stream.h"
26
27namespace webrtc {
28namespace internal {
29
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000030VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
31 const VideoReceiveStream::Config& config,
32 newapi::Transport* transport)
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000033 : transport_(transport), config_(config), channel_(-1) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +000034 video_engine_base_ = ViEBase::GetInterface(video_engine);
35 // TODO(mflodman): Use the other CreateChannel method.
36 video_engine_base_->CreateChannel(channel_);
37 assert(channel_ != -1);
38
39 rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
40 assert(rtp_rtcp_ != NULL);
41
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000042 // TODO(pbos): This is not fine grained enough...
43 rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000044 rtp_rtcp_->SetKeyFrameRequestMethod(channel_, kViEKeyFrameRequestPliRtcp);
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +000045
pbos@webrtc.org29d58392013-05-16 12:08:03 +000046 assert(config_.rtp.ssrc != 0);
47
48 network_ = ViENetwork::GetInterface(video_engine);
49 assert(network_ != NULL);
50
51 network_->RegisterSendTransport(channel_, *this);
52
53 codec_ = ViECodec::GetInterface(video_engine);
54
55 for (size_t i = 0; i < config_.codecs.size(); ++i) {
56 if (codec_->SetReceiveCodec(channel_, config_.codecs[i]) != 0) {
57 // TODO(pbos): Abort gracefully, this can be a runtime error.
58 // Factor out to an Init() method.
59 abort();
60 }
61 }
62
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000063 external_codec_ = ViEExternalCodec::GetInterface(video_engine);
64 for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
65 ExternalVideoDecoder* decoder = &config_.external_decoders[i];
66 if (external_codec_->RegisterExternalReceiveCodec(
67 channel_,
68 decoder->payload_type,
69 decoder->decoder,
70 decoder->renderer,
71 decoder->expected_delay_ms) !=
72 0) {
73 // TODO(pbos): Abort gracefully? Can this be a runtime error?
74 abort();
75 }
76 }
77
pbos@webrtc.org29d58392013-05-16 12:08:03 +000078 render_ = webrtc::ViERender::GetInterface(video_engine);
79 assert(render_ != NULL);
80
81 if (render_->AddRenderer(channel_, kVideoI420, this) != 0) {
82 abort();
83 }
84
85 clock_ = Clock::GetRealTimeClock();
86}
87
88VideoReceiveStream::~VideoReceiveStream() {
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000089 for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
90 external_codec_->DeRegisterExternalReceiveCodec(
91 channel_, config_.external_decoders[i].payload_type);
92 }
93
pbos@webrtc.org29d58392013-05-16 12:08:03 +000094 network_->DeregisterSendTransport(channel_);
95
96 video_engine_base_->Release();
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000097 external_codec_->Release();
pbos@webrtc.org29d58392013-05-16 12:08:03 +000098 codec_->Release();
99 network_->Release();
100 render_->Release();
101 rtp_rtcp_->Release();
102}
103
104void VideoReceiveStream::StartReceive() {
105 if (render_->StartRender(channel_)) {
106 abort();
107 }
108 if (video_engine_base_->StartReceive(channel_) != 0) {
109 abort();
110 }
111}
112
113void VideoReceiveStream::StopReceive() {
114 if (render_->StopRender(channel_)) {
115 abort();
116 }
117 if (video_engine_base_->StopReceive(channel_) != 0) {
118 abort();
119 }
120}
121
122void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
123 // TODO(pbos): Implement
124}
125
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000126bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000127 return network_->ReceivedRTCPPacket(channel_, packet, length) == 0;
128}
129
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000130bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000131 return network_->ReceivedRTPPacket(channel_, packet, length) == 0;
132}
133
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000134int VideoReceiveStream::FrameSizeChange(unsigned int width,
135 unsigned int height,
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000136 unsigned int /*number_of_streams*/) {
137 width_ = width;
138 height_ = height;
139 return 0;
140}
141
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000142int VideoReceiveStream::DeliverFrame(uint8_t* frame,
143 int buffer_size,
144 uint32_t timestamp,
145 int64_t render_time,
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000146 void* /*handle*/) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000147 if (config_.renderer == NULL) {
148 return 0;
149 }
150
151 I420VideoFrame video_frame;
152 video_frame.CreateEmptyFrame(width_, height_, width_, height_, height_);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000153 ConvertToI420(kI420,
154 frame,
155 0,
156 0,
157 width_,
158 height_,
159 buffer_size,
160 webrtc::kRotateNone,
161 &video_frame);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000162 video_frame.set_timestamp(timestamp);
163 video_frame.set_render_time_ms(render_time);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000164
165 if (config_.post_decode_callback != NULL) {
166 config_.post_decode_callback->FrameCallback(&video_frame);
167 }
168
169 if (config_.renderer != NULL) {
170 // TODO(pbos): Add timing to RenderFrame call
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000171 config_.renderer->RenderFrame(video_frame,
172 render_time - clock_->TimeInMilliseconds());
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000173 }
174
175 return 0;
176}
177
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000178bool VideoReceiveStream::IsTextureSupported() { return false; }
179
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000180int VideoReceiveStream::SendPacket(int /*channel*/,
181 const void* packet,
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000182 int length) {
183 assert(length >= 0);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000184 bool success = transport_->SendRTP(static_cast<const uint8_t*>(packet),
185 static_cast<size_t>(length));
186 return success ? 0 : -1;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000187}
188
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000189int VideoReceiveStream::SendRTCPPacket(int /*channel*/,
190 const void* packet,
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000191 int length) {
192 assert(length >= 0);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000193 bool success = transport_->SendRTCP(static_cast<const uint8_t*>(packet),
194 static_cast<size_t>(length));
195 return success ? 0 : -1;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000196}
197} // internal
198} // webrtc