Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /*
     12  * This file contains the declaration of the VP8 packetizer class.
     13  * A packetizer object is created for each encoded video frame. The
     14  * constructor is called with the payload data and size,
     15  * together with the fragmentation information and a packetizer mode
     16  * of choice. Alternatively, if no fragmentation info is available, the
     17  * second constructor can be used with only payload data and size; in that
     18  * case the mode kEqualSize is used.
     19  *
     20  * After creating the packetizer, the method NextPacket is called
     21  * repeatedly to get all packets for the frame. The method returns
     22  * false as long as there are more packets left to fetch.
     23  */
     24 
     25 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_
     26 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_
     27 
     28 #include <queue>
     29 #include <vector>
     30 
     31 #include "webrtc/base/constructormagic.h"
     32 #include "webrtc/modules/interface/module_common_types.h"
     33 #include "webrtc/typedefs.h"
     34 
     35 namespace webrtc {
     36 
     37 enum VP8PacketizerMode {
     38   kStrict = 0,  // Split partitions if too large;
     39                 // never aggregate, balance size.
     40   kAggregate,   // Split partitions if too large; aggregate whole partitions.
     41   kEqualSize,   // Split entire payload without considering partition limits.
     42                 // This will produce equal size packets for the whole frame.
     43   kNumModes,
     44 };
     45 
     46 // Packetizer for VP8.
     47 class RtpFormatVp8 {
     48  public:
     49   // Initialize with payload from encoder and fragmentation info.
     50   // The payload_data must be exactly one encoded VP8 frame.
     51   RtpFormatVp8(const uint8_t* payload_data,
     52                uint32_t payload_size,
     53                const RTPVideoHeaderVP8& hdr_info,
     54                int max_payload_len,
     55                const RTPFragmentationHeader& fragmentation,
     56                VP8PacketizerMode mode);
     57 
     58   // Initialize without fragmentation info. Mode kEqualSize will be used.
     59   // The payload_data must be exactly one encoded VP8 frame.
     60   RtpFormatVp8(const uint8_t* payload_data,
     61                uint32_t payload_size,
     62                const RTPVideoHeaderVP8& hdr_info,
     63                int max_payload_len);
     64 
     65   ~RtpFormatVp8();
     66 
     67   // Get the next payload with VP8 payload header.
     68   // max_payload_len limits the sum length of payload and VP8 payload header.
     69   // buffer is a pointer to where the output will be written.
     70   // bytes_to_send is an output variable that will contain number of bytes
     71   // written to buffer. Parameter last_packet is true for the last packet of
     72   // the frame, false otherwise (i.e., call the function again to get the
     73   // next packet).
     74   // For the kStrict and kAggregate mode: returns the partition index from which
     75   // the first payload byte in the packet is taken, with the first partition
     76   // having index 0; returns negative on error.
     77   // For the kEqualSize mode: returns 0 on success, return negative on error.
     78   int NextPacket(uint8_t* buffer,
     79                  int* bytes_to_send,
     80                  bool* last_packet);
     81 
     82  private:
     83   typedef struct {
     84     int payload_start_pos;
     85     int size;
     86     bool first_fragment;
     87     int first_partition_ix;
     88   } InfoStruct;
     89   typedef std::queue<InfoStruct> InfoQueue;
     90   enum AggregationMode {
     91     kAggrNone = 0,    // No aggregation.
     92     kAggrPartitions,  // Aggregate intact partitions.
     93     kAggrFragments    // Aggregate intact and fragmented partitions.
     94   };
     95 
     96   static const AggregationMode aggr_modes_[kNumModes];
     97   static const bool balance_modes_[kNumModes];
     98   static const bool separate_first_modes_[kNumModes];
     99   static const int kXBit        = 0x80;
    100   static const int kNBit        = 0x20;
    101   static const int kSBit        = 0x10;
    102   static const int kPartIdField = 0x0F;
    103   static const int kKeyIdxField = 0x1F;
    104   static const int kIBit        = 0x80;
    105   static const int kLBit        = 0x40;
    106   static const int kTBit        = 0x20;
    107   static const int kKBit        = 0x10;
    108   static const int kYBit        = 0x20;
    109 
    110   // Calculate size of next chunk to send. Returns 0 if none can be sent.
    111   int CalcNextSize(int max_payload_len, int remaining_bytes,
    112                    bool split_payload) const;
    113 
    114   // Calculate all packet sizes and load to packet info queue.
    115   int GeneratePackets();
    116 
    117   // Calculate all packet sizes using Vp8PartitionAggregator and load to packet
    118   // info queue.
    119   int GeneratePacketsBalancedAggregates();
    120 
    121   // Helper function to GeneratePacketsBalancedAggregates(). Find all
    122   // continuous sets of partitions smaller than the max payload size (not
    123   // max_size), and aggregate them into balanced packets. The result is written
    124   // to partition_vec, which is of the same length as the number of partitions.
    125   // A value of -1 indicates that the partition is too large and must be split.
    126   // Aggregates are numbered 0, 1, 2, etc. For each set of small partitions,
    127   // the aggregate numbers restart at 0. Output values min_size and max_size
    128   // will hold the smallest and largest resulting aggregates (i.e., not counting
    129   // those that must be split).
    130   void AggregateSmallPartitions(std::vector<int>* partition_vec,
    131                                 int* min_size,
    132                                 int* max_size);
    133 
    134   // Insert packet into packet queue.
    135   void QueuePacket(int start_pos,
    136                    int packet_size,
    137                    int first_partition_in_packet,
    138                    bool start_on_new_fragment);
    139 
    140   // Write the payload header and copy the payload to the buffer.
    141   // The info in packet_info determines which part of the payload is written
    142   // and what to write in the header fields.
    143   int WriteHeaderAndPayload(const InfoStruct& packet_info,
    144                             uint8_t* buffer,
    145                             int buffer_length) const;
    146 
    147 
    148   // Write the X field and the appropriate extension fields to buffer.
    149   // The function returns the extension length (including X field), or -1
    150   // on error.
    151   int WriteExtensionFields(uint8_t* buffer, int buffer_length) const;
    152 
    153   // Set the I bit in the x_field, and write PictureID to the appropriate
    154   // position in buffer. The function returns 0 on success, -1 otherwise.
    155   int WritePictureIDFields(uint8_t* x_field, uint8_t* buffer,
    156                            int buffer_length, int* extension_length) const;
    157 
    158   // Set the L bit in the x_field, and write Tl0PicIdx to the appropriate
    159   // position in buffer. The function returns 0 on success, -1 otherwise.
    160   int WriteTl0PicIdxFields(uint8_t* x_field, uint8_t* buffer,
    161                            int buffer_length, int* extension_length) const;
    162 
    163   // Set the T and K bits in the x_field, and write TID, Y and KeyIdx to the
    164   // appropriate position in buffer. The function returns 0 on success,
    165   // -1 otherwise.
    166   int WriteTIDAndKeyIdxFields(uint8_t* x_field, uint8_t* buffer,
    167                               int buffer_length, int* extension_length) const;
    168 
    169   // Write the PictureID from codec_specific_info_ to buffer. One or two
    170   // bytes are written, depending on magnitude of PictureID. The function
    171   // returns the number of bytes written.
    172   int WritePictureID(uint8_t* buffer, int buffer_length) const;
    173 
    174   // Calculate and return length (octets) of the variable header fields in
    175   // the next header (i.e., header length in addition to vp8_header_bytes_).
    176   int PayloadDescriptorExtraLength() const;
    177 
    178   // Calculate and return length (octets) of PictureID field in the next
    179   // header. Can be 0, 1, or 2.
    180   int PictureIdLength() const;
    181 
    182   // Check whether each of the optional fields will be included in the header.
    183   bool XFieldPresent() const;
    184   bool TIDFieldPresent() const;
    185   bool KeyIdxFieldPresent() const;
    186   bool TL0PicIdxFieldPresent() const;
    187   bool PictureIdPresent() const { return (PictureIdLength() > 0); }
    188 
    189   const uint8_t* payload_data_;
    190   const int payload_size_;
    191   RTPFragmentationHeader part_info_;
    192   const int vp8_fixed_payload_descriptor_bytes_;  // Length of VP8 payload
    193                                                   // descriptors's fixed part.
    194   const AggregationMode aggr_mode_;
    195   const bool balance_;
    196   const bool separate_first_;
    197   const RTPVideoHeaderVP8 hdr_info_;
    198   const int num_partitions_;
    199   const int max_payload_len_;
    200   InfoQueue packets_;
    201   bool packets_calculated_;
    202 
    203   DISALLOW_COPY_AND_ASSIGN(RtpFormatVp8);
    204 };
    205 
    206 }  // namespace
    207 
    208 #endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_
    209