15
15
#include < vector>
16
16
17
17
#import " RTCCodecSpecificInfoH265.h"
18
- #import " api/peerconnection/RTCRtpFragmentationHeader+Private.h"
19
18
#import " api/peerconnection/RTCVideoCodecInfo+Private.h"
20
19
#import " base/RTCI420Buffer.h"
21
20
#import " base/RTCVideoFrame.h"
38
37
#include " sdk/objc/Framework/Classes/VideoToolbox/nalu_rewriter.h"
39
38
#include " system_wrappers/include/clock.h"
40
39
41
- @interface RTCVideoEncoderH265 ()
40
+ @interface RTC_OBJC_TYPE (RTCVideoEncoderH265)
41
+ ()
42
42
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;
51
48
52
49
@end
53
50
@@ -65,7 +62,8 @@ - (void)frameWasEncoded:(OSStatus)status
65
62
// Struct that we pass to the encoder per frame to encode. We receive it again
66
63
// in the encoder callback.
67
64
struct API_AVAILABLE (ios(11.0 )) RTCFrameEncodeParams {
68
- RTCFrameEncodeParams (RTCVideoEncoderH265* e,
65
+ RTCFrameEncodeParams (RTC_OBJC_TYPE (RTCVideoEncoderH265) * e,
66
+ RTC_OBJC_TYPE (RTCCodecSpecificInfoH265) * csi,
69
67
int32_t w,
70
68
int32_t h,
71
69
int64_t rtms,
@@ -76,9 +74,16 @@ struct API_AVAILABLE(ios(11.0)) RTCFrameEncodeParams {
76
74
height (h),
77
75
render_time_ms (rtms),
78
76
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
+ }
80
84
81
- RTCVideoEncoderH265* encoder;
85
+ RTC_OBJC_TYPE (RTCVideoEncoderH265) * encoder;
86
+ RTC_OBJC_TYPE (RTCCodecSpecificInfoH265) * codecSpecificInfo;
82
87
int32_t width;
83
88
int32_t height;
84
89
int64_t render_time_ms;
@@ -149,13 +154,17 @@ void compressionOutputCallback(void* encoder,
149
154
VTEncodeInfoFlags infoFlags,
150
155
CMSampleBufferRef sampleBuffer)
151
156
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
+ }
153
161
std::unique_ptr<RTCFrameEncodeParams> encodeParams (
154
162
reinterpret_cast <RTCFrameEncodeParams*>(params));
155
163
RTC_CHECK (encodeParams->encoder );
156
164
[encodeParams->encoder frameWasEncoded: status
157
165
flags: infoFlags
158
166
sampleBuffer: sampleBuffer
167
+ codecSpecificInfo: encodeParams->codecSpecificInfo
159
168
width: encodeParams->width
160
169
height: encodeParams->height
161
170
renderTimeMs: encodeParams->render_time_ms
@@ -319,8 +328,9 @@ - (NSInteger)encode:(RTCVideoFrame*)frame
319
328
320
329
std::unique_ptr<RTCFrameEncodeParams> encodeParams;
321
330
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 ));
324
334
325
335
// Update the bitrate if needed.
326
336
[self setBitrateBps: _bitrateAdjuster->GetAdjustedBitrateBps ()];
@@ -530,6 +540,7 @@ - (void)setEncoderBitrateBps:(uint32_t)bitrateBps {
530
540
- (void )frameWasEncoded : (OSStatus)status
531
541
flags : (VTEncodeInfoFlags)infoFlags
532
542
sampleBuffer : (CMSampleBufferRef)sampleBuffer
543
+ codecSpecificInfo : (id <RTC_OBJC_TYPE(RTCCodecSpecificInfo)>)codecSpecificInfo
533
544
width : (int32_t )width
534
545
height : (int32_t )height
535
546
renderTimeMs : (int64_t )renderTimeMs
@@ -558,20 +569,9 @@ - (void)frameWasEncoded:(OSStatus)status
558
569
RTC_LOG (LS_INFO) << " Generated keyframe" ;
559
570
}
560
571
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 ;
575
575
}
576
576
577
577
RTCEncodedImage* frame = [[RTCEncodedImage alloc ] init ];
@@ -580,7 +580,6 @@ - (void)frameWasEncoded:(OSStatus)status
580
580
freeWhenDone: NO ];
581
581
frame.encodedWidth = width;
582
582
frame.encodedHeight = height;
583
- frame.completeFrame = YES ;
584
583
frame.frameType =
585
584
isKeyframe ? RTCFrameTypeVideoFrameKey : RTCFrameTypeVideoFrameDelta;
586
585
frame.captureTimeMs = renderTimeMs;
@@ -596,7 +595,9 @@ - (void)frameWasEncoded:(OSStatus)status
596
595
_h265BitstreamParser.GetLastSliceQp (&qp);
597
596
frame.qp = @(qp);
598
597
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);
600
601
if (!res) {
601
602
RTC_LOG (LS_ERROR) << " Encode callback failed." ;
602
603
return ;
0 commit comments