2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
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.
11 #include "rtp_sender_h264.h"
13 #include "rtp_utility.h"
16 RTPSenderH264::RTPSenderH264(RTPSenderInterface* rtpSender) :
18 _rtpSender(*rtpSender),
19 _h264Mode(H264_SINGLE_NAL_MODE),
20 _h264SendPPS_SPS(true),
21 _h264SVCPayloadType(-1),
22 _h264SVCRelaySequenceNumber(0),
23 _h264SVCRelayTimeStamp(0),
24 _h264SVCRelayLayerComplete(false),
26 _useHighestSendLayer(false),
27 _highestDependencyLayerOld(MAX_NUMBER_OF_TEMPORAL_ID-1),
28 _highestDependencyQualityIDOld(MAX_NUMBER_OF_DEPENDENCY_QUALITY_ID-1),
29 _highestDependencyLayer(0),
30 _highestDependencyQualityID(0),
31 _highestTemporalLayer(0)
35 RTPSenderH264::~RTPSenderH264()
42 _h264SendPPS_SPS = true;
43 _h264Mode = H264_SINGLE_NAL_MODE;
51 NI-TC timestamps/CS-DON
54 Non-interleaved timestamp based mode (NI-T)
55 Non-interleaved cross-session decoding order number (CS-DON) based mode (NI-C)
56 Non-interleaved combined timestamp and CS-DON mode (NI-TC)
58 NOT supported Interleaved CS-DON (I-C) mode.
60 NI-T and NI-TC modes both use timestamps to recover the decoding
61 order. In order to be able to do so, it is necessary for the RTP
62 packet stream to contain data for all sampling instances of a given
63 RTP session in all enhancement RTP sessions that depend on the given
64 RTP session. The NI-C and I-C modes do not have this limitation,
65 and use the CS-DON values as a means to explicitly indicate decoding
66 order, either directly coded in PACSI NAL units, or inferred from
67 them using the packetization rules. It is noted that the NI-TC mode
68 offers both alternatives and it is up to the receiver to select
73 RTPSenderH264::AddH264SVCNALUHeader(const H264_SVC_NALUHeader& svc,
75 int32_t& curByte) const
77 // +---------------+---------------+---------------+
78 // |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
79 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 // |R|I| PRID |N| DID | QID | TID |U|D|O| RR|
81 // +---------------+---------------+---------------+
83 // R - Reserved for future extensions (MUST be 1). Receivers SHOULD ignore the value of R.
84 // I - Is layer representation an IDR layer (1) or not (0).
85 // PRID - Priority identifier for the NAL unit.
86 // N - Specifies whether inter-layer prediction may be used for decoding the coded slice (1) or not (0).
87 // DID - Indicates the int32_t:er-layer coding dependency level of a layer representation.
88 // QID - Indicates the quality level of an MGS layer representation.
89 // TID - Indicates the temporal level of a layer representation.
90 // U - Use only reference base pictures during the int32_t:er prediction process (1) or not (0).
91 // D - Discardable flag.
92 // O - Output_flag. Affects the decoded picture output process as defined in Annex C of [H.264].
93 // RR - Reserved_three_2bits (MUST be '11'). Receivers SHOULD ignore the value of RR.
96 databuffer[curByte++] = (svc.r << 7) + (svc.idr << 6) + (svc.priorityID & 0x3F);
97 databuffer[curByte++] = (svc.interLayerPred << 7) + (svc.dependencyID << 4) + (svc.qualityID & 0x0F);
98 databuffer[curByte++] = (svc.temporalID << 5) + (svc.useRefBasePic << 4) + (svc.discardable << 3) +
99 (svc.output << 2) + (svc.rr & 0x03);
104 RTPSenderH264::AddH264PACSINALU(const bool firstPacketInNALU,
105 const bool lastPacketInNALU,
106 const H264_PACSI_NALU& pacsi,
107 const H264_SVC_NALUHeader& svc,
110 int32_t& curByte) const
113 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
114 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 // |F|NRI|Type(30) | SVC NAL unit header |
116 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 // |X|Y|T|A|P|C|S|E| TL0PICIDX (o.)| IDRPICID (o.) |
118 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 // | DONC (o.) | NAL unit size 1 |
120 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 // | SEI NAL unit 1 |
124 // | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 // | | NAL unit size 2 | |
126 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
128 // | SEI NAL unit 2 |
129 // | +-+-+-+-+-+-+-+-+-+-+
131 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134 // If present, MUST be first NAL unit in aggregation packet + there MUST be at least
135 // one additional unit in the same packet! The RTPHeader and payload header are set as if the 2nd NAL unit
136 // (first non-PACSI NAL unit) is encapsulated in the same packet.
137 // contains scalability info common for all remaining NAL units.
139 // todo add API to configure this required for multisession
140 const bool addDONC = false;
142 if (svc.length == 0 || pacsi.NALlength == 0)
147 int32_t startByte = curByte;
150 databuffer[curByte++] = 30; // NRI will be added later
152 // Extended SVC header
153 AddH264SVCNALUHeader(svc, databuffer, curByte);
156 databuffer[curByte++] = (pacsi.X << 7) +
162 firstPacketInNALU?(pacsi.S << 1):0 +
163 lastPacketInNALU?(pacsi.E):0;
168 databuffer[curByte++] = pacsi.TL0picIDx;
169 databuffer[curByte++] = (uint8_t)(pacsi.IDRpicID >> 8);
170 databuffer[curByte++] = (uint8_t)(pacsi.IDRpicID);
172 // Decoding order number
173 if (addDONC) // pacsi.T
175 databuffer[curByte++] = (uint8_t)(DONC >> 8);
176 databuffer[curByte++] = (uint8_t)(DONC);
180 if(firstPacketInNALU) // IMPROVEMENT duplicate it to make sure it arrives...
182 // we only set this for NALU 0 to make sure we send it only once per frame
183 for (uint32_t i = 0; i < pacsi.numSEINALUs; i++)
186 databuffer[curByte++] = (uint8_t)(pacsi.seiMessageLength[i] >> 8);
187 databuffer[curByte++] = (uint8_t)(pacsi.seiMessageLength[i]);
190 memcpy(databuffer + curByte, pacsi.seiMessageData[i], pacsi.seiMessageLength[i]);
191 curByte += pacsi.seiMessageLength[i];
194 return curByte - startByte;
198 RTPSenderH264::SetH264RelaySequenceNumber(const uint16_t seqNum)
200 _h264SVCRelaySequenceNumber = seqNum;
205 RTPSenderH264::SetH264RelayCompleteLayer(const bool complete)
207 _h264SVCRelayLayerComplete = complete;
214 The only restriction of filler data NAL units within an
215 access unit is that they shall not precede the first VCL
216 NAL unit with the same access unit.
219 RTPSenderH264::SendH264FillerData(const WebRtcRTPHeader* rtpHeader,
220 const uint16_t bytesToSend,
223 uint16_t fillerLength = bytesToSend - 12 - 1;
225 if (fillerLength > WEBRTC_IP_PACKET_SIZE - 12 - 1)
230 if (fillerLength == 0)
232 // do not send an empty packet, will not reach JB
236 // send codec valid data, H.264 has defined data which is binary 1111111
237 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
239 dataBuffer[0] = static_cast<uint8_t>(0x80); // version 2
240 dataBuffer[1] = rtpHeader->header.payloadType;
241 ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer+2, _rtpSender.IncrementSequenceNumber()); // get the current SequenceNumber and add by 1 after returning
242 ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer+4, rtpHeader->header.timestamp);
243 ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer+8, rtpHeader->header.ssrc);
245 // set filler NALU type
246 dataBuffer[12] = 12; // NRI field = 0, type 12
249 memset(dataBuffer + 12 + 1, 0xff, fillerLength);
251 return _rtpSender.SendToNetwork(dataBuffer,
257 RTPSenderH264::SendH264FillerData(const uint32_t captureTimestamp,
258 const uint8_t payloadType,
263 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
264 uint16_t maxLength = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - _rtpSender.RTPHeaderLength();
266 int32_t bytesToSend=bytes;
267 uint16_t fillerLength=0;
269 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
273 fillerLength=maxLength;
274 if(fillerLength<maxLength)
276 fillerLength = (uint16_t) bytesToSend;
279 bytesToSend-=fillerLength;
281 if (fillerLength > WEBRTC_IP_PACKET_SIZE - 12 - 1)
286 if (fillerLength == 0)
288 // do not send an empty packet, will not reach JB
293 // correct seq num, time stamp and payloadtype
294 _rtpSender.BuildRTPheader(dataBuffer, payloadType, false,captureTimestamp, true, true);
296 // set filler NALU type
297 dataBuffer[12] = 12; // NRI field = 0, type 12
299 // send codec valid data, H.264 has defined data which is binary 1111111
301 memset(dataBuffer + 12 + 1, 0xff, fillerLength-1);
303 if( _rtpSender.SendToNetwork(dataBuffer,
315 RTPSenderH264::SendH264SVCRelayPacket(const WebRtcRTPHeader* rtpHeader,
316 const uint8_t* incomingRTPPacket,
317 const uint16_t incomingRTPPacketSize,
319 const bool higestLayer)
321 if (rtpHeader->header.sequenceNumber != (uint16_t)(_h264SVCRelaySequenceNumber + 1))
323 // not continous, signal loss
324 _rtpSender.IncrementSequenceNumber();
326 _h264SVCRelaySequenceNumber = rtpHeader->header.sequenceNumber;
329 if (rtpHeader->header.timestamp != _h264SVCRelayTimeStamp)
332 _h264SVCRelayLayerComplete = false;
335 if (rtpHeader->header.timestamp == _h264SVCRelayTimeStamp &&
336 _h264SVCRelayLayerComplete)
338 // sanity, end of layer already sent
339 // Could happened for fragmented packet with missing PACSI info (PACSI packet reorded and received after packet it belongs to)
340 // fragmented packet has no layer info set (default info 0)
343 _h264SVCRelayTimeStamp = rtpHeader->header.timestamp;
345 // re-packetize H.264-SVC packets
346 // we keep the timestap unchanged
347 // make a copy and only change the SSRC and seqNum
349 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
350 memcpy(dataBuffer, incomingRTPPacket, incomingRTPPacketSize);
352 // _sequenceNumber initiated in Init()
353 // _ssrc initiated in constructor
355 // re-write payload type
356 if(_h264SVCPayloadType != -1)
358 dataBuffer[1] &= kRtpMarkerBitMask;
359 dataBuffer[1] += _h264SVCPayloadType;
362 // _sequenceNumber will not work for re-ordering by NACK from original sender
363 // engine responsible for this
364 ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer+2, _rtpSender.IncrementSequenceNumber()); // get the current SequenceNumber and add by 1 after returning
365 //ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer+8, ssrc);
367 // how do we know it's the last relayed packet in a frame?
368 // 1) packets arrive in order, the engine manages that
369 // 2) highest layer that we relay
370 // 3) the end bit is set for the highest layer
372 if(higestLayer && rtpHeader->type.Video.codecHeader.H264.relayE)
375 dataBuffer[1] |= kRtpMarkerBitMask;
377 // set relayed layer as complete
378 _h264SVCRelayLayerComplete = true;
380 return _rtpSender.SendToNetwork(dataBuffer,
381 incomingRTPPacketSize - rtpHeader->header.headerLength,
382 rtpHeader->header.headerLength);
386 RTPSenderH264::SendH264_STAP_A(const FrameType frameType,
387 const H264Info* ptrH264Info,
389 const int8_t payloadType,
390 const uint32_t captureTimeStamp,
392 int32_t &payloadBytesToSend,
393 const uint8_t*& data,
394 const uint16_t rtpHeaderLength)
396 const int32_t H264_NALU_LENGTH = 2;
398 uint16_t h264HeaderLength = 1; // normal header length
399 uint16_t maxPayloadLengthSTAP_A = _rtpSender.MaxPayloadLength() -
400 FECPacketOverhead() - rtpHeaderLength -
401 h264HeaderLength - H264_NALU_LENGTH;
403 int32_t dataOffset = rtpHeaderLength + h264HeaderLength;
405 uint16_t payloadBytesInPacket = 0;
406 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
408 if (ptrH264Info->payloadSize[idxNALU] > maxPayloadLengthSTAP_A)
410 // we need to fragment NAL switch to mode FU-A
414 // combine as many NAL units in every IP packet
417 if(!_h264SendPPS_SPS)
419 // don't send NALU of type 7 and 8 SPS and PPS
420 if(ptrH264Info->type[idxNALU] == 7 || ptrH264Info->type[idxNALU] == 8)
422 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
423 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
428 if(ptrH264Info->payloadSize[idxNALU] + payloadBytesInPacket <= maxPayloadLengthSTAP_A)
430 if(ptrH264Info->NRI[idxNALU] > NRI)
432 NRI = ptrH264Info->NRI[idxNALU];
434 // put NAL size into packet
435 dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] >> 8);
437 dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] & 0xff);
439 // Put payload in packet
440 memcpy(&dataBuffer[dataOffset], &data[ptrH264Info->startCodeSize[idxNALU]], ptrH264Info->payloadSize[idxNALU]);
441 dataOffset += ptrH264Info->payloadSize[idxNALU];
442 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
443 payloadBytesInPacket += (uint16_t)(ptrH264Info->payloadSize[idxNALU] + H264_NALU_LENGTH);
444 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
447 // we don't fitt the next NALU in this packet
451 }while(payloadBytesToSend);
455 // don't send empty packets
456 if (payloadBytesInPacket)
459 _rtpSender.BuildRTPheader(dataBuffer, payloadType, (payloadBytesToSend==0)?true:false, captureTimeStamp);
460 dataBuffer[rtpHeaderLength] = 24 + NRI; // STAP-A == 24
461 uint16_t payloadLength = payloadBytesInPacket + h264HeaderLength;
463 if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength))
471 // STAP-A for H.264 SVC
473 RTPSenderH264::SendH264_STAP_A_PACSI(const FrameType frameType,
474 const H264Info* ptrH264Info,
476 const int8_t payloadType,
477 const uint32_t captureTimeStamp,
479 int32_t &payloadBytesToSend,
480 const uint8_t*& data,
481 const uint16_t rtpHeaderLength,
482 uint16_t& decodingOrderNumber)
484 const int32_t H264_NALU_LENGTH = 2;
486 uint16_t h264HeaderLength = 1; // normal header length
487 uint16_t maxPayloadLengthSTAP_A = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - rtpHeaderLength - h264HeaderLength - H264_NALU_LENGTH;
488 int32_t dataOffset = rtpHeaderLength + h264HeaderLength;
490 uint16_t payloadBytesInPacket = 0;
491 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
492 bool firstNALUNotIDR = true; //delta
494 // Put PACSI NAL unit into packet
495 int32_t lengthPACSI = 0;
496 uint32_t PACSI_NALlength = ptrH264Info->PACSI[idxNALU].NALlength;
497 if (PACSI_NALlength > maxPayloadLengthSTAP_A)
501 dataBuffer[dataOffset++] = (uint8_t)(PACSI_NALlength >> 8);
502 dataBuffer[dataOffset++] = (uint8_t)(PACSI_NALlength & 0xff);
504 // end bit will be updated later, since another NALU in this packet might be the last
505 int32_t lengthPASCINALU = AddH264PACSINALU(true,
507 ptrH264Info->PACSI[idxNALU],
508 ptrH264Info->SVCheader[idxNALU],
512 if (lengthPASCINALU <= 0)
516 decodingOrderNumber++;
518 lengthPACSI = H264_NALU_LENGTH + lengthPASCINALU;
519 maxPayloadLengthSTAP_A -= (uint16_t)lengthPACSI;
520 if (ptrH264Info->payloadSize[idxNALU] > maxPayloadLengthSTAP_A)
522 // we need to fragment NAL switch to mode FU-A
526 if(!ptrH264Info->SVCheader[idxNALU].idr)
528 firstNALUNotIDR = true;
531 uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+
532 (ptrH264Info->SVCheader[idxNALU].qualityID << 8) +
533 ptrH264Info->SVCheader[idxNALU].temporalID;
536 // combine as many NAL units in every IP packet, with the same priorityID
537 // Improvement we could allow several very small MGS NALU from different layers to be sent in one packet
541 if(!_h264SendPPS_SPS)
543 // Don't send NALU of type 7 and 8 SPS and PPS,
544 // they could be signaled outofband
545 if(ptrH264Info->type[idxNALU] == 7 || ptrH264Info->type[idxNALU] == 8)
547 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
548 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
553 // don't send NALU type 6 (SEI message) not allowed when we send it in PACSI
554 if(ptrH264Info->type[idxNALU] == 6)
556 // SEI NALU Don't send, not allowed when we send it in PACSI
557 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
558 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
563 const uint32_t layerNALU = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+
564 (ptrH264Info->SVCheader[idxNALU].qualityID << 8) +
565 ptrH264Info->SVCheader[idxNALU].temporalID;
567 // we need to break on a new layer
568 if( ptrH264Info->payloadSize[idxNALU] + payloadBytesInPacket <= maxPayloadLengthSTAP_A &&
571 if(ptrH264Info->NRI[idxNALU] > NRI)
573 NRI = ptrH264Info->NRI[idxNALU];
575 // put NAL size into packet
576 dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] >> 8);
578 dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] & 0xff);
580 // Put payload in packet
581 memcpy(&dataBuffer[dataOffset], &data[ptrH264Info->startCodeSize[idxNALU]], ptrH264Info->payloadSize[idxNALU]);
582 dataOffset += ptrH264Info->payloadSize[idxNALU];
583 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
584 payloadBytesInPacket += (uint16_t)(ptrH264Info->payloadSize[idxNALU] + H264_NALU_LENGTH);
585 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
588 // we don't fitt the next NALU in this packet or,
589 // it's the next layer
591 // check if we should send this NALU
592 // based on the layer
594 if(_useHighestSendLayer && layerNALU != layer)
596 // we don't send this NALU due to it's a new layer
597 // check if we should send the next or if this is the last
598 const uint8_t dependencyQualityID = (ptrH264Info->SVCheader[idxNALU].dependencyID << 4) + ptrH264Info->SVCheader[idxNALU].qualityID;
601 if(SendH264SVCLayer(frameType,
602 ptrH264Info->SVCheader[idxNALU].temporalID,
604 highestLayer) == false)
606 // will trigger markerbit and stop sending this frame
607 payloadBytesToSend = 0;
614 }while(payloadBytesToSend);
617 // sanity, don't send empty packets
618 if (payloadBytesInPacket)
621 _rtpSender.BuildRTPheader(dataBuffer, payloadType, (payloadBytesToSend==0)?true:false, captureTimeStamp);
623 dataBuffer[rtpHeaderLength] = 24 + NRI; // STAP-A == 24
626 dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 1] &= 0x1f; // zero out NRI field
627 dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 1] |= NRI;
629 if(ptrH264Info->PACSI[idxNALU-1].E)
632 dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 5] |= 0x01;
636 // we have to check if any of the NALU in this packet is an IDR NALU
637 bool setIBit = false;
638 for(int i = 0; i < idxNALU; i++)
640 if(ptrH264Info->SVCheader[i].idr)
649 dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 2] |= 0x40;
652 const uint16_t payloadLength = payloadBytesInPacket + h264HeaderLength + (uint16_t)lengthPACSI;
653 if(-1 == SendVideoPacket(frameType,
666 RTPSenderH264::SendH264_FU_A(const FrameType frameType,
667 const H264Info* ptrH264Info,
669 const int8_t payloadType,
670 const uint32_t captureTimeStamp,
671 int32_t &payloadBytesToSend,
672 const uint8_t*& data,
673 const uint16_t rtpHeaderLength,
674 uint16_t& decodingOrderNumber,
675 const bool sendSVCPACSI)
678 // FUA for the rest of the frame
679 uint16_t maxPayloadLength = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - rtpHeaderLength;
680 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
681 uint32_t payloadBytesRemainingInNALU = ptrH264Info->payloadSize[idxNALU];
683 bool isBaseLayer=false;
685 if(payloadBytesRemainingInNALU > maxPayloadLength)
687 // we need to fragment NALU
688 const uint16_t H264_FUA_LENGTH = 2; // FU-a H.264 header is 2 bytes
692 SendH264_SinglePACSI(frameType,
700 uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+
701 (ptrH264Info->SVCheader[idxNALU].qualityID << 8) +
702 ptrH264Info->SVCheader[idxNALU].temporalID;
703 isBaseLayer=(layer==0);
707 _rtpSender.BuildRTPheader(dataBuffer,payloadType, false, captureTimeStamp);
709 uint16_t maxPayloadLengthFU_A = maxPayloadLength - H264_FUA_LENGTH ;
710 uint8_t fuaIndc = 28 + ptrH264Info->NRI[idxNALU];
711 dataBuffer[rtpHeaderLength] = fuaIndc; // FU-A indicator
712 dataBuffer[rtpHeaderLength+1] = (uint8_t)(ptrH264Info->type[idxNALU] + 0x80)/*start*/; // FU-A header
714 memcpy(&dataBuffer[rtpHeaderLength + H264_FUA_LENGTH], &data[ptrH264Info->startCodeSize[idxNALU]+1], maxPayloadLengthFU_A);
715 uint16_t payloadLength = maxPayloadLengthFU_A + H264_FUA_LENGTH;
716 if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength, isBaseLayer))
721 //+1 is from the type that is coded into the FU-a header
722 data += maxPayloadLengthFU_A + 1 + ptrH264Info->startCodeSize[idxNALU]; // inc data ptr
723 payloadBytesToSend -= maxPayloadLengthFU_A+1+ptrH264Info->startCodeSize[idxNALU];
724 payloadBytesRemainingInNALU -= maxPayloadLengthFU_A+1;
726 // all non first/last packets
727 while(payloadBytesRemainingInNALU > maxPayloadLengthFU_A)
731 SendH264_SinglePACSI(frameType,
740 // prepare next header
741 _rtpSender.BuildRTPheader(dataBuffer, payloadType, false, captureTimeStamp);
743 dataBuffer[rtpHeaderLength] = (uint8_t)fuaIndc; // FU-A indicator
744 dataBuffer[rtpHeaderLength+1] = ptrH264Info->type[idxNALU]; // FU-A header
746 memcpy(&dataBuffer[rtpHeaderLength+H264_FUA_LENGTH], data, maxPayloadLengthFU_A);
747 payloadLength = maxPayloadLengthFU_A + H264_FUA_LENGTH;
749 if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength,isBaseLayer))
753 data += maxPayloadLengthFU_A; // inc data ptr
754 payloadBytesToSend -= maxPayloadLengthFU_A;
755 payloadBytesRemainingInNALU -= maxPayloadLengthFU_A;
756 dataBuffer[rtpHeaderLength] = fuaIndc; // FU-A indicator
757 dataBuffer[rtpHeaderLength+1] = ptrH264Info->type[idxNALU]; // FU-A header
761 SendH264_SinglePACSI(frameType,
767 true); // last packet in NALU
769 if(_useHighestSendLayer && idxNALU+1 < ptrH264Info->numNALUs)
771 // not last NALU in frame
772 // check if it's the the next layer should not be sent
774 // check if we should send the next or if this is the last
775 const uint8_t dependencyQualityID = (ptrH264Info->SVCheader[idxNALU+1].dependencyID << 4) +
776 ptrH264Info->SVCheader[idxNALU+1].qualityID;
779 if(SendH264SVCLayer(frameType,
780 ptrH264Info->SVCheader[idxNALU+1].temporalID,
782 highestLayer) == false)
784 // will trigger markerbit and stop sending this frame
785 payloadBytesToSend = payloadBytesRemainingInNALU;
789 // last packet in NALU
790 _rtpSender.BuildRTPheader(dataBuffer, payloadType,(payloadBytesToSend == (int32_t)payloadBytesRemainingInNALU)?true:false, captureTimeStamp);
791 dataBuffer[rtpHeaderLength+1] = ptrH264Info->type[idxNALU] + 0x40/*stop*/; // FU-A header
793 memcpy(&dataBuffer[rtpHeaderLength+H264_FUA_LENGTH], data, payloadBytesRemainingInNALU);
794 payloadLength = (uint16_t)payloadBytesRemainingInNALU + H264_FUA_LENGTH;
795 payloadBytesToSend -= payloadBytesRemainingInNALU;
796 if(payloadBytesToSend != 0)
798 data += payloadBytesRemainingInNALU; // inc data ptr
801 if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength,isBaseLayer))
807 // send NAL unit in singel mode
808 return SendH264_SingleMode(frameType,
823 RTPSenderH264::SendH264_SingleMode(const FrameType frameType,
824 const H264Info* ptrH264Info,
826 const int8_t payloadType,
827 const uint32_t captureTimeStamp,
828 int32_t &payloadBytesToSend,
829 const uint8_t*& data,
830 const uint16_t rtpHeaderLength,
831 uint16_t& decodingOrderNumber,
832 const bool sendSVCPACSI)
834 // no H.264 header lenght in single mode
835 // we use WEBRTC_IP_PACKET_SIZE instead of the configured MTU since it's better to send fragmented UDP than not to send
836 const uint16_t maxPayloadLength = WEBRTC_IP_PACKET_SIZE - _rtpSender.PacketOverHead() - FECPacketOverhead() - rtpHeaderLength;
837 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
838 bool isBaseLayer=false;
840 if(ptrH264Info->payloadSize[idxNALU] > maxPayloadLength)
844 if(!_h264SendPPS_SPS)
846 // don't send NALU of type 7 and 8 SPS and PPS
847 if(ptrH264Info->type[idxNALU] == 7 || ptrH264Info->type[idxNALU] == 8)
849 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
850 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
857 SendH264_SinglePACSI(frameType,
865 uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+
866 (ptrH264Info->SVCheader[idxNALU].qualityID << 8) +
867 ptrH264Info->SVCheader[idxNALU].temporalID;
868 isBaseLayer=(layer==0);
871 // Put payload in packet
872 memcpy(&dataBuffer[rtpHeaderLength], &data[ptrH264Info->startCodeSize[idxNALU]], ptrH264Info->payloadSize[idxNALU]);
874 uint16_t payloadBytesInPacket = (uint16_t)ptrH264Info->payloadSize[idxNALU];
875 payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; // left to send
878 _rtpSender.BuildRTPheader(dataBuffer,payloadType,(payloadBytesToSend ==0)?true:false, captureTimeStamp);
880 dataBuffer[rtpHeaderLength] &= 0x1f; // zero out NRI field
881 dataBuffer[rtpHeaderLength] |= ptrH264Info->NRI[idxNALU]; // nri
882 if(payloadBytesToSend > 0)
884 data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU];
887 if(-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket, rtpHeaderLength,isBaseLayer))
895 RTPSenderH264::SendH264_SinglePACSI(const FrameType frameType,
896 const H264Info* ptrH264Info,
897 const uint16_t idxNALU,
898 const int8_t payloadType,
899 const uint32_t captureTimeStamp,
900 const bool firstPacketInNALU,
901 const bool lastPacketInNALU);
903 // Send PACSI in single mode
904 uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE];
905 uint16_t rtpHeaderLength = (uint16_t)_rtpSender.BuildRTPheader(dataBuffer, payloadType,false, captureTimeStamp);
906 int32_t dataOffset = rtpHeaderLength;
908 int32_t lengthPASCINALU = AddH264PACSINALU(firstPacketInNALU,
910 ptrH264Info->PACSI[idxNALU],
911 ptrH264Info->SVCheader[idxNALU],
916 if (lengthPASCINALU <= 0)
920 decodingOrderNumber++;
922 uint16_t payloadBytesInPacket = (uint16_t)lengthPASCINALU;
924 // Set payload header (first payload byte co-serves as the payload header)
925 dataBuffer[rtpHeaderLength] &= 0x1f; // zero out NRI field
926 dataBuffer[rtpHeaderLength] |= ptrH264Info->NRI[idxNALU]; // nri
928 const uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+
929 (ptrH264Info->SVCheader[idxNALU].qualityID << 8) +
930 ptrH264Info->SVCheader[idxNALU].temporalID;
932 if (-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket, rtpHeaderLength,layer==0))
943 RTPSenderH264::SendH264SVC(const FrameType frameType,
944 const int8_t payloadType,
945 const uint32_t captureTimeStamp,
946 const uint8_t* payloadData,
947 const uint32_t payloadSize,
948 H264Information& h264Information,
949 uint16_t& decodingOrderNumber)
951 int32_t payloadBytesToSend = payloadSize;
952 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
954 const H264Info* ptrH264Info = NULL;
955 if (h264Information.GetInfo(payloadData,payloadSize, ptrH264Info) == -1)
959 if(_useHighestSendLayer)
961 // we need to check if we should drop the frame
962 // it could be a temporal layer (aka a temporal frame)
963 const uint8_t dependencyQualityID = (ptrH264Info->SVCheader[0].dependencyID << 4) + ptrH264Info->SVCheader[0].qualityID;
965 bool dummyHighestLayer;
966 if(SendH264SVCLayer(frameType,
967 ptrH264Info->SVCheader[0].temporalID,
969 dummyHighestLayer) == false)
971 // skip send this frame
976 uint16_t idxNALU = 0;
977 while (payloadBytesToSend > 0)
979 bool switchToFUA = false;
980 if (SendH264_STAP_A_PACSI(frameType,
989 decodingOrderNumber) != 0)
995 // FU_A for this NALU
996 if (SendH264_FU_A(frameType,
1014 RTPSenderH264::SetH264PacketizationMode(const H264PacketizationMode mode)
1021 RTPSenderH264::SetH264SendModeNALU_PPS_SPS(const bool dontSend)
1023 _h264SendPPS_SPS = !dontSend;
1028 RTPSenderH264::SendH264SVCLayer(const FrameType frameType,
1029 const uint8_t temporalID,
1030 const uint8_t dependencyQualityID,
1033 uint8_t dependencyID = dependencyQualityID >> 4;
1035 // keyframe required to switch between dependency layers not quality and temporal
1036 if( _highestDependencyLayer != _highestDependencyLayerOld)
1038 // we want to switch dependency layer
1039 if(frameType == kVideoFrameKey)
1041 // key frame we can change layer if it's correct layer
1042 if(_highestDependencyLayer > _highestDependencyLayerOld)
1044 // we want to switch up
1045 // does this packet belong to a new layer?
1047 if( dependencyID > _highestDependencyLayerOld &&
1048 dependencyID <= _highestDependencyLayer)
1050 _highestDependencyLayerOld = dependencyID;
1051 _highestDependencyQualityIDOld = _highestDependencyQualityID;
1053 if( dependencyID == _highestDependencyLayer &&
1054 dependencyQualityID == _highestDependencyQualityID)
1062 if(_highestDependencyLayer < _highestDependencyLayerOld)
1064 // we want to switch down
1065 // does this packet belong to a low layer?
1066 if( dependencyID <= _highestDependencyLayer)
1068 _highestDependencyLayerOld = dependencyID;
1069 _highestDependencyQualityIDOld = _highestDependencyQualityID;
1070 if( dependencyID == _highestDependencyLayer &&
1071 dependencyQualityID == _highestDependencyQualityID)
1081 // Delta frame and we are waiting to switch dependency layer
1082 if(_highestDependencyLayer > _highestDependencyLayerOld)
1084 // we want to switch up to a higher dependency layer
1085 // use old setting until we get a key-frame
1087 // filter based on old dependency
1088 // we could have allowed to add a MGS layer lower than the dependency ID
1089 // but then we can't know the highest layer relayed we assume that the user
1090 // will add one layer at a time
1091 if( _highestTemporalLayer < temporalID ||
1092 _highestDependencyLayerOld < dependencyID ||
1093 _highestDependencyQualityIDOld < dependencyQualityID)
1098 // highest layer based on old
1099 if( dependencyID == _highestDependencyLayerOld &&
1100 dependencyQualityID == _highestDependencyQualityIDOld)
1106 // we want to switch down to a lower dependency layer,
1107 // use old setting, done bellow
1108 // drop all temporal layers while waiting for the key-frame
1114 // we can't drop a lower MGS layer since this might depend on it
1115 // however we can drop MGS layers larger than dependecyQualityId
1116 // with dependency from old and quality 0
1117 if( _highestDependencyLayerOld < dependencyID ||
1118 (_highestDependencyQualityIDOld & 0xf0) < dependencyQualityID)
1123 if( dependencyID == _highestDependencyLayerOld &&
1124 dependencyQualityID == (_highestDependencyQualityIDOld & 0xf0))
1132 // filter based on current state
1133 if( _highestTemporalLayer < temporalID ||
1134 _highestDependencyLayer < dependencyID ||
1135 _highestDependencyQualityID < dependencyQualityID)
1140 if( dependencyID == _highestDependencyLayer &&
1141 dependencyQualityID == _highestDependencyQualityID)
1150 RTPSenderH264::SetHighestSendLayer(const uint8_t dependencyQualityLayer,
1151 const uint8_t temporalLayer)
1153 const uint8_t dependencyLayer = (dependencyQualityLayer >> 4);
1155 if(_highestDependencyLayerOld != _highestDependencyLayer)
1157 // we have not switched to the new dependency yet
1160 if(_highestDependencyLayer == dependencyLayer)
1162 // no change of dependency
1163 // switch now _highestDependencyQualityIDOld
1164 _highestDependencyQualityIDOld = dependencyQualityLayer;
1167 // change of dependency, update _highestDependencyQualityIDOld store as old
1168 _highestDependencyQualityIDOld = _highestDependencyQualityID;
1171 _useHighestSendLayer = true;
1172 _highestDependencyLayer = dependencyLayer;
1173 _highestDependencyQualityID = dependencyQualityLayer;
1174 _highestTemporalLayer = temporalLayer;
1179 RTPSenderH264::HighestSendLayer(uint8_t& dependencyQualityLayer,
1180 uint8_t& temporalLayer)
1182 if (!_useHighestSendLayer)
1184 // No information set
1187 dependencyQualityLayer = _highestDependencyQualityID;
1188 temporalLayer = _highestTemporalLayer;
1195 RTPSenderH264::SendH264(const FrameType frameType,
1196 const int8_t payloadType,
1197 const uint32_t captureTimeStamp,
1198 const uint8_t* payloadData,
1199 const uint32_t payloadSize,
1200 H264Information& h264Information)
1202 int32_t payloadBytesToSend = payloadSize;
1203 const uint8_t* data = payloadData;
1204 bool switchToFUA = false;
1205 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
1207 const H264Info* ptrH264Info = NULL;
1208 if (h264Information.GetInfo(payloadData,payloadSize, ptrH264Info) == -1)
1212 uint16_t idxNALU = 0;
1213 uint16_t DONCdummy = 0;
1215 while (payloadBytesToSend > 0)
1219 case H264_NON_INTERLEAVED_MODE:
1223 if(SendH264_STAP_A(frameType,
1231 rtpHeaderLength) != 0)
1238 // FUA for the rest of the frame
1239 if(SendH264_FU_A(frameType,
1251 // try to go back to STAP_A
1252 switchToFUA = false;
1255 case H264_SINGLE_NAL_MODE:
1258 if(SendH264_SingleMode(frameType,
1272 case H264_INTERLEAVED_MODE:
1280 } // namespace webrtc