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.
5 #include "media/cast/framer/framer.h"
7 #include "base/logging.h"
12 typedef FrameList::const_iterator ConstFrameIterator
;
14 Framer::Framer(RtpPayloadFeedback
* incoming_payload_feedback
,
16 bool decoder_faster_than_max_frame_rate
,
17 int max_unacked_frames
)
18 : decoder_faster_than_max_frame_rate_(decoder_faster_than_max_frame_rate
),
19 clock_(&default_tick_clock_
),
20 cast_msg_builder_(new CastMessageBuilder(incoming_payload_feedback
,
21 &frame_id_map_
, ssrc
, decoder_faster_than_max_frame_rate
,
22 max_unacked_frames
)) {
23 DCHECK(incoming_payload_feedback
) << "Invalid argument";
28 void Framer::InsertPacket(const uint8
* payload_data
,
30 const RtpCastHeader
& rtp_header
) {
31 bool complete
= false;
32 if (!frame_id_map_
.InsertPacket(rtp_header
, &complete
)) return;
34 // Does this packet belong to a new frame?
35 FrameList::iterator it
= frames_
.find(rtp_header
.frame_id
);
36 if (it
== frames_
.end()) {
38 linked_ptr
<FrameBuffer
> frame_buffer(new FrameBuffer());
39 frame_buffer
->InsertPacket(payload_data
, payload_size
, rtp_header
);
40 frames_
.insert(std::make_pair(rtp_header
.frame_id
, frame_buffer
));
42 // Insert packet to existing frame buffer.
43 it
->second
->InsertPacket(payload_data
, payload_size
, rtp_header
);
47 // ACK as soon as possible.
48 cast_msg_builder_
->CompleteFrameReceived(rtp_header
.frame_id
,
49 rtp_header
.is_key_frame
);
53 // This does not release the frame.
54 bool Framer::GetEncodedAudioFrame(const base::TimeTicks
& timeout
,
55 EncodedAudioFrame
* audio_frame
,
56 uint32
* rtp_timestamp
,
60 if (frame_id_map_
.NextContinuousFrame(&frame_id
)) {
61 // We have our next frame.
64 if (WaitForNextFrame(timeout
)) return false;
66 if (!frame_id_map_
.NextAudioFrameAllowingMissingFrames(&frame_id
)) {
72 ConstFrameIterator it
= frames_
.find(frame_id
);
73 DCHECK(it
!= frames_
.end());
74 if (it
== frames_
.end()) return false;
76 return it
->second
->GetEncodedAudioFrame(audio_frame
, rtp_timestamp
);
79 // This does not release the frame.
80 bool Framer::GetEncodedVideoFrame(const base::TimeTicks
& timeout
,
81 EncodedVideoFrame
* video_frame
,
82 uint32
* rtp_timestamp
,
86 if (frame_id_map_
.NextContinuousFrame(&frame_id
)) {
87 // We have our next frame.
90 if (WaitForNextFrame(timeout
)) return false;
92 // Check if we can skip frames when our decoder is too slow.
93 if (!decoder_faster_than_max_frame_rate_
) return false;
95 if (!frame_id_map_
.NextVideoFrameAllowingSkippingFrames(&frame_id
)) {
101 ConstFrameIterator it
= frames_
.find(frame_id
);
102 DCHECK(it
!= frames_
.end());
103 if (it
== frames_
.end()) return false;
105 return it
->second
->GetEncodedVideoFrame(video_frame
, rtp_timestamp
);
108 bool Framer::WaitForNextFrame(const base::TimeTicks
& timeout
) const {
109 base::TimeDelta wait_time
= timeout
- clock_
->NowTicks();
110 if (wait_time
.InMilliseconds() > 0)
116 void Framer::Reset() {
117 frame_id_map_
.Clear();
119 cast_msg_builder_
->Reset();
122 void Framer::ReleaseFrame(uint8 frame_id
) {
123 frame_id_map_
.RemoveOldFrames(frame_id
);
124 frames_
.erase(frame_id
);
126 // We have a frame - remove all frames with lower frame id.
127 FrameList::iterator it
;
128 for (it
= frames_
.begin(); it
!= frames_
.end(); ) {
129 if (IsOlderFrameId(it
->first
, frame_id
)) {
137 bool Framer::TimeToSendNextCastMessage(base::TimeTicks
* time_to_send
) {
138 return cast_msg_builder_
->TimeToSendNextCastMessage(time_to_send
);
141 void Framer::SendCastMessage() {
142 cast_msg_builder_
->UpdateCastMessage();