OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/client/plugin/media_source_video_renderer.h" | 5 #include "remoting/client/plugin/media_source_video_renderer.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 int64_t last_frame_timestamp() { return timecode_ - kFrameIntervalNs; } | 28 int64_t last_frame_timestamp() { return timecode_ - kFrameIntervalNs; } |
29 | 29 |
30 // IMkvWriter interface. | 30 // IMkvWriter interface. |
31 virtual mkvmuxer::int32 Write(const void* buf, mkvmuxer::uint32 len) OVERRIDE; | 31 virtual mkvmuxer::int32 Write(const void* buf, mkvmuxer::uint32 len) OVERRIDE; |
32 virtual mkvmuxer::int64 Position() const OVERRIDE; | 32 virtual mkvmuxer::int64 Position() const OVERRIDE; |
33 virtual mkvmuxer::int32 Position(mkvmuxer::int64 position) OVERRIDE; | 33 virtual mkvmuxer::int32 Position(mkvmuxer::int64 position) OVERRIDE; |
34 virtual bool Seekable() const OVERRIDE; | 34 virtual bool Seekable() const OVERRIDE; |
35 virtual void ElementStartNotify(mkvmuxer::uint64 element_id, | 35 virtual void ElementStartNotify(mkvmuxer::uint64 element_id, |
36 mkvmuxer::int64 position) OVERRIDE; | 36 mkvmuxer::int64 position) OVERRIDE; |
37 | 37 |
38 scoped_ptr<DataBuffer> OnVideoFrame(const std::string& video_data); | 38 scoped_ptr<DataBuffer> OnVideoFrame(const std::string& video_data, |
| 39 bool keyframe); |
39 | 40 |
40 private: | 41 private: |
41 webrtc::DesktopSize frame_size_; | 42 webrtc::DesktopSize frame_size_; |
42 scoped_ptr<DataBuffer> output_data_; | 43 scoped_ptr<DataBuffer> output_data_; |
43 int64_t position_; | 44 int64_t position_; |
44 scoped_ptr<mkvmuxer::Segment> segment_; | 45 scoped_ptr<mkvmuxer::Segment> segment_; |
45 int64_t timecode_; | 46 int64_t timecode_; |
46 }; | 47 }; |
47 | 48 |
48 MediaSourceVideoRenderer::VideoWriter::VideoWriter( | 49 MediaSourceVideoRenderer::VideoWriter::VideoWriter( |
(...skipping 30 matching lines...) Expand all Loading... |
79 crop_bottom = 1; | 80 crop_bottom = 1; |
80 } | 81 } |
81 | 82 |
82 segment_->AddVideoTrack(width, height, 1); | 83 segment_->AddVideoTrack(width, height, 1); |
83 mkvmuxer::VideoTrack* video_track = | 84 mkvmuxer::VideoTrack* video_track = |
84 reinterpret_cast<mkvmuxer::VideoTrack*>(segment_->GetTrackByNumber(1)); | 85 reinterpret_cast<mkvmuxer::VideoTrack*>(segment_->GetTrackByNumber(1)); |
85 video_track->set_crop_right(crop_right); | 86 video_track->set_crop_right(crop_right); |
86 video_track->set_crop_bottom(crop_bottom); | 87 video_track->set_crop_bottom(crop_bottom); |
87 video_track->set_frame_rate(base::Time::kNanosecondsPerSecond / | 88 video_track->set_frame_rate(base::Time::kNanosecondsPerSecond / |
88 kFrameIntervalNs); | 89 kFrameIntervalNs); |
89 video_track->set_default_duration(base::Time::kNanosecondsPerSecond); | 90 video_track->set_default_duration(kFrameIntervalNs); |
90 mkvmuxer::SegmentInfo* const info = segment_->GetSegmentInfo(); | 91 mkvmuxer::SegmentInfo* const info = segment_->GetSegmentInfo(); |
91 info->set_writing_app("ChromotingViewer"); | 92 info->set_writing_app("ChromotingViewer"); |
92 info->set_muxing_app("ChromotingViewer"); | 93 info->set_muxing_app("ChromotingViewer"); |
93 } | 94 } |
94 | 95 |
95 MediaSourceVideoRenderer::VideoWriter::~VideoWriter() {} | 96 MediaSourceVideoRenderer::VideoWriter::~VideoWriter() {} |
96 | 97 |
97 mkvmuxer::int32 MediaSourceVideoRenderer::VideoWriter::Write( | 98 mkvmuxer::int32 MediaSourceVideoRenderer::VideoWriter::Write( |
98 const void* buf, | 99 const void* buf, |
99 mkvmuxer::uint32 len) { | 100 mkvmuxer::uint32 len) { |
(...skipping 17 matching lines...) Expand all Loading... |
117 return false; | 118 return false; |
118 } | 119 } |
119 | 120 |
120 void MediaSourceVideoRenderer::VideoWriter::ElementStartNotify( | 121 void MediaSourceVideoRenderer::VideoWriter::ElementStartNotify( |
121 mkvmuxer::uint64 element_id, | 122 mkvmuxer::uint64 element_id, |
122 mkvmuxer::int64 position) { | 123 mkvmuxer::int64 position) { |
123 } | 124 } |
124 | 125 |
125 scoped_ptr<MediaSourceVideoRenderer::VideoWriter::DataBuffer> | 126 scoped_ptr<MediaSourceVideoRenderer::VideoWriter::DataBuffer> |
126 MediaSourceVideoRenderer::VideoWriter::OnVideoFrame( | 127 MediaSourceVideoRenderer::VideoWriter::OnVideoFrame( |
127 const std::string& video_data) { | 128 const std::string& video_data, |
| 129 bool keyframe) { |
128 DCHECK(!output_data_); | 130 DCHECK(!output_data_); |
129 | 131 |
130 output_data_.reset(new DataBuffer()); | 132 output_data_.reset(new DataBuffer()); |
131 bool first_frame = (timecode_ == 0); | |
132 segment_->AddFrame(reinterpret_cast<const uint8_t*>(video_data.data()), | 133 segment_->AddFrame(reinterpret_cast<const uint8_t*>(video_data.data()), |
133 video_data.size(), 1, timecode_, first_frame); | 134 video_data.size(), 1, timecode_, keyframe); |
134 timecode_ += kFrameIntervalNs; | 135 timecode_ += kFrameIntervalNs; |
135 return output_data_.Pass(); | 136 return output_data_.Pass(); |
136 } | 137 } |
137 | 138 |
138 MediaSourceVideoRenderer::MediaSourceVideoRenderer(Delegate* delegate) | 139 MediaSourceVideoRenderer::MediaSourceVideoRenderer(Delegate* delegate) |
139 : delegate_(delegate), | 140 : delegate_(delegate), |
140 latest_sequence_number_(0) { | 141 latest_sequence_number_(0) { |
141 } | 142 } |
142 | 143 |
143 MediaSourceVideoRenderer::~MediaSourceVideoRenderer() {} | 144 MediaSourceVideoRenderer::~MediaSourceVideoRenderer() {} |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 // Fallback for the case when the host didn't include the desktop shape. | 209 // Fallback for the case when the host didn't include the desktop shape. |
209 desktop_shape = | 210 desktop_shape = |
210 webrtc::DesktopRegion(webrtc::DesktopRect::MakeSize(frame_size)); | 211 webrtc::DesktopRegion(webrtc::DesktopRect::MakeSize(frame_size)); |
211 } | 212 } |
212 | 213 |
213 if (!desktop_shape_.Equals(desktop_shape)) { | 214 if (!desktop_shape_.Equals(desktop_shape)) { |
214 desktop_shape_.Swap(&desktop_shape); | 215 desktop_shape_.Swap(&desktop_shape); |
215 delegate_->OnMediaSourceShape(desktop_shape_); | 216 delegate_->OnMediaSourceShape(desktop_shape_); |
216 } | 217 } |
217 | 218 |
| 219 // First bit is set to 0 for key frames. |
| 220 bool keyframe = (packet->data()[0] & 1) == 0; |
| 221 |
218 scoped_ptr<VideoWriter::DataBuffer> buffer = | 222 scoped_ptr<VideoWriter::DataBuffer> buffer = |
219 writer_->OnVideoFrame(packet->data()); | 223 writer_->OnVideoFrame(packet->data(), keyframe); |
220 delegate_->OnMediaSourceData(&(*(buffer->begin())), buffer->size()); | 224 delegate_->OnMediaSourceData(&(*(buffer->begin())), buffer->size(), keyframe); |
221 } | 225 } |
222 | 226 |
223 } // namespace remoting | 227 } // namespace remoting |
OLD | NEW |