| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "media/cast/video_receiver/video_receiver.h" | 5 #include "media/cast/video_receiver/video_receiver.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 GetEncodedVideoFrame(base::Bind( | 87 GetEncodedVideoFrame(base::Bind( |
| 88 &VideoReceiver::DecodeEncodedVideoFrame, | 88 &VideoReceiver::DecodeEncodedVideoFrame, |
| 89 // Note: Use of Unretained is safe since this Closure is guaranteed to be | 89 // Note: Use of Unretained is safe since this Closure is guaranteed to be |
| 90 // invoked before destruction of |this|. | 90 // invoked before destruction of |this|. |
| 91 base::Unretained(this), | 91 base::Unretained(this), |
| 92 callback)); | 92 callback)); |
| 93 } | 93 } |
| 94 | 94 |
| 95 void VideoReceiver::DecodeEncodedVideoFrame( | 95 void VideoReceiver::DecodeEncodedVideoFrame( |
| 96 const VideoFrameDecodedCallback& callback, | 96 const VideoFrameDecodedCallback& callback, |
| 97 scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 97 scoped_ptr<transport::EncodedFrame> encoded_frame) { |
| 98 const base::TimeTicks& playout_time) { | |
| 99 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 98 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 100 if (!encoded_frame) { | 99 if (!encoded_frame) { |
| 101 callback.Run(make_scoped_refptr<VideoFrame>(NULL), playout_time, false); | 100 callback.Run( |
| 101 make_scoped_refptr<VideoFrame>(NULL), base::TimeTicks(), false); |
| 102 return; | 102 return; |
| 103 } | 103 } |
| 104 const uint32 frame_id = encoded_frame->frame_id; | 104 const uint32 frame_id = encoded_frame->frame_id; |
| 105 const uint32 rtp_timestamp = encoded_frame->rtp_timestamp; | 105 const uint32 rtp_timestamp = encoded_frame->rtp_timestamp; |
| 106 const base::TimeTicks playout_time = encoded_frame->reference_time; |
| 106 video_decoder_->DecodeFrame(encoded_frame.Pass(), | 107 video_decoder_->DecodeFrame(encoded_frame.Pass(), |
| 107 base::Bind(&VideoReceiver::EmitRawVideoFrame, | 108 base::Bind(&VideoReceiver::EmitRawVideoFrame, |
| 108 cast_environment_, | 109 cast_environment_, |
| 109 callback, | 110 callback, |
| 110 frame_id, | 111 frame_id, |
| 111 rtp_timestamp, | 112 rtp_timestamp, |
| 112 playout_time)); | 113 playout_time)); |
| 113 } | 114 } |
| 114 | 115 |
| 115 // static | 116 // static |
| (...skipping 15 matching lines...) Expand all Loading... |
| 131 playout_time - now); | 132 playout_time - now); |
| 132 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 133 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 133 TRACE_EVENT_INSTANT1( | 134 TRACE_EVENT_INSTANT1( |
| 134 "cast_perf_test", "FrameDecoded", | 135 "cast_perf_test", "FrameDecoded", |
| 135 TRACE_EVENT_SCOPE_THREAD, | 136 TRACE_EVENT_SCOPE_THREAD, |
| 136 "rtp_timestamp", rtp_timestamp); | 137 "rtp_timestamp", rtp_timestamp); |
| 137 } | 138 } |
| 138 callback.Run(video_frame, playout_time, is_continuous); | 139 callback.Run(video_frame, playout_time, is_continuous); |
| 139 } | 140 } |
| 140 | 141 |
| 141 void VideoReceiver::GetEncodedVideoFrame( | 142 void VideoReceiver::GetEncodedVideoFrame(const FrameEncodedCallback& callback) { |
| 142 const VideoFrameEncodedCallback& callback) { | |
| 143 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 143 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 144 frame_request_queue_.push_back(callback); | 144 frame_request_queue_.push_back(callback); |
| 145 EmitAvailableEncodedFrames(); | 145 EmitAvailableEncodedFrames(); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void VideoReceiver::EmitAvailableEncodedFrames() { | 148 void VideoReceiver::EmitAvailableEncodedFrames() { |
| 149 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 149 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 150 | 150 |
| 151 while (!frame_request_queue_.empty()) { | 151 while (!frame_request_queue_.empty()) { |
| 152 // Attempt to peek at the next completed frame from the |framer_|. | 152 // Attempt to peek at the next completed frame from the |framer_|. |
| 153 // TODO(miu): We should only be peeking at the metadata, and not copying the | 153 // TODO(miu): We should only be peeking at the metadata, and not copying the |
| 154 // payload yet! Or, at least, peek using a StringPiece instead of a copy. | 154 // payload yet! Or, at least, peek using a StringPiece instead of a copy. |
| 155 scoped_ptr<transport::EncodedVideoFrame> encoded_frame( | 155 scoped_ptr<transport::EncodedFrame> encoded_frame( |
| 156 new transport::EncodedVideoFrame()); | 156 new transport::EncodedFrame()); |
| 157 bool is_consecutively_next_frame = false; | 157 bool is_consecutively_next_frame = false; |
| 158 if (!framer_.GetEncodedVideoFrame(encoded_frame.get(), | 158 if (!framer_.GetEncodedVideoFrame(encoded_frame.get(), |
| 159 &is_consecutively_next_frame)) { | 159 &is_consecutively_next_frame)) { |
| 160 VLOG(1) << "Wait for more video packets to produce a completed frame."; | 160 VLOG(1) << "Wait for more video packets to produce a completed frame."; |
| 161 return; // OnReceivedPayloadData() will invoke this method in the future. | 161 return; // OnReceivedPayloadData() will invoke this method in the future. |
| 162 } | 162 } |
| 163 | 163 |
| 164 // If |framer_| has a frame ready that is out of sequence, examine the | 164 // If |framer_| has a frame ready that is out of sequence, examine the |
| 165 // playout time to determine whether it's acceptable to continue, thereby | 165 // playout time to determine whether it's acceptable to continue, thereby |
| 166 // skipping one or more frames. Skip if the missing frame wouldn't complete | 166 // skipping one or more frames. Skip if the missing frame wouldn't complete |
| (...skipping 27 matching lines...) Expand all Loading... |
| 194 encoded_frame->data, | 194 encoded_frame->data, |
| 195 &decrypted_video_data)) { | 195 &decrypted_video_data)) { |
| 196 // Decryption failed. Give up on this frame, releasing it from the | 196 // Decryption failed. Give up on this frame, releasing it from the |
| 197 // jitter buffer. | 197 // jitter buffer. |
| 198 framer_.ReleaseFrame(encoded_frame->frame_id); | 198 framer_.ReleaseFrame(encoded_frame->frame_id); |
| 199 continue; | 199 continue; |
| 200 } | 200 } |
| 201 encoded_frame->data.swap(decrypted_video_data); | 201 encoded_frame->data.swap(decrypted_video_data); |
| 202 } | 202 } |
| 203 | 203 |
| 204 // At this point, we have a decrypted EncodedVideoFrame ready to be emitted. | 204 // At this point, we have a decrypted EncodedFrame ready to be emitted. |
| 205 encoded_frame->codec = codec_; | 205 encoded_frame->reference_time = playout_time; |
| 206 framer_.ReleaseFrame(encoded_frame->frame_id); | 206 framer_.ReleaseFrame(encoded_frame->frame_id); |
| 207 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 207 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 208 TRACE_EVENT_INSTANT2( | 208 TRACE_EVENT_INSTANT2( |
| 209 "cast_perf_test", "PullEncodedVideoFrame", | 209 "cast_perf_test", "PullEncodedVideoFrame", |
| 210 TRACE_EVENT_SCOPE_THREAD, | 210 TRACE_EVENT_SCOPE_THREAD, |
| 211 "rtp_timestamp", encoded_frame->rtp_timestamp, | 211 "rtp_timestamp", encoded_frame->rtp_timestamp, |
| 212 // TODO(miu): Need to find an alternative to using ToInternalValue(): | 212 // TODO(miu): Need to find an alternative to using ToInternalValue(): |
| 213 "render_time", playout_time.ToInternalValue()); | 213 "render_time", playout_time.ToInternalValue()); |
| 214 cast_environment_->PostTask(CastEnvironment::MAIN, | 214 cast_environment_->PostTask(CastEnvironment::MAIN, |
| 215 FROM_HERE, | 215 FROM_HERE, |
| 216 base::Bind(frame_request_queue_.front(), | 216 base::Bind(frame_request_queue_.front(), |
| 217 base::Passed(&encoded_frame), | 217 base::Passed(&encoded_frame))); |
| 218 playout_time)); | |
| 219 frame_request_queue_.pop_front(); | 218 frame_request_queue_.pop_front(); |
| 220 } | 219 } |
| 221 } | 220 } |
| 222 | 221 |
| 223 void VideoReceiver::EmitAvailableEncodedFramesAfterWaiting() { | 222 void VideoReceiver::EmitAvailableEncodedFramesAfterWaiting() { |
| 224 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 223 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 225 DCHECK(is_waiting_for_consecutive_frame_); | 224 DCHECK(is_waiting_for_consecutive_frame_); |
| 226 is_waiting_for_consecutive_frame_ = false; | 225 is_waiting_for_consecutive_frame_ = false; |
| 227 EmitAvailableEncodedFrames(); | 226 EmitAvailableEncodedFrames(); |
| 228 } | 227 } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 } | 409 } |
| 411 | 410 |
| 412 void VideoReceiver::SendNextRtcpReport() { | 411 void VideoReceiver::SendNextRtcpReport() { |
| 413 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 412 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 414 rtcp_.SendRtcpFromRtpReceiver(NULL, NULL); | 413 rtcp_.SendRtcpFromRtpReceiver(NULL, NULL); |
| 415 ScheduleNextRtcpReport(); | 414 ScheduleNextRtcpReport(); |
| 416 } | 415 } |
| 417 | 416 |
| 418 } // namespace cast | 417 } // namespace cast |
| 419 } // namespace media | 418 } // namespace media |
| OLD | NEW |