1515#include < vector>
1616
1717#import " RTCCodecSpecificInfoH265.h"
18- #import " api/peerconnection/RTCRtpFragmentationHeader+Private.h"
1918#import " api/peerconnection/RTCVideoCodecInfo+Private.h"
2019#import " base/RTCI420Buffer.h"
2120#import " base/RTCVideoFrame.h"
3837#include " sdk/objc/Framework/Classes/VideoToolbox/nalu_rewriter.h"
3938#include " system_wrappers/include/clock.h"
4039
41- @interface RTCVideoEncoderH265 ()
40+ @interface RTC_OBJC_TYPE (RTCVideoEncoderH265)
41+ ()
4242
43- - (void )frameWasEncoded : (OSStatus)status
44- flags : (VTEncodeInfoFlags)infoFlags
45- sampleBuffer : (CMSampleBufferRef)sampleBuffer
46- width : (int32_t )width
47- height : (int32_t )height
48- renderTimeMs : (int64_t )renderTimeMs
49- timestamp : (uint32_t )timestamp
50- rotation : (RTCVideoRotation)rotation ;
43+ - (void )frameWasEncoded : (OSStatus)status flags : (VTEncodeInfoFlags)infoFlags sampleBuffer
44+ : (CMSampleBufferRef)sampleBuffer codecSpecificInfo
45+ : (id <RTC_OBJC_TYPE(RTCCodecSpecificInfo)>)codecSpecificInfo width : (int32_t )width height
46+ : (int32_t )height renderTimeMs : (int64_t )renderTimeMs timestamp : (uint32_t )timestamp rotation
47+ : (RTCVideoRotation)rotation;
5148
5249@end
5350
@@ -65,7 +62,8 @@ - (void)frameWasEncoded:(OSStatus)status
6562// Struct that we pass to the encoder per frame to encode. We receive it again
6663// in the encoder callback.
6764struct API_AVAILABLE (ios(11.0 )) RTCFrameEncodeParams {
68- RTCFrameEncodeParams (RTCVideoEncoderH265* e,
65+ RTCFrameEncodeParams (RTC_OBJC_TYPE (RTCVideoEncoderH265) * e,
66+ RTC_OBJC_TYPE (RTCCodecSpecificInfoH265) * csi,
6967 int32_t w,
7068 int32_t h,
7169 int64_t rtms,
@@ -76,9 +74,16 @@ struct API_AVAILABLE(ios(11.0)) RTCFrameEncodeParams {
7674 height (h),
7775 render_time_ms (rtms),
7876 timestamp (ts),
79- rotation (r) {}
77+ rotation (r) {
78+ if (csi) {
79+ codecSpecificInfo = csi;
80+ } else {
81+ codecSpecificInfo = [[RTC_OBJC_TYPE (RTCCodecSpecificInfoH265) alloc ] init ];
82+ }
83+ }
8084
81- RTCVideoEncoderH265* encoder;
85+ RTC_OBJC_TYPE (RTCVideoEncoderH265) * encoder;
86+ RTC_OBJC_TYPE (RTCCodecSpecificInfoH265) * codecSpecificInfo;
8287 int32_t width;
8388 int32_t height;
8489 int64_t render_time_ms;
@@ -149,13 +154,17 @@ void compressionOutputCallback(void* encoder,
149154 VTEncodeInfoFlags infoFlags,
150155 CMSampleBufferRef sampleBuffer)
151156 API_AVAILABLE(ios(11.0 )) {
152- RTC_CHECK (params);
157+ if (!params) {
158+ // If there are pending callbacks when the encoder is destroyed, this can happen.
159+ return ;
160+ }
153161 std::unique_ptr<RTCFrameEncodeParams> encodeParams (
154162 reinterpret_cast <RTCFrameEncodeParams*>(params));
155163 RTC_CHECK (encodeParams->encoder );
156164 [encodeParams->encoder frameWasEncoded: status
157165 flags: infoFlags
158166 sampleBuffer: sampleBuffer
167+ codecSpecificInfo: encodeParams->codecSpecificInfo
159168 width: encodeParams->width
160169 height: encodeParams->height
161170 renderTimeMs: encodeParams->render_time_ms
@@ -319,8 +328,9 @@ - (NSInteger)encode:(RTCVideoFrame*)frame
319328
320329 std::unique_ptr<RTCFrameEncodeParams> encodeParams;
321330 encodeParams.reset (new RTCFrameEncodeParams (
322- self, _width, _height, frame.timeStampNs / rtc::kNumNanosecsPerMillisec ,
323- frame.timeStamp , frame.rotation ));
331+ self, codecSpecificInfo,_width, _height,
332+ frame.timeStampNs / rtc::kNumNanosecsPerMillisec , frame.timeStamp ,
333+ frame.rotation ));
324334
325335 // Update the bitrate if needed.
326336 [self setBitrateBps: _bitrateAdjuster->GetAdjustedBitrateBps ()];
@@ -530,6 +540,7 @@ - (void)setEncoderBitrateBps:(uint32_t)bitrateBps {
530540- (void )frameWasEncoded : (OSStatus)status
531541 flags : (VTEncodeInfoFlags)infoFlags
532542 sampleBuffer : (CMSampleBufferRef)sampleBuffer
543+ codecSpecificInfo : (id <RTC_OBJC_TYPE(RTCCodecSpecificInfo)>)codecSpecificInfo
533544 width : (int32_t )width
534545 height : (int32_t )height
535546 renderTimeMs : (int64_t )renderTimeMs
@@ -558,20 +569,9 @@ - (void)frameWasEncoded:(OSStatus)status
558569 RTC_LOG (LS_INFO) << " Generated keyframe" ;
559570 }
560571
561- // Convert the sample buffer into a buffer suitable for RTP packetization.
562- // TODO(tkchin): Allocate buffers through a pool.
563- std::unique_ptr<rtc::Buffer> buffer (new rtc::Buffer ());
564- RTCRtpFragmentationHeader* header;
565- {
566- std::unique_ptr<webrtc::RTPFragmentationHeader> header_cpp;
567- bool result = H265CMSampleBufferToAnnexBBuffer (sampleBuffer, isKeyframe,
568- buffer.get (), &header_cpp);
569- header = [[RTCRtpFragmentationHeader alloc ]
570- initWithNativeFragmentationHeader: header_cpp.get ()];
571- if (!result) {
572- RTC_LOG (LS_ERROR) << " Failed to convert sample buffer." ;
573- return ;
574- }
572+ __block std::unique_ptr<rtc::Buffer> buffer = std::make_unique<rtc::Buffer>();
573+ if (!webrtc::H265CMSampleBufferToAnnexBBuffer (sampleBuffer, isKeyframe, buffer.get ())) {
574+ return ;
575575 }
576576
577577 RTCEncodedImage* frame = [[RTCEncodedImage alloc ] init ];
@@ -580,7 +580,6 @@ - (void)frameWasEncoded:(OSStatus)status
580580 freeWhenDone: NO ];
581581 frame.encodedWidth = width;
582582 frame.encodedHeight = height;
583- frame.completeFrame = YES ;
584583 frame.frameType =
585584 isKeyframe ? RTCFrameTypeVideoFrameKey : RTCFrameTypeVideoFrameDelta;
586585 frame.captureTimeMs = renderTimeMs;
@@ -596,7 +595,9 @@ - (void)frameWasEncoded:(OSStatus)status
596595 _h265BitstreamParser.GetLastSliceQp (&qp);
597596 frame.qp = @(qp);
598597
599- BOOL res = _callback (frame, [[RTCCodecSpecificInfoH265 alloc ] init ], header);
598+ RTC_OBJC_TYPE (RTCRtpFragmentationHeader) *header =
599+ [[RTC_OBJC_TYPE (RTCRtpFragmentationHeader) alloc ] init ];
600+ BOOL res = _callback (frame, codecSpecificInfo, header);
600601 if (!res) {
601602 RTC_LOG (LS_ERROR) << " Encode callback failed." ;
602603 return ;
0 commit comments