ObjC: Support non-native frames in encoder
Frames might be non-native, i.e. normal I420 frames, and we should handle that in the encoder. BUG=webrtc:7785,webrtc:7924 Review-Url: https://codereview.webrtc.org/2992943002 Cr-Commit-Position: refs/heads/master@{#19245}
This commit is contained in:
@ -13,6 +13,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#import "NSString+StdString.h"
|
#import "NSString+StdString.h"
|
||||||
|
#import "RTCI420Buffer+Private.h"
|
||||||
#import "RTCVideoCodec+Private.h"
|
#import "RTCVideoCodec+Private.h"
|
||||||
#import "WebRTC/RTCVideoCodec.h"
|
#import "WebRTC/RTCVideoCodec.h"
|
||||||
#import "WebRTC/RTCVideoCodecFactory.h"
|
#import "WebRTC/RTCVideoCodecFactory.h"
|
||||||
@ -33,6 +34,22 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
id<RTCVideoFrameBuffer> nativeToRtcFrameBuffer(const rtc::scoped_refptr<VideoFrameBuffer> &buffer) {
|
||||||
|
return buffer->type() == VideoFrameBuffer::Type::kNative ?
|
||||||
|
static_cast<ObjCFrameBuffer *>(buffer.get())->wrapped_frame_buffer() :
|
||||||
|
[[RTCI420Buffer alloc] initWithFrameBuffer:buffer->ToI420()];
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCVideoFrame *nativeToRtcFrame(const VideoFrame &frame) {
|
||||||
|
RTCVideoFrame *rtcFrame =
|
||||||
|
[[RTCVideoFrame alloc] initWithBuffer:nativeToRtcFrameBuffer(frame.video_frame_buffer())
|
||||||
|
rotation:RTCVideoRotation(frame.rotation())
|
||||||
|
timeStampNs:frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
|
||||||
|
rtcFrame.timeStamp = frame.timestamp();
|
||||||
|
return rtcFrame;
|
||||||
|
}
|
||||||
|
|
||||||
class ObjCVideoEncoder : public VideoEncoder {
|
class ObjCVideoEncoder : public VideoEncoder {
|
||||||
public:
|
public:
|
||||||
ObjCVideoEncoder(id<RTCVideoEncoder> encoder)
|
ObjCVideoEncoder(id<RTCVideoEncoder> encoder)
|
||||||
@ -53,14 +70,13 @@ class ObjCVideoEncoder : public VideoEncoder {
|
|||||||
RTCRtpFragmentationHeader *header) {
|
RTCRtpFragmentationHeader *header) {
|
||||||
EncodedImage encodedImage = [frame nativeEncodedImage];
|
EncodedImage encodedImage = [frame nativeEncodedImage];
|
||||||
|
|
||||||
// Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded
|
// Handle types than can be converted into one of CodecSpecificInfo's hard coded cases.
|
||||||
// cases.
|
|
||||||
CodecSpecificInfo codecSpecificInfo;
|
CodecSpecificInfo codecSpecificInfo;
|
||||||
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
|
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
|
||||||
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info nativeCodecSpecificInfo];
|
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info nativeCodecSpecificInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<webrtc::RTPFragmentationHeader> fragmentationHeader =
|
std::unique_ptr<RTPFragmentationHeader> fragmentationHeader =
|
||||||
[header createNativeFragmentationHeader];
|
[header createNativeFragmentationHeader];
|
||||||
callback->OnEncodedImage(encodedImage, &codecSpecificInfo, fragmentationHeader.release());
|
callback->OnEncodedImage(encodedImage, &codecSpecificInfo, fragmentationHeader.release());
|
||||||
}];
|
}];
|
||||||
@ -73,17 +89,7 @@ class ObjCVideoEncoder : public VideoEncoder {
|
|||||||
int32_t Encode(const VideoFrame &frame,
|
int32_t Encode(const VideoFrame &frame,
|
||||||
const CodecSpecificInfo *codec_specific_info,
|
const CodecSpecificInfo *codec_specific_info,
|
||||||
const std::vector<FrameType> *frame_types) {
|
const std::vector<FrameType> *frame_types) {
|
||||||
RTC_CHECK(frame.video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative);
|
// CodecSpecificInfo only handles a hard coded list of codecs
|
||||||
|
|
||||||
id<RTCVideoFrameBuffer> frame_buffer =
|
|
||||||
static_cast<ObjCFrameBuffer *>(frame.video_frame_buffer().get())->wrapped_frame_buffer();
|
|
||||||
RTCVideoFrame *rtcFrame =
|
|
||||||
[[RTCVideoFrame alloc] initWithBuffer:frame_buffer
|
|
||||||
rotation:RTCVideoRotation(frame.rotation())
|
|
||||||
timeStampNs:frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
|
|
||||||
rtcFrame.timeStamp = frame.timestamp();
|
|
||||||
|
|
||||||
// webrtc::CodecSpecificInfo only handles a hard coded list of codecs
|
|
||||||
id<RTCCodecSpecificInfo> rtcCodecSpecificInfo = nil;
|
id<RTCCodecSpecificInfo> rtcCodecSpecificInfo = nil;
|
||||||
if (codec_specific_info) {
|
if (codec_specific_info) {
|
||||||
if (strcmp(codec_specific_info->codec_name, "H264") == 0) {
|
if (strcmp(codec_specific_info->codec_name, "H264") == 0) {
|
||||||
@ -99,8 +105,9 @@ class ObjCVideoEncoder : public VideoEncoder {
|
|||||||
[rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))];
|
[rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))];
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return [encoder_ encode:nativeToRtcFrame(frame)
|
||||||
[encoder_ encode:rtcFrame codecSpecificInfo:rtcCodecSpecificInfo frameTypes:rtcFrameTypes];
|
codecSpecificInfo:rtcCodecSpecificInfo
|
||||||
|
frameTypes:rtcFrameTypes];
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) { return WEBRTC_VIDEO_CODEC_OK; }
|
int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) { return WEBRTC_VIDEO_CODEC_OK; }
|
||||||
@ -139,8 +146,7 @@ id<RTCVideoEncoderFactory> ObjCVideoEncoderFactory::wrapped_encoder_factory() co
|
|||||||
return encoder_factory_;
|
return encoder_factory_;
|
||||||
}
|
}
|
||||||
|
|
||||||
webrtc::VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(
|
VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(const cricket::VideoCodec &codec) {
|
||||||
const cricket::VideoCodec &codec) {
|
|
||||||
RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeVideoCodec:codec];
|
RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeVideoCodec:codec];
|
||||||
id<RTCVideoEncoder> encoder = [encoder_factory_ createEncoder:info];
|
id<RTCVideoEncoder> encoder = [encoder_factory_ createEncoder:info];
|
||||||
return new ObjCVideoEncoder(encoder);
|
return new ObjCVideoEncoder(encoder);
|
||||||
@ -156,7 +162,7 @@ const std::vector<cricket::VideoCodec> &ObjCVideoEncoderFactory::supported_codec
|
|||||||
return supported_codecs_;
|
return supported_codecs_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCVideoEncoderFactory::DestroyVideoEncoder(webrtc::VideoEncoder *encoder) {
|
void ObjCVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder *encoder) {
|
||||||
delete encoder;
|
delete encoder;
|
||||||
encoder = nullptr;
|
encoder = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user