Home | History | Annotate | Download | only in framer
      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.
      4 
      5 #include "media/cast/framer/frame_buffer.h"
      6 
      7 #include "base/logging.h"
      8 
      9 namespace media {
     10 namespace cast {
     11 
     12 FrameBuffer::FrameBuffer()
     13     : frame_id_(0),
     14       max_packet_id_(0),
     15       num_packets_received_(0),
     16       is_key_frame_(false),
     17       total_data_size_(0),
     18       last_referenced_frame_id_(0),
     19       packets_() {}
     20 
     21 FrameBuffer::~FrameBuffer() {}
     22 
     23 void FrameBuffer::InsertPacket(const uint8* payload_data,
     24                                size_t payload_size,
     25                                const RtpCastHeader& rtp_header) {
     26   // Is this the first packet in the frame?
     27   if (packets_.empty()) {
     28     frame_id_ = rtp_header.frame_id;
     29     max_packet_id_ = rtp_header.max_packet_id;
     30     is_key_frame_ = rtp_header.is_key_frame;
     31     if (rtp_header.is_reference) {
     32       last_referenced_frame_id_ = rtp_header.reference_frame_id;
     33     } else {
     34       last_referenced_frame_id_ = rtp_header.frame_id - 1;
     35     }
     36 
     37     rtp_timestamp_ = rtp_header.webrtc.header.timestamp;
     38   }
     39   // Is this the correct frame?
     40   if (rtp_header.frame_id != frame_id_) return;
     41 
     42   // Insert every packet only once.
     43   if (packets_.find(rtp_header.packet_id) != packets_.end()) {
     44     VLOG(3) << "Packet already received, ignored: frame "
     45             << frame_id_ << ", packet " << rtp_header.packet_id;
     46     return;
     47   }
     48 
     49   std::vector<uint8> data;
     50   std::pair<PacketMap::iterator, bool> retval =
     51       packets_.insert(make_pair(rtp_header.packet_id, data));
     52 
     53   // Insert the packet.
     54   retval.first->second.resize(payload_size);
     55   std::copy(payload_data, payload_data + payload_size,
     56             retval.first->second.begin());
     57 
     58   ++num_packets_received_;
     59   total_data_size_ += payload_size;
     60 }
     61 
     62 bool FrameBuffer::Complete() const {
     63   return num_packets_received_ - 1 == max_packet_id_;
     64 }
     65 
     66 bool FrameBuffer::GetEncodedAudioFrame(EncodedAudioFrame* audio_frame,
     67                                        uint32* rtp_timestamp) const {
     68   if (!Complete()) return false;
     69 
     70   *rtp_timestamp = rtp_timestamp_;
     71 
     72   // Frame is complete -> construct.
     73   audio_frame->frame_id = frame_id_;
     74 
     75   // Build the data vector.
     76   audio_frame->data.clear();
     77   audio_frame->data.reserve(total_data_size_);
     78   PacketMap::const_iterator it;
     79   for (it = packets_.begin(); it != packets_.end(); ++it) {
     80     audio_frame->data.insert(audio_frame->data.end(),
     81                              it->second.begin(), it->second.end());
     82   }
     83   return true;
     84 }
     85 
     86 bool FrameBuffer::GetEncodedVideoFrame(EncodedVideoFrame* video_frame,
     87                                        uint32* rtp_timestamp) const {
     88   if (!Complete()) return false;
     89 
     90   *rtp_timestamp = rtp_timestamp_;
     91 
     92   // Frame is complete -> construct.
     93   video_frame->key_frame = is_key_frame_;
     94   video_frame->frame_id = frame_id_;
     95   video_frame->last_referenced_frame_id = last_referenced_frame_id_;
     96 
     97   // Build the data vector.
     98   video_frame->data.clear();
     99   video_frame->data.reserve(total_data_size_);
    100   PacketMap::const_iterator it;
    101   for (it = packets_.begin(); it != packets_.end(); ++it) {
    102     video_frame->data.insert(video_frame->data.end(),
    103                              it->second.begin(), it->second.end());
    104   }
    105   return true;
    106 }
    107 
    108 }  // namespace cast
    109 }  // namespace media
    110