summaryrefslogtreecommitdiffstats
path: root/remoting/protocol/rtp_video_writer.cc
blob: da16444a7acec26b8435ac016ed975820b01bcfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright (c) 2010 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 "remoting/protocol/rtp_video_writer.h"

#include "base/task.h"
#include "net/base/io_buffer.h"
#include "remoting/base/compound_buffer.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/rtp_writer.h"
#include "remoting/protocol/session.h"

namespace remoting {
namespace protocol {

namespace {
const int kMtu = 1200;
}  // namespace

RtpVideoWriter::RtpVideoWriter() { }

RtpVideoWriter::~RtpVideoWriter() { }

void RtpVideoWriter::Init(protocol::Session* session) {
  rtp_writer_.Init(session->video_rtp_channel());
}

void RtpVideoWriter::ProcessVideoPacket(const VideoPacket* packet, Task* done) {
  CHECK(packet->format().encoding() == VideoPacketFormat::ENCODING_VP8)
      << "Only VP8 is supported in RTP.";

  CompoundBuffer payload;
  // TODO(sergeyu): This copy would not be necessary CompoundBuffer was used
  // inside of VideoPacket.
  payload.AppendCopyOf(packet->data().data(), packet->data().size());

  Vp8Descriptor vp8_desriptor;
  // TODO(sergeyu): Add a flag in VideoPacket that indicates whether this is a
  // key frame or not.
  vp8_desriptor.non_reference_frame = false;
  vp8_desriptor.picture_id = kuint32max;

  int position = 0;
  while (position < payload.total_bytes()) {
    int size = std::min(kMtu, payload.total_bytes() - position);

    // Frame beginning flag is set only for the first packet in the first
    // partition.
    vp8_desriptor.frame_beginning =
        (packet->flags() & VideoPacket::FIRST_PACKET) != 0 && position == 0;

    // Marker bit is set only for the last packet in the last partition.
    bool marker = (position + size) == payload.total_bytes() &&
        (packet->flags() & VideoPacket::LAST_PACKET) != 0;

    // Set fragmentation flag appropriately.
    if (position == 0) {
      if (size == payload.total_bytes()) {
        vp8_desriptor.fragmentation_info = Vp8Descriptor::NOT_FRAGMENTED;
      } else {
        vp8_desriptor.fragmentation_info = Vp8Descriptor::FIRST_FRAGMENT;
      }
    } else {
      if (position + size == payload.total_bytes()) {
        vp8_desriptor.fragmentation_info = Vp8Descriptor::LAST_FRAGMENT;
      } else {
        vp8_desriptor.fragmentation_info = Vp8Descriptor::MIDDLE_FRAGMENT;
      }
    }

    // Create CompoundBuffer for the chunk.
    CompoundBuffer chunk;
    chunk.CopyFrom(payload, position, position + size);

    // And send it.
    rtp_writer_.SendPacket(packet->timestamp(), marker, vp8_desriptor, chunk);

    position += size;
  }
  DCHECK_EQ(position, payload.total_bytes());

  done->Run();
  delete done;
}

int RtpVideoWriter::GetPendingPackets() {
  return rtp_writer_.GetPendingPackets();
}

}  // namespace protocol
}  // namespace remoting