diff options
Diffstat (limited to 'webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h')
-rw-r--r-- | webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h new file mode 100644 index 0000000000..63db349c74 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +/* + * This file contains the declaration of the VP8 packetizer class. + * A packetizer object is created for each encoded video frame. The + * constructor is called with the payload data and size, + * together with the fragmentation information and a packetizer mode + * of choice. Alternatively, if no fragmentation info is available, the + * second constructor can be used with only payload data and size; in that + * case the mode kEqualSize is used. + * + * After creating the packetizer, the method NextPacket is called + * repeatedly to get all packets for the frame. The method returns + * false as long as there are more packets left to fetch. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ + +#include <queue> +#include <string> +#include <vector> + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_format.h" +#include "webrtc/typedefs.h" + +namespace webrtc { + +enum VP8PacketizerMode { + kStrict = 0, // Split partitions if too large; + // never aggregate, balance size. + kAggregate, // Split partitions if too large; aggregate whole partitions. + kEqualSize, // Split entire payload without considering partition limits. + // This will produce equal size packets for the whole frame. + kNumModes, +}; + +// Packetizer for VP8. +class RtpPacketizerVp8 : public RtpPacketizer { + public: + // Initialize with payload from encoder and fragmentation info. + // The payload_data must be exactly one encoded VP8 frame. + RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, + size_t max_payload_len, + VP8PacketizerMode mode); + + // Initialize without fragmentation info. Mode kEqualSize will be used. + // The payload_data must be exactly one encoded VP8 frame. + RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, size_t max_payload_len); + + virtual ~RtpPacketizerVp8(); + + void SetPayloadData(const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation) override; + + // Get the next payload with VP8 payload header. + // max_payload_len limits the sum length of payload and VP8 payload header. + // buffer is a pointer to where the output will be written. + // bytes_to_send is an output variable that will contain number of bytes + // written to buffer. Parameter last_packet is true for the last packet of + // the frame, false otherwise (i.e., call the function again to get the + // next packet). + // For the kStrict and kAggregate mode: returns the partition index from which + // the first payload byte in the packet is taken, with the first partition + // having index 0; returns negative on error. + // For the kEqualSize mode: returns 0 on success, return negative on error. + bool NextPacket(uint8_t* buffer, + size_t* bytes_to_send, + bool* last_packet) override; + + ProtectionType GetProtectionType() override; + + StorageType GetStorageType(uint32_t retransmission_settings) override; + + std::string ToString() override; + + private: + typedef struct { + size_t payload_start_pos; + size_t size; + bool first_fragment; + size_t first_partition_ix; + } InfoStruct; + typedef std::queue<InfoStruct> InfoQueue; + enum AggregationMode { + kAggrNone = 0, // No aggregation. + kAggrPartitions, // Aggregate intact partitions. + kAggrFragments // Aggregate intact and fragmented partitions. + }; + + static const AggregationMode aggr_modes_[kNumModes]; + static const bool balance_modes_[kNumModes]; + static const bool separate_first_modes_[kNumModes]; + static const int kXBit = 0x80; + static const int kNBit = 0x20; + static const int kSBit = 0x10; + static const int kPartIdField = 0x0F; + static const int kKeyIdxField = 0x1F; + static const int kIBit = 0x80; + static const int kLBit = 0x40; + static const int kTBit = 0x20; + static const int kKBit = 0x10; + static const int kYBit = 0x20; + + // Calculate size of next chunk to send. Returns 0 if none can be sent. + size_t CalcNextSize(size_t max_payload_len, + size_t remaining_bytes, + bool split_payload) const; + + // Calculate all packet sizes and load to packet info queue. + int GeneratePackets(); + + // Calculate all packet sizes using Vp8PartitionAggregator and load to packet + // info queue. + int GeneratePacketsBalancedAggregates(); + + // Helper function to GeneratePacketsBalancedAggregates(). Find all + // continuous sets of partitions smaller than the max payload size (not + // max_size), and aggregate them into balanced packets. The result is written + // to partition_vec, which is of the same length as the number of partitions. + // A value of -1 indicates that the partition is too large and must be split. + // Aggregates are numbered 0, 1, 2, etc. For each set of small partitions, + // the aggregate numbers restart at 0. Output values min_size and max_size + // will hold the smallest and largest resulting aggregates (i.e., not counting + // those that must be split). + void AggregateSmallPartitions(std::vector<int>* partition_vec, + int* min_size, + int* max_size); + + // Insert packet into packet queue. + void QueuePacket(size_t start_pos, + size_t packet_size, + size_t first_partition_in_packet, + bool start_on_new_fragment); + + // Write the payload header and copy the payload to the buffer. + // The info in packet_info determines which part of the payload is written + // and what to write in the header fields. + int WriteHeaderAndPayload(const InfoStruct& packet_info, + uint8_t* buffer, + size_t buffer_length) const; + + // Write the X field and the appropriate extension fields to buffer. + // The function returns the extension length (including X field), or -1 + // on error. + int WriteExtensionFields(uint8_t* buffer, size_t buffer_length) const; + + // Set the I bit in the x_field, and write PictureID to the appropriate + // position in buffer. The function returns 0 on success, -1 otherwise. + int WritePictureIDFields(uint8_t* x_field, + uint8_t* buffer, + size_t buffer_length, + size_t* extension_length) const; + + // Set the L bit in the x_field, and write Tl0PicIdx to the appropriate + // position in buffer. The function returns 0 on success, -1 otherwise. + int WriteTl0PicIdxFields(uint8_t* x_field, + uint8_t* buffer, + size_t buffer_length, + size_t* extension_length) const; + + // Set the T and K bits in the x_field, and write TID, Y and KeyIdx to the + // appropriate position in buffer. The function returns 0 on success, + // -1 otherwise. + int WriteTIDAndKeyIdxFields(uint8_t* x_field, + uint8_t* buffer, + size_t buffer_length, + size_t* extension_length) const; + + // Write the PictureID from codec_specific_info_ to buffer. One or two + // bytes are written, depending on magnitude of PictureID. The function + // returns the number of bytes written. + int WritePictureID(uint8_t* buffer, size_t buffer_length) const; + + // Calculate and return length (octets) of the variable header fields in + // the next header (i.e., header length in addition to vp8_header_bytes_). + size_t PayloadDescriptorExtraLength() const; + + // Calculate and return length (octets) of PictureID field in the next + // header. Can be 0, 1, or 2. + size_t PictureIdLength() const; + + // Check whether each of the optional fields will be included in the header. + bool XFieldPresent() const; + bool TIDFieldPresent() const; + bool KeyIdxFieldPresent() const; + bool TL0PicIdxFieldPresent() const; + bool PictureIdPresent() const { return (PictureIdLength() > 0); } + + const uint8_t* payload_data_; + size_t payload_size_; + RTPFragmentationHeader part_info_; + const size_t vp8_fixed_payload_descriptor_bytes_; // Length of VP8 payload + // descriptors' fixed part. + const AggregationMode aggr_mode_; + const bool balance_; + const bool separate_first_; + const RTPVideoHeaderVP8 hdr_info_; + size_t num_partitions_; + const size_t max_payload_len_; + InfoQueue packets_; + bool packets_calculated_; + + RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerVp8); +}; + +// Depacketizer for VP8. +class RtpDepacketizerVp8 : public RtpDepacketizer { + public: + virtual ~RtpDepacketizerVp8() {} + + bool Parse(ParsedPayload* parsed_payload, + const uint8_t* payload_data, + size_t payload_data_length) override; +}; +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ |